diff --git a/.appveyor.yml b/.appveyor.yml index 552fdbd2f..586eb059e 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -12,7 +12,11 @@ install: - vcpkg --no-dry-run upgrade - rd /Q /S C:\Tools\vcpkg\buildtrees before_build: -- cmake . -DCMAKE_PREFIX_PATH=C:\Qt\5.15\msvc2019_64 -DCMAKE_TOOLCHAIN_FILE=C:\Tools\vcpkg\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-release -DCMAKE_CONFIGURATION_TYPES=Release +- cmake . -DCMAKE_PREFIX_PATH=C:\Qt\5.15\msvc2019_64 \ + -DCMAKE_TOOLCHAIN_FILE=C:\Tools\vcpkg\scripts\buildsystems\vcpkg.cmake \ + -DVCPKG_TARGET_TRIPLET=x64-windows-release \ + -DCMAKE_CONFIGURATION_TYPES=Release \ + -DCMAKE_SYSTEM_VERSION=10.0.22000.1 build: parallel: true project: mGBA.sln diff --git a/.gitignore b/.gitignore index 999fdd673..e9e3b3956 100644 Binary files a/.gitignore and b/.gitignore differ diff --git a/CHANGES b/CHANGES index 7876950e6..e432bee67 100644 --- a/CHANGES +++ b/CHANGES @@ -1,46 +1,98 @@ 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: 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 I/O: Fix audio register 8-bit write behavior (fixes mgba.io/i/3086) + - GBA Serialize: Fix some minor save state edge cases + - GBA Serialize: Properly restore GPIO register state (fixes mgba.io/i/3294) + - 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) + - Core: Fix patch autoloading leaking the file handle + - 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 + - Qt: Fix saving named states breaking when screenshot states disabled (fixes mgba.io/i/3320) + - 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) + - Core: Add MD5 hashing for ROMs + - 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 SIO: Rewrite lockstep driver for improved stability + - 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 + - Qt: Make window corners square on Windows 11 (fixes mgba.io/i/3285) + - Qt: Show a dummy shader settings tab if shaders aren't supported + - Res: Port NSO-gba-colors shader (closes mgba.io/i/2834) + - 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 + +0.10.3: (2024-01-07) Emulation fixes: - ARM: Remove obsolete force-alignment in `bx pc` (fixes mgba.io/i/2964) - ARM: Fake bpkt instruction should take no cycles (fixes mgba.io/i/2551) - GB Audio: Fix channels 1/2 staying muted if restarted after long silence - GB Audio: Fix channel 1 restarting if sweep applies after stop (fixes mgba.io/i/2965) + - GB Audio: Fix restarting envelope when writing to register (fixes mgba.io/i/3067) + - GB Audio: Improve "zombie mode" emulation in CGB mode (fixes mgba.io/i/2029) - GB I/O: Read back proper SVBK value after writing 0 (fixes mgba.io/i/2921) - - GB I/O: Fix STAT writing IRQ trigger conditions (fixes mgba.io/i/2501) - - GB Serialize: Add missing Pocket Cam state to savestates - GB SIO: Disabling SIO should cancel pending transfers (fixes mgba.io/i/2537) - - GB Video: Implement DMG-style sprite ordering - - GBA: Unhandled bkpt should be treated as an undefined exception - GBA Audio: Fix sample timing drifting when changing sample interval - GBA Audio: Fix initial channel 3 wave RAM (fixes mgba.io/i/2947) - GBA Audio: Fix sample position issues when rate changes (fixes mgba.io/i/3006) - GBA GPIO: Fix tilt scale and orientation (fixes mgba.io/i/2703) - GBA BIOS: Fix clobbering registers with word-sized CpuSet - GBA SIO: Fix normal mode SI/SO semantics (fixes mgba.io/i/2925) - - GBA Video: Disable BG target 1 blending when OBJ blending (fixes mgba.io/i/2722) 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 - - mGUI: Fix cases where an older save state screenshot would be shown. (fixes mgba.io/i/2183) - - Qt: Fix savestate preview sizes with different scales (fixes mgba.io/i/2560) + - GB: Fix applying a patch that changes the cartridge mapper (fixes mgba.io/i/3077) + - GBA Savedata: Fix crash when resizing flash save games for RTC data + - mGUI: Fix cases where an older save state screenshot would be shown (fixes mgba.io/i/2183) - Qt: Re-enable sync for multiplayer windows that aren't connected (fixes mgba.io/i/2974) - Qt: Fix mute settings not being loaded on setting screen (fixes mgba.io/i/2990) + - Qt: Fix screen freezing on macOS after closing save state window (fixes mgba.io/i/2885) - Vita: Fix camera setting not appearing (fixes mgba.io/i/3012) Misc: - - Core: Handle relative paths for saves, screenshots, etc consistently (fixes mgba.io/i/2826) - - 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 - - mGUI: Enable auto-softpatching (closes mgba.io/i/2899) + - mGUI: Persist fast forwarding after closing menu (fixes mgba.io/i/2414) - Qt: Add exporting of SAV + RTC saves from Save Converter to strip RTC data - - 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) - - Scripting: Add `callbacks:oneshot` for single-call callbacks + - VFS: Use anonymousMemoryMap for large 7z allocations (fixes mgba.io/i/3013) 0.10.2: (2023-04-23) Emulation fixes: diff --git a/CMakeLists.txt b/CMakeLists.txt index 81fdeec3f..78fddfce4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,18 +39,18 @@ if(NOT MSVC) # TODO: Remove this once mScript KV pairs support const correctness set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=incompatible-pointer-types") endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -Woverloaded-virtual") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -Woverloaded-virtual -Werror=reorder") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267 /Zc:preprocessor-") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267 /Zc:preprocessor-") 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,11 +77,12 @@ 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") set(BUILD_DOCGEN OFF CACHE BOOL "Build the scripting API documentation generator") + set(BUILD_MAINTAINER_TOOLS OFF CACHE BOOL "Build tools only useful for maintainers") set(USE_EPOXY ON CACHE STRING "Build with libepoxy") set(DISABLE_DEPS OFF CACHE BOOL "Build without dependencies") set(DISTBUILD OFF CACHE BOOL "Build distribution packages") @@ -93,6 +91,7 @@ if(NOT LIBMGBA_ONLY) mark_as_advanced(WIN32_UNIX_PATHS) endif() mark_as_advanced(BUILD_DOCGEN) + mark_as_advanced(BUILD_MAINTAINER_TOOLS) else() set(DISABLE_FRONTENDS ON) set(DISABLE_DEPS ON) @@ -142,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) @@ -213,18 +207,22 @@ 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}") - add_definitions(-D_WIN32_WINNT=0x0600) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) if(MSVC) add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) add_definitions(-D_UNICODE -DUNICODE) else() add_definitions(-D_GNU_SOURCE) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + add_compile_definitions(_FILE_OFFSET_BITS=64) + 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) @@ -234,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() @@ -273,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() @@ -297,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 "") @@ -309,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) @@ -341,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) @@ -489,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) @@ -537,14 +521,12 @@ if(USE_EDITLINE) set(DEBUGGER_LIB ${LIBEDIT_LIBRARIES}) endif() set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libedit2") - list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/editline/cli-el-backend.c") else() set(DEBUGGER_LIB "") endif() -if(USE_GDB_STUB) - list(APPEND FEATURES GDB_STUB) - list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/gdb-stub.c) +if(ENABLE_GDB_STUB) + list(APPEND ENABLES GDB_STUB) endif() source_group("Debugger" FILES ${DEBUGGER_SRC}) @@ -588,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) @@ -853,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) @@ -864,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() @@ -877,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() @@ -902,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) @@ -934,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}) @@ -994,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) @@ -1005,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() @@ -1029,7 +1000,7 @@ if(BUILD_UPDATER) add_executable(updater-stub WIN32 ${CORE_VFS_SRC} ${VFS_SRC} ${OS_SRC} ${UTIL_BASE_SRC} ${THIRD_PARTY_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/src/core/config.c ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/updater.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/updater-main.c) + ${CMAKE_CURRENT_SOURCE_DIR}/src/tools/updater-main.c) target_link_libraries(updater-stub ${ZLIB_LIBRARY} ${ZLIB_LIBRARY} ${ZIP_LIBRARIES} ${OS_LIB} ${PLATFORM_LIBRARY}) set_target_properties(updater-stub PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FUNCTION_DEFINES};${FEATURE_DEFINES};BUILD_STATIC") if(MSVC) @@ -1041,8 +1012,14 @@ if(BUILD_UPDATER) endif() if(ENABLE_SCRIPTING AND BUILD_DOCGEN) - add_executable(docgen ${CMAKE_CURRENT_SOURCE_DIR}/src/script/docgen.c) + 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) + add_executable(font-sdf-tool ${CMAKE_CURRENT_SOURCE_DIR}/src/tools/font-sdf.c ${CMAKE_CURRENT_SOURCE_DIR}/src/util/gui/font-metrics.c) + target_link_libraries(font-sdf-tool ${OS_LIB} ${PLATFORM_LIBRARY} ${BINARY_NAME}) endif() if(BUILD_SDL) @@ -1082,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}) @@ -1309,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}") @@ -1344,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}") diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 000000000..584b1987d --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,21 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "clang", + "generator": "Ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + }, + { + "name": "gcc", + "generator": "Ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + } + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 78b69f255..d937fa0c9 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/README_DE.md b/README_DE.md index 9b653c5d2..9a4066a0f 100644 --- a/README_DE.md +++ b/README_DE.md @@ -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. diff --git a/README_ES.md b/README_ES.md index f174e114c..1a6d0b797 100644 --- a/README_ES.md +++ b/README_ES.md @@ -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. diff --git a/README_ZH_CN.md b/README_ZH_CN.md index 757f1d0c6..1991e2d1d 100644 --- a/README_ZH_CN.md +++ b/README_ZH_CN.md @@ -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 硬件[[1]](#missing)。 - 支持 Game Boy/Game Boy Color 硬件。 - 快速模拟:已知即使在低端硬件(例如上网本)上也能够全速运行。 -- 用于重型和轻型前端的 Qt 和 SDL 端口。 +- 可用于重型和轻型前端的 Qt 和 SDL 移植。 - 支持本地(同一台计算机)链接电缆。 - 存档类型检测,即使是闪存大小也可检测[[2]](#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 +脚注 --------- [1] 目前缺失的功能有 @@ -232,7 +247,7 @@ Footnotes [2] 闪存大小检测在某些情况下不起作用。 这些可以在运行时中进行配置,但如果遇到此类情况,建议提交错误。 -[3] 仅 Qt 端口需要 10.9。应该可以在 10.7 或更早版本上构建或运行 Qt 端口,但这类操作不受官方支持。已知 SDL 端口可以在 10.5 上运行,并且可能能够在旧版本上运行。 +[3] 仅 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/):属公有领域使用。 diff --git a/cinema/gb/mooneye-gb/misc/boot_div-cgb0/xbaseline_0000.png b/cinema/gb/mooneye-gb/misc/boot_div-cgb0/xbaseline_0000.png index b9d24cc3a..767dc72dd 100644 Binary files a/cinema/gb/mooneye-gb/misc/boot_div-cgb0/xbaseline_0000.png and b/cinema/gb/mooneye-gb/misc/boot_div-cgb0/xbaseline_0000.png differ diff --git a/cinema/gb/mooneye-gb/manual-only/sprite_priority/config.ini b/cinema/gb/samesuite/apu/channel_1/align/config.ini similarity index 100% rename from cinema/gb/mooneye-gb/manual-only/sprite_priority/config.ini rename to cinema/gb/samesuite/apu/channel_1/align/config.ini diff --git a/cinema/gb/samesuite/apu/channel_1/align/test.gb b/cinema/gb/samesuite/apu/channel_1/align/test.gb new file mode 100644 index 000000000..2d3b6c8b1 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/align/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/align/test.sym b/cinema/gb/samesuite/apu/channel_1/align/test.sym new file mode 100644 index 000000000..c2dc87faf --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/align/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05db RunTest +00:0b92 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/align/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/align/xbaseline_0000.png new file mode 100644 index 000000000..10bf03557 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/align/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/align_cpu/config.ini b/cinema/gb/samesuite/apu/channel_1/align_cpu/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/align_cpu/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/align_cpu/test.gb b/cinema/gb/samesuite/apu/channel_1/align_cpu/test.gb new file mode 100644 index 000000000..b5fe60418 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/align_cpu/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/align_cpu/test.sym b/cinema/gb/samesuite/apu/channel_1/align_cpu/test.sym new file mode 100644 index 000000000..c2dc87faf --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/align_cpu/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05db RunTest +00:0b92 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/align_cpu/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/align_cpu/xbaseline_0000.png new file mode 100644 index 000000000..091b2f2d2 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/align_cpu/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/delay/config.ini b/cinema/gb/samesuite/apu/channel_1/delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/delay/test.gb b/cinema/gb/samesuite/apu/channel_1/delay/test.gb new file mode 100644 index 000000000..68f46f118 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/delay/test.sym b/cinema/gb/samesuite/apu/channel_1/delay/test.sym new file mode 100644 index 000000000..9d3c63f11 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb RunTest +00:09ed StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/delay/xbaseline_0000.png new file mode 100644 index 000000000..f42030316 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/duty/config.ini b/cinema/gb/samesuite/apu/channel_1/duty/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/duty/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/duty/test.gb b/cinema/gb/samesuite/apu/channel_1/duty/test.gb new file mode 100644 index 000000000..2ffcd2b6e Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/duty/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/duty/test.sym b/cinema/gb/samesuite/apu/channel_1/duty/test.sym new file mode 100644 index 000000000..8086ebfcc --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/duty/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:0649 TestGroup +00:0a39 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/duty/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/duty/xbaseline_0000.png new file mode 100644 index 000000000..915645259 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/duty/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/duty_delay/config.ini b/cinema/gb/samesuite/apu/channel_1/duty_delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/duty_delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/duty_delay/test.gb b/cinema/gb/samesuite/apu/channel_1/duty_delay/test.gb new file mode 100644 index 000000000..c31b55e3b Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/duty_delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/duty_delay/test.sym b/cinema/gb/samesuite/apu/channel_1/duty_delay/test.sym new file mode 100644 index 000000000..b29c8ca51 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/duty_delay/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:0639 TestGroup +00:0ec9 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/duty_delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/duty_delay/xbaseline_0000.png new file mode 100644 index 000000000..1ce7f7009 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/duty_delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/config.ini b/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/test.gb b/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/test.gb new file mode 100644 index 000000000..ae71d4fa5 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/test.sym b/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/test.sym new file mode 100644 index 000000000..947b9e80d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05c3 RunTest +00:091d StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/xbaseline_0000.png new file mode 100644 index 000000000..da02bff6c Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/extra_length_clocking-cgb0B/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change/config.ini b/cinema/gb/samesuite/apu/channel_1/freq_change/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/freq_change/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change/test.gb b/cinema/gb/samesuite/apu/channel_1/freq_change/test.gb new file mode 100644 index 000000000..7cc20d0df Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/freq_change/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change/test.sym b/cinema/gb/samesuite/apu/channel_1/freq_change/test.sym new file mode 100644 index 000000000..642158c69 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/freq_change/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:0639 TestGroup +00:0ed6 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/freq_change/xbaseline_0000.png new file mode 100644 index 000000000..03e8af34a Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/freq_change/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/config.ini b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/test.gb b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/test.gb new file mode 100644 index 000000000..674567b25 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/test.sym b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/test.sym new file mode 100644 index 000000000..41a009237 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:0875 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/xbaseline_0000.png new file mode 100644 index 000000000..c15aafeff Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-A/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/config.ini b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/test.gb b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/test.gb new file mode 100644 index 000000000..7cc87d6d3 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/test.sym b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/test.sym new file mode 100644 index 000000000..41a009237 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:0875 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/xbaseline_0000.png new file mode 100644 index 000000000..37d552ff9 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgb0BC/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/config.ini b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/test.gb b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/test.gb new file mode 100644 index 000000000..c456cc12c Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/test.sym b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/test.sym new file mode 100644 index 000000000..41a009237 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:0875 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/xbaseline_0000.png new file mode 100644 index 000000000..c15aafeff Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/freq_change_timing-cgbDE/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/config.ini b/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/test.gb b/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/test.gb new file mode 100644 index 000000000..19fbbd625 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/test.sym b/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/test.sym new file mode 100644 index 000000000..ba31606e6 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:088f StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/xbaseline_0000.png new file mode 100644 index 000000000..24c22936b Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/nrx2_glitch/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/config.ini b/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/config.ini new file mode 100644 index 000000000..5c2a99de9 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/config.ini @@ -0,0 +1,3 @@ +[testinfo] +fail=1 +skip=180 diff --git a/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/test.gb b/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/test.gb new file mode 100644 index 000000000..a628e4dfc Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/test.sym b/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/test.sym new file mode 100644 index 000000000..db14b866d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05f3 RunTest +00:1a0f StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/xbaseline_0000.png new file mode 100644 index 000000000..e541e5c0b Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/nrx2_speed_change/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/restart/config.ini b/cinema/gb/samesuite/apu/channel_1/restart/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/restart/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/restart/test.gb b/cinema/gb/samesuite/apu/channel_1/restart/test.gb new file mode 100644 index 000000000..c6924dd22 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/restart/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/restart/test.sym b/cinema/gb/samesuite/apu/channel_1/restart/test.sym new file mode 100644 index 000000000..b02f7d89d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/restart/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:063b RunTest +00:1a82 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/restart/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/restart/xbaseline_0000.png new file mode 100644 index 000000000..7d68bb0cd Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/restart/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/config.ini b/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/test.gb b/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/test.gb new file mode 100644 index 000000000..ed3cee586 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/test.sym b/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/test.sym new file mode 100644 index 000000000..ad1017c62 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:085e StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/xbaseline_0000.png new file mode 100644 index 000000000..69fb020dd Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/restart_nrx2_glitch/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/stop_div/config.ini b/cinema/gb/samesuite/apu/channel_1/stop_div/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/stop_div/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/stop_div/test.gb b/cinema/gb/samesuite/apu/channel_1/stop_div/test.gb new file mode 100644 index 000000000..d6167bf40 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/stop_div/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/stop_div/test.sym b/cinema/gb/samesuite/apu/channel_1/stop_div/test.sym new file mode 100644 index 000000000..ccb41512d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/stop_div/test.sym @@ -0,0 +1,46 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05e3 RunTest +00:05f9 TestGroup +00:0801 ShortTestGroup +00:0912 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/stop_div/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/stop_div/xbaseline_0000.png new file mode 100644 index 000000000..aa1e6dc91 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/stop_div/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/stop_restart/config.ini b/cinema/gb/samesuite/apu/channel_1/stop_restart/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/stop_restart/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/stop_restart/test.gb b/cinema/gb/samesuite/apu/channel_1/stop_restart/test.gb new file mode 100644 index 000000000..3c666629d Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/stop_restart/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/stop_restart/test.sym b/cinema/gb/samesuite/apu/channel_1/stop_restart/test.sym new file mode 100644 index 000000000..dcdf4b403 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/stop_restart/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:063b RunTest +00:1f92 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/stop_restart/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/stop_restart/xbaseline_0000.png new file mode 100644 index 000000000..454b9dc1e Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/stop_restart/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/sweep/config.ini b/cinema/gb/samesuite/apu/channel_1/sweep/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/sweep/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/sweep/test.gb b/cinema/gb/samesuite/apu/channel_1/sweep/test.gb new file mode 100644 index 000000000..02308c0c2 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/sweep/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/sweep/test.sym b/cinema/gb/samesuite/apu/channel_1/sweep/test.sym new file mode 100644 index 000000000..f9664ac54 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/sweep/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:063b RunTest +00:1cce StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/sweep/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/sweep/xbaseline_0000.png new file mode 100644 index 000000000..dde05538e Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/sweep/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/sweep_restart/config.ini b/cinema/gb/samesuite/apu/channel_1/sweep_restart/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/sweep_restart/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/sweep_restart/test.gb b/cinema/gb/samesuite/apu/channel_1/sweep_restart/test.gb new file mode 100644 index 000000000..61812c099 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/sweep_restart/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/sweep_restart/test.sym b/cinema/gb/samesuite/apu/channel_1/sweep_restart/test.sym new file mode 100644 index 000000000..28c7f230e --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/sweep_restart/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:063b RunTest +00:0940 RunTest.round_6 +00:1545 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/sweep_restart/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/sweep_restart/xbaseline_0000.png new file mode 100644 index 000000000..daac7431a Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/sweep_restart/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/config.ini b/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/test.gb b/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/test.gb new file mode 100644 index 000000000..848286fe7 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/test.sym b/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/test.sym new file mode 100644 index 000000000..c3a4f1938 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:1e2a StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/xbaseline_0000.png new file mode 100644 index 000000000..f4485a7d7 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/sweep_restart_2/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/volume/config.ini b/cinema/gb/samesuite/apu/channel_1/volume/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/volume/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_1/volume/test.gb b/cinema/gb/samesuite/apu/channel_1/volume/test.gb new file mode 100644 index 000000000..a5f1b1516 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/volume/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/volume/test.sym b/cinema/gb/samesuite/apu/channel_1/volume/test.sym new file mode 100644 index 000000000..a1d34fe55 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/volume/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:0643 SubTestGroup +00:0ac4 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/volume/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/volume/xbaseline_0000.png new file mode 100644 index 000000000..e639befda Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/volume/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_1/volume_div/config.ini b/cinema/gb/samesuite/apu/channel_1/volume_div/config.ini new file mode 100644 index 000000000..26f3fb74a --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/volume_div/config.ini @@ -0,0 +1,3 @@ +[testinfo] +fail=1 +skip=120 diff --git a/cinema/gb/samesuite/apu/channel_1/volume_div/test.gb b/cinema/gb/samesuite/apu/channel_1/volume_div/test.gb new file mode 100644 index 000000000..bf03c8346 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/volume_div/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_1/volume_div/test.sym b/cinema/gb/samesuite/apu/channel_1/volume_div/test.sym new file mode 100644 index 000000000..36b01a6dc --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_1/volume_div/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05eb RunTest +00:05fb TestGroup +00:0a7c StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_1/volume_div/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_1/volume_div/xbaseline_0000.png new file mode 100644 index 000000000..93f9b150a Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_1/volume_div/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/align/config.ini b/cinema/gb/samesuite/apu/channel_2/align/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/align/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/align/test.gb b/cinema/gb/samesuite/apu/channel_2/align/test.gb new file mode 100644 index 000000000..7cdcd4840 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/align/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/align/test.sym b/cinema/gb/samesuite/apu/channel_2/align/test.sym new file mode 100644 index 000000000..c2dc87faf --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/align/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05db RunTest +00:0b92 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/align/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/align/xbaseline_0000.png new file mode 100644 index 000000000..c7a3758e7 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/align/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/align_cpu/config.ini b/cinema/gb/samesuite/apu/channel_2/align_cpu/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/align_cpu/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/align_cpu/test.gb b/cinema/gb/samesuite/apu/channel_2/align_cpu/test.gb new file mode 100644 index 000000000..b4d8b644a Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/align_cpu/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/align_cpu/test.sym b/cinema/gb/samesuite/apu/channel_2/align_cpu/test.sym new file mode 100644 index 000000000..c2dc87faf --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/align_cpu/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05db RunTest +00:0b92 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/align_cpu/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/align_cpu/xbaseline_0000.png new file mode 100644 index 000000000..5b3549917 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/align_cpu/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/delay/config.ini b/cinema/gb/samesuite/apu/channel_2/delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/delay/test.gb b/cinema/gb/samesuite/apu/channel_2/delay/test.gb new file mode 100644 index 000000000..0fa95c101 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/delay/test.sym b/cinema/gb/samesuite/apu/channel_2/delay/test.sym new file mode 100644 index 000000000..9d3c63f11 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb RunTest +00:09ed StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/delay/xbaseline_0000.png new file mode 100644 index 000000000..f4ab7b2dc Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/duty/config.ini b/cinema/gb/samesuite/apu/channel_2/duty/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/duty/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/duty/test.gb b/cinema/gb/samesuite/apu/channel_2/duty/test.gb new file mode 100644 index 000000000..4d8275548 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/duty/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/duty/test.sym b/cinema/gb/samesuite/apu/channel_2/duty/test.sym new file mode 100644 index 000000000..8086ebfcc --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/duty/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:0649 TestGroup +00:0a39 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/duty/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/duty/xbaseline_0000.png new file mode 100644 index 000000000..6a9c96269 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/duty/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/duty_delay/config.ini b/cinema/gb/samesuite/apu/channel_2/duty_delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/duty_delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/duty_delay/test.gb b/cinema/gb/samesuite/apu/channel_2/duty_delay/test.gb new file mode 100644 index 000000000..a3df171e0 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/duty_delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/duty_delay/test.sym b/cinema/gb/samesuite/apu/channel_2/duty_delay/test.sym new file mode 100644 index 000000000..b29c8ca51 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/duty_delay/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:0639 TestGroup +00:0ec9 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/duty_delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/duty_delay/xbaseline_0000.png new file mode 100644 index 000000000..2bcbf07e1 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/duty_delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/config.ini b/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/test.gb b/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/test.gb new file mode 100644 index 000000000..fba679c8d Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/test.sym b/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/test.sym new file mode 100644 index 000000000..947b9e80d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05c3 RunTest +00:091d StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/xbaseline_0000.png new file mode 100644 index 000000000..3221aa805 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/extra_length_clocking-cgb0B/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/freq_change/config.ini b/cinema/gb/samesuite/apu/channel_2/freq_change/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/freq_change/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/freq_change/test.gb b/cinema/gb/samesuite/apu/channel_2/freq_change/test.gb new file mode 100644 index 000000000..1951af03d Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/freq_change/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/freq_change/test.sym b/cinema/gb/samesuite/apu/channel_2/freq_change/test.sym new file mode 100644 index 000000000..642158c69 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/freq_change/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:0639 TestGroup +00:0ed6 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/freq_change/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/freq_change/xbaseline_0000.png new file mode 100644 index 000000000..ed3726007 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/freq_change/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/config.ini b/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/test.gb b/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/test.gb new file mode 100644 index 000000000..5db3a126e Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/test.sym b/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/test.sym new file mode 100644 index 000000000..ba31606e6 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:088f StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/xbaseline_0000.png new file mode 100644 index 000000000..eefe570bd Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/nrx2_glitch/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/config.ini b/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/config.ini new file mode 100644 index 000000000..5c2a99de9 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/config.ini @@ -0,0 +1,3 @@ +[testinfo] +fail=1 +skip=180 diff --git a/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/test.gb b/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/test.gb new file mode 100644 index 000000000..06ba9b13c Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/test.sym b/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/test.sym new file mode 100644 index 000000000..db14b866d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05f3 RunTest +00:1a0f StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/xbaseline_0000.png new file mode 100644 index 000000000..5173a31fd Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/nrx2_speed_change/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/restart/config.ini b/cinema/gb/samesuite/apu/channel_2/restart/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/restart/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/restart/test.gb b/cinema/gb/samesuite/apu/channel_2/restart/test.gb new file mode 100644 index 000000000..147398aeb Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/restart/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/restart/test.sym b/cinema/gb/samesuite/apu/channel_2/restart/test.sym new file mode 100644 index 000000000..b02f7d89d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/restart/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:063b RunTest +00:1a82 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/restart/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/restart/xbaseline_0000.png new file mode 100644 index 000000000..23b8dcf15 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/restart/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/config.ini b/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/test.gb b/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/test.gb new file mode 100644 index 000000000..734c80b57 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/test.sym b/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/test.sym new file mode 100644 index 000000000..ad1017c62 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:085e StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/xbaseline_0000.png new file mode 100644 index 000000000..21dfc5ad6 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/restart_nrx2_glitch/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/stop_div/config.ini b/cinema/gb/samesuite/apu/channel_2/stop_div/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/stop_div/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/stop_div/test.gb b/cinema/gb/samesuite/apu/channel_2/stop_div/test.gb new file mode 100644 index 000000000..6c8d6e3fc Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/stop_div/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/stop_div/test.sym b/cinema/gb/samesuite/apu/channel_2/stop_div/test.sym new file mode 100644 index 000000000..ccb41512d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/stop_div/test.sym @@ -0,0 +1,46 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05e3 RunTest +00:05f9 TestGroup +00:0801 ShortTestGroup +00:0912 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/stop_div/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/stop_div/xbaseline_0000.png new file mode 100644 index 000000000..99bec969b Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/stop_div/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/stop_restart/config.ini b/cinema/gb/samesuite/apu/channel_2/stop_restart/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/stop_restart/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/stop_restart/test.gb b/cinema/gb/samesuite/apu/channel_2/stop_restart/test.gb new file mode 100644 index 000000000..66ef68f06 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/stop_restart/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/stop_restart/test.sym b/cinema/gb/samesuite/apu/channel_2/stop_restart/test.sym new file mode 100644 index 000000000..dcdf4b403 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/stop_restart/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:063b RunTest +00:1f92 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/stop_restart/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/stop_restart/xbaseline_0000.png new file mode 100644 index 000000000..842c0c627 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/stop_restart/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/volume/config.ini b/cinema/gb/samesuite/apu/channel_2/volume/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/volume/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/volume/test.gb b/cinema/gb/samesuite/apu/channel_2/volume/test.gb new file mode 100644 index 000000000..34b005a47 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/volume/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/volume/test.sym b/cinema/gb/samesuite/apu/channel_2/volume/test.sym new file mode 100644 index 000000000..bd3d42fd4 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/volume/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05b3 RunTest +00:06e7 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/volume/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/volume/xbaseline_0000.png new file mode 100644 index 000000000..cb59bd6b2 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/volume/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_2/volume_div/config.ini b/cinema/gb/samesuite/apu/channel_2/volume_div/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/volume_div/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_2/volume_div/test.gb b/cinema/gb/samesuite/apu/channel_2/volume_div/test.gb new file mode 100644 index 000000000..27bf21d21 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/volume_div/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_2/volume_div/test.sym b/cinema/gb/samesuite/apu/channel_2/volume_div/test.sym new file mode 100644 index 000000000..8409a414e --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_2/volume_div/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb RunTest +00:05db TestGroup +00:0804 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_2/volume_div/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_2/volume_div/xbaseline_0000.png new file mode 100644 index 000000000..e25e4f2ad Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_2/volume_div/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/and_glitch/config.ini b/cinema/gb/samesuite/apu/channel_3/and_glitch/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/and_glitch/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/and_glitch/test.gb b/cinema/gb/samesuite/apu/channel_3/and_glitch/test.gb new file mode 100644 index 000000000..623eed9fe Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/and_glitch/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/and_glitch/test.sym b/cinema/gb/samesuite/apu/channel_3/and_glitch/test.sym new file mode 100644 index 000000000..21f313c3e --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/and_glitch/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05db RunTest +00:145b StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/and_glitch/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/and_glitch/xbaseline_0000.png new file mode 100644 index 000000000..9a28b07ee Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/and_glitch/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/delay/config.ini b/cinema/gb/samesuite/apu/channel_3/delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/delay/test.gb b/cinema/gb/samesuite/apu/channel_3/delay/test.gb new file mode 100644 index 000000000..4c36bc173 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/delay/test.sym b/cinema/gb/samesuite/apu/channel_3/delay/test.sym new file mode 100644 index 000000000..3076b5b94 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:0895 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/delay/xbaseline_0000.png new file mode 100644 index 000000000..ff6fedbd8 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/config.ini b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/test.gb b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/test.gb new file mode 100644 index 000000000..71616256c Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/test.sym b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/test.sym new file mode 100644 index 000000000..8487ba99e --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb RunTest +00:0a95 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/xbaseline_0000.png new file mode 100644 index 000000000..dc270dfc3 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgb0/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/config.ini b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/test.gb b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/test.gb new file mode 100644 index 000000000..74a355af1 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/test.sym b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/test.sym new file mode 100644 index 000000000..8487ba99e --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb RunTest +00:0a95 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/xbaseline_0000.png new file mode 100644 index 000000000..b7f37174e Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/extra_length_clocking-cgbB/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/first_sample/config.ini b/cinema/gb/samesuite/apu/channel_3/first_sample/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/first_sample/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/first_sample/test.gb b/cinema/gb/samesuite/apu/channel_3/first_sample/test.gb new file mode 100644 index 000000000..5bf9cdfd7 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/first_sample/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/first_sample/test.sym b/cinema/gb/samesuite/apu/channel_3/first_sample/test.sym new file mode 100644 index 000000000..5a9ec787b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/first_sample/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05b3 RunTest +00:073d StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/first_sample/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/first_sample/xbaseline_0000.png new file mode 100644 index 000000000..d37796fda Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/first_sample/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/freq_change_delay/config.ini b/cinema/gb/samesuite/apu/channel_3/freq_change_delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/freq_change_delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/freq_change_delay/test.gb b/cinema/gb/samesuite/apu/channel_3/freq_change_delay/test.gb new file mode 100644 index 000000000..216db98db Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/freq_change_delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/freq_change_delay/test.sym b/cinema/gb/samesuite/apu/channel_3/freq_change_delay/test.sym new file mode 100644 index 000000000..82413a291 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/freq_change_delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:08d5 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/freq_change_delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/freq_change_delay/xbaseline_0000.png new file mode 100644 index 000000000..9c3996d97 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/freq_change_delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/restart_delay/baseline_0000.png b/cinema/gb/samesuite/apu/channel_3/restart_delay/baseline_0000.png new file mode 100644 index 000000000..1ebbf24f5 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/restart_delay/baseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/restart_delay/test.gb b/cinema/gb/samesuite/apu/channel_3/restart_delay/test.gb new file mode 100644 index 000000000..21f6777e7 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/restart_delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/restart_delay/test.sym b/cinema/gb/samesuite/apu/channel_3/restart_delay/test.sym new file mode 100644 index 000000000..5084d7002 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/restart_delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05b3 RunTest +00:0760 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/restart_during_delay/config.ini b/cinema/gb/samesuite/apu/channel_3/restart_during_delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/restart_during_delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/restart_during_delay/test.gb b/cinema/gb/samesuite/apu/channel_3/restart_during_delay/test.gb new file mode 100644 index 000000000..0d57843da Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/restart_during_delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/restart_during_delay/test.sym b/cinema/gb/samesuite/apu/channel_3/restart_during_delay/test.sym new file mode 100644 index 000000000..298329bc3 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/restart_during_delay/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb RunTest +00:05e1 TestGroup +00:0a52 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/restart_during_delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/restart_during_delay/xbaseline_0000.png new file mode 100644 index 000000000..bb317a73e Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/restart_during_delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/config.ini b/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/test.gb b/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/test.gb new file mode 100644 index 000000000..652f49d4f Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/test.sym b/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/test.sym new file mode 100644 index 000000000..c71922409 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05b3 RunTest +00:0887 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/xbaseline_0000.png new file mode 100644 index 000000000..6b865f6a4 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/restart_stop_delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/shift_delay/baseline_0000.png b/cinema/gb/samesuite/apu/channel_3/shift_delay/baseline_0000.png new file mode 100644 index 000000000..60bdedff2 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/shift_delay/baseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/shift_delay/test.gb b/cinema/gb/samesuite/apu/channel_3/shift_delay/test.gb new file mode 100644 index 000000000..c038ef468 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/shift_delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/shift_delay/test.sym b/cinema/gb/samesuite/apu/channel_3/shift_delay/test.sym new file mode 100644 index 000000000..5084d7002 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/shift_delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05b3 RunTest +00:0760 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/config.ini b/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/test.gb b/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/test.gb new file mode 100644 index 000000000..5ba0f55d5 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/test.sym b/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/test.sym new file mode 100644 index 000000000..0ff37b3f8 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05b3 RunTest +00:074d StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/xbaseline_0000.png new file mode 100644 index 000000000..d37796fda Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/shift_skip_delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/stop_delay/config.ini b/cinema/gb/samesuite/apu/channel_3/stop_delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/stop_delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/stop_delay/test.gb b/cinema/gb/samesuite/apu/channel_3/stop_delay/test.gb new file mode 100644 index 000000000..01918cd5e Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/stop_delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/stop_delay/test.sym b/cinema/gb/samesuite/apu/channel_3/stop_delay/test.sym new file mode 100644 index 000000000..cdba80c5c --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/stop_delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05b3 RunTest +00:074f StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/stop_delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/stop_delay/xbaseline_0000.png new file mode 100644 index 000000000..08605d056 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/stop_delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/stop_div/config.ini b/cinema/gb/samesuite/apu/channel_3/stop_div/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/stop_div/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/stop_div/test.gb b/cinema/gb/samesuite/apu/channel_3/stop_div/test.gb new file mode 100644 index 000000000..78b3bdac5 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/stop_div/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/stop_div/test.sym b/cinema/gb/samesuite/apu/channel_3/stop_div/test.sym new file mode 100644 index 000000000..a94de9cad --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/stop_div/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05db RunTest +00:05f7 SubTestGroup +00:0980 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/stop_div/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/stop_div/xbaseline_0000.png new file mode 100644 index 000000000..5386fe3b3 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/stop_div/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_dac_on_rw/baseline_0000.png b/cinema/gb/samesuite/apu/channel_3/wave_ram_dac_on_rw/baseline_0000.png new file mode 100644 index 000000000..f1c82d032 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/wave_ram_dac_on_rw/baseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_dac_on_rw/test.gb b/cinema/gb/samesuite/apu/channel_3/wave_ram_dac_on_rw/test.gb new file mode 100644 index 000000000..4489a70a5 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/wave_ram_dac_on_rw/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_dac_on_rw/test.sym b/cinema/gb/samesuite/apu/channel_3/wave_ram_dac_on_rw/test.sym new file mode 100644 index 000000000..a67599160 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/wave_ram_dac_on_rw/test.sym @@ -0,0 +1,48 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05db RunTest +00:05db CorrectResults.end +00:05f0 RunTest.initWaveRAM +00:0612 ReadWaveRAM +00:0615 ReadWaveRAM.loop +01:4000 NopSlide +00:c000 RESULTS_START diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_locked_write/baseline_0000.png b/cinema/gb/samesuite/apu/channel_3/wave_ram_locked_write/baseline_0000.png new file mode 100644 index 000000000..8c633955d Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/wave_ram_locked_write/baseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_locked_write/test.gb b/cinema/gb/samesuite/apu/channel_3/wave_ram_locked_write/test.gb new file mode 100644 index 000000000..38c67595d Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/wave_ram_locked_write/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_locked_write/test.sym b/cinema/gb/samesuite/apu/channel_3/wave_ram_locked_write/test.sym new file mode 100644 index 000000000..abaa17e35 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/wave_ram_locked_write/test.sym @@ -0,0 +1,53 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:063b RunTest +00:065d RunTest.clearSMCBuffer +00:066d RunTest.subTest +00:0670 RunTest.initWaveRAM +00:0683 RunTest.copyWaveRAM +00:0697 RunTest.doSubTest +01:4000 NopSlide +00:c000 RESULTS_START +00:c090 SelfModifyingCodeBuffer +00:c090 ResultsBufferEnd +00:c09c SMCWritePtrLow +00:c09c SelfModifyingCodeBufferEnd diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/config.ini b/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/test.gb b/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/test.gb new file mode 100644 index 000000000..d6662f11a Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/test.sym b/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/test.sym new file mode 100644 index 000000000..c3a3706e9 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05bb RunTest +00:05d1 TestGroup +00:07e2 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/xbaseline_0000.png new file mode 100644 index 000000000..c29819498 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_3/wave_ram_sync/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/align/config.ini b/cinema/gb/samesuite/apu/channel_4/align/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/align/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/align/test.gb b/cinema/gb/samesuite/apu/channel_4/align/test.gb new file mode 100644 index 000000000..ec45dc61e Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/align/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/align/test.sym b/cinema/gb/samesuite/apu/channel_4/align/test.sym new file mode 100644 index 000000000..c29866d1a --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/align/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05eb RunTest +00:0d55 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/align/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/align/xbaseline_0000.png new file mode 100644 index 000000000..68428b0d5 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/align/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/delay/config.ini b/cinema/gb/samesuite/apu/channel_4/delay/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/delay/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/delay/test.gb b/cinema/gb/samesuite/apu/channel_4/delay/test.gb new file mode 100644 index 000000000..5d900d024 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/delay/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/delay/test.sym b/cinema/gb/samesuite/apu/channel_4/delay/test.sym new file mode 100644 index 000000000..1523a234d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/delay/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb RunTest +00:095c StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/delay/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/delay/xbaseline_0000.png new file mode 100644 index 000000000..ce84afb70 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/delay/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/config.ini b/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/test.gb b/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/test.gb new file mode 100644 index 000000000..8c9aa69de Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/test.sym b/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/test.sym new file mode 100644 index 000000000..12e97e4f2 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:1431 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/xbaseline_0000.png new file mode 100644 index 000000000..38a3795cf Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/equivalent_frequencies/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/config.ini b/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/test.gb b/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/test.gb new file mode 100644 index 000000000..d114f5ac0 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/test.sym b/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/test.sym new file mode 100644 index 000000000..947b9e80d --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05c3 RunTest +00:091d StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/xbaseline_0000.png new file mode 100644 index 000000000..6119a5f68 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/extra_length_clocking-cgb0B/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/freq_change/config.ini b/cinema/gb/samesuite/apu/channel_4/freq_change/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/freq_change/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/freq_change/test.gb b/cinema/gb/samesuite/apu/channel_4/freq_change/test.gb new file mode 100644 index 000000000..153b7abd5 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/freq_change/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/freq_change/test.sym b/cinema/gb/samesuite/apu/channel_4/freq_change/test.sym new file mode 100644 index 000000000..29fd7a580 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/freq_change/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05eb RunTest +00:0eaf StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/freq_change/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/freq_change/xbaseline_0000.png new file mode 100644 index 000000000..e1ec0cdd9 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/freq_change/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/frequency_alignment/config.ini b/cinema/gb/samesuite/apu/channel_4/frequency_alignment/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/frequency_alignment/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/frequency_alignment/test.gb b/cinema/gb/samesuite/apu/channel_4/frequency_alignment/test.gb new file mode 100644 index 000000000..b60a62200 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/frequency_alignment/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/frequency_alignment/test.sym b/cinema/gb/samesuite/apu/channel_4/frequency_alignment/test.sym new file mode 100644 index 000000000..cb91fb5d8 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/frequency_alignment/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:063b RunTest +00:1768 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/frequency_alignment/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/frequency_alignment/xbaseline_0000.png new file mode 100644 index 000000000..f77e3c8b1 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/frequency_alignment/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr/config.ini b/cinema/gb/samesuite/apu/channel_4/lfsr/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr/test.gb b/cinema/gb/samesuite/apu/channel_4/lfsr/test.gb new file mode 100644 index 000000000..879492218 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr/test.sym b/cinema/gb/samesuite/apu/channel_4/lfsr/test.sym new file mode 100644 index 000000000..8bf35e53f --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:1511 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/lfsr/xbaseline_0000.png new file mode 100644 index 000000000..f58f4c214 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr15/config.ini b/cinema/gb/samesuite/apu/channel_4/lfsr15/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr15/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr15/test.gb b/cinema/gb/samesuite/apu/channel_4/lfsr15/test.gb new file mode 100644 index 000000000..82164ad20 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr15/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr15/test.sym b/cinema/gb/samesuite/apu/channel_4/lfsr15/test.sym new file mode 100644 index 000000000..7cda89079 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr15/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:1489 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr15/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/lfsr15/xbaseline_0000.png new file mode 100644 index 000000000..f987e3982 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr15/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/config.ini b/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/test.gb b/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/test.gb new file mode 100644 index 000000000..211fda068 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/test.sym b/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/test.sym new file mode 100644 index 000000000..e6060af1f --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:1954 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/xbaseline_0000.png new file mode 100644 index 000000000..2c83204a8 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr_15_7/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/config.ini b/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/test.gb b/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/test.gb new file mode 100644 index 000000000..68d330b95 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/test.sym b/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/test.sym new file mode 100644 index 000000000..e6060af1f --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:1954 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/xbaseline_0000.png new file mode 100644 index 000000000..c965f51b7 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr_7_15/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_restart/config.ini b/cinema/gb/samesuite/apu/channel_4/lfsr_restart/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr_restart/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_restart/test.gb b/cinema/gb/samesuite/apu/channel_4/lfsr_restart/test.gb new file mode 100644 index 000000000..67806ea6c Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr_restart/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_restart/test.sym b/cinema/gb/samesuite/apu/channel_4/lfsr_restart/test.sym new file mode 100644 index 000000000..0fe12197b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr_restart/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:17b9 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_restart/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/lfsr_restart/xbaseline_0000.png new file mode 100644 index 000000000..d425c2d3f Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr_restart/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/config.ini b/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/test.gb b/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/test.gb new file mode 100644 index 000000000..46fb4e418 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/test.sym b/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/test.sym new file mode 100644 index 000000000..31a200412 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/test.sym @@ -0,0 +1,44 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b RunTest +00:1621 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/xbaseline_0000.png b/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/xbaseline_0000.png new file mode 100644 index 000000000..d425c2d3f Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/lfsr_restart_fast/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/volume_div/baseline_0000.png b/cinema/gb/samesuite/apu/channel_4/volume_div/baseline_0000.png new file mode 100644 index 000000000..189f5f289 Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/volume_div/baseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/channel_4/volume_div/config.ini b/cinema/gb/samesuite/apu/channel_4/volume_div/config.ini new file mode 100644 index 000000000..da67580a4 --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/volume_div/config.ini @@ -0,0 +1,2 @@ +[testinfo] +skip=120 diff --git a/cinema/gb/samesuite/apu/channel_4/volume_div/test.gb b/cinema/gb/samesuite/apu/channel_4/volume_div/test.gb new file mode 100644 index 000000000..5cdb7be8c Binary files /dev/null and b/cinema/gb/samesuite/apu/channel_4/volume_div/test.gb differ diff --git a/cinema/gb/samesuite/apu/channel_4/volume_div/test.sym b/cinema/gb/samesuite/apu/channel_4/volume_div/test.sym new file mode 100644 index 000000000..36b01a6dc --- /dev/null +++ b/cinema/gb/samesuite/apu/channel_4/volume_div/test.sym @@ -0,0 +1,45 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05eb RunTest +00:05fb TestGroup +00:0a7c StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/div_trigger_volume_10/baseline_0000.png b/cinema/gb/samesuite/apu/div_trigger_volume_10/baseline_0000.png new file mode 100644 index 000000000..3cdc8e21b Binary files /dev/null and b/cinema/gb/samesuite/apu/div_trigger_volume_10/baseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/div_trigger_volume_10/config.ini b/cinema/gb/samesuite/apu/div_trigger_volume_10/config.ini new file mode 100644 index 000000000..8f7eb1c12 --- /dev/null +++ b/cinema/gb/samesuite/apu/div_trigger_volume_10/config.ini @@ -0,0 +1,2 @@ +[testinfo] +skip=80 diff --git a/cinema/gb/samesuite/apu/div_trigger_volume_10/test.gb b/cinema/gb/samesuite/apu/div_trigger_volume_10/test.gb new file mode 100644 index 000000000..942cd8049 Binary files /dev/null and b/cinema/gb/samesuite/apu/div_trigger_volume_10/test.gb differ diff --git a/cinema/gb/samesuite/apu/div_trigger_volume_10/test.sym b/cinema/gb/samesuite/apu/div_trigger_volume_10/test.sym new file mode 100644 index 000000000..ceca33fa2 --- /dev/null +++ b/cinema/gb/samesuite/apu/div_trigger_volume_10/test.sym @@ -0,0 +1,305 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb WaitDIVEvent +00:05cb WaitDIVEvent.waitOn +00:05cf WaitDIVEvent.waitOff +00:05d4 WaitDIV10 +00:05d6 WaitDIV10.waitDIV +00:05da RunTest +00:0602 RunTest.done_u16403 +00:0608 RunTest.done_u16405 +00:060e RunTest.done_u16407 +00:0614 RunTest.done_u16409 +00:061a RunTest.done_u16411 +00:0620 RunTest.done_u16413 +00:0626 RunTest.done_u16415 +00:062c RunTest.done_u16417 +00:0657 RunTest.done_u16421 +00:065d RunTest.done_u16423 +00:0663 RunTest.done_u16425 +00:0669 RunTest.done_u16427 +00:066f RunTest.done_u16429 +00:0675 RunTest.done_u16431 +00:067b RunTest.done_u16433 +00:0681 RunTest.done_u16435 +00:06af RunTest.done_u16440 +00:06b5 RunTest.done_u16442 +00:06bb RunTest.done_u16444 +00:06c1 RunTest.done_u16446 +00:06c7 RunTest.done_u16448 +00:06cd RunTest.done_u16450 +00:06d3 RunTest.done_u16452 +00:06d9 RunTest.done_u16454 +00:070a RunTest.done_u16460 +00:0710 RunTest.done_u16462 +00:0716 RunTest.done_u16464 +00:071c RunTest.done_u16466 +00:0722 RunTest.done_u16468 +00:0728 RunTest.done_u16470 +00:072e RunTest.done_u16472 +00:0734 RunTest.done_u16474 +00:0768 RunTest.done_u16481 +00:076e RunTest.done_u16483 +00:0774 RunTest.done_u16485 +00:077a RunTest.done_u16487 +00:0780 RunTest.done_u16489 +00:0786 RunTest.done_u16491 +00:078c RunTest.done_u16493 +00:0792 RunTest.done_u16495 +00:07c9 RunTest.done_u16503 +00:07cf RunTest.done_u16505 +00:07d5 RunTest.done_u16507 +00:07db RunTest.done_u16509 +00:07e1 RunTest.done_u16511 +00:07e7 RunTest.done_u16513 +00:07ed RunTest.done_u16515 +00:07f3 RunTest.done_u16517 +00:082d RunTest.done_u16526 +00:0833 RunTest.done_u16528 +00:0839 RunTest.done_u16530 +00:083f RunTest.done_u16532 +00:0845 RunTest.done_u16534 +00:084b RunTest.done_u16536 +00:0851 RunTest.done_u16538 +00:0857 RunTest.done_u16540 +00:0894 RunTest.done_u16550 +00:089a RunTest.done_u16552 +00:08a0 RunTest.done_u16554 +00:08a6 RunTest.done_u16556 +00:08ac RunTest.done_u16558 +00:08b2 RunTest.done_u16560 +00:08b8 RunTest.done_u16562 +00:08be RunTest.done_u16564 +00:08fe RunTest.done_u16575 +00:0904 RunTest.done_u16577 +00:090a RunTest.done_u16579 +00:0910 RunTest.done_u16581 +00:0916 RunTest.done_u16583 +00:091c RunTest.done_u16585 +00:0922 RunTest.done_u16587 +00:0928 RunTest.done_u16589 +00:096b RunTest.done_u16601 +00:0971 RunTest.done_u16603 +00:0977 RunTest.done_u16605 +00:097d RunTest.done_u16607 +00:0983 RunTest.done_u16609 +00:0989 RunTest.done_u16611 +00:098f RunTest.done_u16613 +00:0995 RunTest.done_u16615 +00:09db RunTest.done_u16628 +00:09e1 RunTest.done_u16630 +00:09e7 RunTest.done_u16632 +00:09ed RunTest.done_u16634 +00:09f3 RunTest.done_u16636 +00:09f9 RunTest.done_u16638 +00:09ff RunTest.done_u16640 +00:0a05 RunTest.done_u16642 +00:0a4e RunTest.done_u16656 +00:0a54 RunTest.done_u16658 +00:0a5a RunTest.done_u16660 +00:0a60 RunTest.done_u16662 +00:0a66 RunTest.done_u16664 +00:0a6c RunTest.done_u16666 +00:0a72 RunTest.done_u16668 +00:0a78 RunTest.done_u16670 +00:0ac4 RunTest.done_u16685 +00:0aca RunTest.done_u16687 +00:0ad0 RunTest.done_u16689 +00:0ad6 RunTest.done_u16691 +00:0adc RunTest.done_u16693 +00:0ae2 RunTest.done_u16695 +00:0ae8 RunTest.done_u16697 +00:0aee RunTest.done_u16699 +00:0b3d RunTest.done_u16715 +00:0b43 RunTest.done_u16717 +00:0b49 RunTest.done_u16719 +00:0b4f RunTest.done_u16721 +00:0b55 RunTest.done_u16723 +00:0b5b RunTest.done_u16725 +00:0b61 RunTest.done_u16727 +00:0b67 RunTest.done_u16729 +00:0bb9 RunTest.done_u16746 +00:0bbf RunTest.done_u16748 +00:0bc5 RunTest.done_u16750 +00:0bcb RunTest.done_u16752 +00:0bd1 RunTest.done_u16754 +00:0bd7 RunTest.done_u16756 +00:0bdd RunTest.done_u16758 +00:0be3 RunTest.done_u16760 +00:0c38 RunTest.done_u16778 +00:0c3e RunTest.done_u16780 +00:0c44 RunTest.done_u16782 +00:0c4a RunTest.done_u16784 +00:0c50 RunTest.done_u16786 +00:0c56 RunTest.done_u16788 +00:0c5c RunTest.done_u16790 +00:0c62 RunTest.done_u16792 +00:0cba RunTest.done_u16811 +00:0cc0 RunTest.done_u16813 +00:0cc6 RunTest.done_u16815 +00:0ccc RunTest.done_u16817 +00:0cd2 RunTest.done_u16819 +00:0cd8 RunTest.done_u16821 +00:0cde RunTest.done_u16823 +00:0ce4 RunTest.done_u16825 +00:0d3f RunTest.done_u16845 +00:0d45 RunTest.done_u16847 +00:0d4b RunTest.done_u16849 +00:0d51 RunTest.done_u16851 +00:0d57 RunTest.done_u16853 +00:0d5d RunTest.done_u16855 +00:0d63 RunTest.done_u16857 +00:0d69 RunTest.done_u16859 +00:0dc7 RunTest.done_u16880 +00:0dcd RunTest.done_u16882 +00:0dd3 RunTest.done_u16884 +00:0dd9 RunTest.done_u16886 +00:0ddf RunTest.done_u16888 +00:0de5 RunTest.done_u16890 +00:0deb RunTest.done_u16892 +00:0df1 RunTest.done_u16894 +00:0e52 RunTest.done_u16916 +00:0e58 RunTest.done_u16918 +00:0e5e RunTest.done_u16920 +00:0e64 RunTest.done_u16922 +00:0e6a RunTest.done_u16924 +00:0e70 RunTest.done_u16926 +00:0e76 RunTest.done_u16928 +00:0e7c RunTest.done_u16930 +00:0ee0 RunTest.done_u16953 +00:0ee6 RunTest.done_u16955 +00:0eec RunTest.done_u16957 +00:0ef2 RunTest.done_u16959 +00:0ef8 RunTest.done_u16961 +00:0efe RunTest.done_u16963 +00:0f04 RunTest.done_u16965 +00:0f0a RunTest.done_u16967 +00:0f71 RunTest.done_u16991 +00:0f77 RunTest.done_u16993 +00:0f7d RunTest.done_u16995 +00:0f83 RunTest.done_u16997 +00:0f89 RunTest.done_u16999 +00:0f8f RunTest.done_u17001 +00:0f95 RunTest.done_u17003 +00:0f9b RunTest.done_u17005 +00:1005 RunTest.done_u17030 +00:100b RunTest.done_u17032 +00:1011 RunTest.done_u17034 +00:1017 RunTest.done_u17036 +00:101d RunTest.done_u17038 +00:1023 RunTest.done_u17040 +00:1029 RunTest.done_u17042 +00:102f RunTest.done_u17044 +00:109c RunTest.done_u17070 +00:10a2 RunTest.done_u17072 +00:10a8 RunTest.done_u17074 +00:10ae RunTest.done_u17076 +00:10b4 RunTest.done_u17078 +00:10ba RunTest.done_u17080 +00:10c0 RunTest.done_u17082 +00:10c6 RunTest.done_u17084 +00:1136 RunTest.done_u17111 +00:113c RunTest.done_u17113 +00:1142 RunTest.done_u17115 +00:1148 RunTest.done_u17117 +00:114e RunTest.done_u17119 +00:1154 RunTest.done_u17121 +00:115a RunTest.done_u17123 +00:1160 RunTest.done_u17125 +00:11d3 RunTest.done_u17153 +00:11d9 RunTest.done_u17155 +00:11df RunTest.done_u17157 +00:11e5 RunTest.done_u17159 +00:11eb RunTest.done_u17161 +00:11f1 RunTest.done_u17163 +00:11f7 RunTest.done_u17165 +00:11fd RunTest.done_u17167 +00:1273 RunTest.done_u17196 +00:1279 RunTest.done_u17198 +00:127f RunTest.done_u17200 +00:1285 RunTest.done_u17202 +00:128b RunTest.done_u17204 +00:1291 RunTest.done_u17206 +00:1297 RunTest.done_u17208 +00:129d RunTest.done_u17210 +00:1316 RunTest.done_u17240 +00:131c RunTest.done_u17242 +00:1322 RunTest.done_u17244 +00:1328 RunTest.done_u17246 +00:132e RunTest.done_u17248 +00:1334 RunTest.done_u17250 +00:133a RunTest.done_u17252 +00:1340 RunTest.done_u17254 +00:13bc RunTest.done_u17285 +00:13c2 RunTest.done_u17287 +00:13c8 RunTest.done_u17289 +00:13ce RunTest.done_u17291 +00:13d4 RunTest.done_u17293 +00:13da RunTest.done_u17295 +00:13e0 RunTest.done_u17297 +00:13e6 RunTest.done_u17299 +00:1465 RunTest.done_u17331 +00:146b RunTest.done_u17333 +00:1471 RunTest.done_u17335 +00:1477 RunTest.done_u17337 +00:147d RunTest.done_u17339 +00:1483 RunTest.done_u17341 +00:1489 RunTest.done_u17343 +00:148f RunTest.done_u17345 +00:1511 RunTest.done_u17378 +00:1517 RunTest.done_u17380 +00:151d RunTest.done_u17382 +00:1523 RunTest.done_u17384 +00:1529 RunTest.done_u17386 +00:152f RunTest.done_u17388 +00:1535 RunTest.done_u17390 +00:153b RunTest.done_u17392 +00:15c0 RunTest.done_u17426 +00:15c6 RunTest.done_u17428 +00:15cc RunTest.done_u17430 +00:15d2 RunTest.done_u17432 +00:15d8 RunTest.done_u17434 +00:15de RunTest.done_u17436 +00:15e4 RunTest.done_u17438 +00:15ea RunTest.done_u17440 +00:15ee StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/div_write_trigger/config.ini b/cinema/gb/samesuite/apu/div_write_trigger/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/div_write_trigger/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/div_write_trigger/test.gb b/cinema/gb/samesuite/apu/div_write_trigger/test.gb new file mode 100644 index 000000000..43c2ce2a9 Binary files /dev/null and b/cinema/gb/samesuite/apu/div_write_trigger/test.gb differ diff --git a/cinema/gb/samesuite/apu/div_write_trigger/test.sym b/cinema/gb/samesuite/apu/div_write_trigger/test.sym new file mode 100644 index 000000000..f78eebc84 --- /dev/null +++ b/cinema/gb/samesuite/apu/div_write_trigger/test.sym @@ -0,0 +1,46 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b TriggerAPU +00:062d TriggerAPU.waitDIV +00:0632 RunTest +00:1e76 StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/div_write_trigger/xbaseline_0000.png b/cinema/gb/samesuite/apu/div_write_trigger/xbaseline_0000.png new file mode 100644 index 000000000..a37111821 Binary files /dev/null and b/cinema/gb/samesuite/apu/div_write_trigger/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/div_write_trigger_10/config.ini b/cinema/gb/samesuite/apu/div_write_trigger_10/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/div_write_trigger_10/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/div_write_trigger_10/test.gb b/cinema/gb/samesuite/apu/div_write_trigger_10/test.gb new file mode 100644 index 000000000..7f82952c0 Binary files /dev/null and b/cinema/gb/samesuite/apu/div_write_trigger_10/test.gb differ diff --git a/cinema/gb/samesuite/apu/div_write_trigger_10/test.sym b/cinema/gb/samesuite/apu/div_write_trigger_10/test.sym new file mode 100644 index 000000000..b6b5cc43d --- /dev/null +++ b/cinema/gb/samesuite/apu/div_write_trigger_10/test.sym @@ -0,0 +1,47 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:062b TriggerAPU +00:0630 WaitDIV10 +00:0632 WaitDIV10.waitDIV +00:0636 RunTest +00:1ffa StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/div_write_trigger_10/xbaseline_0000.png b/cinema/gb/samesuite/apu/div_write_trigger_10/xbaseline_0000.png new file mode 100644 index 000000000..b8f75bf0b Binary files /dev/null and b/cinema/gb/samesuite/apu/div_write_trigger_10/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/div_write_trigger_volume/config.ini b/cinema/gb/samesuite/apu/div_write_trigger_volume/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/div_write_trigger_volume/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/div_write_trigger_volume/test.gb b/cinema/gb/samesuite/apu/div_write_trigger_volume/test.gb new file mode 100644 index 000000000..c8c137e51 Binary files /dev/null and b/cinema/gb/samesuite/apu/div_write_trigger_volume/test.gb differ diff --git a/cinema/gb/samesuite/apu/div_write_trigger_volume/test.sym b/cinema/gb/samesuite/apu/div_write_trigger_volume/test.sym new file mode 100644 index 000000000..b0f84055f --- /dev/null +++ b/cinema/gb/samesuite/apu/div_write_trigger_volume/test.sym @@ -0,0 +1,303 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb TriggerAPU +00:05d0 WaitDIV10 +00:05d2 WaitDIV10.waitDIV +00:05d6 RunTest +00:05fb RunTest.done_u16403 +00:0601 RunTest.done_u16405 +00:0607 RunTest.done_u16407 +00:060d RunTest.done_u16409 +00:0613 RunTest.done_u16411 +00:0619 RunTest.done_u16413 +00:061f RunTest.done_u16415 +00:0625 RunTest.done_u16417 +00:064d RunTest.done_u16421 +00:0653 RunTest.done_u16423 +00:0659 RunTest.done_u16425 +00:065f RunTest.done_u16427 +00:0665 RunTest.done_u16429 +00:066b RunTest.done_u16431 +00:0671 RunTest.done_u16433 +00:0677 RunTest.done_u16435 +00:06a2 RunTest.done_u16440 +00:06a8 RunTest.done_u16442 +00:06ae RunTest.done_u16444 +00:06b4 RunTest.done_u16446 +00:06ba RunTest.done_u16448 +00:06c0 RunTest.done_u16450 +00:06c6 RunTest.done_u16452 +00:06cc RunTest.done_u16454 +00:06fa RunTest.done_u16460 +00:0700 RunTest.done_u16462 +00:0706 RunTest.done_u16464 +00:070c RunTest.done_u16466 +00:0712 RunTest.done_u16468 +00:0718 RunTest.done_u16470 +00:071e RunTest.done_u16472 +00:0724 RunTest.done_u16474 +00:0755 RunTest.done_u16481 +00:075b RunTest.done_u16483 +00:0761 RunTest.done_u16485 +00:0767 RunTest.done_u16487 +00:076d RunTest.done_u16489 +00:0773 RunTest.done_u16491 +00:0779 RunTest.done_u16493 +00:077f RunTest.done_u16495 +00:07b3 RunTest.done_u16503 +00:07b9 RunTest.done_u16505 +00:07bf RunTest.done_u16507 +00:07c5 RunTest.done_u16509 +00:07cb RunTest.done_u16511 +00:07d1 RunTest.done_u16513 +00:07d7 RunTest.done_u16515 +00:07dd RunTest.done_u16517 +00:0814 RunTest.done_u16526 +00:081a RunTest.done_u16528 +00:0820 RunTest.done_u16530 +00:0826 RunTest.done_u16532 +00:082c RunTest.done_u16534 +00:0832 RunTest.done_u16536 +00:0838 RunTest.done_u16538 +00:083e RunTest.done_u16540 +00:0878 RunTest.done_u16550 +00:087e RunTest.done_u16552 +00:0884 RunTest.done_u16554 +00:088a RunTest.done_u16556 +00:0890 RunTest.done_u16558 +00:0896 RunTest.done_u16560 +00:089c RunTest.done_u16562 +00:08a2 RunTest.done_u16564 +00:08df RunTest.done_u16575 +00:08e5 RunTest.done_u16577 +00:08eb RunTest.done_u16579 +00:08f1 RunTest.done_u16581 +00:08f7 RunTest.done_u16583 +00:08fd RunTest.done_u16585 +00:0903 RunTest.done_u16587 +00:0909 RunTest.done_u16589 +00:0949 RunTest.done_u16601 +00:094f RunTest.done_u16603 +00:0955 RunTest.done_u16605 +00:095b RunTest.done_u16607 +00:0961 RunTest.done_u16609 +00:0967 RunTest.done_u16611 +00:096d RunTest.done_u16613 +00:0973 RunTest.done_u16615 +00:09b6 RunTest.done_u16628 +00:09bc RunTest.done_u16630 +00:09c2 RunTest.done_u16632 +00:09c8 RunTest.done_u16634 +00:09ce RunTest.done_u16636 +00:09d4 RunTest.done_u16638 +00:09da RunTest.done_u16640 +00:09e0 RunTest.done_u16642 +00:0a26 RunTest.done_u16656 +00:0a2c RunTest.done_u16658 +00:0a32 RunTest.done_u16660 +00:0a38 RunTest.done_u16662 +00:0a3e RunTest.done_u16664 +00:0a44 RunTest.done_u16666 +00:0a4a RunTest.done_u16668 +00:0a50 RunTest.done_u16670 +00:0a99 RunTest.done_u16685 +00:0a9f RunTest.done_u16687 +00:0aa5 RunTest.done_u16689 +00:0aab RunTest.done_u16691 +00:0ab1 RunTest.done_u16693 +00:0ab7 RunTest.done_u16695 +00:0abd RunTest.done_u16697 +00:0ac3 RunTest.done_u16699 +00:0b0f RunTest.done_u16715 +00:0b15 RunTest.done_u16717 +00:0b1b RunTest.done_u16719 +00:0b21 RunTest.done_u16721 +00:0b27 RunTest.done_u16723 +00:0b2d RunTest.done_u16725 +00:0b33 RunTest.done_u16727 +00:0b39 RunTest.done_u16729 +00:0b88 RunTest.done_u16746 +00:0b8e RunTest.done_u16748 +00:0b94 RunTest.done_u16750 +00:0b9a RunTest.done_u16752 +00:0ba0 RunTest.done_u16754 +00:0ba6 RunTest.done_u16756 +00:0bac RunTest.done_u16758 +00:0bb2 RunTest.done_u16760 +00:0c04 RunTest.done_u16778 +00:0c0a RunTest.done_u16780 +00:0c10 RunTest.done_u16782 +00:0c16 RunTest.done_u16784 +00:0c1c RunTest.done_u16786 +00:0c22 RunTest.done_u16788 +00:0c28 RunTest.done_u16790 +00:0c2e RunTest.done_u16792 +00:0c83 RunTest.done_u16811 +00:0c89 RunTest.done_u16813 +00:0c8f RunTest.done_u16815 +00:0c95 RunTest.done_u16817 +00:0c9b RunTest.done_u16819 +00:0ca1 RunTest.done_u16821 +00:0ca7 RunTest.done_u16823 +00:0cad RunTest.done_u16825 +00:0d05 RunTest.done_u16845 +00:0d0b RunTest.done_u16847 +00:0d11 RunTest.done_u16849 +00:0d17 RunTest.done_u16851 +00:0d1d RunTest.done_u16853 +00:0d23 RunTest.done_u16855 +00:0d29 RunTest.done_u16857 +00:0d2f RunTest.done_u16859 +00:0d8a RunTest.done_u16880 +00:0d90 RunTest.done_u16882 +00:0d96 RunTest.done_u16884 +00:0d9c RunTest.done_u16886 +00:0da2 RunTest.done_u16888 +00:0da8 RunTest.done_u16890 +00:0dae RunTest.done_u16892 +00:0db4 RunTest.done_u16894 +00:0e12 RunTest.done_u16916 +00:0e18 RunTest.done_u16918 +00:0e1e RunTest.done_u16920 +00:0e24 RunTest.done_u16922 +00:0e2a RunTest.done_u16924 +00:0e30 RunTest.done_u16926 +00:0e36 RunTest.done_u16928 +00:0e3c RunTest.done_u16930 +00:0e9d RunTest.done_u16953 +00:0ea3 RunTest.done_u16955 +00:0ea9 RunTest.done_u16957 +00:0eaf RunTest.done_u16959 +00:0eb5 RunTest.done_u16961 +00:0ebb RunTest.done_u16963 +00:0ec1 RunTest.done_u16965 +00:0ec7 RunTest.done_u16967 +00:0f2b RunTest.done_u16991 +00:0f31 RunTest.done_u16993 +00:0f37 RunTest.done_u16995 +00:0f3d RunTest.done_u16997 +00:0f43 RunTest.done_u16999 +00:0f49 RunTest.done_u17001 +00:0f4f RunTest.done_u17003 +00:0f55 RunTest.done_u17005 +00:0fbc RunTest.done_u17030 +00:0fc2 RunTest.done_u17032 +00:0fc8 RunTest.done_u17034 +00:0fce RunTest.done_u17036 +00:0fd4 RunTest.done_u17038 +00:0fda RunTest.done_u17040 +00:0fe0 RunTest.done_u17042 +00:0fe6 RunTest.done_u17044 +00:1050 RunTest.done_u17070 +00:1056 RunTest.done_u17072 +00:105c RunTest.done_u17074 +00:1062 RunTest.done_u17076 +00:1068 RunTest.done_u17078 +00:106e RunTest.done_u17080 +00:1074 RunTest.done_u17082 +00:107a RunTest.done_u17084 +00:10e7 RunTest.done_u17111 +00:10ed RunTest.done_u17113 +00:10f3 RunTest.done_u17115 +00:10f9 RunTest.done_u17117 +00:10ff RunTest.done_u17119 +00:1105 RunTest.done_u17121 +00:110b RunTest.done_u17123 +00:1111 RunTest.done_u17125 +00:1181 RunTest.done_u17153 +00:1187 RunTest.done_u17155 +00:118d RunTest.done_u17157 +00:1193 RunTest.done_u17159 +00:1199 RunTest.done_u17161 +00:119f RunTest.done_u17163 +00:11a5 RunTest.done_u17165 +00:11ab RunTest.done_u17167 +00:121e RunTest.done_u17196 +00:1224 RunTest.done_u17198 +00:122a RunTest.done_u17200 +00:1230 RunTest.done_u17202 +00:1236 RunTest.done_u17204 +00:123c RunTest.done_u17206 +00:1242 RunTest.done_u17208 +00:1248 RunTest.done_u17210 +00:12be RunTest.done_u17240 +00:12c4 RunTest.done_u17242 +00:12ca RunTest.done_u17244 +00:12d0 RunTest.done_u17246 +00:12d6 RunTest.done_u17248 +00:12dc RunTest.done_u17250 +00:12e2 RunTest.done_u17252 +00:12e8 RunTest.done_u17254 +00:1361 RunTest.done_u17285 +00:1367 RunTest.done_u17287 +00:136d RunTest.done_u17289 +00:1373 RunTest.done_u17291 +00:1379 RunTest.done_u17293 +00:137f RunTest.done_u17295 +00:1385 RunTest.done_u17297 +00:138b RunTest.done_u17299 +00:1407 RunTest.done_u17331 +00:140d RunTest.done_u17333 +00:1413 RunTest.done_u17335 +00:1419 RunTest.done_u17337 +00:141f RunTest.done_u17339 +00:1425 RunTest.done_u17341 +00:142b RunTest.done_u17343 +00:1431 RunTest.done_u17345 +00:14b0 RunTest.done_u17378 +00:14b6 RunTest.done_u17380 +00:14bc RunTest.done_u17382 +00:14c2 RunTest.done_u17384 +00:14c8 RunTest.done_u17386 +00:14ce RunTest.done_u17388 +00:14d4 RunTest.done_u17390 +00:14da RunTest.done_u17392 +00:155c RunTest.done_u17426 +00:1562 RunTest.done_u17428 +00:1568 RunTest.done_u17430 +00:156e RunTest.done_u17432 +00:1574 RunTest.done_u17434 +00:157a RunTest.done_u17436 +00:1580 RunTest.done_u17438 +00:1586 RunTest.done_u17440 +00:158a StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/div_write_trigger_volume/xbaseline_0000.png b/cinema/gb/samesuite/apu/div_write_trigger_volume/xbaseline_0000.png new file mode 100644 index 000000000..1faa3d928 Binary files /dev/null and b/cinema/gb/samesuite/apu/div_write_trigger_volume/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/apu/div_write_trigger_volume_10/config.ini b/cinema/gb/samesuite/apu/div_write_trigger_volume_10/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/apu/div_write_trigger_volume_10/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/apu/div_write_trigger_volume_10/test.gb b/cinema/gb/samesuite/apu/div_write_trigger_volume_10/test.gb new file mode 100644 index 000000000..0e911652c Binary files /dev/null and b/cinema/gb/samesuite/apu/div_write_trigger_volume_10/test.gb differ diff --git a/cinema/gb/samesuite/apu/div_write_trigger_volume_10/test.sym b/cinema/gb/samesuite/apu/div_write_trigger_volume_10/test.sym new file mode 100644 index 000000000..48706594f --- /dev/null +++ b/cinema/gb/samesuite/apu/div_write_trigger_volume_10/test.sym @@ -0,0 +1,303 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb TriggerAPU +00:05d0 WaitDIV10 +00:05d2 WaitDIV10.waitDIV +00:05d6 RunTest +00:05fe RunTest.done_u16403 +00:0604 RunTest.done_u16405 +00:060a RunTest.done_u16407 +00:0610 RunTest.done_u16409 +00:0616 RunTest.done_u16411 +00:061c RunTest.done_u16413 +00:0622 RunTest.done_u16415 +00:0628 RunTest.done_u16417 +00:0653 RunTest.done_u16421 +00:0659 RunTest.done_u16423 +00:065f RunTest.done_u16425 +00:0665 RunTest.done_u16427 +00:066b RunTest.done_u16429 +00:0671 RunTest.done_u16431 +00:0677 RunTest.done_u16433 +00:067d RunTest.done_u16435 +00:06ab RunTest.done_u16440 +00:06b1 RunTest.done_u16442 +00:06b7 RunTest.done_u16444 +00:06bd RunTest.done_u16446 +00:06c3 RunTest.done_u16448 +00:06c9 RunTest.done_u16450 +00:06cf RunTest.done_u16452 +00:06d5 RunTest.done_u16454 +00:0706 RunTest.done_u16460 +00:070c RunTest.done_u16462 +00:0712 RunTest.done_u16464 +00:0718 RunTest.done_u16466 +00:071e RunTest.done_u16468 +00:0724 RunTest.done_u16470 +00:072a RunTest.done_u16472 +00:0730 RunTest.done_u16474 +00:0764 RunTest.done_u16481 +00:076a RunTest.done_u16483 +00:0770 RunTest.done_u16485 +00:0776 RunTest.done_u16487 +00:077c RunTest.done_u16489 +00:0782 RunTest.done_u16491 +00:0788 RunTest.done_u16493 +00:078e RunTest.done_u16495 +00:07c5 RunTest.done_u16503 +00:07cb RunTest.done_u16505 +00:07d1 RunTest.done_u16507 +00:07d7 RunTest.done_u16509 +00:07dd RunTest.done_u16511 +00:07e3 RunTest.done_u16513 +00:07e9 RunTest.done_u16515 +00:07ef RunTest.done_u16517 +00:0829 RunTest.done_u16526 +00:082f RunTest.done_u16528 +00:0835 RunTest.done_u16530 +00:083b RunTest.done_u16532 +00:0841 RunTest.done_u16534 +00:0847 RunTest.done_u16536 +00:084d RunTest.done_u16538 +00:0853 RunTest.done_u16540 +00:0890 RunTest.done_u16550 +00:0896 RunTest.done_u16552 +00:089c RunTest.done_u16554 +00:08a2 RunTest.done_u16556 +00:08a8 RunTest.done_u16558 +00:08ae RunTest.done_u16560 +00:08b4 RunTest.done_u16562 +00:08ba RunTest.done_u16564 +00:08fa RunTest.done_u16575 +00:0900 RunTest.done_u16577 +00:0906 RunTest.done_u16579 +00:090c RunTest.done_u16581 +00:0912 RunTest.done_u16583 +00:0918 RunTest.done_u16585 +00:091e RunTest.done_u16587 +00:0924 RunTest.done_u16589 +00:0967 RunTest.done_u16601 +00:096d RunTest.done_u16603 +00:0973 RunTest.done_u16605 +00:0979 RunTest.done_u16607 +00:097f RunTest.done_u16609 +00:0985 RunTest.done_u16611 +00:098b RunTest.done_u16613 +00:0991 RunTest.done_u16615 +00:09d7 RunTest.done_u16628 +00:09dd RunTest.done_u16630 +00:09e3 RunTest.done_u16632 +00:09e9 RunTest.done_u16634 +00:09ef RunTest.done_u16636 +00:09f5 RunTest.done_u16638 +00:09fb RunTest.done_u16640 +00:0a01 RunTest.done_u16642 +00:0a4a RunTest.done_u16656 +00:0a50 RunTest.done_u16658 +00:0a56 RunTest.done_u16660 +00:0a5c RunTest.done_u16662 +00:0a62 RunTest.done_u16664 +00:0a68 RunTest.done_u16666 +00:0a6e RunTest.done_u16668 +00:0a74 RunTest.done_u16670 +00:0ac0 RunTest.done_u16685 +00:0ac6 RunTest.done_u16687 +00:0acc RunTest.done_u16689 +00:0ad2 RunTest.done_u16691 +00:0ad8 RunTest.done_u16693 +00:0ade RunTest.done_u16695 +00:0ae4 RunTest.done_u16697 +00:0aea RunTest.done_u16699 +00:0b39 RunTest.done_u16715 +00:0b3f RunTest.done_u16717 +00:0b45 RunTest.done_u16719 +00:0b4b RunTest.done_u16721 +00:0b51 RunTest.done_u16723 +00:0b57 RunTest.done_u16725 +00:0b5d RunTest.done_u16727 +00:0b63 RunTest.done_u16729 +00:0bb5 RunTest.done_u16746 +00:0bbb RunTest.done_u16748 +00:0bc1 RunTest.done_u16750 +00:0bc7 RunTest.done_u16752 +00:0bcd RunTest.done_u16754 +00:0bd3 RunTest.done_u16756 +00:0bd9 RunTest.done_u16758 +00:0bdf RunTest.done_u16760 +00:0c34 RunTest.done_u16778 +00:0c3a RunTest.done_u16780 +00:0c40 RunTest.done_u16782 +00:0c46 RunTest.done_u16784 +00:0c4c RunTest.done_u16786 +00:0c52 RunTest.done_u16788 +00:0c58 RunTest.done_u16790 +00:0c5e RunTest.done_u16792 +00:0cb6 RunTest.done_u16811 +00:0cbc RunTest.done_u16813 +00:0cc2 RunTest.done_u16815 +00:0cc8 RunTest.done_u16817 +00:0cce RunTest.done_u16819 +00:0cd4 RunTest.done_u16821 +00:0cda RunTest.done_u16823 +00:0ce0 RunTest.done_u16825 +00:0d3b RunTest.done_u16845 +00:0d41 RunTest.done_u16847 +00:0d47 RunTest.done_u16849 +00:0d4d RunTest.done_u16851 +00:0d53 RunTest.done_u16853 +00:0d59 RunTest.done_u16855 +00:0d5f RunTest.done_u16857 +00:0d65 RunTest.done_u16859 +00:0dc3 RunTest.done_u16880 +00:0dc9 RunTest.done_u16882 +00:0dcf RunTest.done_u16884 +00:0dd5 RunTest.done_u16886 +00:0ddb RunTest.done_u16888 +00:0de1 RunTest.done_u16890 +00:0de7 RunTest.done_u16892 +00:0ded RunTest.done_u16894 +00:0e4e RunTest.done_u16916 +00:0e54 RunTest.done_u16918 +00:0e5a RunTest.done_u16920 +00:0e60 RunTest.done_u16922 +00:0e66 RunTest.done_u16924 +00:0e6c RunTest.done_u16926 +00:0e72 RunTest.done_u16928 +00:0e78 RunTest.done_u16930 +00:0edc RunTest.done_u16953 +00:0ee2 RunTest.done_u16955 +00:0ee8 RunTest.done_u16957 +00:0eee RunTest.done_u16959 +00:0ef4 RunTest.done_u16961 +00:0efa RunTest.done_u16963 +00:0f00 RunTest.done_u16965 +00:0f06 RunTest.done_u16967 +00:0f6d RunTest.done_u16991 +00:0f73 RunTest.done_u16993 +00:0f79 RunTest.done_u16995 +00:0f7f RunTest.done_u16997 +00:0f85 RunTest.done_u16999 +00:0f8b RunTest.done_u17001 +00:0f91 RunTest.done_u17003 +00:0f97 RunTest.done_u17005 +00:1001 RunTest.done_u17030 +00:1007 RunTest.done_u17032 +00:100d RunTest.done_u17034 +00:1013 RunTest.done_u17036 +00:1019 RunTest.done_u17038 +00:101f RunTest.done_u17040 +00:1025 RunTest.done_u17042 +00:102b RunTest.done_u17044 +00:1098 RunTest.done_u17070 +00:109e RunTest.done_u17072 +00:10a4 RunTest.done_u17074 +00:10aa RunTest.done_u17076 +00:10b0 RunTest.done_u17078 +00:10b6 RunTest.done_u17080 +00:10bc RunTest.done_u17082 +00:10c2 RunTest.done_u17084 +00:1132 RunTest.done_u17111 +00:1138 RunTest.done_u17113 +00:113e RunTest.done_u17115 +00:1144 RunTest.done_u17117 +00:114a RunTest.done_u17119 +00:1150 RunTest.done_u17121 +00:1156 RunTest.done_u17123 +00:115c RunTest.done_u17125 +00:11cf RunTest.done_u17153 +00:11d5 RunTest.done_u17155 +00:11db RunTest.done_u17157 +00:11e1 RunTest.done_u17159 +00:11e7 RunTest.done_u17161 +00:11ed RunTest.done_u17163 +00:11f3 RunTest.done_u17165 +00:11f9 RunTest.done_u17167 +00:126f RunTest.done_u17196 +00:1275 RunTest.done_u17198 +00:127b RunTest.done_u17200 +00:1281 RunTest.done_u17202 +00:1287 RunTest.done_u17204 +00:128d RunTest.done_u17206 +00:1293 RunTest.done_u17208 +00:1299 RunTest.done_u17210 +00:1312 RunTest.done_u17240 +00:1318 RunTest.done_u17242 +00:131e RunTest.done_u17244 +00:1324 RunTest.done_u17246 +00:132a RunTest.done_u17248 +00:1330 RunTest.done_u17250 +00:1336 RunTest.done_u17252 +00:133c RunTest.done_u17254 +00:13b8 RunTest.done_u17285 +00:13be RunTest.done_u17287 +00:13c4 RunTest.done_u17289 +00:13ca RunTest.done_u17291 +00:13d0 RunTest.done_u17293 +00:13d6 RunTest.done_u17295 +00:13dc RunTest.done_u17297 +00:13e2 RunTest.done_u17299 +00:1461 RunTest.done_u17331 +00:1467 RunTest.done_u17333 +00:146d RunTest.done_u17335 +00:1473 RunTest.done_u17337 +00:1479 RunTest.done_u17339 +00:147f RunTest.done_u17341 +00:1485 RunTest.done_u17343 +00:148b RunTest.done_u17345 +00:150d RunTest.done_u17378 +00:1513 RunTest.done_u17380 +00:1519 RunTest.done_u17382 +00:151f RunTest.done_u17384 +00:1525 RunTest.done_u17386 +00:152b RunTest.done_u17388 +00:1531 RunTest.done_u17390 +00:1537 RunTest.done_u17392 +00:15bc RunTest.done_u17426 +00:15c2 RunTest.done_u17428 +00:15c8 RunTest.done_u17430 +00:15ce RunTest.done_u17432 +00:15d4 RunTest.done_u17434 +00:15da RunTest.done_u17436 +00:15e0 RunTest.done_u17438 +00:15e6 RunTest.done_u17440 +00:15ea StoreResult +01:4000 NopSlide diff --git a/cinema/gb/samesuite/apu/div_write_trigger_volume_10/xbaseline_0000.png b/cinema/gb/samesuite/apu/div_write_trigger_volume_10/xbaseline_0000.png new file mode 100644 index 000000000..5f5f952c1 Binary files /dev/null and b/cinema/gb/samesuite/apu/div_write_trigger_volume_10/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/config.ini b/cinema/gb/samesuite/config.ini new file mode 100644 index 000000000..6b38213c9 --- /dev/null +++ b/cinema/gb/samesuite/config.ini @@ -0,0 +1,6 @@ +[testinfo] +skip=60 +frames=1 + +[ports.cinema] +sgb.borders=0 diff --git a/cinema/gb/samesuite/dma/gbc_dma_cont/baseline_0000.png b/cinema/gb/samesuite/dma/gbc_dma_cont/baseline_0000.png new file mode 100644 index 000000000..b016da291 Binary files /dev/null and b/cinema/gb/samesuite/dma/gbc_dma_cont/baseline_0000.png differ diff --git a/cinema/gb/samesuite/dma/gbc_dma_cont/test.gb b/cinema/gb/samesuite/dma/gbc_dma_cont/test.gb new file mode 100644 index 000000000..15b9bc666 Binary files /dev/null and b/cinema/gb/samesuite/dma/gbc_dma_cont/test.gb differ diff --git a/cinema/gb/samesuite/dma/gbc_dma_cont/test.sym b/cinema/gb/samesuite/dma/gbc_dma_cont/test.sym new file mode 100644 index 000000000..a95387c7d --- /dev/null +++ b/cinema/gb/samesuite/dma/gbc_dma_cont/test.sym @@ -0,0 +1,47 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05db RunTest +00:05e8 RunTest.initTestBuf +00:05fb RunTest.initSrcBuf +01:4000 NopSlide +00:8800 vTestBuf +00:c000 SrcBuf diff --git a/cinema/gb/samesuite/dma/gdma_addr_mask/baseline_0000.png b/cinema/gb/samesuite/dma/gdma_addr_mask/baseline_0000.png new file mode 100644 index 000000000..367a0b27e Binary files /dev/null and b/cinema/gb/samesuite/dma/gdma_addr_mask/baseline_0000.png differ diff --git a/cinema/gb/samesuite/dma/gdma_addr_mask/test.gb b/cinema/gb/samesuite/dma/gdma_addr_mask/test.gb new file mode 100644 index 000000000..1180a5e34 Binary files /dev/null and b/cinema/gb/samesuite/dma/gdma_addr_mask/test.gb differ diff --git a/cinema/gb/samesuite/dma/gdma_addr_mask/test.sym b/cinema/gb/samesuite/dma/gdma_addr_mask/test.sym new file mode 100644 index 000000000..0e45f9371 --- /dev/null +++ b/cinema/gb/samesuite/dma/gdma_addr_mask/test.sym @@ -0,0 +1,48 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb RunTest +00:05db RunTest.initTestBuf +00:05f0 RunTest.initSrcBuf +00:05fc RunTest.initHRAM +01:4000 NopSlide +00:8800 vTestBuf +00:c000 SrcBuf diff --git a/cinema/gb/samesuite/dma/hdma_lcd_off/config.ini b/cinema/gb/samesuite/dma/hdma_lcd_off/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/dma/hdma_lcd_off/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/dma/hdma_lcd_off/test.gb b/cinema/gb/samesuite/dma/hdma_lcd_off/test.gb new file mode 100644 index 000000000..04db06c83 Binary files /dev/null and b/cinema/gb/samesuite/dma/hdma_lcd_off/test.gb differ diff --git a/cinema/gb/samesuite/dma/hdma_lcd_off/test.sym b/cinema/gb/samesuite/dma/hdma_lcd_off/test.sym new file mode 100644 index 000000000..6e3b35efb --- /dev/null +++ b/cinema/gb/samesuite/dma/hdma_lcd_off/test.sym @@ -0,0 +1,48 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05d3 RunTest +00:05e1 RunTest.initTestBuf +00:05f4 RunTest.initSrcBuf +00:0600 RunTest.initHRAM +01:4000 NopSlide +00:8800 vTestBuf +00:c000 SrcBuf diff --git a/cinema/gb/samesuite/dma/hdma_lcd_off/xbaseline_0000.png b/cinema/gb/samesuite/dma/hdma_lcd_off/xbaseline_0000.png new file mode 100644 index 000000000..d1b4ff643 Binary files /dev/null and b/cinema/gb/samesuite/dma/hdma_lcd_off/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/dma/hdma_mode0/config.ini b/cinema/gb/samesuite/dma/hdma_mode0/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/dma/hdma_mode0/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/dma/hdma_mode0/test.gb b/cinema/gb/samesuite/dma/hdma_mode0/test.gb new file mode 100644 index 000000000..cb7df3705 Binary files /dev/null and b/cinema/gb/samesuite/dma/hdma_mode0/test.gb differ diff --git a/cinema/gb/samesuite/dma/hdma_mode0/test.sym b/cinema/gb/samesuite/dma/hdma_mode0/test.sym new file mode 100644 index 000000000..6e3b35efb --- /dev/null +++ b/cinema/gb/samesuite/dma/hdma_mode0/test.sym @@ -0,0 +1,48 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05d3 RunTest +00:05e1 RunTest.initTestBuf +00:05f4 RunTest.initSrcBuf +00:0600 RunTest.initHRAM +01:4000 NopSlide +00:8800 vTestBuf +00:c000 SrcBuf diff --git a/cinema/gb/samesuite/dma/hdma_mode0/xbaseline_0000.png b/cinema/gb/samesuite/dma/hdma_mode0/xbaseline_0000.png new file mode 100644 index 000000000..d1b4ff643 Binary files /dev/null and b/cinema/gb/samesuite/dma/hdma_mode0/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/interrupt/ei_delay_halt/config.ini b/cinema/gb/samesuite/interrupt/ei_delay_halt/config.ini new file mode 100644 index 000000000..7ddee425b --- /dev/null +++ b/cinema/gb/samesuite/interrupt/ei_delay_halt/config.ini @@ -0,0 +1,2 @@ +[testinfo] +fail=1 diff --git a/cinema/gb/samesuite/interrupt/ei_delay_halt/test.gb b/cinema/gb/samesuite/interrupt/ei_delay_halt/test.gb new file mode 100644 index 000000000..22d67738c Binary files /dev/null and b/cinema/gb/samesuite/interrupt/ei_delay_halt/test.gb differ diff --git a/cinema/gb/samesuite/interrupt/ei_delay_halt/test.sym b/cinema/gb/samesuite/interrupt/ei_delay_halt/test.sym new file mode 100644 index 000000000..57b57266c --- /dev/null +++ b/cinema/gb/samesuite/interrupt/ei_delay_halt/test.sym @@ -0,0 +1,47 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05cb RunTest +00:0604 RunTest.halt +01:4000 NopSlide +00:c000 RESULTS_START +00:c020 RESULTS_START.end +00:c020 wSPSave diff --git a/cinema/gb/samesuite/interrupt/ei_delay_halt/xbaseline_0000.png b/cinema/gb/samesuite/interrupt/ei_delay_halt/xbaseline_0000.png new file mode 100644 index 000000000..e8ff40eb1 Binary files /dev/null and b/cinema/gb/samesuite/interrupt/ei_delay_halt/xbaseline_0000.png differ diff --git a/cinema/gb/samesuite/ppu/blocking_bgpi_increase/baseline_0000.png b/cinema/gb/samesuite/ppu/blocking_bgpi_increase/baseline_0000.png new file mode 100644 index 000000000..86ad2e3f7 Binary files /dev/null and b/cinema/gb/samesuite/ppu/blocking_bgpi_increase/baseline_0000.png differ diff --git a/cinema/gb/samesuite/ppu/blocking_bgpi_increase/test.gb b/cinema/gb/samesuite/ppu/blocking_bgpi_increase/test.gb new file mode 100644 index 000000000..862260c53 Binary files /dev/null and b/cinema/gb/samesuite/ppu/blocking_bgpi_increase/test.gb differ diff --git a/cinema/gb/samesuite/ppu/blocking_bgpi_increase/test.sym b/cinema/gb/samesuite/ppu/blocking_bgpi_increase/test.sym new file mode 100644 index 000000000..d9a1dee8e --- /dev/null +++ b/cinema/gb/samesuite/ppu/blocking_bgpi_increase/test.sym @@ -0,0 +1,48 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05b3 RunTest +00:05d0 RunTest.waitWrite_u16402 +00:05e1 RunTest.waitWrite_u16403 +00:05f2 RunTest.waitWrite_u16404 +00:0605 RunTest.delay_u16405 +00:0609 RunTest.waitWrite_u16405 +01:4000 NopSlide diff --git a/cinema/gb/samesuite/sgb/command_mlt_req/baseline_0000.png b/cinema/gb/samesuite/sgb/command_mlt_req/baseline_0000.png new file mode 100644 index 000000000..602e3026a Binary files /dev/null and b/cinema/gb/samesuite/sgb/command_mlt_req/baseline_0000.png differ diff --git a/cinema/gb/samesuite/sgb/command_mlt_req/test.gb b/cinema/gb/samesuite/sgb/command_mlt_req/test.gb new file mode 100644 index 000000000..8d8b9514b Binary files /dev/null and b/cinema/gb/samesuite/sgb/command_mlt_req/test.gb differ diff --git a/cinema/gb/samesuite/sgb/command_mlt_req/test.sym b/cinema/gb/samesuite/sgb/command_mlt_req/test.sym new file mode 100644 index 000000000..8e0961ba3 --- /dev/null +++ b/cinema/gb/samesuite/sgb/command_mlt_req/test.sym @@ -0,0 +1,55 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05c3 RunTest +00:07e2 SendSgbPacket +00:07ed SendSgbPacket.sgbByte +00:07f1 SendSgbPacket.sgbByteLoop +00:07f9 SendSgbPacket.sgbBit +00:0811 SgbWait +00:0815 SgbWait.waitloop +00:081f Increment +00:0828 StoreResult +00:082b MLT_REQ_0 +00:083b MLT_REQ_1 +00:084b MLT_REQ_2 +00:085b MLT_REQ_3 +01:4000 NopSlide diff --git a/cinema/gb/samesuite/sgb/command_mlt_req_1/baseline_0000.png b/cinema/gb/samesuite/sgb/command_mlt_req_1/baseline_0000.png new file mode 100644 index 000000000..602e3026a Binary files /dev/null and b/cinema/gb/samesuite/sgb/command_mlt_req_1/baseline_0000.png differ diff --git a/cinema/gb/samesuite/sgb/command_mlt_req_1/test.gb b/cinema/gb/samesuite/sgb/command_mlt_req_1/test.gb new file mode 100644 index 000000000..3b4f846f1 Binary files /dev/null and b/cinema/gb/samesuite/sgb/command_mlt_req_1/test.gb differ diff --git a/cinema/gb/samesuite/sgb/command_mlt_req_1/test.sym b/cinema/gb/samesuite/sgb/command_mlt_req_1/test.sym new file mode 100644 index 000000000..8a6eef44c --- /dev/null +++ b/cinema/gb/samesuite/sgb/command_mlt_req_1/test.sym @@ -0,0 +1,50 @@ +; File generated by rgblink + +00:0100 Start +00:04C3 _Start +00:0163 LCDOff.ret +00:0157 LCDOff.LCDOffLoop +00:01A1 HexDigits +00:0176 LoadFont.loop +00:017C LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:03B7 LoadPalettes +00:03BC LoadPalettes.loop +00:0150 LCDOff +00:016E LoadFont +00:03A1 Palette +00:03B5 LoadBGPalettes +00:03B1 LoadObjPalettes +00:03F9 ModemCh1Freqs +00:0409 ModemCh2Freqs +00:0419 ModemCh3Freqs +00:03E0 ModemSleep +00:0429 ModemSendByte +00:04BB ModemSendBuffer +00:03C2 CommonInit +00:05B4 RunTest +00:0523 PrintResults +00:0165 LCDOn +00:04DF _Start.loop_16399 +00:04FA _Start.failed +00:0501 _Start.sendSerial +00:0597 SerialSendByte +00:0519 _Start.loop_16400 +00:05A4 CorrectResults +00:0562 PrintResults.correct +00:0576 PrintResults.correct2 +00:0550 PrintResults.xLoop +00:052C PrintResults.yLoop +00:059D SerialSendByte.loop +00:0715 MLT_REQ_1 +00:06BC SendSgbPacket +00:0702 StoreResult +00:06F9 Increment +00:0705 MLT_REQ_0 +00:0725 MLT_REQ_2 +00:0735 MLT_REQ_3 +00:06D3 SendSgbPacket.sgbBit +00:06CB SendSgbPacket.sgbByteLoop +00:06C7 SendSgbPacket.sgbByte +00:06EF SgbWait.waitloop diff --git a/cinema/gb/samesuite/sgb/command_mlt_req_1_incrementing/baseline_0000.png b/cinema/gb/samesuite/sgb/command_mlt_req_1_incrementing/baseline_0000.png new file mode 100644 index 000000000..111d30360 Binary files /dev/null and b/cinema/gb/samesuite/sgb/command_mlt_req_1_incrementing/baseline_0000.png differ diff --git a/cinema/gb/samesuite/sgb/command_mlt_req_1_incrementing/test.gb b/cinema/gb/samesuite/sgb/command_mlt_req_1_incrementing/test.gb new file mode 100644 index 000000000..bd1aef6c9 Binary files /dev/null and b/cinema/gb/samesuite/sgb/command_mlt_req_1_incrementing/test.gb differ diff --git a/cinema/gb/samesuite/sgb/command_mlt_req_1_incrementing/test.sym b/cinema/gb/samesuite/sgb/command_mlt_req_1_incrementing/test.sym new file mode 100644 index 000000000..9d0a8fb79 --- /dev/null +++ b/cinema/gb/samesuite/sgb/command_mlt_req_1_incrementing/test.sym @@ -0,0 +1,52 @@ +; File generated by rgblink +00:00ff reboot +00:0100 Start +00:0150 LCDOff +00:0157 LCDOff.LCDOffLoop +00:0163 LCDOff.ret +00:0165 LCDOn +00:016e LoadFont +00:0176 LoadFont.loop +00:017c LoadFont.loop2 +00:0185 LoadFont.loop3 +00:0192 LoadFont.loop4 +00:01a1 HexDigits +00:03a1 Palette +00:03b1 LoadObjPalettes +00:03b5 LoadBGPalettes +00:03b7 LoadPalettes +00:03bc LoadPalettes.loop +00:03c2 CommonInit +00:03d0 CommonInit.clearLogoTilemap +00:03e9 ModemSleep +00:0401 ModemCh1Freqs +00:0411 ModemCh2Freqs +00:0421 ModemCh3Freqs +00:0431 ModemSendByte +00:0485 ModemStart +00:04bf ModemStop +00:04c3 ModemSendBuffer +00:04cb _Start +00:04e7 _Start.loop_u16400 +00:0502 _Start.failed +00:0509 _Start.sendSerial +00:0521 _Start.loop_u16401 +00:052a PrintResults +00:0533 PrintResults.yLoop +00:0557 PrintResults.xLoop +00:0569 PrintResults.correct +00:057d PrintResults.correct2 +00:059e SerialSendByte +00:05a4 SerialSendByte.loop +00:05ab CorrectResults +00:05b3 RunTest +00:063c SendSgbPacket +00:0647 SendSgbPacket.sgbByte +00:064b SendSgbPacket.sgbByteLoop +00:0653 SendSgbPacket.sgbBit +00:066b SgbWait +00:066f SgbWait.waitloop +00:0679 StoreResult +00:067c MLT_REQ_0 +00:068c MLT_REQ_1 +01:4000 NopSlide diff --git a/include/mgba-util/audio-buffer.h b/include/mgba-util/audio-buffer.h new file mode 100644 index 000000000..b6d760822 --- /dev/null +++ b/include/mgba-util/audio-buffer.h @@ -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 + +CXX_GUARD_START + +#include + +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 diff --git a/include/mgba-util/audio-resampler.h b/include/mgba-util/audio-resampler.h new file mode 100644 index 000000000..e1ec3d84c --- /dev/null +++ b/include/mgba-util/audio-resampler.h @@ -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 + +CXX_GUARD_START + +#include + +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 + diff --git a/include/mgba-util/circle-buffer.h b/include/mgba-util/circle-buffer.h index dee1f1f2a..c93040c6a 100644 --- a/include/mgba-util/circle-buffer.h +++ b/include/mgba-util/circle-buffer.h @@ -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 diff --git a/include/mgba-util/common.h b/include/mgba-util/common.h index 0fc10be58..c5008e01f 100644 --- a/include/mgba-util/common.h +++ b/include/mgba-util/common.h @@ -14,12 +14,21 @@ #define CXX_GUARD_END #endif -#ifdef __MINGW32__ -#define __USE_MINGW_ANSI_STDIO 1 -#endif - CXX_GUARD_START +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +// Require Windows 7 or newer +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0601 +#elif _WIN32_WINNT < 0x0601 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0601 +#endif +// WinSock2 gets very angry if it's included too late +#include +#endif + #include #include #include @@ -35,11 +44,6 @@ CXX_GUARD_START #include #include -#ifdef _WIN32 -// WinSock2 gets very angry if it's included too late -#include -#endif - #if defined(_MSC_VER) || defined(__cplusplus) #define restrict __restrict #endif @@ -310,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 diff --git a/include/mgba-util/configuration.h b/include/mgba-util/configuration.h index e19ad13ef..f4c206d6a 100644 --- a/include/mgba-util/configuration.h +++ b/include/mgba-util/configuration.h @@ -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); diff --git a/include/mgba-util/geometry.h b/include/mgba-util/geometry.h index aa7d65e94..5164b0b8d 100644 --- a/include/mgba-util/geometry.h +++ b/include/mgba-util/geometry.h @@ -11,15 +11,15 @@ CXX_GUARD_START struct mSize { - int width; - int height; + int width; + int height; }; struct mRectangle { - int x; - int y; - int width; - int height; + int x; + int y; + int width; + int height; }; void mRectangleUnion(struct mRectangle* dst, const struct mRectangle* add); diff --git a/include/mgba-util/gui/font-metrics.h b/include/mgba-util/gui/font-metrics.h index c60d6dfc8..c2e6668d4 100644 --- a/include/mgba-util/gui/font-metrics.h +++ b/include/mgba-util/gui/font-metrics.h @@ -6,9 +6,10 @@ #ifndef DEFAULT_FONT_METRICS_H #define DEFAULT_FONT_METRICS_H +#include #include -extern struct GUIFontGlyphMetric defaultFontMetrics[]; -extern struct GUIIconMetric defaultIconMetrics[]; +extern const struct GUIFontGlyphMetric defaultFontMetrics[128]; +extern const struct GUIIconMetric defaultIconMetrics[GUI_ICON_MAX]; #endif diff --git a/include/mgba-util/image.h b/include/mgba-util/image.h index 31514687d..dd135a0b4 100644 --- a/include/mgba-util/image.h +++ b/include/mgba-util/image.h @@ -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); @@ -138,6 +142,7 @@ void mPainterInit(struct mPainter*, struct mImage* backing); void mPainterDrawRectangle(struct mPainter*, int x, int y, int width, int height); void mPainterDrawLine(struct mPainter*, int x1, int y1, int x2, int y2); void mPainterDrawCircle(struct mPainter*, int x, int y, int diameter); +void mPainterDrawMask(struct mPainter*, const struct mImage* mask, int x, int y); uint32_t mColorConvert(uint32_t color, enum mColorFormat from, enum mColorFormat to); uint32_t mImageColorConvert(uint32_t color, const struct mImage* from, enum mColorFormat to); @@ -205,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; diff --git a/include/mgba-util/interpolator.h b/include/mgba-util/interpolator.h new file mode 100644 index 000000000..b7a59acd5 --- /dev/null +++ b/include/mgba-util/interpolator.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_INTERPOLATOR_H +#define M_INTERPOLATOR_H + +#include + +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 diff --git a/include/mgba-util/md5.h b/include/mgba-util/md5.h new file mode 100644 index 000000000..9a2c58145 --- /dev/null +++ b/include/mgba-util/md5.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2013-2014 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/. + * + * Based on https://github.com/Zunawe/md5-c + * Originally released under the Unlicense */ +#ifndef MD5_H +#define MD5_H + +#include + +CXX_GUARD_START + +struct MD5Context { + size_t size; // Size of input in bytes + uint32_t buffer[4]; // Current accumulation of hash + uint8_t input[0x40]; // Input to be used in the next step + uint8_t digest[0x10]; // Result of algorithm +}; + +void md5Init(struct MD5Context* ctx); +void md5Update(struct MD5Context* ctx, const void* input, size_t len); +void md5Finalize(struct MD5Context* ctx); + +void md5Buffer(const void* input, size_t len, uint8_t* result); + +struct VFile; +bool md5File(struct VFile* vf, uint8_t* result); + +CXX_GUARD_END + +#endif diff --git a/include/mgba-util/platform/psp2/threading.h b/include/mgba-util/platform/psp2/threading.h index 4c084804c..2edcc4806 100644 --- a/include/mgba-util/platform/psp2/threading.h +++ b/include/mgba-util/platform/psp2/threading.h @@ -9,7 +9,7 @@ #include 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) { diff --git a/include/mgba-util/platform/windows/threading.h b/include/mgba-util/platform/windows/threading.h index 3f5de5a77..7b1589075 100644 --- a/include/mgba-util/platform/windows/threading.h +++ b/include/mgba-util/platform/windows/threading.h @@ -8,8 +8,6 @@ #include -#define _WIN32_WINNT 0x0600 -#include #define THREAD_ENTRY DWORD WINAPI typedef THREAD_ENTRY ThreadEntry(LPVOID); #define THREAD_EXIT(RES) return RES diff --git a/include/mgba-util/socket.h b/include/mgba-util/socket.h index ff9d89626..4b109eaea 100644 --- a/include/mgba-util/socket.h +++ b/include/mgba-util/socket.h @@ -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)); diff --git a/include/mgba-util/vector.h b/include/mgba-util/vector.h index 8c0f11e45..c837379e2 100644 --- a/include/mgba-util/vector.h +++ b/include/mgba-util/vector.h @@ -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); diff --git a/include/mgba-util/vfs.h b/include/mgba-util/vfs.h index eee68b99e..0279fb755 100644 --- a/include/mgba-util/vfs.h +++ b/include/mgba-util/vfs.h @@ -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); diff --git a/include/mgba/core/bitmap-cache.h b/include/mgba/core/bitmap-cache.h index d8bd416e9..1529fddc2 100644 --- a/include/mgba/core/bitmap-cache.h +++ b/include/mgba/core/bitmap-cache.h @@ -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 diff --git a/include/mgba/core/blip_buf.h b/include/mgba/core/blip_buf.h deleted file mode 100644 index 22b0a3ec8..000000000 --- a/include/mgba/core/blip_buf.h +++ /dev/null @@ -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 diff --git a/include/mgba/core/cache-set.h b/include/mgba/core/cache-set.h index 5749c0e64..627a647c7 100644 --- a/include/mgba/core/cache-set.h +++ b/include/mgba/core/cache-set.h @@ -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 diff --git a/include/mgba/core/cheats.h b/include/mgba/core/cheats.h index 1da1aa859..a1c6c555c 100644 --- a/include/mgba/core/cheats.h +++ b/include/mgba/core/cheats.h @@ -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 diff --git a/include/mgba/core/config.h b/include/mgba/core/config.h index ef7437487..4a68b49ee 100644 --- a/include/mgba/core/config.h +++ b/include/mgba/core/config.h @@ -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); @@ -72,8 +72,9 @@ bool mCoreConfigSavePath(const struct mCoreConfig*, const char* path); bool mCoreConfigLoadVFile(struct mCoreConfig*, struct VFile* vf); bool mCoreConfigSaveVFile(const struct mCoreConfig*, struct VFile* vf); -void mCoreConfigMakePortable(const struct mCoreConfig*); +void mCoreConfigMakePortable(const struct mCoreConfig*, const char* path); void mCoreConfigDirectory(char* out, size_t outLength); +void mCoreConfigPortableIniPath(char* out, size_t outLength); void mCoreConfigPortablePath(char* out, size_t outLength); bool mCoreConfigIsPortable(void); #endif diff --git a/include/mgba/core/core.h b/include/mgba/core/core.h index 052e36795..94dfb1114 100644 --- a/include/mgba/core/core.h +++ b/include/mgba/core/core.h @@ -11,14 +11,14 @@ CXX_GUARD_START #include -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#ifdef ENABLE_VFS #include #endif #ifndef MINIMAL_CORE #include #endif #include -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS #include #endif @@ -30,8 +30,10 @@ enum mPlatform { enum mCoreChecksumType { mCHECKSUM_CRC32, + mCHECKSUM_MD5, }; +struct mAudioBuffer; struct mCoreConfig; struct mCoreSync; struct mDebuggerSymbols; @@ -45,7 +47,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 +74,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 +110,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 +122,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 +150,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 +178,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 +220,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 diff --git a/include/mgba/core/directories.h b/include/mgba/core/directories.h index d421e7f51..f9f59cb8d 100644 --- a/include/mgba/core/directories.h +++ b/include/mgba/core/directories.h @@ -10,7 +10,7 @@ CXX_GUARD_START -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#ifdef ENABLE_VFS struct VDir; struct mDirectorySet { diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index f1af5e50d..033047cac 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -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,23 @@ 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*); +void mRumbleIntegratorReset(struct mRumbleIntegrator*); + struct mCoreChannelInfo { size_t id; const char* internalName; diff --git a/include/mgba/core/library.h b/include/mgba/core/library.h index d12aa0411..ededd5463 100644 --- a/include/mgba/core/library.h +++ b/include/mgba/core/library.h @@ -10,6 +10,8 @@ CXX_GUARD_START +#ifdef ENABLE_VFS + #include #include @@ -48,6 +50,8 @@ void mLibraryAttachGameDB(struct mLibrary* library, const struct NoIntroDB* db); #endif +#endif + CXX_GUARD_END #endif diff --git a/include/mgba/core/lockstep.h b/include/mgba/core/lockstep.h index ac6cb3f84..b83d17657 100644 --- a/include/mgba/core/lockstep.h +++ b/include/mgba/core/lockstep.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016 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 @@ -53,6 +53,25 @@ static inline void mLockstepUnlock(struct mLockstep* lockstep) { } } +struct mLockstepUser { + void (*sleep)(struct mLockstepUser*); + void (*wake)(struct mLockstepUser*); + + int (*requestedId)(struct mLockstepUser*); + void (*playerIdChanged)(struct mLockstepUser*, int id); +}; + +#ifndef DISABLE_THREADING +struct mCoreThread; +struct mLockstepThreadUser { + struct mLockstepUser d; + + struct mCoreThread* thread; +}; + +void mLockstepThreadUserInit(struct mLockstepThreadUser* lockstep, struct mCoreThread* thread); +#endif + CXX_GUARD_END #endif diff --git a/include/mgba/core/log.h b/include/mgba/core/log.h index 9f55ec772..892a8f2f9 100644 --- a/include/mgba/core/log.h +++ b/include/mgba/core/log.h @@ -44,6 +44,9 @@ struct mStandardLogger { struct mLogger* mLogGetContext(void); void mLogSetDefaultLogger(struct mLogger*); +void mLogSetThreadLogger(struct mLogger*); +struct mLogger* mLogGetThreadLogger(void); + int mLogGenerateCategory(const char*, const char*); const char* mLogCategoryName(int); const char* mLogCategoryId(int); diff --git a/include/mgba/core/map-cache.h b/include/mgba/core/map-cache.h index 349fc1663..29f17866c 100644 --- a/include/mgba/core/map-cache.h +++ b/include/mgba/core/map-cache.h @@ -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 diff --git a/include/mgba/core/rewind.h b/include/mgba/core/rewind.h index 9d2595557..2f33886ca 100644 --- a/include/mgba/core/rewind.h +++ b/include/mgba/core/rewind.h @@ -40,7 +40,7 @@ void mCoreRewindContextDeinit(struct mCoreRewindContext*); struct mCore; void mCoreRewindAppend(struct mCoreRewindContext*, struct mCore*); -bool mCoreRewindRestore(struct mCoreRewindContext*, struct mCore*); +bool mCoreRewindRestore(struct mCoreRewindContext*, struct mCore*, unsigned count); CXX_GUARD_END diff --git a/include/mgba/core/scripting.h b/include/mgba/core/scripting.h index 645874883..bab2009cf 100644 --- a/include/mgba/core/scripting.h +++ b/include/mgba/core/scripting.h @@ -10,7 +10,7 @@ CXX_GUARD_START -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS #include #endif #include @@ -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 diff --git a/include/mgba/core/serialize.h b/include/mgba/core/serialize.h index ee9de69a1..177a7871a 100644 --- a/include/mgba/core/serialize.h +++ b/include/mgba/core/serialize.h @@ -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); diff --git a/include/mgba/core/sync.h b/include/mgba/core/sync.h index a44994b07..df4e777bb 100644 --- a/include/mgba/core/sync.h +++ b/include/mgba/core/sync.h @@ -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); diff --git a/include/mgba/core/thread.h b/include/mgba/core/thread.h index fee447ae7..9f2c229be 100644 --- a/include/mgba/core/thread.h +++ b/include/mgba/core/thread.h @@ -87,7 +87,8 @@ struct mCoreThreadInternal { int requested; Mutex stateMutex; - Condition stateCond; + Condition stateOnThreadCond; + Condition stateOffThreadCond; int interruptDepth; bool frameWasOn; @@ -128,7 +129,6 @@ void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool); void mCoreThreadRewindParamsChanged(struct mCoreThread* threadContext); struct mCoreThread* mCoreThreadGet(void); -struct mLogger* mCoreThreadLogger(void); CXX_GUARD_END diff --git a/include/mgba/core/tile-cache.h b/include/mgba/core/tile-cache.h index f8600b3ad..24458b011 100644 --- a/include/mgba/core/tile-cache.h +++ b/include/mgba/core/tile-cache.h @@ -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 diff --git a/include/mgba/feature/commandline.h b/include/mgba/feature/commandline.h index 964d9bdf9..17af655fe 100644 --- a/include/mgba/feature/commandline.h +++ b/include/mgba/feature/commandline.h @@ -59,6 +59,8 @@ void version(const char* arg0); bool mArgumentsParse(struct mArguments* args, int argc, char* const* argv, struct mSubParser* subparsers, int nSubparsers); void mArgumentsApply(const struct mArguments* args, struct mSubParser* subparsers, int nSubparsers, struct mCoreConfig* config); +bool mArgumentsApplyDebugger(const struct mArguments*, struct mCore*, struct mDebugger*); +void mArgumentsApplyFileLoads(const struct mArguments*, struct mCore*); void mArgumentsDeinit(struct mArguments* args); void mSubParserGraphicsInit(struct mSubParser* parser, struct mGraphicsOpts* opts); diff --git a/include/mgba/feature/proxy-backend.h b/include/mgba/feature/proxy-backend.h index 8c0b9e427..0851b3a68 100644 --- a/include/mgba/feature/proxy-backend.h +++ b/include/mgba/feature/proxy-backend.h @@ -38,6 +38,8 @@ union mVideoBackendCommandData { struct { unsigned width; unsigned height; + unsigned maxW; + unsigned maxH; } u; const void* image; }; @@ -55,7 +57,7 @@ struct mVideoBackendCommand { struct mVideoProxyBackend { struct VideoBackend d; struct VideoBackend* backend; - + struct RingFIFO in; struct RingFIFO out; diff --git a/include/mgba/feature/video-backend.h b/include/mgba/feature/video-backend.h index 292dc9c82..f01e656c9 100644 --- a/include/mgba/feature/video-backend.h +++ b/include/mgba/feature/video-backend.h @@ -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); @@ -74,6 +74,7 @@ struct VideoShader { void VideoBackendGetFrame(const struct VideoBackend*, struct mRectangle* frame); void VideoBackendGetFrameSize(const struct VideoBackend*, unsigned* width, unsigned* height); +void VideoBackendRecenter(struct VideoBackend* v, unsigned scale); CXX_GUARD_END diff --git a/include/mgba/feature/video-logger.h b/include/mgba/feature/video-logger.h index cf50dd58e..373ea8069 100644 --- a/include/mgba/feature/video-logger.h +++ b/include/mgba/feature/video-logger.h @@ -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); diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h index ecd99e2f9..de26ef731 100644 --- a/include/mgba/gb/interface.h +++ b/include/mgba/gb/interface.h @@ -58,6 +58,13 @@ enum GBVideoLayer { GB_LAYER_OBJ }; +enum GBColorLookup { + GB_COLORS_NONE = 0, + GB_COLORS_CGB = 1, + GB_COLORS_SGB = 2, + GB_COLORS_SGB_CGB_FALLBACK = GB_COLORS_CGB | GB_COLORS_SGB +}; + struct GBSIODriver { struct GBSIO* p; @@ -67,6 +74,20 @@ struct GBSIODriver { uint8_t (*writeSC)(struct GBSIODriver* driver, uint8_t value); }; +struct GBCartridgeOverride { + int headerCrc32; + enum GBModel model; + enum GBMemoryBankControllerType mbc; + + uint32_t gbColors[12]; +}; + +struct GBColorPreset { + const char* name; + uint32_t colors[12]; +}; + +struct Configuration; struct VFile; bool GBIsROM(struct VFile* vf); @@ -78,6 +99,12 @@ const char* GBModelToName(enum GBModel); int GBValidModels(const uint8_t* bank0); +bool GBOverrideFind(const struct Configuration*, struct GBCartridgeOverride* override); +bool GBOverrideColorFind(struct GBCartridgeOverride* override, enum GBColorLookup); +void GBOverrideSave(struct Configuration*, const struct GBCartridgeOverride* override); + +size_t GBColorPresetList(const struct GBColorPreset** presets); + CXX_GUARD_END #endif diff --git a/include/mgba/gba/interface.h b/include/mgba/gba/interface.h index bf10c59ba..cbbb4d23a 100644 --- a/include/mgba/gba/interface.h +++ b/include/mgba/gba/interface.h @@ -13,18 +13,20 @@ CXX_GUARD_START #include #include +#define GBA_IDLE_LOOP_NONE 0xFFFFFFFF + enum { GBA_VIDEO_HORIZONTAL_PIXELS = 240, GBA_VIDEO_VERTICAL_PIXELS = 160, }; 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 { @@ -45,7 +47,31 @@ enum GBAVideoLayer { GBA_LAYER_OBJWIN, }; -struct GBA; +enum GBASavedataType { + GBA_SAVEDATA_AUTODETECT = -1, + GBA_SAVEDATA_FORCE_NONE = 0, + GBA_SAVEDATA_SRAM = 1, + GBA_SAVEDATA_FLASH512 = 2, + GBA_SAVEDATA_FLASH1M = 3, + GBA_SAVEDATA_EEPROM = 4, + GBA_SAVEDATA_EEPROM512 = 5, + GBA_SAVEDATA_SRAM512 = 6, +}; + +enum GBAHardwareDevice { + HW_NO_OVERRIDE = 0x8000, + HW_NONE = 0, + HW_RTC = 1, + HW_RUMBLE = 2, + HW_LIGHT_SENSOR = 4, + HW_GYRO = 8, + HW_TILT = 16, + HW_GB_PLAYER = 32, + HW_GB_PLAYER_DETECTION = 64, + HW_EREADER = 128 +}; + +struct Configuration; struct GBAAudio; struct GBASIO; struct GBAVideoRenderer; @@ -55,12 +81,16 @@ extern MGBA_EXPORT const int GBA_LUX_LEVELS[10]; enum { mPERIPH_GBA_LUMINANCE = 0x1000, - mPERIPH_GBA_BATTLECHIP_GATE, + mPERIPH_GBA_LINK_PORT, }; -bool GBAIsROM(struct VFile* vf); -bool GBAIsMB(struct VFile* vf); -bool GBAIsBIOS(struct VFile* vf); +struct GBACartridgeOverride { + char id[4]; + enum GBASavedataType savetype; + int hardware; + uint32_t idleLoop; + bool vbaBugCompat; +}; struct GBALuminanceSource { void (*sample)(struct GBALuminanceSource*); @@ -68,18 +98,34 @@ struct GBALuminanceSource { uint8_t (*readLuminance)(struct GBALuminanceSource*); }; +bool GBAIsROM(struct VFile* vf); +bool GBAIsMB(struct VFile* vf); +bool GBAIsBIOS(struct VFile* vf); + +bool GBAOverrideFind(const struct Configuration*, struct GBACartridgeOverride* override); +void GBAOverrideSave(struct Configuration*, const struct GBACartridgeOverride* override); + struct GBASIODriver { struct GBASIO* p; bool (*init)(struct GBASIODriver* driver); void (*deinit)(struct GBASIODriver* driver); - bool (*load)(struct GBASIODriver* driver); - bool (*unload)(struct GBASIODriver* driver); - uint16_t (*writeRegister)(struct GBASIODriver* driver, uint32_t address, uint16_t value); + void (*reset)(struct GBASIODriver* driver); + uint32_t (*driverId)(const struct GBASIODriver* renderer); + bool (*loadState)(struct GBASIODriver* renderer, const void* state, size_t size); + void (*saveState)(struct GBASIODriver* renderer, void** state, size_t* size); + void (*setMode)(struct GBASIODriver* driver, enum GBASIOMode mode); + bool (*handlesMode)(struct GBASIODriver* driver, enum GBASIOMode mode); + int (*connectedDevices)(struct GBASIODriver* driver); + int (*deviceId)(struct GBASIODriver* driver); + uint16_t (*writeSIOCNT)(struct GBASIODriver* driver, uint16_t value); + uint16_t (*writeRCNT)(struct GBASIODriver* driver, uint16_t value); + bool (*start)(struct GBASIODriver* driver); + void (*finishMultiplayer)(struct GBASIODriver* driver, uint16_t data[4]); + uint8_t (*finishNormal8)(struct GBASIODriver* driver); + uint32_t (*finishNormal32)(struct GBASIODriver* driver); }; -void GBASIOJOYCreate(struct GBASIODriver* sio); - enum GBASIOBattleChipGateFlavor { GBA_FLAVOR_BATTLECHIP_GATE = 4, GBA_FLAVOR_PROGRESS_GATE = 5, @@ -89,7 +135,6 @@ enum GBASIOBattleChipGateFlavor { struct GBASIOBattlechipGate { struct GBASIODriver d; - struct mTimingEvent event; uint16_t chipId; uint16_t data[2]; int state; @@ -98,10 +143,11 @@ struct GBASIOBattlechipGate { void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate*); +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); @@ -111,7 +157,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 diff --git a/include/mgba/internal/arm/arm.h b/include/mgba/internal/arm/arm.h index f9eeafdb6..5f25acf90 100644 --- a/include/mgba/internal/arm/arm.h +++ b/include/mgba/internal/arm/arm.h @@ -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; diff --git a/include/mgba/internal/arm/decoder.h b/include/mgba/internal/arm/decoder.h index c0efb22e8..f6e197698 100644 --- a/include/mgba/internal/arm/decoder.h +++ b/include/mgba/internal/arm/decoder.h @@ -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 diff --git a/include/mgba/internal/arm/emitter-arm.h b/include/mgba/internal/arm/emitter-arm.h index e99a1b7ee..bdea1db8a 100644 --- a/include/mgba/internal/arm/emitter-arm.h +++ b/include/mgba/internal/arm/emitter-arm.h @@ -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 diff --git a/src/feature/editline/cli-el-backend.h b/include/mgba/internal/debugger/cli-el-backend.h similarity index 100% rename from src/feature/editline/cli-el-backend.h rename to include/mgba/internal/debugger/cli-el-backend.h diff --git a/include/mgba/internal/defines.h b/include/mgba/internal/defines.h index 8af603736..67b8ec8fd 100644 --- a/include/mgba/internal/defines.h +++ b/include/mgba/internal/defines.h @@ -9,23 +9,23 @@ #define mSAVEDATA_CLEANUP_THRESHOLD 15 enum { - mSAVEDATA_DIRT_NONE = 0, + mSAVEDATA_DIRT_NONE = 0, mSAVEDATA_DIRT_NEW = 1, mSAVEDATA_DIRT_SEEN = 2, }; static inline bool mSavedataClean(int* dirty, uint32_t* dirtAge, uint32_t frameCount) { - if (*dirty & mSAVEDATA_DIRT_NEW) { - *dirtAge = frameCount; - *dirty &= ~mSAVEDATA_DIRT_NEW; - if (!(*dirty & mSAVEDATA_DIRT_SEEN)) { - *dirty |= mSAVEDATA_DIRT_SEEN; - } - } else if ((*dirty & mSAVEDATA_DIRT_SEEN) && frameCount - *dirtAge > mSAVEDATA_CLEANUP_THRESHOLD) { - *dirty = 0; - return true; - } - return false; + if (*dirty & mSAVEDATA_DIRT_NEW) { + *dirtAge = frameCount; + *dirty &= ~mSAVEDATA_DIRT_NEW; + if (!(*dirty & mSAVEDATA_DIRT_SEEN)) { + *dirty |= mSAVEDATA_DIRT_SEEN; + } + } else if ((*dirty & mSAVEDATA_DIRT_SEEN) && frameCount - *dirtAge > mSAVEDATA_CLEANUP_THRESHOLD) { + *dirty = 0; + return true; + } + return false; } #endif diff --git a/include/mgba/internal/gb/audio.h b/include/mgba/internal/gb/audio.h index 5b8993ac5..8b9b775c3 100644 --- a/include/mgba/internal/gb/audio.h +++ b/include/mgba/internal/gb/audio.h @@ -12,6 +12,7 @@ CXX_GUARD_START #include #include +#include #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; diff --git a/include/mgba/internal/gb/gb.h b/include/mgba/internal/gb/gb.h index 08068ec58..64579d3c1 100644 --- a/include/mgba/internal/gb/gb.h +++ b/include/mgba/internal/gb/gb.h @@ -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); diff --git a/include/mgba/internal/gb/memory.h b/include/mgba/internal/gb/memory.h index 052a9f77e..e4b34088b 100644 --- a/include/mgba/internal/gb/memory.h +++ b/include/mgba/internal/gb/memory.h @@ -339,6 +339,7 @@ struct GBMemory { struct mRTCSource* rtc; struct mRotationSource* rotation; struct mRumble* rumble; + int32_t lastRumble; struct mImageSource* cam; }; diff --git a/include/mgba/internal/gb/overrides.h b/include/mgba/internal/gb/overrides.h index 86cac0f9d..9d16ce65c 100644 --- a/include/mgba/internal/gb/overrides.h +++ b/include/mgba/internal/gb/overrides.h @@ -12,33 +12,6 @@ CXX_GUARD_START #include -enum GBColorLookup { - GB_COLORS_NONE = 0, - GB_COLORS_CGB = 1, - GB_COLORS_SGB = 2, - GB_COLORS_SGB_CGB_FALLBACK = GB_COLORS_CGB | GB_COLORS_SGB -}; - -struct GBCartridgeOverride { - int headerCrc32; - enum GBModel model; - enum GBMemoryBankControllerType mbc; - - uint32_t gbColors[12]; -}; - -struct GBColorPreset { - const char* name; - uint32_t colors[12]; -}; - -struct Configuration; -bool GBOverrideFind(const struct Configuration*, struct GBCartridgeOverride* override); -bool GBOverrideColorFind(struct GBCartridgeOverride* override, enum GBColorLookup); -void GBOverrideSave(struct Configuration*, const struct GBCartridgeOverride* override); - -size_t GBColorPresetList(const struct GBColorPreset** presets); - struct GB; void GBOverrideApply(struct GB*, const struct GBCartridgeOverride*); void GBOverrideApplyDefaults(struct GB*); diff --git a/include/mgba/internal/gb/renderers/proxy.h b/include/mgba/internal/gb/renderers/proxy.h index ca3b59f29..b7db8d00f 100644 --- a/include/mgba/internal/gb/renderers/proxy.h +++ b/include/mgba/internal/gb/renderers/proxy.h @@ -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); diff --git a/include/mgba/internal/gb/renderers/software.h b/include/mgba/internal/gb/renderers/software.h index c61f2270d..4ca4c1c1f 100644 --- a/include/mgba/internal/gb/renderers/software.h +++ b/include/mgba/internal/gb/renderers/software.h @@ -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; diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h index c9b179739..fc0f650ca 100644 --- a/include/mgba/internal/gb/video.h +++ b/include/mgba/internal/gb/video.h @@ -109,7 +109,7 @@ struct GBVideoRenderer { bool highlightBG; bool highlightOBJ[GB_VIDEO_MAX_OBJ]; bool highlightWIN; - color_t highlightColor; + mColor highlightColor; uint8_t highlightAmount; }; diff --git a/include/mgba/internal/gba/audio.h b/include/mgba/internal/gba/audio.h index 8b212dd6a..fba5090bf 100644 --- a/include/mgba/internal/gba/audio.h +++ b/include/mgba/internal/gba/audio.h @@ -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 diff --git a/include/mgba/internal/gba/cart/gpio.h b/include/mgba/internal/gba/cart/gpio.h index 86ddc941f..77785e612 100644 --- a/include/mgba/internal/gba/cart/gpio.h +++ b/include/mgba/internal/gba/cart/gpio.h @@ -18,19 +18,6 @@ mLOG_DECLARE_CATEGORY(GBA_HW); #define IS_GPIO_REGISTER(reg) ((reg) == GPIO_REG_DATA || (reg) == GPIO_REG_DIRECTION || (reg) == GPIO_REG_CONTROL) -enum GBAHardwareDevice { - HW_NO_OVERRIDE = 0x8000, - HW_NONE = 0, - HW_RTC = 1, - HW_RUMBLE = 2, - HW_LIGHT_SENSOR = 4, - HW_GYRO = 8, - HW_TILT = 16, - HW_GB_PLAYER = 32, - HW_GB_PLAYER_DETECTION = 64, - HW_EREADER = 128 -}; - enum GPIORegister { GPIO_REG_DATA = 0xC4, GPIO_REG_DIRECTION = 0xC6, diff --git a/include/mgba/internal/gba/cart/vfame.h b/include/mgba/internal/gba/cart/vfame.h index eff24a039..5bee28848 100644 --- a/include/mgba/internal/gba/cart/vfame.h +++ b/include/mgba/internal/gba/cart/vfame.h @@ -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); diff --git a/include/mgba/internal/gba/dma.h b/include/mgba/internal/gba/dma.h index 192b3995a..58d590948 100644 --- a/include/mgba/internal/gba/dma.h +++ b/include/mgba/internal/gba/dma.h @@ -48,6 +48,7 @@ struct GBADMA { uint32_t nextDest; int32_t nextCount; uint32_t when; + int32_t cycles; }; struct GBA; @@ -65,6 +66,7 @@ void GBADMARunHblank(struct GBA* gba, int32_t cycles); void GBADMARunVblank(struct GBA* gba, int32_t cycles); void GBADMARunDisplayStart(struct GBA* gba, int32_t cycles); void GBADMAUpdate(struct GBA* gba); +void GBADMARecalculateCycles(struct GBA* gba); CXX_GUARD_END diff --git a/include/mgba/internal/gba/extra/audio-mixer.h b/include/mgba/internal/gba/extra/audio-mixer.h deleted file mode 100644 index 369a4aaa3..000000000 --- a/include/mgba/internal/gba/extra/audio-mixer.h +++ /dev/null @@ -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 - -CXX_GUARD_START - -#include - -void GBAAudioMixerCreate(struct GBAAudioMixer* mixer); - -CXX_GUARD_END - -#endif diff --git a/include/mgba/internal/gba/gba.h b/include/mgba/internal/gba/gba.h index 020dd2ab5..ea9d69961 100644 --- a/include/mgba/internal/gba/gba.h +++ b/include/mgba/internal/gba/gba.h @@ -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); diff --git a/include/mgba/internal/gba/memory.h b/include/mgba/internal/gba/memory.h index f9e963d76..c88e1d092 100644 --- a/include/mgba/internal/gba/memory.h +++ b/include/mgba/internal/gba/memory.h @@ -138,8 +138,6 @@ struct GBAMemory { struct GBAPrintContext agbPrintCtxBackup; uint32_t agbPrintFuncBackup; uint16_t* agbPrintBufferBackup; - - bool mirroring; }; struct GBA; diff --git a/include/mgba/internal/gba/overrides.h b/include/mgba/internal/gba/overrides.h index c835a62a1..4bec8bf15 100644 --- a/include/mgba/internal/gba/overrides.h +++ b/include/mgba/internal/gba/overrides.h @@ -10,22 +10,7 @@ CXX_GUARD_START -#include - -#define IDLE_LOOP_NONE 0xFFFFFFFF - -struct GBACartridgeOverride { - char id[4]; - enum SavedataType savetype; - int hardware; - uint32_t idleLoop; - bool mirroring; - bool vbaBugCompat; -}; - -struct Configuration; -bool GBAOverrideFind(const struct Configuration*, struct GBACartridgeOverride* override); -void GBAOverrideSave(struct Configuration*, const struct GBACartridgeOverride* override); +#include struct GBA; void GBAOverrideApply(struct GBA*, const struct GBACartridgeOverride*); diff --git a/include/mgba/internal/gba/renderers/gl.h b/include/mgba/internal/gba/renderers/gl.h index 14cf11678..74baec41e 100644 --- a/include/mgba/internal/gba/renderers/gl.h +++ b/include/mgba/internal/gba/renderers/gl.h @@ -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, diff --git a/include/mgba/internal/gba/renderers/proxy.h b/include/mgba/internal/gba/renderers/proxy.h index c1044c77e..6cb58d092 100644 --- a/include/mgba/internal/gba/renderers/proxy.h +++ b/include/mgba/internal/gba/renderers/proxy.h @@ -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); diff --git a/include/mgba/internal/gba/renderers/video-software.h b/include/mgba/internal/gba/renderers/video-software.h index d9985f960..d9a012fa8 100644 --- a/include/mgba/internal/gba/renderers/video-software.h +++ b/include/mgba/internal/gba/renderers/video-software.h @@ -42,6 +42,8 @@ struct GBAVideoSoftwareBackground { uint16_t mapCache[64]; uint32_t flags; uint32_t objwinFlags; + int objwinForceEnable; + bool objwinOnly; bool variant; int32_t offsetX; int32_t offsetY; @@ -80,7 +82,7 @@ struct Window { struct GBAVideoSoftwareRenderer { struct GBAVideoRenderer d; - color_t* outputBuffer; + mColor* outputBuffer; int outputBufferStride; uint32_t* temporaryBuffer; @@ -98,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; @@ -116,6 +118,7 @@ struct GBAVideoSoftwareRenderer { struct WindowControl control; int16_t offsetX; int16_t offsetY; + bool on; } winN[2]; struct WindowControl winout; @@ -140,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; diff --git a/include/mgba/internal/gba/savedata.h b/include/mgba/internal/gba/savedata.h index 102c23041..274241a76 100644 --- a/include/mgba/internal/gba/savedata.h +++ b/include/mgba/internal/gba/savedata.h @@ -12,22 +12,12 @@ CXX_GUARD_START #include #include +#include mLOG_DECLARE_CATEGORY(GBA_SAVE); struct VFile; -enum SavedataType { - SAVEDATA_AUTODETECT = -1, - SAVEDATA_FORCE_NONE = 0, - SAVEDATA_SRAM = 1, - SAVEDATA_FLASH512 = 2, - SAVEDATA_FLASH1M = 3, - SAVEDATA_EEPROM = 4, - SAVEDATA_EEPROM512 = 5, - SAVEDATA_SRAM512 = 6, -}; - enum SavedataCommand { EEPROM_COMMAND_NULL = 0, EEPROM_COMMAND_PENDING = 1, @@ -68,7 +58,7 @@ enum { }; struct GBASavedata { - enum SavedataType type; + enum GBASavedataType type; uint8_t* data; enum SavedataCommand command; struct VFile* vf; @@ -108,7 +98,7 @@ void GBASavedataUnmask(struct GBASavedata* savedata); size_t GBASavedataSize(const struct GBASavedata* savedata); bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out); bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in); -void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type); +void GBASavedataForceType(struct GBASavedata* savedata, enum GBASavedataType type); void GBASavedataInitFlash(struct GBASavedata* savedata); void GBASavedataInitEEPROM(struct GBASavedata* savedata); diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 25bd170d6..8b1823a17 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -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 @@ -188,7 +191,7 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | bits 2 - 3: GB Player inputs posted * | bits 4 - 8: GB Player transmit position * | bits 9 - 23: Reserved - * 0x002C4 - 0x002C7: Game Boy Player next event + * 0x002C4 - 0x002C7: SIO next event * 0x002C8 - 0x002CB: Current DMA transfer word * 0x002CC - 0x002CF: Last DMA transfer PC * 0x002D0 - 0x002DF: Matrix memory command buffer @@ -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,12 @@ DECL_BIT(GBASerializedMiscFlags, IrqPending, 2); DECL_BIT(GBASerializedMiscFlags, Blocked, 3); DECL_BITS(GBASerializedMiscFlags, KeyIRQKeys, 4, 11); +enum { + GBA_SUBSYSTEM_VIDEO_RENDERER = 0, + GBA_SUBSYSTEM_SIO_DRIVER = 1, + GBA_SUBSYSTEM_MAX, +}; + struct GBASerializedState { uint32_t versionMagic; uint32_t biosChecksum; @@ -359,7 +371,7 @@ struct GBASerializedState { uint8_t lightSample; GBASerializedHWFlags2 flags2; GBASerializedHWFlags3 flags3; - uint32_t gbpNextEvent; + uint32_t sioNextEvent; } hw; uint32_t dmaTransferRegister; @@ -405,7 +417,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]; diff --git a/include/mgba/internal/gba/sio.h b/include/mgba/internal/gba/sio.h index 260772f55..14a2136b8 100644 --- a/include/mgba/internal/gba/sio.h +++ b/include/mgba/internal/gba/sio.h @@ -16,8 +16,6 @@ CXX_GUARD_START #define MAX_GBAS 4 -extern const int GBASIOCyclesPerTransfer[4][MAX_GBAS]; - mLOG_DECLARE_CATEGORY(GBA_SIO); enum { @@ -54,37 +52,45 @@ DECL_BITS(GBASIOMultiplayer, Id, 4, 2); DECL_BIT(GBASIOMultiplayer, Error, 6); DECL_BIT(GBASIOMultiplayer, Busy, 7); DECL_BIT(GBASIOMultiplayer, Irq, 14); - -struct GBASIODriverSet { - struct GBASIODriver* normal; - struct GBASIODriver* multiplayer; - struct GBASIODriver* joybus; -}; +DECL_BITFIELD(GBASIORegisterRCNT, uint16_t); +DECL_BIT(GBASIORegisterRCNT, Sc, 0); +DECL_BIT(GBASIORegisterRCNT, Sd, 1); +DECL_BIT(GBASIORegisterRCNT, Si, 2); +DECL_BIT(GBASIORegisterRCNT, So, 3); +DECL_BIT(GBASIORegisterRCNT, ScDirection, 4); +DECL_BIT(GBASIORegisterRCNT, SdDirection, 5); +DECL_BIT(GBASIORegisterRCNT, SiDirection, 6); +DECL_BIT(GBASIORegisterRCNT, SoDirection, 7); struct GBASIO { struct GBA* p; enum GBASIOMode mode; - struct GBASIODriverSet drivers; - struct GBASIODriver* activeDriver; + struct GBASIODriver* driver; uint16_t rcnt; uint16_t siocnt; struct GBASIOPlayer gbp; + struct mTimingEvent completeEvent; }; void GBASIOInit(struct GBASIO* sio); void GBASIODeinit(struct GBASIO* sio); void GBASIOReset(struct GBASIO* sio); -void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers); -void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode); +void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver); void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value); void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value); uint16_t GBASIOWriteRegister(struct GBASIO* sio, uint32_t address, uint16_t value); +int32_t GBASIOTransferCycles(enum GBASIOMode mode, uint16_t siocnt, int connected); + +void GBASIOMultiplayerFinishTransfer(struct GBASIO* sio, uint16_t data[4], uint32_t cyclesLate); +void GBASIONormal8FinishTransfer(struct GBASIO* sio, uint8_t data, uint32_t cyclesLate); +void GBASIONormal32FinishTransfer(struct GBASIO* sio, uint32_t data, uint32_t cyclesLate); + int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data); CXX_GUARD_END diff --git a/include/mgba/internal/gba/sio/gbp.h b/include/mgba/internal/gba/sio/gbp.h index 6713cdcaf..fe32cd8c1 100644 --- a/include/mgba/internal/gba/sio/gbp.h +++ b/include/mgba/internal/gba/sio/gbp.h @@ -21,7 +21,6 @@ struct GBASIOPlayer { struct GBA* p; unsigned inputsPosted; int txPosition; - struct mTimingEvent event; struct GBASIOPlayerKeyCallback callback; bool oldOpposingDirections; struct mKeyCallback* oldCallback; diff --git a/include/mgba/internal/gba/sio/lockstep.h b/include/mgba/internal/gba/sio/lockstep.h index 13c181039..0053e6b94 100644 --- a/include/mgba/internal/gba/sio/lockstep.h +++ b/include/mgba/internal/gba/sio/lockstep.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015 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 @@ -13,40 +13,82 @@ CXX_GUARD_START #include #include #include +#include +#include +#include -struct GBASIOLockstep { - struct mLockstep d; - struct GBASIOLockstepNode* players[MAX_GBAS]; - int attachedMulti; - int attachedNormal; +#define MAX_LOCKSTEP_EVENTS 8 - uint16_t multiRecv[MAX_GBAS]; - uint32_t normalRecv[MAX_GBAS]; +enum GBASIOLockstepEventType { + SIO_EV_ATTACH, + SIO_EV_DETACH, + SIO_EV_HARD_SYNC, + SIO_EV_MODE_SET, + SIO_EV_TRANSFER_START, }; -struct GBASIOLockstepNode { - struct GBASIODriver d; - struct GBASIOLockstep* p; - struct mTimingEvent event; +struct GBASIOLockstepCoordinator { + struct Table players; + Mutex mutex; - volatile int32_t nextEvent; - int32_t eventDiff; - bool normalSO; - int id; + unsigned nextId; + + unsigned attachedPlayers[MAX_GBAS]; + int nAttached; + uint32_t waiting; + + bool transferActive; + enum GBASIOMode transferMode; + + int32_t cycle; + int32_t nextHardSync; + + uint16_t multiData[4]; + uint32_t normalData[4]; +}; + +struct GBASIOLockstepEvent { + enum GBASIOLockstepEventType type; + int32_t timestamp; + struct GBASIOLockstepEvent* next; + int playerId; + union { + enum GBASIOMode mode; + int32_t finishCycle; + }; +}; + +struct GBASIOLockstepPlayer { + struct GBASIOLockstepDriver* driver; + int playerId; enum GBASIOMode mode; - bool transferFinished; -#ifndef NDEBUG - int transferId; - enum mLockstepPhase phase; -#endif + enum GBASIOMode otherModes[MAX_GBAS]; + bool asleep; + int32_t cycleOffset; + struct GBASIOLockstepEvent* queue; + bool dataReceived; + + struct GBASIOLockstepEvent buffer[MAX_LOCKSTEP_EVENTS]; + struct GBASIOLockstepEvent* freeList; }; -void GBASIOLockstepInit(struct GBASIOLockstep*); +struct GBASIOLockstepDriver { + struct GBASIODriver d; + struct GBASIOLockstepCoordinator* coordinator; + struct mTimingEvent event; + unsigned lockstepId; -void GBASIOLockstepNodeCreate(struct GBASIOLockstepNode*); + struct mLockstepUser* user; +}; -bool GBASIOLockstepAttachNode(struct GBASIOLockstep*, struct GBASIOLockstepNode*); -void GBASIOLockstepDetachNode(struct GBASIOLockstep*, struct GBASIOLockstepNode*); +void GBASIOLockstepCoordinatorInit(struct GBASIOLockstepCoordinator*); +void GBASIOLockstepCoordinatorDeinit(struct GBASIOLockstepCoordinator*); + +void GBASIOLockstepCoordinatorAttach(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepDriver*); +void GBASIOLockstepCoordinatorDetach(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepDriver*); +size_t GBASIOLockstepCoordinatorAttached(struct GBASIOLockstepCoordinator*); + +void GBASIOLockstepDriverCreate(struct GBASIOLockstepDriver*, struct mLockstepUser*); CXX_GUARD_END diff --git a/include/mgba/internal/gba/video.h b/include/mgba/internal/gba/video.h index 5b12d1541..5fc68eb59 100644 --- a/include/mgba/internal/gba/video.h +++ b/include/mgba/internal/gba/video.h @@ -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; diff --git a/include/mgba/script.h b/include/mgba/script.h index 747dfedc1..44ec86b3c 100644 --- a/include/mgba/script.h +++ b/include/mgba/script.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include diff --git a/include/mgba/script/console.h b/include/mgba/script/console.h new file mode 100644 index 000000000..8e7a64345 --- /dev/null +++ b/include/mgba/script/console.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 + +CXX_GUARD_START + +#include +#include +#include + +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 diff --git a/include/mgba/script/context.h b/include/mgba/script/context.h index 25628d785..ef740fb45 100644 --- a/include/mgba/script/context.h +++ b/include/mgba/script/context.h @@ -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*); diff --git a/include/mgba/script/macros.h b/include/mgba/script/macros.h index 4acf7591a..70eed0af5 100644 --- a/include/mgba/script/macros.h +++ b/include/mgba/script/macros.h @@ -254,7 +254,7 @@ CXX_GUARD_START return false; \ } -#define _mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, S, NRET, RETURN, NPARAMS, DEFAULTS, ...) \ +#define _mSCRIPT_DECLARE_STRUCT_METHOD_HEAD(TYPE, NAME) \ static bool _mSTStructBinding_ ## TYPE ## _ ## NAME(struct mScriptFrame* frame, void* ctx); \ static const struct mScriptFunction _mSTStructBindingFunction_ ## TYPE ## _ ## NAME = { \ .call = &_mSTStructBinding_ ## TYPE ## _ ## NAME \ @@ -269,6 +269,9 @@ CXX_GUARD_START .alloc = _mSTStructBindingAlloc_ ## TYPE ## _ ## NAME, \ .details = { \ .function = { \ + +#define _mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, S, NRET, RETURN, NPARAMS, DEFAULTS, ...) \ + _mSCRIPT_DECLARE_STRUCT_METHOD_HEAD(TYPE, NAME) \ .parameters = { \ .count = _mSUCC_ ## NPARAMS, \ .entries = { mSCRIPT_TYPE_MS_ ## S(TYPE), _mCALL(mSCRIPT_PREFIX_ ## NPARAMS, mSCRIPT_TYPE_MS_, _mEVEN_ ## NPARAMS(__VA_ARGS__)) }, \ @@ -283,6 +286,23 @@ CXX_GUARD_START } \ }; +#define _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, S, NRET, RETURN) \ + _mSCRIPT_DECLARE_STRUCT_METHOD_HEAD(TYPE, NAME) \ + .parameters = { \ + .count = 1, \ + .entries = { mSCRIPT_TYPE_MS_ ## S(TYPE) }, \ + .names = { "this" }, \ + .defaults = NULL, \ + .variable = true, \ + }, \ + .returnType = { \ + .count = NRET, \ + .entries = { RETURN } \ + }, \ + }, \ + } \ + }; + #define _mSCRIPT_DECLARE_STRUCT_METHOD_SIGNATURE(TYPE, RETURN, NAME, CONST, NPARAMS, ...) \ typedef RETURN (*_mSTStructFunctionType_ ## TYPE ## _ ## NAME)(_mCOMMA_ ## NPARAMS(CONST struct TYPE* , mSCRIPT_PREFIX_ ## NPARAMS(mSCRIPT_TYPE_C_, __VA_ARGS__))) @@ -302,6 +322,20 @@ CXX_GUARD_START return true; \ } \ +#define _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, T) \ + 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); \ + if (!overload) { \ + return false; \ + } \ + if (!mScriptCoerceFrame(&overload->type->details.function.parameters, &frame->arguments, &frame->arguments)) { \ + return false; \ + } \ + return overload->function->call(frame, overload->function->context); \ + } + #define mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, RETURN, NAME, FUNCTION, NPARAMS, ...) \ _mSCRIPT_DECLARE_STRUCT_METHOD_SIGNATURE(TYPE, mSCRIPT_TYPE_C_ ## RETURN, NAME, , NPARAMS, _mEVEN_ ## NPARAMS(__VA_ARGS__)); \ _mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, S, 1, mSCRIPT_TYPE_MS_ ## RETURN, NPARAMS, NULL, __VA_ARGS__) \ @@ -346,6 +380,22 @@ CXX_GUARD_START _mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, NAME, CS, 0, 0, NPARAMS, _mIDENT(_mSTStructBindingDefaults_ ## TYPE ## _ ## NAME, __VA_ARGS__) \ _mSCRIPT_DECLARE_STRUCT_VOID_METHOD_BINDING(TYPE, NAME, FUNCTION, CS, NPARAMS, __VA_ARGS__) +#define mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, RETURN, NAME) \ + _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, S, 1, mSCRIPT_TYPE_MS_ ## RETURN) \ + _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, S) + +#define mSCRIPT_DECLARE_STRUCT_OVERLOADED_VOID_METHOD(TYPE, NAME) \ + _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, S, 0, 0) \ + _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, S) + +#define mSCRIPT_DECLARE_STRUCT_OVERLOADED_C_METHOD(TYPE, RETURN, NAME) \ + _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, CS, 1, mSCRIPT_TYPE_MS_ ## RETURN) \ + _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, CS) + +#define mSCRIPT_DECLARE_STRUCT_OVERLOADED_VOID_C_METHOD(TYPE, NAME) \ + _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD(TYPE, NAME, CS, 0, 0) \ + _mSCRIPT_DECLARE_STRUCT_OVERLOADED_METHOD_BINDING(TYPE, NAME, CS) + #define mSCRIPT_DECLARE_STRUCT_D_METHOD(TYPE, RETURN, NAME, NPARAMS, ...) \ mSCRIPT_DECLARE_STRUCT_METHOD(TYPE, RETURN, NAME, p0->NAME, NPARAMS, __VA_ARGS__) @@ -417,27 +467,39 @@ CXX_GUARD_START #define mSCRIPT_DEFINE_DEFAULTS_END } -#define _mSCRIPT_DEFINE_STRUCT_BINDING(INIT_TYPE, TYPE, EXPORTED_NAME, NAME) { \ +#define mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOADS(STRUCT, METHOD) \ + static const struct mScriptFunctionOverload _mSTStructBindingOverloads_ ## STRUCT ## _ ## METHOD[mSCRIPT_OVERLOADS_MAX] = { \ + +#define mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(TYPE, FUNCTION) { \ + .type = &_mSTStructBindingType_ ## TYPE ## _ ## FUNCTION, \ + .function = &_mSTStructBindingFunction_ ## TYPE ## _ ## FUNCTION \ +}, + +#define mSCRIPT_DEFINE_OVERLOADS_END { NULL, NULL } } + +#define _mSCRIPT_DEFINE_STRUCT_BINDING(INIT_TYPE, TYPE, EXPORTED_NAME, NAME, OVERLOADS) { \ .type = mSCRIPT_CLASS_INIT_ ## INIT_TYPE, \ .info = { \ .member = { \ .name = #EXPORTED_NAME, \ - .type = &_mSTStructBindingType_ ## TYPE ## _ ## NAME \ + .type = &_mSTStructBindingType_ ## TYPE ## _ ## NAME, \ + .overloads = OVERLOADS, \ } \ }, \ }, #define mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(TYPE, EXPORTED_NAME, NAME) \ - _mSCRIPT_DEFINE_STRUCT_BINDING(INSTANCE_MEMBER, TYPE, EXPORTED_NAME, NAME) + _mSCRIPT_DEFINE_STRUCT_BINDING(INSTANCE_MEMBER, TYPE, EXPORTED_NAME, NAME, NULL) #define mSCRIPT_DEFINE_STRUCT_METHOD(TYPE, NAME) mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(TYPE, NAME, NAME) +#define mSCRIPT_DEFINE_STRUCT_OVERLOADED_METHOD(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(INSTANCE_MEMBER, TYPE, NAME, NAME, _mSTStructBindingOverloads_ ## TYPE ## _ ## NAME) -#define mSCRIPT_DEFINE_STRUCT_INIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(INIT, TYPE, _init, _init) -#define mSCRIPT_DEFINE_STRUCT_INIT_NAMED(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(INIT, TYPE, _init, NAME) -#define mSCRIPT_DEFINE_STRUCT_DEINIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(DEINIT, TYPE, _deinit, _deinit) -#define mSCRIPT_DEFINE_STRUCT_DEINIT_NAMED(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(DEINIT, TYPE, _deinit, NAME) -#define mSCRIPT_DEFINE_STRUCT_DEFAULT_GET(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(GET, TYPE, _get, _get) -#define mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(TYPE, SETTER) _mSCRIPT_DEFINE_STRUCT_BINDING(SET, TYPE, SETTER, SETTER) +#define mSCRIPT_DEFINE_STRUCT_INIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(INIT, TYPE, _init, _init, NULL) +#define mSCRIPT_DEFINE_STRUCT_INIT_NAMED(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(INIT, TYPE, _init, NAME, NULL) +#define mSCRIPT_DEFINE_STRUCT_DEINIT(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(DEINIT, TYPE, _deinit, _deinit, NULL) +#define mSCRIPT_DEFINE_STRUCT_DEINIT_NAMED(TYPE, NAME) _mSCRIPT_DEFINE_STRUCT_BINDING(DEINIT, TYPE, _deinit, NAME, NULL) +#define mSCRIPT_DEFINE_STRUCT_DEFAULT_GET(TYPE) _mSCRIPT_DEFINE_STRUCT_BINDING(GET, TYPE, _get, _get, NULL) +#define mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(TYPE, SETTER) _mSCRIPT_DEFINE_STRUCT_BINDING(SET, TYPE, SETTER, SETTER, NULL) #define mSCRIPT_DEFINE_DOC_STRUCT_METHOD(SCOPE, TYPE, NAME) mSCRIPT_DEFINE_STRUCT_METHOD_NAMED(doc_ ## TYPE, NAME, NAME) diff --git a/include/mgba/script/types.h b/include/mgba/script/types.h index 1475f1a6e..5b07abe3b 100644 --- a/include/mgba/script/types.h +++ b/include/mgba/script/types.h @@ -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) @@ -259,6 +260,7 @@ struct mScriptClassMember { const char* name; const char* docstring; const struct mScriptType* type; + const struct mScriptFunctionOverload* overloads; size_t offset; bool readonly; }; @@ -275,6 +277,7 @@ struct mScriptClassInitDetails { const struct mScriptType* parent; struct mScriptClassMember member; struct mScriptClassCastMember castMember; + const struct mScriptFunctionOverload* overload; } info; }; @@ -332,6 +335,11 @@ struct mScriptFunction { void* context; }; +struct mScriptFunctionOverload { + const struct mScriptType* type; + const struct mScriptFunction* function; +}; + struct mScriptValue* mScriptValueAlloc(const struct mScriptType* type); void mScriptValueRef(struct mScriptValue* val); void mScriptValueDeref(struct mScriptValue* val); @@ -385,7 +393,8 @@ bool mScriptPopBool(struct mScriptList* list, bool* out); bool mScriptPopPointer(struct mScriptList* list, void** out); bool mScriptCast(const struct mScriptType* type, const struct mScriptValue* input, struct mScriptValue* output); -bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, struct mScriptList* frame); +bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, const struct mScriptList* input, struct mScriptList* output); +const struct mScriptFunctionOverload* mScriptFunctionFindOverload(const struct mScriptFunctionOverload* overloads, struct mScriptList* frame); CXX_GUARD_END diff --git a/res/entitlements.plist b/res/entitlements.plist new file mode 100644 index 000000000..33cd79505 --- /dev/null +++ b/res/entitlements.plist @@ -0,0 +1,7 @@ + + + + com.apple.security.device.camera + + + diff --git a/res/font-mask.png b/res/font-mask.png new file mode 100644 index 000000000..2e223597b Binary files /dev/null and b/res/font-mask.png differ diff --git a/res/font-sdf.png b/res/font-sdf.png new file mode 100644 index 000000000..95960e26c Binary files /dev/null and b/res/font-sdf.png differ diff --git a/res/licenses/blip_buf.txt b/res/licenses/blip_buf.txt deleted file mode 100644 index 5faba9d48..000000000 --- a/res/licenses/blip_buf.txt +++ /dev/null @@ -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. - - - Copyright (C) - - 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. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/res/mgba-qt.desktop b/res/mgba-qt.desktop index d5d98ab37..2dc96901c 100644 --- a/res/mgba-qt.desktop +++ b/res/mgba-qt.desktop @@ -10,3 +10,4 @@ Comment=Nintendo Game Boy Advance Emulator Categories=Game;Emulator; MimeType=application/x-gameboy-advance-rom;application/x-agb-rom;application/x-gba-rom; Keywords=emulator;Nintendo;advance;gba;Game Boy Advance; +StartupWMClass=mGBA diff --git a/res/nointro.dat b/res/nointro.dat index cb73775b6..48047026f 100644 --- a/res/nointro.dat +++ b/res/nointro.dat @@ -1,8 +1,8 @@ clrmamepro ( name "Nintendo - Game Boy Advance" description "Nintendo - Game Boy Advance" - version 20230422-084331 - author "aci68, Arctic Circle System, Aringon, Bent, BigFred, bikerspade, C. V. Reynolds, chillerecke, DeadSkullzJr, Densetsu, DeriLoko3, einstein95, ElBarto, Enker, Flashfire42, fuzzball, Gefflon, Hiccup, hking0036, hydr0x, InternalLoss, Jack, jimmsu, kazumi213, Larsenv, Lesserkuma, Madeline, MeguCocoa, Money_114, NESBrew12, niemand, nnssxx, norkmetnoil577, NovaAurora, omonim2007, Powerpuff, PPLToast, rarenight, relax, RetroGamer, Rifu, sCZther, SonGoku, Tauwasser, Tescu, togemet2, ufocrossing, Vallaine01, Whovian9369, xprism, xuom2, zg" + version 20240807-214821 + author "aci68, Arctic Circle System, Aringon, Bent, BigFred, bikerspade, C. V. Reynolds, chillerecke, DeadSkullzJr, Densetsu, DeriLoko3, einstein95, ElBarto, Enker, FakeShemp, Flashfire42, fuzzball, Gefflon, Hiccup, hking0036, hydr0x, InternalLoss, Jack, jimmsu, Just001Kim, kazumi213, Larsenv, Lesserkuma, Madeline, MeguCocoa, Money_114, NESBrew12, niemand, nnssxx, norkmetnoil577, NovaAurora, omonim2007, Powerpuff, PPLToast, Prominos, Psychofox11, psykopat, rarenight, relax, RetroGamer, Rifu, sCZther, SonGoku, Tauwasser, Tescu, togemet2, ufocrossing, Vallaine01, Whovian9369, xprism, xuom2, zg" homepage No-Intro url "https://www.no-intro.org" forcenodump required @@ -19,9 +19,9 @@ game ( ) game ( - name "[BIOS] Game Boy Advance (Japan) (Debug Version)" - description "[BIOS] Game Boy Advance (Japan) (Debug Version)" - rom ( name "[BIOS] Game Boy Advance (Japan) (Debug Version).bin" size 16384 crc 15e1f676 sha1 aa98a2ad32b86106340665d1222d7d973a1361c7 ) + name "[BIOS] Game Boy Advance (World) (Beta)" + description "[BIOS] Game Boy Advance (World) (Beta)" + rom ( name "[BIOS] Game Boy Advance (World) (Beta).bin" size 16384 crc 15e1f676 sha1 aa98a2ad32b86106340665d1222d7d973a1361c7 ) ) game ( @@ -30,6 +30,12 @@ game ( rom ( name "[BIOS] Game Boy Advance (World).bin" size 16384 crc 81977335 sha1 300c20df6731a33952ded8c436f7f186d25d3492 flags verified ) ) +game ( + name "[BIOS] Game Boy Advance (GBC Mode) (World)" + description "[BIOS] Game Boy Advance (GBC Mode) (World)" + rom ( name "[BIOS] Game Boy Advance (GBC Mode) (World).gbc" size 2304 crc ffd6b0f1 sha1 fa5287e24b0fa533b3b5ef2b28a81245346c1a0f ) +) + game ( name "007 - Everything or Nothing (USA, Europe) (En,Fr,De)" description "007 - Everything or Nothing (USA, Europe) (En,Fr,De)" @@ -423,7 +429,7 @@ game ( game ( name "2 Games in 1 - Sonic Battle + Sonic Pinball Party (Europe) (En,Ja,Fr,De,Es,It)" description "2 Games in 1 - Sonic Battle + Sonic Pinball Party (Europe) (En,Ja,Fr,De,Es,It)" - rom ( name "2 Games in 1 - Sonic Battle + Sonic Pinball Party (Europe) (En,Ja,Fr,De,Es,It).gba" size 33554432 crc a50de233 sha1 df086e816109a18d0f037e8c0aa7a2ae40677c14 ) + rom ( name "2 Games in 1 - Sonic Battle + Sonic Pinball Party (Europe) (En,Ja,Fr,De,Es,It).gba" size 33554432 crc a50de233 sha1 df086e816109a18d0f037e8c0aa7a2ae40677c14 flags verified ) ) game ( @@ -483,7 +489,7 @@ game ( game ( name "2 Games in 1 - The SpongeBob SquarePants Movie + SpongeBob SquarePants and Friends in Freeze Frame Frenzy (Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,Nl)" description "2 Games in 1 - The SpongeBob SquarePants Movie + SpongeBob SquarePants and Friends in Freeze Frame Frenzy (Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,Nl)" - rom ( name "2 Games in 1 - The SpongeBob SquarePants Movie + SpongeBob SquarePants and Friends in Freeze Frame Frenzy (Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,Nl).gba" size 16777216 crc a04cebfe sha1 0286e31772601f7c7420722e8fbf8a210d562a06 ) + rom ( name "2 Games in 1 - The SpongeBob SquarePants Movie + SpongeBob SquarePants and Friends in Freeze Frame Frenzy (Europe) (En,Fr,De,Es,It,Nl+En,Fr,De,Es,Nl).gba" size 16777216 crc a04cebfe sha1 0286e31772601f7c7420722e8fbf8a210d562a06 flags verified ) ) game ( @@ -561,7 +567,7 @@ game ( game ( name "2 in 1 - V-Rally 3 + Stuntman (Europe) (En,Fr,De,Es,It)" description "2 in 1 - V-Rally 3 + Stuntman (Europe) (En,Fr,De,Es,It)" - rom ( name "2 in 1 - V-Rally 3 + Stuntman (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 5813810f sha1 f116cc8e6a7f6dba49564031a2ac63d837d4f11b ) + rom ( name "2 in 1 - V-Rally 3 + Stuntman (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 5813810f sha1 f116cc8e6a7f6dba49564031a2ac63d837d4f11b flags verified ) ) game ( @@ -585,13 +591,13 @@ game ( game ( name "2 in 1 Game Pack - Spider-Man & Spider-Man 2 (Europe) (En,Fr,De+En,Fr,De,Es,It)" description "2 in 1 Game Pack - Spider-Man & Spider-Man 2 (Europe) (En,Fr,De+En,Fr,De,Es,It)" - rom ( name "2 in 1 Game Pack - Spider-Man & Spider-Man 2 (Europe) (En,Fr,De+En,Fr,De,Es,It).gba" size 33554432 crc d732e52d sha1 5bf33c1f0fd50f268ed5941d3246cfad1893ef89 ) + rom ( name "2 in 1 Game Pack - Spider-Man & Spider-Man 2 (Europe) (En,Fr,De+En,Fr,De,Es,It).gba" size 33554432 crc e76db6ef sha1 287071f81572a95cf3a3b35fab93862733864c3e ) ) game ( name "2 in 1 Game Pack - Spider-Man + Spider-Man 2 (USA) (En,Fr,De+En,Fr,De,Es)" description "2 in 1 Game Pack - Spider-Man + Spider-Man 2 (USA) (En,Fr,De+En,Fr,De,Es)" - rom ( name "2 in 1 Game Pack - Spider-Man + Spider-Man 2 (USA) (En,Fr,De+En,Fr,De,Es).gba" size 33554432 crc 0ae3637f sha1 8bc2b600a043b776bc61fe8c0f4007b4360545f9 ) + rom ( name "2 in 1 Game Pack - Spider-Man + Spider-Man 2 (USA) (En,Fr,De+En,Fr,De,Es).gba" size 33554432 crc 3abc30bd sha1 1438db8336bd6204ad81011a7ed2b2e04850326a ) ) game ( @@ -630,24 +636,30 @@ game ( rom ( name "2-in-1 Fun Pack - Shrek 2 + Madagascar - Operation Penguin (Europe).gba" size 16777216 crc 3535b2bf sha1 be51cfa607d461efd1dab640a5b4f5b037c060df ) ) +game ( + name "2004Mbit Competition (World) (Unl)" + description "2004Mbit Competition (World) (Unl)" + rom ( name "2004Mbit Competition (World) (Unl).gba" size 4194304 crc 107de6b7 sha1 0cf3dec1b8ff2372e4fbe339c0b338d590b39256 ) +) + game ( name "2006 FIFA World Cup - Germany 2006 (USA, Europe) (En,Fr,De,Es,It)" description "2006 FIFA World Cup - Germany 2006 (USA, Europe) (En,Fr,De,Es,It)" rom ( name "2006 FIFA World Cup - Germany 2006 (USA, Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 50ab4544 sha1 295580745787ba9593799213564484aaaa7fd463 flags verified ) ) -game ( - name "2K Sports - Major League Baseball 2K7 (USA)" - description "2K Sports - Major League Baseball 2K7 (USA)" - rom ( name "2K Sports - Major League Baseball 2K7 (USA).gba" size 8388608 crc 8f3ff0e4 sha1 07390bc2bd53cd9ee5c6d2805ad374c59c195d9f ) -) - game ( name "2K Sports - Major League Baseball 2K7 (USA) (Beta)" description "2K Sports - Major League Baseball 2K7 (USA) (Beta)" rom ( name "2K Sports - Major League Baseball 2K7 (USA) (Beta).gba" size 8388608 crc ea51532d sha1 776e084ac31336114f23230bde4adfc1f231934b ) ) +game ( + name "2K Sports - Major League Baseball 2K7 (USA)" + description "2K Sports - Major League Baseball 2K7 (USA)" + rom ( name "2K Sports - Major League Baseball 2K7 (USA).gba" size 8388608 crc 8f3ff0e4 sha1 07390bc2bd53cd9ee5c6d2805ad374c59c195d9f ) +) + game ( name "3 Game Pack! - Candy Land + Chutes and Ladders + Original Memory Game (USA)" description "3 Game Pack! - Candy Land + Chutes and Ladders + Original Memory Game (USA)" @@ -693,7 +705,7 @@ game ( game ( name "3 Games in One! - Breakout + Centipede + Warlords (USA)" description "3 Games in One! - Breakout + Centipede + Warlords (USA)" - rom ( name "3 Games in One! - Breakout + Centipede + Warlords (USA).gba" size 4194304 crc 02e0cca4 sha1 e91e58c62363fb10dd4ffcaeb09c98ca6b9b5a77 ) + rom ( name "3 Games in One! - Breakout + Centipede + Warlords (USA).gba" size 4194304 crc 02e0cca4 sha1 e91e58c62363fb10dd4ffcaeb09c98ca6b9b5a77 flags verified ) ) game ( @@ -741,7 +753,7 @@ game ( game ( name "4 Games on One Game Pak (Racing) (USA) (En,Fr,De,Es,It)" description "4 Games on One Game Pak (Racing) (USA) (En,Fr,De,Es,It)" - rom ( name "4 Games on One Game Pak (Racing) (USA) (En,Fr,De,Es,It).gba" size 33554432 crc 04a40017 sha1 a99bbc7ec018af85260669917939004baabf4ac1 ) + rom ( name "4 Games on One Game Pak (Racing) (USA) (En,Fr,De,Es,It).gba" size 33554432 crc 04a40017 sha1 a99bbc7ec018af85260669917939004baabf4ac1 flags verified ) ) game ( @@ -756,18 +768,18 @@ game ( rom ( name "Ab durch die Hecke (Germany).gba" size 8388608 crc 31e57a19 sha1 05fc0931ecbdfaed18ffd59df86fa36a7ed6da9d ) ) -game ( - name "Ace Combat Advance (Europe) (En,Fr,De,Es,It) (Beta)" - description "Ace Combat Advance (Europe) (En,Fr,De,Es,It) (Beta)" - rom ( name "Ace Combat Advance (Europe) (En,Fr,De,Es,It) (Beta).gba" size 4194304 crc 76da5c78 sha1 6e5c57049866596db0e977b80e499b868e0394c2 ) -) - game ( name "Ace Combat Advance (USA, Europe)" description "Ace Combat Advance (USA, Europe)" rom ( name "Ace Combat Advance (USA, Europe).gba" size 4194304 crc 43f5e157 sha1 856a08e8f60f817b96add5bf2f6db186bea832ef flags verified ) ) +game ( + name "Ace Combat Advance (Europe) (En,Fr,De,Es,It) (Beta)" + description "Ace Combat Advance (Europe) (En,Fr,De,Es,It) (Beta)" + rom ( name "Ace Combat Advance (Europe) (En,Fr,De,Es,It) (Beta).gba" size 4194304 crc 76da5c78 sha1 6e5c57049866596db0e977b80e499b868e0394c2 ) +) + game ( name "Ace Lightning (Europe)" description "Ace Lightning (Europe)" @@ -975,13 +987,13 @@ game ( game ( name "Adventures of Jimmy Neutron Boy Genius, The - Attack of the Twonkies (USA, Europe)" description "Adventures of Jimmy Neutron Boy Genius, The - Attack of the Twonkies (USA, Europe)" - rom ( name "Adventures of Jimmy Neutron Boy Genius, The - Attack of the Twonkies (USA, Europe).gba" size 4194304 crc d59d753b sha1 16ba112f07d02484febd554f902bb18776144186 ) + rom ( name "Adventures of Jimmy Neutron Boy Genius, The - Attack of the Twonkies (USA, Europe).gba" size 4194304 crc d59d753b sha1 16ba112f07d02484febd554f902bb18776144186 flags verified ) ) game ( name "Adventures of Jimmy Neutron Boy Genius, The - Jet Fusion (USA, Europe)" description "Adventures of Jimmy Neutron Boy Genius, The - Jet Fusion (USA, Europe)" - rom ( name "Adventures of Jimmy Neutron Boy Genius, The - Jet Fusion (USA, Europe).gba" size 4194304 crc 67756000 sha1 68778c93fc16d06b97462174d91035cb0d0d8bd5 ) + rom ( name "Adventures of Jimmy Neutron Boy Genius, The - Jet Fusion (USA, Europe).gba" size 4194304 crc 67756000 sha1 68778c93fc16d06b97462174d91035cb0d0d8bd5 flags verified ) ) game ( @@ -997,9 +1009,15 @@ game ( ) game ( - name "Aero the Acro-Bat - Rascal Rival Revenge (Europe)" - description "Aero the Acro-Bat - Rascal Rival Revenge (Europe)" - rom ( name "Aero the Acro-Bat - Rascal Rival Revenge (Europe).gba" size 4194304 crc a7e98ebe sha1 11050975c211550a8bea751212ceb8856daea759 flags verified ) + name "Aero the Acro-Bat (Europe)" + description "Aero the Acro-Bat (Europe)" + rom ( name "Aero the Acro-Bat (Europe).gba" size 4194304 crc a7e98ebe sha1 11050975c211550a8bea751212ceb8856daea759 flags verified ) +) + +game ( + name "Aero the Acro-Bat (USA)" + description "Aero the Acro-Bat (USA)" + rom ( name "Aero the Acro-Bat (USA).gba" size 4194304 crc b47ac020 sha1 cdbc609df128127d05c435f59b781958c0e751fd ) ) game ( @@ -1008,12 +1026,6 @@ game ( rom ( name "Aero the Acro-Bat - Rascal Rival Revenge (USA) (Beta 2) (2002-03-27).gba" size 4194304 crc 6f3ea564 sha1 3f88084c501fb15820f6ad9a9c87ac21af3b59eb ) ) -game ( - name "Aero the Acro-Bat - Rascal Rival Revenge (USA)" - description "Aero the Acro-Bat - Rascal Rival Revenge (USA)" - rom ( name "Aero the Acro-Bat - Rascal Rival Revenge (USA).gba" size 4194304 crc b47ac020 sha1 cdbc609df128127d05c435f59b781958c0e751fd ) -) - game ( name "Agassi Tennis Generation (Europe) (En,Fr,De,Es,It)" description "Agassi Tennis Generation (Europe) (En,Fr,De,Es,It)" @@ -1029,7 +1041,7 @@ game ( game ( name "AGB Aging Cartridge (World) (v1.0) (Test Program)" description "AGB Aging Cartridge (World) (v1.0) (Test Program)" - rom ( name "AGB Aging Cartridge (World) (v1.0) (Test Program).gba" size 2097152 crc bf553530 sha1 2445bf11a5f905695b00011d77d18c99e754b633 ) + rom ( name "AGB Aging Cartridge (World) (v1.0) (Test Program).gba" size 4194304 crc d2e80e33 sha1 30b3ea4b0c2611a7d8aaf1cacbe8c3b79eb2ab78 ) ) game ( @@ -1057,9 +1069,9 @@ game ( ) game ( - name "AGS Aging Cartridge (World) (Rev 1, v7.0) (Test Program)" - description "AGS Aging Cartridge (World) (Rev 1, v7.0) (Test Program)" - rom ( name "AGS Aging Cartridge (World) (Rev 1, v7.0) (Test Program).gba" size 2097152 crc bbb6a960 sha1 c67e0a5e26ea5eba2bc11c99d003027a96e44060 flags verified ) + name "Agoria - Ode to Fate (World) (Unl)" + description "Agoria - Ode to Fate (World) (Unl)" + rom ( name "Agoria - Ode to Fate (World) (Unl).gba" size 2725504 crc 67d3361f sha1 cb0b83b85a290c223cd3249b37ae7207d3efde06 ) ) game ( @@ -1075,9 +1087,15 @@ game ( ) game ( - name "AGS Aging Cartridge (World) (Rev 3, v9.0) (Test Program)" - description "AGS Aging Cartridge (World) (Rev 3, v9.0) (Test Program)" - rom ( name "AGS Aging Cartridge (World) (Rev 3, v9.0) (Test Program).gba" size 2097152 crc 2e69686d sha1 03d3a486482b61128872519fd755d0c072c12d93 flags verified ) + name "AGS Aging Cartridge (World) (Rev 3) (v9.0) (Test Program)" + description "AGS Aging Cartridge (World) (Rev 3) (v9.0) (Test Program)" + rom ( name "AGS Aging Cartridge (World) (Rev 3) (v9.0) (Test Program).gba" size 4194304 crc 584bbdc7 sha1 4a21b60c23014750250e56a8a22b886032f0d33d ) +) + +game ( + name "AGS Aging Cartridge (World) (Rev 1) (v7.0) (Test Program)" + description "AGS Aging Cartridge (World) (Rev 1) (v7.0) (Test Program)" + rom ( name "AGS Aging Cartridge (World) (Rev 1) (v7.0) (Test Program).gba" size 4194304 crc e16e1360 sha1 5c73fb4074b19c5a1a9bb60fd359b528d2ed99a6 ) ) game ( @@ -1086,6 +1104,12 @@ game ( rom ( name "Aigle de Guerre, L' (France).gba" size 8388608 crc 36a0e152 sha1 567809bf35d62418a69e469d0cfa9993a889c030 ) ) +game ( + name "Airball (World) (v1.3) (Unl)" + description "Airball (World) (v1.3) (Unl)" + rom ( name "Airball (World) (v1.3) (Unl).gba" size 1365740 crc 52dac8c6 sha1 50c772f91fa431b8b3d01133762015e127d4f816 ) +) + game ( name "AirForce Delta II (Japan) (En,Ja,Fr,De)" description "AirForce Delta II (Japan) (En,Ja,Fr,De)" @@ -1098,18 +1122,18 @@ game ( rom ( name "AirForce Delta Storm (USA) (En,Ja,Fr,De).gba" size 4194304 crc ebf757b8 sha1 7bc53480a43ada2aad32d798ab00b6e761726728 flags verified ) ) -game ( - name "Aka-chan Doubutsuen (Japan) (Rev 1)" - description "Aka-chan Doubutsuen (Japan) (Rev 1)" - rom ( name "Aka-chan Doubutsuen (Japan) (Rev 1).gba" size 4194304 crc c1072e26 sha1 634624c77c90a8ff40bec9046133c50041efc49b ) -) - game ( name "Aka-chan Doubutsuen (Japan)" description "Aka-chan Doubutsuen (Japan)" rom ( name "Aka-chan Doubutsuen (Japan).gba" size 4194304 crc b50cd166 sha1 9a0623a8680c4cf9b745f940b99da0a192764828 ) ) +game ( + name "Aka-chan Doubutsuen (Japan) (Rev 1)" + description "Aka-chan Doubutsuen (Japan) (Rev 1)" + rom ( name "Aka-chan Doubutsuen (Japan) (Rev 1).gba" size 4194304 crc c1072e26 sha1 634624c77c90a8ff40bec9046133c50041efc49b ) +) + game ( name "Akumajou Dracula - Circle of the Moon (Japan) (Virtual Console)" description "Akumajou Dracula - Circle of the Moon (Japan) (Virtual Console)" @@ -1161,7 +1185,7 @@ game ( game ( name "Alex Rider - Stormbreaker (USA)" description "Alex Rider - Stormbreaker (USA)" - rom ( name "Alex Rider - Stormbreaker (USA).gba" size 4194304 crc cca55dfd sha1 e9ba9d340701173ccd3a4d279630e1541ed96a73 ) + rom ( name "Alex Rider - Stormbreaker (USA).gba" size 4194304 crc cca55dfd sha1 e9ba9d340701173ccd3a4d279630e1541ed96a73 flags verified ) ) game ( @@ -1245,7 +1269,7 @@ game ( game ( name "American Idol (USA)" description "American Idol (USA)" - rom ( name "American Idol (USA).gba" size 16777216 crc f053ffbf sha1 13236689db1e2236673ae59c2a8ff84340a8a8c2 ) + rom ( name "American Idol (USA).gba" size 16777216 crc f053ffbf sha1 13236689db1e2236673ae59c2a8ff84340a8a8c2 flags verified ) ) game ( @@ -1278,72 +1302,6 @@ game ( rom ( name "Angelique (Japan).gba" size 4194304 crc c9d41f35 sha1 cf01dfc9f25c805b9a72524903f742f11570a8eb ) ) -game ( - name "Anguna - Warriors of Virtue (World) (v0.95) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (World) (v0.95) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (World) (v0.95) (Aftermarket) (Unl).gba" size 1710888 crc 3346891f sha1 270c426705df767a4ad2dc69d039842442f779b2 flags verified ) -) - -game ( - name "Anguna - Warriors of Virtue (World) (2021-02-28) (Patreon) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (World) (2021-02-28) (Patreon) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (World) (2021-02-28) (Patreon) (Aftermarket) (Unl).gba" size 1729120 crc a354d555 sha1 d7cd0ab9d622187d4ce55bf0c7f14a24ee781710 ) -) - -game ( - name "Anguna - Warriors of Virtue (World) (v0.95) (Itch.io) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (World) (v0.95) (Itch.io) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (World) (v0.95) (Itch.io) (Aftermarket) (Unl).gba" size 1775856 crc 41ea5b0b sha1 e351bc6a9046ec002fc2dfdee061047908bd4350 ) -) - -game ( - name "Anguna - Warriors of Virtue (Unknown) (Retro-Bit Generations) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (Unknown) (Retro-Bit Generations) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (Unknown) (Retro-Bit Generations) (Aftermarket) (Unl).gba" size 1775660 crc a234813c sha1 ad904624bf198a164ba580eea326cd30fffebac8 ) -) - -game ( - name "Anguna - Warriors of Virtue (World) (Demo) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (World) (Demo) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (World) (Demo) (Aftermarket) (Unl).gba" size 597104 crc 0a9098b4 sha1 0992fb6f38e49426adc834fb3831748a1caa1bc0 ) -) - -game ( - name "Anguna - Warriors of Virtue (World) (v2.0) (Demo) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (World) (v2.0) (Demo) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (World) (v2.0) (Demo) (Aftermarket) (Unl).gba" size 811840 crc 63c1cc2c sha1 faca8225ee20b8e5edb14e005af77b63c6f51446 ) -) - -game ( - name "Anguna - Warriors of Virtue (World) (v0.91) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (World) (v0.91) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (World) (v0.91) (Aftermarket) (Unl).gba" size 1714000 crc eebb016f sha1 008a9d06f78bccc540ca4ece4d1982de76f95901 ) -) - -game ( - name "Anguna - Warriors of Virtue (World) (v0.92) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (World) (v0.92) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (World) (v0.92) (Aftermarket) (Unl).gba" size 1710624 crc ba271987 sha1 04f1e79e79e894d8f45ed1ea2ff5aa67053f0ab3 ) -) - -game ( - name "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl).gba" size 1710624 crc df7108e3 sha1 bd267fd7e762acb8cd595e54bfd51a139864759e ) -) - -game ( - name "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl) (Alt)" - description "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl) (Alt)" - rom ( name "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl) (Alt).gba" size 1714000 crc 54ff2e56 sha1 0386315fc140db2a43a6f927c04de658bd800da9 ) -) - -game ( - name "Anguna - Warriors of Virtue (World) (v0.94) (Aftermarket) (Unl)" - description "Anguna - Warriors of Virtue (World) (v0.94) (Aftermarket) (Unl)" - rom ( name "Anguna - Warriors of Virtue (World) (v0.94) (Aftermarket) (Unl).gba" size 1710952 crc cb4e2768 sha1 a7297cf4ecffc1f93f86edde68e1ff42e8099f3b ) -) - game ( name "Animal Mania - Dokidoki Aishou Check (Japan)" description "Animal Mania - Dokidoki Aishou Check (Japan)" @@ -1381,15 +1339,15 @@ game ( ) game ( - name "Another World (Europe) (En,Fr) (v2.1) (Unl)" - description "Another World (Europe) (En,Fr) (v2.1) (Unl)" - rom ( name "Another World (Europe) (En,Fr) (v2.1) (Unl).gba" size 2010358 crc 86c4f772 sha1 41d39a0c34f72469dd3fbcc90190605b8ada93e6 ) + name "Another World (World) (En,Fr) (v2.1) (Unl)" + description "Another World (World) (En,Fr) (v2.1) (Unl)" + rom ( name "Another World (World) (En,Fr) (v2.1) (Unl).gba" size 2010358 crc 86c4f772 sha1 41d39a0c34f72469dd3fbcc90190605b8ada93e6 ) ) game ( - name "Another World (Europe) (Fr) (v1.2) (Unl)" - description "Another World (Europe) (Fr) (v1.2) (Unl)" - rom ( name "Another World (Europe) (Fr) (v1.2) (Unl).gba" size 1823864 crc 1a1397de sha1 5bcc5c9a633e2226411dd41f1a191b9fcc793d92 ) + name "Another World (World) (Fr) (v1.2) (Unl)" + description "Another World (World) (Fr) (v1.2) (Unl)" + rom ( name "Another World (World) (Fr) (v1.2) (Unl).gba" size 1823864 crc 1a1397de sha1 5bcc5c9a633e2226411dd41f1a191b9fcc793d92 ) ) game ( @@ -1404,40 +1362,34 @@ game ( rom ( name "Ant Bully, The (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 52dc386b sha1 a735364887c31a19fa7d250ec830d02220d6a6cd ) ) -game ( - name "Antz - Extreme Racing (USA)" - description "Antz - Extreme Racing (USA)" - rom ( name "Antz - Extreme Racing (USA).gba" size 4194304 crc f4efc5ed sha1 ad6ded0f643457d652292bb97e30b1ad442e41da ) -) - game ( name "Antz - Extreme Racing (Europe) (En,Fr,De,Es,It,Nl)" description "Antz - Extreme Racing (Europe) (En,Fr,De,Es,It,Nl)" rom ( name "Antz - Extreme Racing (Europe) (En,Fr,De,Es,It,Nl).gba" size 4194304 crc 367927ed sha1 68fca49cba74dc108f50ec762ab91b6dff5a92b8 ) ) +game ( + name "Antz - Extreme Racing (USA)" + description "Antz - Extreme Racing (USA)" + rom ( name "Antz - Extreme Racing (USA).gba" size 4194304 crc f4efc5ed sha1 ad6ded0f643457d652292bb97e30b1ad442e41da ) +) + game ( name "Ao-Zora to Nakama-tachi - Yume no Bouken (Japan)" description "Ao-Zora to Nakama-tachi - Yume no Bouken (Japan)" rom ( name "Ao-Zora to Nakama-tachi - Yume no Bouken (Japan).gba" size 4194304 crc ad9af125 sha1 0e6c92477793ce495caa400899effb4f87384f3c ) ) -game ( - name "Apotris (World) (v3.4.5) (Aftermarket) (Unl)" - description "Apotris (World) (v3.4.5) (Aftermarket) (Unl)" - rom ( name "Apotris (World) (v3.4.5) (Aftermarket) (Unl).gba" size 4194304 crc 55ae4312 sha1 fb7142bcc30f71f187cc51b7fcbc5a3958374c6c ) -) - game ( name "Archer Maclean's 3D Pool (USA)" description "Archer Maclean's 3D Pool (USA)" - rom ( name "Archer Maclean's 3D Pool (USA).gba" size 4194304 crc 4202a9cd sha1 5b1dcab6984d454e3ed3f3fe107f43a645283c0f ) + rom ( name "Archer Maclean's 3D Pool (USA).gba" size 4194304 crc 4202a9cd sha1 5b1dcab6984d454e3ed3f3fe107f43a645283c0f flags verified ) ) game ( name "Arctic Tale (USA)" description "Arctic Tale (USA)" - rom ( name "Arctic Tale (USA).gba" size 4194304 crc 81397ac0 sha1 9654a5c6a40b946c35cc9e09aae48bdd47ea7692 ) + rom ( name "Arctic Tale (USA).gba" size 4194304 crc 81397ac0 sha1 9654a5c6a40b946c35cc9e09aae48bdd47ea7692 flags verified ) ) game ( @@ -1521,7 +1473,7 @@ game ( game ( name "Astro Boy - Omega Factor (Europe) (En,Ja,Fr,De,Es,It)" description "Astro Boy - Omega Factor (Europe) (En,Ja,Fr,De,Es,It)" - rom ( name "Astro Boy - Omega Factor (Europe) (En,Ja,Fr,De,Es,It).gba" size 8388608 crc 1e2e8937 sha1 9a4fc3533bbdb28fd5945bd1ee7d84d992eee12f ) + rom ( name "Astro Boy - Omega Factor (Europe) (En,Ja,Fr,De,Es,It).gba" size 8388608 crc 1e2e8937 sha1 9a4fc3533bbdb28fd5945bd1ee7d84d992eee12f flags verified ) ) game ( @@ -1554,6 +1506,12 @@ game ( rom ( name "Atlantis - The Lost Empire (Europe) (En,Fr,De,Es,It,Nl).gba" size 4194304 crc b3948dbc sha1 93624eaa9a80cdb791bd14955b55dd7c58c4abbd ) ) +game ( + name "Atomic Betty (USA, Europe) (Beta)" + description "Atomic Betty (USA, Europe) (Beta)" + rom ( name "Atomic Betty (USA, Europe) (Beta).gba" size 8388608 crc b79472b8 sha1 1dfa6ad1bdc0ee52b4e53c78f29d92ec208db1b1 ) +) + game ( name "Atomic Betty (USA, Europe)" description "Atomic Betty (USA, Europe)" @@ -1561,9 +1519,9 @@ game ( ) game ( - name "Atomic Betty (USA, Europe) (Beta)" - description "Atomic Betty (USA, Europe) (Beta)" - rom ( name "Atomic Betty (USA, Europe) (Beta).gba" size 8388608 crc b79472b8 sha1 1dfa6ad1bdc0ee52b4e53c78f29d92ec208db1b1 ) + name "Atomix (World) (Unl)" + description "Atomix (World) (Unl)" + rom ( name "Atomix (World) (Unl).gba" size 934600 crc fc610889 sha1 ecf3848324a25fa57988f67167f0b58e648989ce ) ) game ( @@ -1623,7 +1581,7 @@ game ( game ( name "Azumanga Daiou Advance (Japan)" description "Azumanga Daiou Advance (Japan)" - rom ( name "Azumanga Daiou Advance (Japan).gba" size 8388608 crc 216704f6 sha1 95b266e8ecdae1938cd180f597e5f21cb86d8b96 ) + rom ( name "Azumanga Daiou Advance (Japan).gba" size 8388608 crc 216704f6 sha1 95b266e8ecdae1938cd180f597e5f21cb86d8b96 flags verified ) ) game ( @@ -1713,7 +1671,7 @@ game ( game ( name "Backyard Football 2006 (USA)" description "Backyard Football 2006 (USA)" - rom ( name "Backyard Football 2006 (USA).gba" size 4194304 crc db0723e3 sha1 53d134268d2fc973388861687e50f77cc4682941 ) + rom ( name "Backyard Football 2006 (USA).gba" size 4194304 crc db0723e3 sha1 53d134268d2fc973388861687e50f77cc4682941 flags verified ) ) game ( @@ -1803,7 +1761,7 @@ game ( game ( name "Banjo-Kazooie - Grunty's Revenge (Europe) (En,Fr,De)" description "Banjo-Kazooie - Grunty's Revenge (Europe) (En,Fr,De)" - rom ( name "Banjo-Kazooie - Grunty's Revenge (Europe) (En,Fr,De).gba" size 8388608 crc fb4f38e2 sha1 f335fede72cd0273fcce925a20ca272ede08c15b ) + rom ( name "Banjo-Kazooie - Grunty's Revenge (Europe) (En,Fr,De).gba" size 8388608 crc fb4f38e2 sha1 f335fede72cd0273fcce925a20ca272ede08c15b flags verified ) ) game ( @@ -1866,6 +1824,30 @@ game ( rom ( name "Barbie - The Princess and the Pauper (Europe) (En,Fr,De,Es,It,Nl).gba" size 4194304 crc 116194f2 sha1 779f2050efcd15cac8b70fedce5bd0ccb773f179 ) ) +game ( + name "Barbie and the Magic of Pegasus (USA) (Beta) (2005-01-21)" + description "Barbie and the Magic of Pegasus (USA) (Beta) (2005-01-21)" + rom ( name "Barbie and the Magic of Pegasus (USA) (Beta) (2005-01-21).gba" size 136680 crc ae6cf631 sha1 fb0548d72eff99b7dabdd34112e55f8bea6326ec ) +) + +game ( + name "Barbie and the Magic of Pegasus (USA) (Beta) (2005-02-18)" + description "Barbie and the Magic of Pegasus (USA) (Beta) (2005-02-18)" + rom ( name "Barbie and the Magic of Pegasus (USA) (Beta) (2005-02-18).gba" size 360672 crc bd807770 sha1 84a5686f5c5dee770e6b1bbbc1a60648387cf255 ) +) + +game ( + name "Barbie and the Magic of Pegasus (USA) (Beta) (2005-03-18)" + description "Barbie and the Magic of Pegasus (USA) (Beta) (2005-03-18)" + rom ( name "Barbie and the Magic of Pegasus (USA) (Beta) (2005-03-18).gba" size 1502628 crc 4b58b5d6 sha1 e822173e315138443e9fec509621dc88afcbcc0b ) +) + +game ( + name "Barbie and the Magic of Pegasus (USA) (Beta) (2005-04-15)" + description "Barbie and the Magic of Pegasus (USA) (Beta) (2005-04-15)" + rom ( name "Barbie and the Magic of Pegasus (USA) (Beta) (2005-04-15).gba" size 2837392 crc 46f21e41 sha1 74e261c56123806b8cbd31ed907fe25a5ad99b62 ) +) + game ( name "Barbie and the Magic of Pegasus (USA)" description "Barbie and the Magic of Pegasus (USA)" @@ -1929,7 +1911,7 @@ game ( game ( name "Barbie Software - Groovy Games (Europe) (En,Fr,De,Es,It)" description "Barbie Software - Groovy Games (Europe) (En,Fr,De,Es,It)" - rom ( name "Barbie Software - Groovy Games (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 749339b2 sha1 e41751c52d5cd84b204ac4d73eefc5b360f56f1d ) + rom ( name "Barbie Software - Groovy Games (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 749339b2 sha1 e41751c52d5cd84b204ac4d73eefc5b360f56f1d flags verified ) ) game ( @@ -2022,6 +2004,18 @@ game ( rom ( name "Battle Network - Rockman EXE 2 (Japan).gba" size 8388608 crc 98e4f096 sha1 6ed31ea56328673ba9d87186a7d506c701508e28 ) ) +game ( + name "Battle Network - Rockman EXE 2 (Japan) (Rev 1) (Virtual Console)" + description "Battle Network - Rockman EXE 2 (Japan) (Rev 1) (Virtual Console)" + rom ( name "Battle Network - Rockman EXE 2 (Japan) (Rev 1) (Virtual Console).gba" size 8388608 crc 44d44721 sha1 1c2416dfb86936752c5f68861f6339feac21458f ) +) + +game ( + name "Battle Network - Rockman EXE 2 (World) (Ja) (Mega Man Battle Network Legacy Collection)" + description "Battle Network - Rockman EXE 2 (World) (Ja) (Mega Man Battle Network Legacy Collection)" + rom ( name "Battle Network - Rockman EXE 2 (World) (Ja) (Mega Man Battle Network Legacy Collection).gba" size 8388608 crc 046eed8d sha1 7f6e770282718813f1115b29ec502f77422ac300 ) +) + game ( name "Battle Network - Rockman EXE 2 (Japan) (Rev 1)" description "Battle Network - Rockman EXE 2 (Japan) (Rev 1)" @@ -2029,9 +2023,9 @@ game ( ) game ( - name "Battle Network - Rockman EXE 2 (Japan) (Rev 1) (Virtual Console)" - description "Battle Network - Rockman EXE 2 (Japan) (Rev 1) (Virtual Console)" - rom ( name "Battle Network - Rockman EXE 2 (Japan) (Rev 1) (Virtual Console).gba" size 8388608 crc 44d44721 sha1 1c2416dfb86936752c5f68861f6339feac21458f ) + name "Battle Network - Rockman EXE 3 (Japan) (Rev 1)" + description "Battle Network - Rockman EXE 3 (Japan) (Rev 1)" + rom ( name "Battle Network - Rockman EXE 3 (Japan) (Rev 1).gba" size 8388608 crc e48e6bc9 sha1 87e0ab10541eaaa5e9c01f7fad822a3e1bf52278 ) ) game ( @@ -2047,15 +2041,9 @@ game ( ) game ( - name "Battle Network - Rockman EXE 3 (Japan) (Rev 1)" - description "Battle Network - Rockman EXE 3 (Japan) (Rev 1)" - rom ( name "Battle Network - Rockman EXE 3 (Japan) (Rev 1).gba" size 8388608 crc e48e6bc9 sha1 87e0ab10541eaaa5e9c01f7fad822a3e1bf52278 ) -) - -game ( - name "Battle Network - Rockman EXE 3 - Black (Japan) (Promo)" - description "Battle Network - Rockman EXE 3 - Black (Japan) (Promo)" - rom ( name "Battle Network - Rockman EXE 3 - Black (Japan) (Promo).gba" size 8388608 crc 1f13c41f sha1 ff65af8fea15ecf5a556595efe414d1211a9ab4e ) + name "Battle Network - Rockman EXE 3 - Black (Japan) (Rev 1)" + description "Battle Network - Rockman EXE 3 - Black (Japan) (Rev 1)" + rom ( name "Battle Network - Rockman EXE 3 - Black (Japan) (Rev 1).gba" size 8388608 crc fd57493b sha1 e089a2254496a4791666c8122585cb785e3012fc ) ) game ( @@ -2065,9 +2053,15 @@ game ( ) game ( - name "Battle Network - Rockman EXE 3 - Black (Japan) (Rev 1)" - description "Battle Network - Rockman EXE 3 - Black (Japan) (Rev 1)" - rom ( name "Battle Network - Rockman EXE 3 - Black (Japan) (Rev 1).gba" size 8388608 crc fd57493b sha1 e089a2254496a4791666c8122585cb785e3012fc ) + name "Battle Network - Rockman EXE 3 - Black (Japan) (Promo)" + description "Battle Network - Rockman EXE 3 - Black (Japan) (Promo)" + rom ( name "Battle Network - Rockman EXE 3 - Black (Japan) (Promo).gba" size 8388608 crc 1f13c41f sha1 ff65af8fea15ecf5a556595efe414d1211a9ab4e ) +) + +game ( + name "Battle Picross (World) (Unl)" + description "Battle Picross (World) (Unl)" + rom ( name "Battle Picross (World) (Unl).gba" size 194784 crc 7f36d6f0 sha1 7431f36c68bba7ad42301b395e1237445f059a9e ) ) game ( @@ -2091,7 +2085,7 @@ game ( game ( name "BattleBots - Design & Destroy (USA)" description "BattleBots - Design & Destroy (USA)" - rom ( name "BattleBots - Design & Destroy (USA).gba" size 4194304 crc 8d5ffbca sha1 635986e584ebdc347c77eb45b1370a1206fbd7d7 ) + rom ( name "BattleBots - Design & Destroy (USA).gba" size 4194304 crc 8d5ffbca sha1 635986e584ebdc347c77eb45b1370a1206fbd7d7 flags verified ) ) game ( @@ -2118,6 +2112,12 @@ game ( rom ( name "Bee Game, The (USA).gba" size 4194304 crc da747c99 sha1 3a073625e7d0f844b940d0d8a71216cdce335a47 ) ) +game ( + name "Bengt Swinger of Longarm (World) (Unl)" + description "Bengt Swinger of Longarm (World) (Unl)" + rom ( name "Bengt Swinger of Longarm (World) (Unl).gba" size 434844 crc e514de30 sha1 5ce8574548fe0ebd587eddf974f837b44a2d3c6c ) +) + game ( name "Berenstain Bears and the Spooky Old Tree, The (USA)" description "Berenstain Bears and the Spooky Old Tree, The (USA)" @@ -2157,7 +2157,7 @@ game ( game ( name "Beyblade V-Force - Ultimate Blader Jam (USA)" description "Beyblade V-Force - Ultimate Blader Jam (USA)" - rom ( name "Beyblade V-Force - Ultimate Blader Jam (USA).gba" size 8388608 crc 4a49272b sha1 cd527c8c24e20e33913fc45199e64b3e6138a6e5 ) + rom ( name "Beyblade V-Force - Ultimate Blader Jam (USA).gba" size 8388608 crc 4a49272b sha1 cd527c8c24e20e33913fc45199e64b3e6138a6e5 flags verified ) ) game ( @@ -2316,6 +2316,12 @@ game ( rom ( name "Black Matrix Zero (Japan).gba" size 8388608 crc 2b2afa2e sha1 697f85513ab5704b8b1d554e087a45bfdb92ec33 ) ) +game ( + name "Black Sigil - Blade of the Exiled (USA) (Proto) (2007-02-10)" + description "Black Sigil - Blade of the Exiled (USA) (Proto) (2007-02-10)" + rom ( name "Black Sigil - Blade of the Exiled (USA) (Proto) (2007-02-10).gba" size 12478504 crc 010035a8 sha1 567e4efa496eabbf1db285e0ec02a8da8a8c07a3 ) +) + game ( name "Blackthorne (USA)" description "Blackthorne (USA)" @@ -2340,12 +2346,6 @@ game ( rom ( name "Bleach Advance - Kurenai ni Somaru Soul Society (Japan).gba" size 33554432 crc 9de5cd08 sha1 29d24c38d3ec8bbe9d81df2f5ff61c4a2dadcee4 ) ) -game ( - name "Blender Bros. (World) (Aftermarket) (Unl)" - description "Blender Bros. (World) (Aftermarket) (Unl)" - rom ( name "Blender Bros. (World) (Aftermarket) (Unl).gba" size 8388608 crc 440f2f06 sha1 8f9ca62306b7ab56d8da45673d7b7d0eb4c349c5 ) -) - game ( name "Blender Bros. (USA)" description "Blender Bros. (USA)" @@ -2379,7 +2379,7 @@ game ( game ( name "Board Game Classics - Backgammon & Chess & Draughts (Europe) (En,Fr,De,Es,It)" description "Board Game Classics - Backgammon & Chess & Draughts (Europe) (En,Fr,De,Es,It)" - rom ( name "Board Game Classics - Backgammon & Chess & Draughts (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc e5c745d8 sha1 f9a3058e55d72efdebc5e2b4d2b5d6e00e71e5ff ) + rom ( name "Board Game Classics - Backgammon & Chess & Draughts (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc e5c745d8 sha1 f9a3058e55d72efdebc5e2b4d2b5d6e00e71e5ff flags verified ) ) game ( @@ -2406,6 +2406,12 @@ game ( rom ( name "Boboboubo Boubobo - Ougi 87.5 Bakuretsu Hanage Shinken (Japan).gba" size 8388608 crc 58105f89 sha1 c93fd22bb10e26cb986161ce1cdc4c2acb38add9 ) ) +game ( + name "Boktai - The Sun Is in Your Hand (USA) (Sample)" + description "Possibly a version given out to press at E3 or an E3 demo" + rom ( name "Boktai - The Sun Is in Your Hand (USA) (Sample).gba" size 16777216 crc cf692572 sha1 f91126cd3a1bf7bf5f770d3a70229171d0d5a6ee ) +) + game ( name "Boktai - The Sun Is in Your Hand (USA)" description "Boktai - The Sun Is in Your Hand (USA)" @@ -2418,12 +2424,6 @@ game ( rom ( name "Boktai - The Sun Is in Your Hand (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc 9686c36b sha1 64f7bf0f0560f6e94da33b549d3206678b29f557 flags verified ) ) -game ( - name "Boktai - The Sun Is in Your Hand (USA) (Sample)" - description "Possibly a version given out to press at E3 or an E3 demo" - rom ( name "Boktai - The Sun Is in Your Hand (USA) (Sample).gba" size 16777216 crc cf692572 sha1 f91126cd3a1bf7bf5f770d3a70229171d0d5a6ee ) -) - game ( name "Boktai 2 - Solar Boy Django (USA)" description "Boktai 2 - Solar Boy Django (USA)" @@ -2505,7 +2505,7 @@ game ( game ( name "Bomberman Max 2 - Red Advance (Europe) (En,Fr,De)" description "Bomberman Max 2 - Red Advance (Europe) (En,Fr,De)" - rom ( name "Bomberman Max 2 - Red Advance (Europe) (En,Fr,De).gba" size 16777216 crc 67d2e5b8 sha1 4d514fe19b59d42be9a118c99e2008efee2aedcb ) + rom ( name "Bomberman Max 2 - Red Advance (Europe) (En,Fr,De).gba" size 16777216 crc 67d2e5b8 sha1 4d514fe19b59d42be9a118c99e2008efee2aedcb flags verified ) ) game ( @@ -2517,7 +2517,7 @@ game ( game ( name "Bomberman Tournament (USA, Europe)" description "Bomberman Tournament (USA, Europe)" - rom ( name "Bomberman Tournament (USA, Europe).gba" size 4194304 crc 240282e6 sha1 da44a5d65f1a00d75a57e5b46e30f9e4e2d18f6c ) + rom ( name "Bomberman Tournament (USA, Europe).gba" size 4194304 crc 240282e6 sha1 da44a5d65f1a00d75a57e5b46e30f9e4e2d18f6c flags verified ) ) game ( @@ -2575,9 +2575,9 @@ game ( ) game ( - name "Bounty Hunter X (Europe) (Unl)" - description "Bounty Hunter X (Europe) (Unl)" - rom ( name "Bounty Hunter X (Europe) (Unl).gba" size 304344 crc 91344285 sha1 6e39d034ccf318a17a8bd044dd58bc31f4ba2ab9 ) + name "Bounty Hunter X (World) (Unl)" + description "Bounty Hunter X (World) (Unl)" + rom ( name "Bounty Hunter X (World) (Unl).gba" size 304344 crc 91344285 sha1 6e39d034ccf318a17a8bd044dd58bc31f4ba2ab9 flags verified ) ) game ( @@ -2655,7 +2655,7 @@ game ( game ( name "Bratz - The Movie (USA)" description "Bratz - The Movie (USA)" - rom ( name "Bratz - The Movie (USA).gba" size 4194304 crc 2ef801c0 sha1 bfab6a139275b6968531a43ab34d4710e9efc7ef ) + rom ( name "Bratz - The Movie (USA).gba" size 4194304 crc 2ef801c0 sha1 bfab6a139275b6968531a43ab34d4710e9efc7ef flags verified ) ) game ( @@ -2685,7 +2685,7 @@ game ( game ( name "Breath of Fire (USA)" description "Breath of Fire (USA)" - rom ( name "Breath of Fire (USA).gba" size 4194304 crc f06422a8 sha1 b30533f68037b47d5439bab0182169e4a643a38d ) + rom ( name "Breath of Fire (USA).gba" size 4194304 crc f06422a8 sha1 b30533f68037b47d5439bab0182169e4a643a38d flags verified ) ) game ( @@ -2745,13 +2745,7 @@ game ( game ( name "Broken Circle (Europe) (En,It) (Proto)" description "Broken Circle (Europe) (En,It) (Proto)" - rom ( name "Broken Circle (Europe) (En,It) (Proto).gba" size 8388608 crc 1e8f8ae0 sha1 fec9fda1c776ac9bb87a609d0be1effe7ea158b6 ) -) - -game ( - name "Broken Circle (World) (En,It) (Aftermarket) (Unl)" - description "Broken Circle (World) (En,It) (Aftermarket) (Unl)" - rom ( name "Broken Circle (World) (En,It) (Aftermarket) (Unl).gba" size 16777216 crc 3212c09b sha1 e04a71dbe7b640cc53e81f447856e60666e64aa3 ) + rom ( name "Broken Circle (Europe) (En,It) (Proto).gba" size 8409344 crc e78bc690 sha1 d015a5039ff5d08eeba3ddb16470eaab259631d0 ) ) game ( @@ -2769,13 +2763,13 @@ game ( game ( name "Brother Bear (USA)" description "Brother Bear (USA)" - rom ( name "Brother Bear (USA).gba" size 8388608 crc 342de1d6 sha1 89e6903500f62e11483402b76c1454af788646c0 ) + rom ( name "Brother Bear (USA).gba" size 8388608 crc 342de1d6 sha1 89e6903500f62e11483402b76c1454af788646c0 flags verified ) ) game ( name "Brother Bear (Europe) (Fr,De,Es,It,Nl,Sv,Da)" description "Brother Bear (Europe) (Fr,De,Es,It,Nl,Sv,Da)" - rom ( name "Brother Bear (Europe) (Fr,De,Es,It,Nl,Sv,Da).gba" size 8388608 crc fd814097 sha1 7e217e5f644b0333c51f3827df5fd64023ac7c0e ) + rom ( name "Brother Bear (Europe) (Fr,De,Es,It,Nl,Sv,Da).gba" size 8388608 crc fd814097 sha1 7e217e5f644b0333c51f3827df5fd64023ac7c0e flags verified ) ) game ( @@ -2841,7 +2835,7 @@ game ( game ( name "Butt-Ugly Martians - B.K.M. Battles (USA)" description "Butt-Ugly Martians - B.K.M. Battles (USA)" - rom ( name "Butt-Ugly Martians - B.K.M. Battles (USA).gba" size 4194304 crc 74be9148 sha1 24962220f242b49231969f6d313e325148886106 ) + rom ( name "Butt-Ugly Martians - B.K.M. Battles (USA).gba" size 4194304 crc 74be9148 sha1 24962220f242b49231969f6d313e325148886106 flags verified ) ) game ( @@ -2865,7 +2859,7 @@ game ( game ( name "Cabela's Big Game Hunter (USA)" description "Cabela's Big Game Hunter (USA)" - rom ( name "Cabela's Big Game Hunter (USA).gba" size 8388608 crc 70a8a141 sha1 f6590b9f069856c1a9e43d19b4b05e3175a97e02 ) + rom ( name "Cabela's Big Game Hunter (USA).gba" size 8388608 crc 70a8a141 sha1 f6590b9f069856c1a9e43d19b4b05e3175a97e02 flags verified ) ) game ( @@ -2931,7 +2925,7 @@ game ( game ( name "Card e-Reader+ (Japan)" description "Card e-Reader+ (Japan)" - rom ( name "Card e-Reader+ (Japan).gba" size 8388608 crc 4139e7c3 sha1 2af41785dd72c664e8a1c0f1e1ce0edcd105dd5e ) + rom ( name "Card e-Reader+ (Japan).gba" size 8388608 crc 4139e7c3 sha1 2af41785dd72c664e8a1c0f1e1ce0edcd105dd5e flags verified ) ) game ( @@ -3042,12 +3036,6 @@ game ( rom ( name "Cartoon Network Speedway (USA).gba" size 4194304 crc 066a2705 sha1 26afa157c527dcaa5a4fa0eccc772426156320d8 ) ) -game ( - name "Casper (Europe) (En,Fr,De,Es,It,Nl,Pt)" - description "Casper (Europe) (En,Fr,De,Es,It,Nl,Pt)" - rom ( name "Casper (Europe) (En,Fr,De,Es,It,Nl,Pt).gba" size 4194304 crc ddaf8bac sha1 2321b90c04690e8e4973a4495d25c9197ab5bfcc ) -) - game ( name "Casper (USA) (En,Fr,Es)" description "Casper (USA) (En,Fr,Es)" @@ -3055,9 +3043,15 @@ game ( ) game ( - name "Castlevania (Europe) (Virtual Console)" - description "Castlevania (Europe) (Virtual Console)" - rom ( name "Castlevania (Europe) (Virtual Console).gba" size 8388608 crc dba05255 sha1 b5fa3402a8fb86786f97d08f88b3cbc790bb5d6e ) + name "Casper (Europe) (En,Fr,De,Es,It,Nl,Pt)" + description "Casper (Europe) (En,Fr,De,Es,It,Nl,Pt)" + rom ( name "Casper (Europe) (En,Fr,De,Es,It,Nl,Pt).gba" size 4194304 crc ddaf8bac sha1 2321b90c04690e8e4973a4495d25c9197ab5bfcc ) +) + +game ( + name "Castle Master (World) (Unl)" + description "Castle Master (World) (Unl)" + rom ( name "Castle Master (World) (Unl).gba" size 259192 crc 307f7d77 sha1 bf78a4efde3b5c3bab65bd7156c69907fb86b512 ) ) game ( @@ -3066,6 +3060,12 @@ game ( rom ( name "Castlevania (Europe) (Castlevania Advance Collection).gba" size 8388608 crc 050e2164 sha1 30a2fd3fe95a8a84b02da7ddbc8b2a90e0553d9b ) ) +game ( + name "Castlevania (Europe) (Virtual Console)" + description "Castlevania (Europe) (Virtual Console)" + rom ( name "Castlevania (Europe) (Virtual Console).gba" size 8388608 crc dba05255 sha1 b5fa3402a8fb86786f97d08f88b3cbc790bb5d6e ) +) + game ( name "Castlevania (Europe)" description "Castlevania (Europe)" @@ -3102,18 +3102,6 @@ game ( rom ( name "Castlevania - Aria of Sorrow (USA) (Castlevania Advance Collection).gba" size 8388608 crc ca9b82dd sha1 f2869a861f1be637a1d1b57009cb42cc06b82e09 ) ) -game ( - name "Castlevania - Aria of Sorrow (USA) (Virtual Console)" - description "Castlevania - Aria of Sorrow (USA) (Virtual Console)" - rom ( name "Castlevania - Aria of Sorrow (USA) (Virtual Console).gba" size 8388608 crc 28baa30e sha1 b69a77970878b453e2b308fe124641f66925ae6a ) -) - -game ( - name "Castlevania - Aria of Sorrow (Europe) (En,Fr,De) (Virtual Console)" - description "Castlevania - Aria of Sorrow (Europe) (En,Fr,De) (Virtual Console)" - rom ( name "Castlevania - Aria of Sorrow (Europe) (En,Fr,De) (Virtual Console).gba" size 8388608 crc d97dbfec sha1 458c42a6b8fd6cf18579b0f7eef9dcd12b43c12b ) -) - game ( name "Castlevania - Aria of Sorrow (Europe) (En,Fr,De)" description "Castlevania - Aria of Sorrow (Europe) (En,Fr,De)" @@ -3127,9 +3115,15 @@ game ( ) game ( - name "Castlevania - Byakuya no Concerto (Japan)" - description "Castlevania - Byakuya no Concerto (Japan)" - rom ( name "Castlevania - Byakuya no Concerto (Japan).gba" size 8388608 crc 379b3248 sha1 3aeb81ee60fa3e56a56ee069b0ce0d8bc34d9c4c ) + name "Castlevania - Aria of Sorrow (USA) (Virtual Console)" + description "Castlevania - Aria of Sorrow (USA) (Virtual Console)" + rom ( name "Castlevania - Aria of Sorrow (USA) (Virtual Console).gba" size 8388608 crc 28baa30e sha1 b69a77970878b453e2b308fe124641f66925ae6a ) +) + +game ( + name "Castlevania - Aria of Sorrow (Europe) (En,Fr,De) (Virtual Console)" + description "Castlevania - Aria of Sorrow (Europe) (En,Fr,De) (Virtual Console)" + rom ( name "Castlevania - Aria of Sorrow (Europe) (En,Fr,De) (Virtual Console).gba" size 8388608 crc d97dbfec sha1 458c42a6b8fd6cf18579b0f7eef9dcd12b43c12b ) ) game ( @@ -3139,9 +3133,9 @@ game ( ) game ( - name "Castlevania - Circle of the Moon (USA) (Castlevania Advance Collection)" - description "Castlevania - Circle of the Moon (USA) (Castlevania Advance Collection)" - rom ( name "Castlevania - Circle of the Moon (USA) (Castlevania Advance Collection).gba" size 8388608 crc 14c1ab7c sha1 9483aa48b384ff3142c47fe81c13ca874a608eb0 ) + name "Castlevania - Byakuya no Concerto (Japan)" + description "Castlevania - Byakuya no Concerto (Japan)" + rom ( name "Castlevania - Byakuya no Concerto (Japan).gba" size 8388608 crc 379b3248 sha1 3aeb81ee60fa3e56a56ee069b0ce0d8bc34d9c4c ) ) game ( @@ -3156,6 +3150,12 @@ game ( rom ( name "Castlevania - Circle of the Moon (USA) (Virtual Console).gba" size 8388608 crc d5412e91 sha1 e055b4ab00e16ec39c9036ef85463c770d809c6c ) ) +game ( + name "Castlevania - Circle of the Moon (USA) (Castlevania Advance Collection)" + description "Castlevania - Circle of the Moon (USA) (Castlevania Advance Collection)" + rom ( name "Castlevania - Circle of the Moon (USA) (Castlevania Advance Collection).gba" size 8388608 crc 14c1ab7c sha1 9483aa48b384ff3142c47fe81c13ca874a608eb0 ) +) + game ( name "Castlevania - Harmony of Dissonance (Europe) (Castlevania Advance Collection)" description "Castlevania - Harmony of Dissonance (Europe) (Castlevania Advance Collection)" @@ -3228,24 +3228,6 @@ game ( rom ( name "Catz (Europe) (En,Fr,De,It).gba" size 8388608 crc c3aa382d sha1 0dab5140ebc541e03dd00a8ce87cce4f0326b0e6 ) ) -game ( - name "Celeste Classic (World) (v1.0) (Aftermarket) (Unl)" - description "Celeste Classic (World) (v1.0) (Aftermarket) (Unl)" - rom ( name "Celeste Classic (World) (v1.0) (Aftermarket) (Unl).gba" size 5416932 crc f79b0d53 sha1 756f02396a150698e695ad4afd24445e2af70576 ) -) - -game ( - name "Celeste Classic (World) (v1.1) (Aftermarket) (Unl)" - description "Celeste Classic (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Celeste Classic (World) (v1.1) (Aftermarket) (Unl).gba" size 5418248 crc f5d36ad2 sha1 95a86dff641b11b4c2ed0d0fe8152c33b462d927 ) -) - -game ( - name "Celeste Classic (World) (v1.2) (Aftermarket) (Unl)" - description "Celeste Classic (World) (v1.2) (Aftermarket) (Unl)" - rom ( name "Celeste Classic (World) (v1.2) (Aftermarket) (Unl).gba" size 5418424 crc ff0e8ada sha1 08512605e5c02e81a72e24c2c8d4959d8e84e1f4 ) -) - game ( name "Chaoji Maliou 2 (China)" description "Chaoji Maliou 2 (China)" @@ -3291,19 +3273,7 @@ game ( game ( name "Cheetah Girls, The (USA)" description "Cheetah Girls, The (USA)" - rom ( name "Cheetah Girls, The (USA).gba" size 8388608 crc e2efc2aa sha1 f46296d4ab97d539dbcfa551e05ed6d58715c5b6 ) -) - -game ( - name "Chessmaster (USA)" - description "Chessmaster (USA)" - rom ( name "Chessmaster (USA).gba" size 4194304 crc 25b0e933 sha1 5e3ac500d119a2bbe67d480edc1c1dd09061e385 ) -) - -game ( - name "Chessmaster (Germany)" - description "Chessmaster (Germany)" - rom ( name "Chessmaster (Germany).gba" size 4194304 crc 06abacc5 sha1 76a69da6183239f4ab0c45ef43c3ef7e2bd96d03 ) + rom ( name "Cheetah Girls, The (USA).gba" size 8388608 crc e2efc2aa sha1 f46296d4ab97d539dbcfa551e05ed6d58715c5b6 flags verified ) ) game ( @@ -3318,6 +3288,18 @@ game ( rom ( name "Chessmaster (France).gba" size 4194304 crc 55ef8392 sha1 eb5630d7b56ebdf4609665d50bf188e3f9eac668 ) ) +game ( + name "Chessmaster (USA)" + description "Chessmaster (USA)" + rom ( name "Chessmaster (USA).gba" size 4194304 crc 25b0e933 sha1 5e3ac500d119a2bbe67d480edc1c1dd09061e385 ) +) + +game ( + name "Chessmaster (Germany)" + description "Chessmaster (Germany)" + rom ( name "Chessmaster (Germany).gba" size 4194304 crc 06abacc5 sha1 76a69da6183239f4ab0c45ef43c3ef7e2bd96d03 ) +) + game ( name "Chi Vuol Essere Milionario (Italy)" description "Chi Vuol Essere Milionario (Italy)" @@ -3372,6 +3354,12 @@ game ( rom ( name "Chinmoku no Iseki - Estpolis Gaiden (Japan) (Virtual Console).gba" size 8388608 crc 36cc41bf sha1 882cc3c71ce7025abbe0a65a2f007428887d7113 ) ) +game ( + name "Chip Advance (World) (En,Fr) (v2.1) (Unl)" + description "Chip Advance (World) (En,Fr) (v2.1) (Unl)" + rom ( name "Chip Advance (World) (En,Fr) (v2.1) (Unl).gba" size 10498128 crc 586c4345 sha1 29c889b3c25b851f590685dea03400110e98fabd ) +) + game ( name "Chobits for Game Boy Advance - Atashi Dake no Hito (Japan)" description "Chobits for Game Boy Advance - Atashi Dake no Hito (Japan)" @@ -3385,9 +3373,9 @@ game ( ) game ( - name "Chopper 2 The Return (Europe) (Unl)" - description "Chopper 2 The Return (Europe) (Unl)" - rom ( name "Chopper 2 The Return (Europe) (Unl).gba" size 861720 crc f33aac43 sha1 50c0eb0f3832a068bb9591d4dfaa8e1389bb87db ) + name "Chopper 2 - The Return (World) (Unl)" + description "Chopper 2 - The Return (World) (Unl)" + rom ( name "Chopper 2 - The Return (World) (Unl).gba" size 861720 crc f33aac43 sha1 50c0eb0f3832a068bb9591d4dfaa8e1389bb87db ) ) game ( @@ -3486,6 +3474,12 @@ game ( rom ( name "Cinnamoroll - Koko ni Iru yo (Japan).gba" size 4194304 crc 8376d53b sha1 f13533eb284f7321d8709df058ff28d61a031802 ) ) +game ( + name "City Connection (World) (Fr) (v1.7) (Unl)" + description "City Connection (World) (Fr) (v1.7) (Unl)" + rom ( name "City Connection (World) (Fr) (v1.7) (Unl).gba" size 1924768 crc 234a42a5 sha1 e1c6d46521310d96fedf46a39982ad1372cdc42c ) +) + game ( name "Classic NES Series - Bomberman (USA, Europe)" description "Classic NES Series - Bomberman (USA, Europe)" @@ -3531,7 +3525,7 @@ game ( game ( name "Classic NES Series - Pac-Man (USA, Europe)" description "Classic NES Series - Pac-Man (USA, Europe)" - rom ( name "Classic NES Series - Pac-Man (USA, Europe).gba" size 1048576 crc c28df82f sha1 843d853ed28a116c85a5357f9a94e9179f36a6d0 ) + rom ( name "Classic NES Series - Pac-Man (USA, Europe).gba" size 1048576 crc c28df82f sha1 843d853ed28a116c85a5357f9a94e9179f36a6d0 flags verified ) ) game ( @@ -3549,7 +3543,7 @@ game ( game ( name "Classic NES Series - Xevious (USA, Europe)" description "Classic NES Series - Xevious (USA, Europe)" - rom ( name "Classic NES Series - Xevious (USA, Europe).gba" size 1048576 crc 9cd2d5dd sha1 b2088582808480e0d70c63a777b046409d4e15c4 ) + rom ( name "Classic NES Series - Xevious (USA, Europe).gba" size 1048576 crc 9cd2d5dd sha1 b2088582808480e0d70c63a777b046409d4e15c4 flags verified ) ) game ( @@ -3582,6 +3576,12 @@ game ( rom ( name "Codename - Kids Next Door - Operation S.O.D.A. (USA).gba" size 8388608 crc 420a81b7 sha1 bbd176cc9a5331fdfdb332ad037d869610e4b3fb ) ) +game ( + name "Coin Adventure (World) (Unl)" + description "Coin Adventure (World) (Unl)" + rom ( name "Coin Adventure (World) (Unl).gba" size 677920 crc bb3a4566 sha1 088aeb8d40927969c690a66321d7006751a73e20 ) +) + game ( name "Colin McRae Rally 2.0 (Europe) (En,Fr,De)" description "Colin McRae Rally 2.0 (Europe) (En,Fr,De)" @@ -3693,7 +3693,7 @@ game ( game ( name "Crash & Spyro Super Pack Volume 1 (Europe) (En,Fr,De,Es,It,Nl)" description "Crash & Spyro Super Pack Volume 1 (Europe) (En,Fr,De,Es,It,Nl)" - rom ( name "Crash & Spyro Super Pack Volume 1 (Europe) (En,Fr,De,Es,It,Nl).gba" size 16777216 crc d8382427 sha1 4e184f8f52e5a6b79a272f7674178d3d3ccc3386 ) + rom ( name "Crash & Spyro Super Pack Volume 1 (Europe) (En,Fr,De,Es,It,Nl).gba" size 16777216 crc d8382427 sha1 4e184f8f52e5a6b79a272f7674178d3d3ccc3386 flags verified ) ) game ( @@ -3705,7 +3705,7 @@ game ( game ( name "Crash & Spyro Super Pack Volume 3 (Europe) (En,Fr,De,Es,It)" description "Crash & Spyro Super Pack Volume 3 (Europe) (En,Fr,De,Es,It)" - rom ( name "Crash & Spyro Super Pack Volume 3 (Europe) (En,Fr,De,Es,It).gba" size 33554432 crc 0510b70f sha1 bf33976d1a26e336416e0fd28b2b8da65450737d ) + rom ( name "Crash & Spyro Super Pack Volume 3 (Europe) (En,Fr,De,Es,It).gba" size 33554432 crc c7269e6a sha1 ec25e705d5129a97b405b6b15197cbb9141e135f flags verified ) ) game ( @@ -3717,7 +3717,7 @@ game ( game ( name "Crash & Spyro Superpack - Spyro Orange - The Cortex Conspiracy + Crash Bandicoot Purple - Ripto's Rampage (USA)" description "Crash & Spyro Superpack - Spyro Orange - The Cortex Conspiracy + Crash Bandicoot Purple - Ripto's Rampage (USA)" - rom ( name "Crash & Spyro Superpack - Spyro Orange - The Cortex Conspiracy + Crash Bandicoot Purple - Ripto's Rampage (USA).gba" size 33554432 crc 5940906e sha1 95b5a68962ce552a71d8212850e85d90d2844b40 ) + rom ( name "Crash & Spyro Superpack - Spyro Orange - The Cortex Conspiracy + Crash Bandicoot Purple - Ripto's Rampage (USA).gba" size 33554432 crc 9b76b90b sha1 a14854c2189516501a51d9e3fce7f10f3593fc9a ) ) game ( @@ -3735,7 +3735,7 @@ game ( game ( name "Crash Bandicoot 2 - N-Tranced (USA)" description "Crash Bandicoot 2 - N-Tranced (USA)" - rom ( name "Crash Bandicoot 2 - N-Tranced (USA).gba" size 8388608 crc 2e16184a sha1 972158859ea08aa5746ab2e0d4c81ac43728adff ) + rom ( name "Crash Bandicoot 2 - N-Tranced (USA).gba" size 8388608 crc 2e16184a sha1 972158859ea08aa5746ab2e0d4c81ac43728adff flags verified ) ) game ( @@ -3831,7 +3831,7 @@ game ( game ( name "Crayon Shin-chan - Densetsu o Yobu Omake no Miyako Shockgaan! (Japan)" description "Crayon Shin-chan - Densetsu o Yobu Omake no Miyako Shockgaan! (Japan)" - rom ( name "Crayon Shin-chan - Densetsu o Yobu Omake no Miyako Shockgaan! (Japan).gba" size 33554432 crc 45c84466 sha1 e17baa57d339f7d85f562441111696e88088fcdd ) + rom ( name "Crayon Shin-chan - Densetsu o Yobu Omake no Miyako Shockgaan! (Japan).gba" size 33554432 crc 52f463fe sha1 10aa9bd3b72ed918e7c59fdbc0cc05e5b48dcc70 ) ) game ( @@ -3924,6 +3924,18 @@ game ( rom ( name "Croket! Great - Toki no Boukensha (Japan).gba" size 16777216 crc f0e81971 sha1 410fb8fe2fe07be146c8454122d874287f92fbac ) ) +game ( + name "Cross Town Heroes (USA)" + description "Cross Town Heroes (USA)" + rom ( name "Cross Town Heroes (USA).gba" size 4194304 crc 0fffb458 sha1 6baa6bfe76b077f365bedffa52346b94689b61d7 ) +) + +game ( + name "Cross Town Heroes (Europe)" + description "Cross Town Heroes (Europe)" + rom ( name "Cross Town Heroes (Europe).gba" size 4194304 crc c9ea02f5 sha1 13310b7f25a0332a8e09e722587ec79aee11c373 ) +) + game ( name "Crouching Tiger, Hidden Dragon (USA) (En,Fr,Es)" description "Crouching Tiger, Hidden Dragon (USA) (En,Fr,Es)" @@ -3937,15 +3949,15 @@ game ( ) game ( - name "Crouching Tiger, Hidden Dragon (USA) (Beta)" - description "Crouching Tiger, Hidden Dragon (USA) (Beta)" - rom ( name "Crouching Tiger, Hidden Dragon (USA) (Beta).gba" size 8388608 crc 204ff8d5 sha1 af24d128b28758a8a1bda45b5a24a299e1e14b90 ) + name "Crouching Tiger, Hidden Dragon (USA) (Beta 2)" + description "Crouching Tiger, Hidden Dragon (USA) (Beta 2)" + rom ( name "Crouching Tiger, Hidden Dragon (USA) (Beta 2).gba" size 8388608 crc 204ff8d5 sha1 af24d128b28758a8a1bda45b5a24a299e1e14b90 ) ) game ( - name "Cruis'n Velocity (USA, Europe) (Beta)" - description "Cruis'n Velocity (USA, Europe) (Beta)" - rom ( name "Cruis'n Velocity (USA, Europe) (Beta).gba" size 8388608 crc 5436d5da sha1 d1716d4603dd8db7ae8715d5142a60230d17e1d2 ) + name "Crouching Tiger, Hidden Dragon (USA) (Beta 1)" + description "Crouching Tiger, Hidden Dragon (USA) (Beta 1)" + rom ( name "Crouching Tiger, Hidden Dragon (USA) (Beta 1).gba" size 3353604 crc a1d2d006 sha1 3d554e4e33563211865b9c5481444b0b8b4e6127 ) ) game ( @@ -3954,6 +3966,12 @@ game ( rom ( name "Cruis'n Velocity (USA, Europe).gba" size 4194304 crc adf14db5 sha1 762aabc26501dee4aa566e8327600433c8edbf7a ) ) +game ( + name "Cruis'n Velocity (USA, Europe) (Beta)" + description "Cruis'n Velocity (USA, Europe) (Beta)" + rom ( name "Cruis'n Velocity (USA, Europe) (Beta).gba" size 8388608 crc 5436d5da sha1 d1716d4603dd8db7ae8715d5142a60230d17e1d2 ) +) + game ( name "Crushed Baseball (USA)" description "Crushed Baseball (USA)" @@ -3966,18 +3984,18 @@ game ( rom ( name "CT Special Forces (USA) (En,Fr,De,Es,It,Nl).gba" size 4194304 crc aea22ae0 sha1 ab151206c142dbcdb4f2ea9877d6bcd2c89b8b55 ) ) -game ( - name "CT Special Forces (Europe) (En,Fr,De,Es,It,Nl)" - description "CT Special Forces (Europe) (En,Fr,De,Es,It,Nl)" - rom ( name "CT Special Forces (Europe) (En,Fr,De,Es,It,Nl).gba" size 4194304 crc a20d9adb sha1 e178192ba2c78759245541bd54d96d83a8d5d9c6 flags verified ) -) - game ( name "CT Special Forces (Europe) (En,Fr,De,Es,It,Nl) (Beta)" description "CT Special Forces (Europe) (En,Fr,De,Es,It,Nl) (Beta)" rom ( name "CT Special Forces (Europe) (En,Fr,De,Es,It,Nl) (Beta).gba" size 4194304 crc 40a0e1c9 sha1 fab8b62a141865f12c69334f4db14c837d9d94af ) ) +game ( + name "CT Special Forces (Europe) (En,Fr,De,Es,It,Nl)" + description "CT Special Forces (Europe) (En,Fr,De,Es,It,Nl)" + rom ( name "CT Special Forces (Europe) (En,Fr,De,Es,It,Nl).gba" size 4194304 crc a20d9adb sha1 e178192ba2c78759245541bd54d96d83a8d5d9c6 flags verified ) +) + game ( name "CT Special Forces - Back to Hell (Europe) (En,Fr,De,Es,It,Nl)" description "CT Special Forces - Back to Hell (Europe) (En,Fr,De,Es,It,Nl)" @@ -4065,7 +4083,7 @@ game ( game ( name "Dancing Sword - Senkou (Japan)" description "Dancing Sword - Senkou (Japan)" - rom ( name "Dancing Sword - Senkou (Japan).gba" size 8388608 crc e2316d47 sha1 5c5f33e0453cba1a60039160564daa53a82db8aa ) + rom ( name "Dancing Sword - Senkou (Japan).gba" size 8388608 crc e2316d47 sha1 5c5f33e0453cba1a60039160564daa53a82db8aa flags verified ) ) game ( @@ -4206,6 +4224,12 @@ game ( rom ( name "Deal or No Deal (USA).gba" size 4194304 crc b6c00edb sha1 3691000350db3b36311439c5d9c9879ee756fea6 ) ) +game ( + name "Decoder Cart (Japan) (En) (Pirate)" + description "Decoder Cart (Japan) (En) (Pirate)" + rom ( name "Decoder Cart (Japan) (En) (Pirate).gba" size 8388608 crc 80aa9cc5 sha1 20c6f5aaf8299dfcdeb76bd633f12da209625b97 ) +) + game ( name "Defender (USA)" description "Defender (USA)" @@ -4230,10 +4254,16 @@ game ( rom ( name "Defender of the Crown (Europe).gba" size 4194304 crc 6968959a sha1 4e37071533e946efd4166efc409562cc21af83d2 ) ) +game ( + name "Deflektor (World) (v1.1) (Unl)" + description "Deflektor (World) (v1.1) (Unl)" + rom ( name "Deflektor (World) (v1.1) (Unl).gba" size 386508 crc 5ec91001 sha1 92682b2404be3b2fd48f96cad0c51f51d07c8159 ) +) + game ( name "DemiKids - Dark Version (USA)" description "DemiKids - Dark Version (USA)" - rom ( name "DemiKids - Dark Version (USA).gba" size 8388608 crc 1bab58bd sha1 f3dbc8c6d58c33b88c28306f54ff742da1c8d6c9 ) + rom ( name "DemiKids - Dark Version (USA).gba" size 8388608 crc 1bab58bd sha1 f3dbc8c6d58c33b88c28306f54ff742da1c8d6c9 flags verified ) ) game ( @@ -4296,18 +4326,18 @@ game ( rom ( name "Densetsu no Stafy 3 (Japan) (Rev 1) (Virtual Console).gba" size 16777216 crc 59ca95c6 sha1 5506cbcfa1a275441f365099822a583c80397fde ) ) -game ( - name "Densetsu no Stafy 3 (Japan)" - description "Densetsu no Stafy 3 (Japan)" - rom ( name "Densetsu no Stafy 3 (Japan).gba" size 16777216 crc fcaf1aa8 sha1 a7a742e779d314f6909f1350db2da8a63445c433 flags verified ) -) - game ( name "Densetsu no Stafy 3 (Japan) (Rev 1)" description "Densetsu no Stafy 3 (Japan) (Rev 1)" rom ( name "Densetsu no Stafy 3 (Japan) (Rev 1).gba" size 16777216 crc 2d6e4c3b sha1 dae5354bfe4ccafc92d22b1389265dbf1f79b636 ) ) +game ( + name "Densetsu no Stafy 3 (Japan)" + description "Densetsu no Stafy 3 (Japan)" + rom ( name "Densetsu no Stafy 3 (Japan).gba" size 16777216 crc fcaf1aa8 sha1 a7a742e779d314f6909f1350db2da8a63445c433 flags verified ) +) + game ( name "Derby Stallion Advance (Japan)" description "Derby Stallion Advance (Japan)" @@ -4326,12 +4356,6 @@ game ( rom ( name "Deutschland Sucht den Superstar (Germany).gba" size 16777216 crc 51f50f7d sha1 ce5253e82671569500af3d5df9d3131916fbe23d ) ) -game ( - name "Dexter's Laboratory - Chess Challenge (Europe) (En,Fr,De,Es)" - description "Dexter's Laboratory - Chess Challenge (Europe) (En,Fr,De,Es)" - rom ( name "Dexter's Laboratory - Chess Challenge (Europe) (En,Fr,De,Es).gba" size 8388608 crc f5436f5d sha1 e04dbb5e0534cf241e8fee85d17b1cc8a0032f14 ) -) - game ( name "Dexter's Laboratory - Chess Challenge (USA)" description "Dexter's Laboratory - Chess Challenge (USA)" @@ -4339,9 +4363,15 @@ game ( ) game ( - name "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It)" - description "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It)" - rom ( name "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It).gba" size 4194304 crc e948d412 sha1 f230375ba4b0346d749e50117fe701d8c1cbfffa ) + name "Dexter's Laboratory - Chess Challenge (Europe) (En,Fr,De,Es)" + description "Dexter's Laboratory - Chess Challenge (Europe) (En,Fr,De,Es)" + rom ( name "Dexter's Laboratory - Chess Challenge (Europe) (En,Fr,De,Es).gba" size 8388608 crc f5436f5d sha1 e04dbb5e0534cf241e8fee85d17b1cc8a0032f14 ) +) + +game ( + name "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It) (Rev 1)" + description "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It) (Rev 1)" + rom ( name "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It) (Rev 1).gba" size 4194304 crc 6bf168e6 sha1 b838b5bb37bfeb3315a68b6d372f29a5de635444 flags verified ) ) game ( @@ -4351,9 +4381,9 @@ game ( ) game ( - name "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It) (Rev 1)" - description "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It) (Rev 1)" - rom ( name "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It) (Rev 1).gba" size 4194304 crc 6bf168e6 sha1 b838b5bb37bfeb3315a68b6d372f29a5de635444 flags verified ) + name "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It)" + description "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It)" + rom ( name "Dexter's Laboratory - Deesaster Strikes! (USA) (En,Fr,De,Es,It).gba" size 4194304 crc e948d412 sha1 f230375ba4b0346d749e50117fe701d8c1cbfffa ) ) game ( @@ -4377,7 +4407,7 @@ game ( game ( name "Diddy Kong Pilot (Unknown) (Proto) (2001)" description "Diddy Kong Pilot (Unknown) (Proto) (2001)" - rom ( name "Diddy Kong Pilot (Unknown) (Proto) (2001).gba" size 7509167 crc 8903cc5f sha1 e14bfb4d63c6bd35c3a1a4aad4eb91e94d0402b3 ) + rom ( name "Diddy Kong Pilot (Unknown) (Proto) (2001).gba" size 5080644 crc 5c206101 sha1 6a76def610829ac1502afb58740e38b5e6926b3d ) ) game ( @@ -4389,7 +4419,7 @@ game ( game ( name "Digimon - Battle Spirit (Europe) (En,Fr,De,Es,It)" description "Digimon - Battle Spirit (Europe) (En,Fr,De,Es,It)" - rom ( name "Digimon - Battle Spirit (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc ea5fc3da sha1 ecf0e597839905c9f23c6d568c79fc00c2719f49 ) + rom ( name "Digimon - Battle Spirit (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc ea5fc3da sha1 ecf0e597839905c9f23c6d568c79fc00c2719f49 flags verified ) ) game ( @@ -4653,7 +4683,7 @@ game ( game ( name "Dogz (USA)" description "Dogz (USA)" - rom ( name "Dogz (USA).gba" size 8388608 crc 124f27c0 sha1 462f05c18534cb22fffc65d47351a29f10a3f254 ) + rom ( name "Dogz (USA).gba" size 8388608 crc 124f27c0 sha1 462f05c18534cb22fffc65d47351a29f10a3f254 flags verified ) ) game ( @@ -4830,12 +4860,6 @@ game ( rom ( name "Donkey Kong Country 3 (USA).gba" size 16777216 crc fe03e5af sha1 c50982b4c26e25ba3538be97b585d95737d7ade7 flags verified ) ) -game ( - name "Donsol (World) (Aftermarket) (Unl)" - description "Donsol (World) (Aftermarket) (Unl)" - rom ( name "Donsol (World) (Aftermarket) (Unl).gba" size 52520 crc aec144b3 sha1 751675b0d77c341f2265b0edd38858b0dbdb7b50 ) -) - game ( name "Doom (USA, Europe)" description "Doom (USA, Europe)" @@ -4863,7 +4887,7 @@ game ( game ( name "Dora the Explorer - Super Spies (USA)" description "Dora the Explorer - Super Spies (USA)" - rom ( name "Dora the Explorer - Super Spies (USA).gba" size 4194304 crc 650fdfdb sha1 fa51e2102ce0a0e70c5db2f8776d2237c8d7db7d ) + rom ( name "Dora the Explorer - Super Spies (USA).gba" size 4194304 crc 650fdfdb sha1 fa51e2102ce0a0e70c5db2f8776d2237c8d7db7d flags verified ) ) game ( @@ -4881,7 +4905,7 @@ game ( game ( name "Dora the Explorer - The Search for the Pirate Pig's Treasure (USA)" description "Dora the Explorer - The Search for the Pirate Pig's Treasure (USA)" - rom ( name "Dora the Explorer - The Search for the Pirate Pig's Treasure (USA).gba" size 4194304 crc 9439541c sha1 10d1df1cb3fd94a14fff239083968b5182772a4d ) + rom ( name "Dora the Explorer - The Search for the Pirate Pig's Treasure (USA).gba" size 4194304 crc 9439541c sha1 10d1df1cb3fd94a14fff239083968b5182772a4d flags verified ) ) game ( @@ -5025,7 +5049,7 @@ game ( game ( name "Dragon Ball - Advanced Adventure (Europe) (En,Fr,De,Es,It)" description "Dragon Ball - Advanced Adventure (Europe) (En,Fr,De,Es,It)" - rom ( name "Dragon Ball - Advanced Adventure (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc 6c135820 sha1 e49ae836b14f84dc8cd817bf912fcdce82d8a587 ) + rom ( name "Dragon Ball - Advanced Adventure (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc 6c135820 sha1 e49ae836b14f84dc8cd817bf912fcdce82d8a587 flags verified ) ) game ( @@ -5040,6 +5064,12 @@ game ( rom ( name "Dragon Ball - Advanced Adventure (Europe) (En,Fr,De,Es,It) (Beta) (2005-02-25).gba" size 16777216 crc 2b136906 sha1 fe190755f05994f1c796286ad767d7da49c36385 ) ) +game ( + name "Dragon Ball GT - Transformation (USA) (Beta) (2005-04-27)" + description "Dragon Ball GT - Transformation (USA) (Beta) (2005-04-27)" + rom ( name "Dragon Ball GT - Transformation (USA) (Beta) (2005-04-27).gba" size 8388608 crc 431bc807 sha1 58875496c9ab89ba3b769dc47d89ac2839b7cb7f ) +) + game ( name "Dragon Ball GT - Transformation (USA)" description "Dragon Ball GT - Transformation (USA)" @@ -5136,6 +5166,18 @@ game ( rom ( name "Dragon Ball Z - The Legacy of Goku II (USA).gba" size 8388608 crc 204142e1 sha1 18e0715dec419f3501c301511530d2edcd590f8b flags verified ) ) +game ( + name "Dragon Ball Z - The Legacy of Goku II (USA) (Beta) (2003-01-23)" + description "Dragon Ball Z - The Legacy of Goku II (USA) (Beta) (2003-01-23)" + rom ( name "Dragon Ball Z - The Legacy of Goku II (USA) (Beta) (2003-01-23).gba" size 7282372 crc 3c30f5b3 sha1 16f4c593a0ab0e243fbeca7cc1033ac88501e387 ) +) + +game ( + name "Dragon Ball Z - The Legacy of Goku II (USA) (Beta) (2003-01-31)" + description "Dragon Ball Z - The Legacy of Goku II (USA) (Beta) (2003-01-31)" + rom ( name "Dragon Ball Z - The Legacy of Goku II (USA) (Beta) (2003-01-31).gba" size 7279012 crc 25f34dbc sha1 fc76f3477f19af7415a42a6f38bd5bda43c640d2 ) +) + game ( name "Dragon Ball Z - The Legacy of Goku II International (Japan)" description "Dragon Ball Z - The Legacy of Goku II International (Japan)" @@ -5157,7 +5199,7 @@ game ( game ( name "Dragon Quest Characters - Torneko no Daibouken 3 Advance - Fushigi no Dungeon (Japan)" description "Dragon Quest Characters - Torneko no Daibouken 3 Advance - Fushigi no Dungeon (Japan)" - rom ( name "Dragon Quest Characters - Torneko no Daibouken 3 Advance - Fushigi no Dungeon (Japan).gba" size 16777216 crc c891b2a0 sha1 f306ce96404cff93caee78c86696a69b431b289a ) + rom ( name "Dragon Quest Characters - Torneko no Daibouken 3 Advance - Fushigi no Dungeon (Japan).gba" size 16777216 crc c891b2a0 sha1 f306ce96404cff93caee78c86696a69b431b289a flags verified ) ) game ( @@ -5376,6 +5418,12 @@ game ( rom ( name "Duel Masters 3 (Japan) (Rev 1).gba" size 8388608 crc d2b9cfb6 sha1 05ad843564c663a050e137ae0ec07d09f585c714 ) ) +game ( + name "Duke Nukem Advance (World) (En,Fr,De,It) (Evercade) (Unl)" + description "Duke Nukem Advance (World) (En,Fr,De,It) (Evercade) (Unl)" + rom ( name "Duke Nukem Advance (World) (En,Fr,De,It) (Evercade) (Unl).gba" size 8388608 crc 2b077058 sha1 926b6c74d408cb3ff37a5276ddc3be8e2512c0b3 ) +) + game ( name "Duke Nukem Advance (USA)" description "Duke Nukem Advance (USA)" @@ -5526,6 +5574,12 @@ game ( rom ( name "Eggo Mania (Europe) (En,Fr,De,Es,It,Nl).gba" size 4194304 crc 0b2961ce sha1 5514d090d08643a07457e4698d848657ae5cd179 ) ) +game ( + name "Elements of Darkness (World) (Demo) (Unl)" + description "Elements of Darkness (World) (Demo) (Unl)" + rom ( name "Elements of Darkness (World) (Demo) (Unl).gba" size 3039348 crc 5f3b0637 sha1 f425b0a88c46bca220bf47c2067020b57e96f736 ) +) + game ( name "Elemix! (Japan)" description "Elemix! (Japan)" @@ -5556,6 +5610,12 @@ game ( rom ( name "Elf Bowling 1 & 2 (USA).gba" size 4194304 crc 68feff40 sha1 013f128c8d67f1165196b4f29297bcd4616c5033 ) ) +game ( + name "Elite - The New Kind (World) (v1.7.1) (Unl)" + description "Elite - The New Kind (World) (v1.7.1) (Unl)" + rom ( name "Elite - The New Kind (World) (v1.7.1) (Unl).gba" size 546392 crc 5f9b4211 sha1 d3e6c12e6475ffb21617e3be7158d60ac535e74b ) +) + game ( name "Enchanted - Once Upon Andalasia (USA) (En,Fr)" description "Enchanted - Once Upon Andalasia (USA) (En,Fr)" @@ -5589,7 +5649,7 @@ game ( game ( name "ESPN Final Round Golf 2002 (USA)" description "ESPN Final Round Golf 2002 (USA)" - rom ( name "ESPN Final Round Golf 2002 (USA).gba" size 8388608 crc c9bc75a5 sha1 ecee20b629a38bab7edbc972c70b2c968f50c23c ) + rom ( name "ESPN Final Round Golf 2002 (USA).gba" size 8388608 crc c9bc75a5 sha1 ecee20b629a38bab7edbc972c70b2c968f50c23c flags verified ) ) game ( @@ -5821,9 +5881,81 @@ game ( ) game ( - name "F-Zero - Maximum Velocity (USA, Europe) (Virtual Console)" - description "F-Zero - Maximum Velocity (USA, Europe) (Virtual Console)" - rom ( name "F-Zero - Maximum Velocity (USA, Europe) (Virtual Console).gba" size 4194304 crc 4b5f1cdd sha1 bd08e426c743c7429efd576ce0ef00a70cffd72a flags verified ) + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-29) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-29) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-29) (Netcard).gba" size 16777216 crc d329df50 sha1 71b626b355813e80f9cc3d6ae3765552b5e09009 ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-26) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-26) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-26) (Netcard).gba" size 16777216 crc c77188b6 sha1 377f0f17ce3cea637dfdf9021f04aa56971db6a6 ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-24) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-24) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-24) (Netcard).gba" size 16777216 crc 77c0c615 sha1 bfe6b7f099998edf6e35bc47dfd86c1e88152cb4 ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-23) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-23) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-23) (Netcard).gba" size 16777216 crc 4d224e17 sha1 685753aa1bff5ed077eaa01ab058fa800b9c50c7 ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-18 23.00.14) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-18 23.00.14) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-18 23.00.14) (Netcard).gba" size 16777216 crc 6f7486d7 sha1 3633a74b5fbed1a129f2ff37f7fd000c70b23a4d ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-18 02.40.54) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-18 02.40.54) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-18 02.40.54) (Netcard).gba" size 16777216 crc 27c8a067 sha1 54fa13e875c899dab0de270f334c283d3f5bb05c ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-17) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-17) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-17) (Netcard).gba" size 16777216 crc e73c5f4a sha1 8397fb78936dd667d0ef45b055613795df4a1c0e ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-16) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-16) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-16) (Netcard).gba" size 16777216 crc aa522f27 sha1 d8d9035e5672cb95fcd49499d5e4e7b6d6daad67 ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-15) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-15) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-15) (Netcard).gba" size 16777216 crc 7ec47244 sha1 c8ca3281e9b329d967e96516f98744226f18974a ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-11) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-11) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-11) (Netcard).gba" size 16777216 crc debc0acb sha1 2d46237c002846b3a5cd1ed3daa173ebcf8e35f2 ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-09) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-08-09) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-08-09) (Netcard).gba" size 16777216 crc c46fd22a sha1 2319499d453179763fc607ffbfe2d24a272237f3 ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-09-02 00.17.57) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-09-02 00.17.57) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-09-02 00.17.57) (Netcard).gba" size 16777216 crc 61f9dc0e sha1 a9c26c71373bfa19c578591fd774f66644c0bdf2 ) +) + +game ( + name "F-Zero - GP Legend (Unknown) (Proto) (2005-09-02 01.21.24) (Netcard)" + description "F-Zero - GP Legend (Unknown) (Proto) (2005-09-02 01.21.24) (Netcard)" + rom ( name "F-Zero - GP Legend (Unknown) (Proto) (2005-09-02 01.21.24) (Netcard).gba" size 16777216 crc 26358b01 sha1 32d0b25c339f814c2840e289b232f38678b88193 ) ) game ( @@ -5833,9 +5965,9 @@ game ( ) game ( - name "F-Zero for Game Boy Advance (Japan)" - description "F-Zero for Game Boy Advance (Japan)" - rom ( name "F-Zero for Game Boy Advance (Japan).gba" size 4194304 crc 25e3fc9a sha1 cd8648b7158cf7c979cc05dea4c1aa927496e8b7 ) + name "F-Zero - Maximum Velocity (USA, Europe) (Virtual Console)" + description "F-Zero - Maximum Velocity (USA, Europe) (Virtual Console)" + rom ( name "F-Zero - Maximum Velocity (USA, Europe) (Virtual Console).gba" size 4194304 crc 4b5f1cdd sha1 bd08e426c743c7429efd576ce0ef00a70cffd72a flags verified ) ) game ( @@ -5845,9 +5977,9 @@ game ( ) game ( - name "F1 2002 (Europe) (En,Fr,De,Es,It)" - description "F1 2002 (Europe) (En,Fr,De,Es,It)" - rom ( name "F1 2002 (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc aac551fd sha1 ae8c986de946e7fde8249e958c6743816fb05784 ) + name "F-Zero for Game Boy Advance (Japan)" + description "F-Zero for Game Boy Advance (Japan)" + rom ( name "F-Zero for Game Boy Advance (Japan).gba" size 4194304 crc 25e3fc9a sha1 cd8648b7158cf7c979cc05dea4c1aa927496e8b7 ) ) game ( @@ -5856,10 +5988,16 @@ game ( rom ( name "F1 2002 (USA, Europe).gba" size 4194304 crc 7dd20f33 sha1 c5b3860403425da6f062dd5b6d433781051e1a85 ) ) +game ( + name "F1 2002 (Europe) (En,Fr,De,Es,It)" + description "F1 2002 (Europe) (En,Fr,De,Es,It)" + rom ( name "F1 2002 (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc aac551fd sha1 ae8c986de946e7fde8249e958c6743816fb05784 ) +) + game ( name "F24 Stealth Fighter (USA)" description "F24 Stealth Fighter (USA)" - rom ( name "F24 Stealth Fighter (USA).gba" size 4194304 crc 9387ea7c sha1 ac9188c7836dd388b488d02e8774dc61b1d30b4a ) + rom ( name "F24 Stealth Fighter (USA).gba" size 4194304 crc 9387ea7c sha1 ac9188c7836dd388b488d02e8774dc61b1d30b4a flags verified ) ) game ( @@ -6039,7 +6177,7 @@ game ( game ( name "Famicom Mini 22 - Nazo no Murasame Jou (Japan)" description "Famicom Mini 22 - Nazo no Murasame Jou (Japan)" - rom ( name "Famicom Mini 22 - Nazo no Murasame Jou (Japan).gba" size 4194304 crc 8233349c sha1 0100d4e94c30adf73cd6082b89911dedf723ecd5 ) + rom ( name "Famicom Mini 22 - Nazo no Murasame Jou (Japan).gba" size 4194304 crc 8233349c sha1 0100d4e94c30adf73cd6082b89911dedf723ecd5 flags verified ) ) game ( @@ -6138,6 +6276,12 @@ game ( rom ( name "Fanqiejiang Wangguo Da Maoxian (China) (Proto).gba" size 8388608 crc 5116a665 sha1 51ab57e6b414bae66f3e3ef4335dc0d68df2ed5e ) ) +game ( + name "Fantastic 4 (Europe)" + description "Fantastic 4 (Europe)" + rom ( name "Fantastic 4 (Europe).gba" size 16777216 crc b30ae33d sha1 758b2afaf4dcd96baab60e04d64eb22718efcecf ) +) + game ( name "Fantastic 4 (USA)" description "Fantastic 4 (USA)" @@ -6150,12 +6294,6 @@ game ( rom ( name "Fantastic 4 (Europe) (Fr,De,Es,Nl).gba" size 16777216 crc 88643de0 sha1 1e6ef7a4c941ea074ed88010f5cd7bab7c807d0d flags verified ) ) -game ( - name "Fantastic 4 (Europe)" - description "Fantastic 4 (Europe)" - rom ( name "Fantastic 4 (Europe).gba" size 16777216 crc b30ae33d sha1 758b2afaf4dcd96baab60e04d64eb22718efcecf ) -) - game ( name "Fantastic 4 - Flame On (USA)" description "Fantastic 4 - Flame On (USA)" @@ -6195,7 +6333,7 @@ game ( game ( name "Fear Factor - Unleashed (USA)" description "Fear Factor - Unleashed (USA)" - rom ( name "Fear Factor - Unleashed (USA).gba" size 8388608 crc 1289639c sha1 bf933c51bdcb52ae54d518e80129c687b751f836 ) + rom ( name "Fear Factor - Unleashed (USA).gba" size 8388608 crc bf91c27d sha1 d6f60f7d1707dca21c61f50db2b6324b7d680012 ) ) game ( @@ -6241,15 +6379,15 @@ game ( ) game ( - name "FILA Decathlon (Europe) (Beta)" - description "FILA Decathlon (Europe) (Beta)" - rom ( name "FILA Decathlon (Europe) (Beta).gba" size 4194304 crc 07434e3a sha1 1dc940dda8da59ade503c1e8901a0e44285f4e9b ) + name "FILA Decathlon (Europe) (En,Fr,De,Es,It,Sv)" + description "FILA Decathlon (Europe) (En,Fr,De,Es,It,Sv)" + rom ( name "FILA Decathlon (Europe) (En,Fr,De,Es,It,Sv).gba" size 4194304 crc 628355b5 sha1 41efd4b2fc8be52a12aadd1e4bf696fcc98230ca flags verified ) ) game ( - name "FILA Decathlon (Europe) (En,Fr,De,Es,It,Sv)" - description "FILA Decathlon (Europe) (En,Fr,De,Es,It,Sv)" - rom ( name "FILA Decathlon (Europe) (En,Fr,De,Es,It,Sv).gba" size 4194304 crc 628355b5 sha1 41efd4b2fc8be52a12aadd1e4bf696fcc98230ca ) + name "FILA Decathlon (Europe) (Beta)" + description "FILA Decathlon (Europe) (Beta)" + rom ( name "FILA Decathlon (Europe) (Beta).gba" size 4194304 crc 07434e3a sha1 1dc940dda8da59ade503c1e8901a0e44285f4e9b ) ) game ( @@ -6312,24 +6450,6 @@ game ( rom ( name "Final Fantasy Tactics Advance (USA) (Virtual Console).gba" size 16777216 crc 5964df89 sha1 3ca7cffe302e733501a4777a576928ea159b89e4 ) ) -game ( - name "Final Fantasy Tactics Advance (USA)" - description "Final Fantasy Tactics Advance (USA)" - rom ( name "Final Fantasy Tactics Advance (USA).gba" size 16777216 crc 5645e56c sha1 4ac05441f4de70a4ec3dd932116346c61b8783d9 flags verified ) -) - -game ( - name "Final Fantasy Tactics Advance (Europe) (En,Fr,De,Es,It)" - description "Final Fantasy Tactics Advance (Europe) (En,Fr,De,Es,It)" - rom ( name "Final Fantasy Tactics Advance (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc ba5de047 sha1 9efaf328cbbcbc830be14940e42e4b92d90dfb58 flags verified ) -) - -game ( - name "Final Fantasy Tactics Advance (Japan)" - description "Final Fantasy Tactics Advance (Japan)" - rom ( name "Final Fantasy Tactics Advance (Japan).gba" size 16777216 crc a57b0034 sha1 fa9d23ee88c7fe24374337aca03eb864b5b991f4 flags verified ) -) - game ( name "Final Fantasy Tactics Advance (Europe) (En,Fr,De,Es,It) (Virtual Console)" description "Final Fantasy Tactics Advance (Europe) (En,Fr,De,Es,It) (Virtual Console)" @@ -6342,6 +6462,24 @@ game ( rom ( name "Final Fantasy Tactics Advance (Japan) (Virtual Console).gba" size 16777216 crc ee31422a sha1 8e90027e0831b27fa174e446e6a773f2a421aed1 ) ) +game ( + name "Final Fantasy Tactics Advance (Japan)" + description "Final Fantasy Tactics Advance (Japan)" + rom ( name "Final Fantasy Tactics Advance (Japan).gba" size 16777216 crc a57b0034 sha1 fa9d23ee88c7fe24374337aca03eb864b5b991f4 flags verified ) +) + +game ( + name "Final Fantasy Tactics Advance (USA)" + description "Final Fantasy Tactics Advance (USA)" + rom ( name "Final Fantasy Tactics Advance (USA).gba" size 16777216 crc 5645e56c sha1 4ac05441f4de70a4ec3dd932116346c61b8783d9 flags verified ) +) + +game ( + name "Final Fantasy Tactics Advance (Europe) (En,Fr,De,Es,It)" + description "Final Fantasy Tactics Advance (Europe) (En,Fr,De,Es,It)" + rom ( name "Final Fantasy Tactics Advance (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc ba5de047 sha1 9efaf328cbbcbc830be14940e42e4b92d90dfb58 flags verified ) +) + game ( name "Final Fantasy V Advance (Japan) (Virtual Console)" description "Final Fantasy V Advance (Japan) (Virtual Console)" @@ -6432,6 +6570,12 @@ game ( rom ( name "Final Fire Pro Wrestling - Yume no Dantai Unei! (Japan).gba" size 16777216 crc a0093822 sha1 4894c960c64b4f2d250e054ffd5d6971940c3b17 ) ) +game ( + name "Final Fire Pro Wrestling - Yume no Dantai Unei! (Japan) (Rev 1)" + description "Final Fire Pro Wrestling - Yume no Dantai Unei! (Japan) (Rev 1)" + rom ( name "Final Fire Pro Wrestling - Yume no Dantai Unei! (Japan) (Rev 1).gba" size 16777216 crc 3f98600b sha1 2fbb9ef803a07c23139709179e6af25f141abe51 ) +) + game ( name "Findet Nemo (Germany) (Beta)" description "Findet Nemo (Germany) (Beta)" @@ -6441,7 +6585,7 @@ game ( game ( name "Findet Nemo (Germany)" description "Findet Nemo (Germany)" - rom ( name "Findet Nemo (Germany).gba" size 8388608 crc 6b6b0908 sha1 5c5ee51c4bc8196bea226b3bf4750c8de1ee7f38 ) + rom ( name "Findet Nemo (Germany).gba" size 8388608 crc 6b6b0908 sha1 5c5ee51c4bc8196bea226b3bf4750c8de1ee7f38 flags verified ) ) game ( @@ -6453,7 +6597,7 @@ game ( game ( name "Finding Nemo (Japan)" description "Finding Nemo (Japan)" - rom ( name "Finding Nemo (Japan).gba" size 8388608 crc f895ba2d sha1 cab85c042c168e46ec42547a87af1b036e45c2a4 ) + rom ( name "Finding Nemo (Japan).gba" size 8388608 crc f895ba2d sha1 cab85c042c168e46ec42547a87af1b036e45c2a4 flags verified ) ) game ( @@ -6543,7 +6687,7 @@ game ( game ( name "Fire Emblem - Fuuin no Tsurugi (Japan)" description "Fire Emblem - Fuuin no Tsurugi (Japan)" - rom ( name "Fire Emblem - Fuuin no Tsurugi (Japan).gba" size 8388608 crc d38763e1 sha1 a57095da867de4d585c33d4394712986245fe6ca ) + rom ( name "Fire Emblem - Fuuin no Tsurugi (Japan).gba" size 8388608 crc d38763e1 sha1 a57095da867de4d585c33d4394712986245fe6ca flags verified ) ) game ( @@ -6579,7 +6723,7 @@ game ( game ( name "Fire Emblem - Seima no Kouseki (Japan)" description "Fire Emblem - Seima no Kouseki (Japan)" - rom ( name "Fire Emblem - Seima no Kouseki (Japan).gba" size 16777216 crc 9d76826f sha1 7da0456035366aa18414faa79d8fe7649f03c1ed ) + rom ( name "Fire Emblem - Seima no Kouseki (Japan).gba" size 16777216 crc 9d76826f sha1 7da0456035366aa18414faa79d8fe7649f03c1ed flags verified ) ) game ( @@ -6648,6 +6792,12 @@ game ( rom ( name "Flintstones, The - Big Trouble in Bedrock (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 39782c26 sha1 3eb5a53a395acfaae672d8b8e3c79fc4442a00ab ) ) +game ( + name "Flood (World) (v0.9) (Proto) (Unl)" + description "Flood (World) (v0.9) (Proto) (Unl)" + rom ( name "Flood (World) (v0.9) (Proto) (Unl).gba" size 485108 crc 46ad658a sha1 c3e6dfaca1570fb7d2af45a25fd93e94e11beb1e ) +) + game ( name "Flushed Away (USA)" description "Flushed Away (USA)" @@ -6741,7 +6891,7 @@ game ( game ( name "Freekstyle (USA)" description "Freekstyle (USA)" - rom ( name "Freekstyle (USA).gba" size 8388608 crc 72434345 sha1 dcecce5ebc93cfc421094ecb00a50dfe371bad24 ) + rom ( name "Freekstyle (USA).gba" size 8388608 crc 72434345 sha1 dcecce5ebc93cfc421094ecb00a50dfe371bad24 flags verified ) ) game ( @@ -6876,6 +7026,12 @@ game ( rom ( name "Futari wa Pretty Cure Max Heart - Maji Maji! Fight de IN Janai (Japan).gba" size 8388608 crc 541c18f9 sha1 fb6b864b13f41af2521c7e9c7bec0b490962452f ) ) +game ( + name "Fuzz & Rocket (USA) (Proto) (2005-01-18)" + description "Fuzz & Rocket (USA) (Proto) (2005-01-18)" + rom ( name "Fuzz & Rocket (USA) (Proto) (2005-01-18).gba" size 4124984 crc fd239437 sha1 e6dab28aa3e9a5b1417bbf3929c45ff7260803b0 ) +) + game ( name "Gachasute! Dino Device - Blue (Japan)" description "Gachasute! Dino Device - Blue (Japan)" @@ -7038,6 +7194,12 @@ game ( rom ( name "Gang del Bosco, La (Italy).gba" size 8388608 crc 52a5b59d sha1 75e7060b7dce72d01fbd6a6d1d8e1d752bfc92d0 ) ) +game ( + name "Gap-Man (World) (Unl)" + description "Gap-Man (World) (Unl)" + rom ( name "Gap-Man (World) (Unl).gba" size 122052 crc 05e327d1 sha1 839b1115f11192864e90637c964e79872c6b4b88 ) +) + game ( name "Garfield - The Search for Pooky (USA) (En,Fr,De,Es,It)" description "Garfield - The Search for Pooky (USA) (En,Fr,De,Es,It)" @@ -7080,6 +7242,18 @@ game ( rom ( name "Gauntlet - Dark Legacy (USA).gba" size 8388608 crc e99de964 sha1 3ea608f4ea2235886fa1d7256f6a9ae88c2c0e28 ) ) +game ( + name "GB-A TV Tuner PAL (China) (v1.3) (Unl)" + description "GB-A TV Tuner PAL (China) (v1.3) (Unl)" + rom ( name "GB-A TV Tuner PAL (China) (v1.3) (Unl).gba" size 524288 crc 63524b0f sha1 256f5510a2051ae0512c4e1e90b9a572b1d859b6 ) +) + +game ( + name "GB-A TV Tuner PAL (China) (v2.0) (Unl)" + description "GB-A TV Tuner PAL (China) (v2.0) (Unl)" + rom ( name "GB-A TV Tuner PAL (China) (v2.0) (Unl).gba" size 524288 crc 0abecb5b sha1 96425bba00c21cd5c1970d6d80de547a1e226338 ) +) + game ( name "GBA AV Adapter (China) (Unl)" description "GBA AV Adapter (China) (Unl)" @@ -7093,9 +7267,15 @@ game ( ) game ( - name "GBA Movie Player 2 CF (Spain) (Unl)" - description "GBA Movie Player 2 CF (Spain) (Unl)" - rom ( name "GBA Movie Player 2 CF (Spain) (Unl).gba" size 1048576 crc c879b340 sha1 55cf23d0b941b68fb89e35d5ee57a78d30b54827 ) + name "GBA Movie Player - 2nd Version (World) (V2.00) (Unl)" + description "GBA Movie Player - 2nd Version (World) (V2.00) (Unl)" + rom ( name "GBA Movie Player - 2nd Version (World) (V2.00) (Unl).gba" size 524288 crc 3fc91d4f sha1 36739e9467204c6b2a64211dcda7370af23972ed ) +) + +game ( + name "GBA Movie Player - 2nd Version (World) (Unl) [b]" + description "GBA Movie Player - 2nd Version (World) (Unl) [b]" + rom ( name "GBA Movie Player - 2nd Version (World) (Unl) [b].gba" size 1048576 crc c879b340 sha1 55cf23d0b941b68fb89e35d5ee57a78d30b54827 flags baddump ) ) game ( @@ -7104,18 +7284,6 @@ game ( rom ( name "GBA Personal Organizer (USA) (Unl).gba" size 1048576 crc 424f71e5 sha1 26e7a5435372c46628985cba57f12a322b59537b ) ) -game ( - name "GBA TV Tuner PAL (China) (v1.3) (Unl)" - description "GBA TV Tuner PAL (China) (v1.3) (Unl)" - rom ( name "GBA TV Tuner PAL (China) (v1.3) (Unl).gba" size 1048576 crc af124f8c sha1 e0899f4097054862d33c03e21e9d4a5eef790402 ) -) - -game ( - name "GBA TV Tuner PAL (China) (v2.0) (Unl)" - description "GBA TV Tuner PAL (China) (v2.0) (Unl)" - rom ( name "GBA TV Tuner PAL (China) (v2.0) (Unl).gba" size 8388608 crc b511df64 sha1 5a62463cbaaa0c4586e227ad6ca6a5d54485d955 ) -) - game ( name "Gegege no Kitarou - Kikiippatsu! Youkai Rettou (Japan)" description "Gegege no Kitarou - Kikiippatsu! Youkai Rettou (Japan)" @@ -7218,12 +7386,6 @@ game ( rom ( name "Ghost Trap (Japan).gba" size 8388608 crc 81ea54e2 sha1 00efb5ed50127f91e2a2827926cf2d4491e4b1b3 ) ) -game ( - name "Glacia Dungeon (World) (En,Es,Ru,Ro) (v1.5.2) (Aftermarket) (Unl)" - description "Glacia Dungeon (World) (En,Es,Ru,Ro) (v1.5.2) (Aftermarket) (Unl)" - rom ( name "Glacia Dungeon (World) (En,Es,Ru,Ro) (v1.5.2) (Aftermarket) (Unl).gba" size 1210608 crc ab5ae65b sha1 e35037ff9cc24f8a7043d9a9d378e86d2ef80f9b ) -) - game ( name "Global Star - Sudoku Fever (USA)" description "Global Star - Sudoku Fever (USA)" @@ -7236,6 +7398,12 @@ game ( rom ( name "Global Star - Sudoku Fever (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 383cf600 sha1 8a6ab9e999cb9618bf169f70a9423abdc0de6a92 ) ) +game ( + name "Glucoboy (Australia)" + description "Glucoboy (Australia)" + rom ( name "Glucoboy (Australia).gba" size 16777216 crc 6e2d7eff sha1 4e9e198aef017bfe49802824e436ce47f2e807bb ) +) + game ( name "Go! Go! Beckham! - Adventure on Soccer Island (Europe) (En,Fr,De,Es,It)" description "Go! Go! Beckham! - Adventure on Soccer Island (Europe) (En,Fr,De,Es,It)" @@ -7269,7 +7437,7 @@ game ( game ( name "Golden Nugget Casino (USA, Europe)" description "Golden Nugget Casino (USA, Europe)" - rom ( name "Golden Nugget Casino (USA, Europe).gba" size 4194304 crc 56b9e9e1 sha1 5ecf4ead4b22a5916086a34bbf2abf299aaf3401 ) + rom ( name "Golden Nugget Casino (USA, Europe).gba" size 4194304 crc 56b9e9e1 sha1 5ecf4ead4b22a5916086a34bbf2abf299aaf3401 flags verified ) ) game ( @@ -7338,48 +7506,6 @@ game ( rom ( name "Golden Sun - The Lost Age (USA, Europe) (Virtual Console).gba" size 16777216 crc 726bb764 sha1 3c15317369ecafcd3c018d13c297d9107790f14f flags verified ) ) -game ( - name "Goodboy Galaxy (World) (En) (Demo) (Aftermarket) (Unl)" - description "Goodboy Galaxy (World) (En) (Demo) (Aftermarket) (Unl)" - rom ( name "Goodboy Galaxy (World) (En) (Demo) (Aftermarket) (Unl).gba" size 13224124 crc 19ba7d80 sha1 1bf95f8730ecdfa6665b85bea8764f42a88e8e3d ) -) - -game ( - name "Goodboy Galaxy (World) (Ja) (Demo) (Aftermarket) (Unl)" - description "Goodboy Galaxy (World) (Ja) (Demo) (Aftermarket) (Unl)" - rom ( name "Goodboy Galaxy (World) (Ja) (Demo) (Aftermarket) (Unl).gba" size 13219728 crc d4621e3e sha1 5bd59fac58c5f9a375216e9d1cf85fa5262f21f7 ) -) - -game ( - name "Goodboy Galaxy (World) (Fr) (Demo) (Aftermarket) (Unl)" - description "Goodboy Galaxy (World) (Fr) (Demo) (Aftermarket) (Unl)" - rom ( name "Goodboy Galaxy (World) (Fr) (Demo) (Aftermarket) (Unl).gba" size 13225068 crc 21512022 sha1 8832d38f787f3e1da620fcae7514d7387445ccf2 ) -) - -game ( - name "Goodboy Galaxy (World) (Es) (Demo) (Aftermarket) (Unl)" - description "Goodboy Galaxy (World) (Es) (Demo) (Aftermarket) (Unl)" - rom ( name "Goodboy Galaxy (World) (Es) (Demo) (Aftermarket) (Unl).gba" size 13223944 crc c1811c9b sha1 9d413bce82708df137215a2968306a5196b1638b ) -) - -game ( - name "Goodboy Galaxy (World) (Zh) (Demo) (Aftermarket) (Unl)" - description "Goodboy Galaxy (World) (Zh) (Demo) (Aftermarket) (Unl)" - rom ( name "Goodboy Galaxy (World) (Zh) (Demo) (Aftermarket) (Unl).gba" size 13269108 crc 3360e114 sha1 50186922ff77714b9ac638948b464cdbf80ab5fb ) -) - -game ( - name "Goodboy Galaxy (World) (Pt) (Demo) (Aftermarket) (Unl)" - description "Goodboy Galaxy (World) (Pt) (Demo) (Aftermarket) (Unl)" - rom ( name "Goodboy Galaxy (World) (Pt) (Demo) (Aftermarket) (Unl).gba" size 13223696 crc 3477ef15 sha1 4b447de09a23fbfdaa6d640824f8ceb5bbe56fab ) -) - -game ( - name "Goodboy Galaxy (World) (Ar) (Demo) (Aftermarket) (Unl)" - description "Goodboy Galaxy (World) (Ar) (Demo) (Aftermarket) (Unl)" - rom ( name "Goodboy Galaxy (World) (Ar) (Demo) (Aftermarket) (Unl).gba" size 13250016 crc a4054c2b sha1 c3cd833b9bdf87a8481c9b05251bba782bc3527e ) -) - game ( name "GP-1 Racing (USA) (Proto)" description "GP-1 Racing (USA) (Proto)" @@ -7440,18 +7566,18 @@ game ( rom ( name "Gremlins - Stripe vs Gizmo (Europe) (En,Fr,De,Es,It,Pt) (Beta).gba" size 4194304 crc 68ae6bbb sha1 6aa43d0624af03214473f329fda6334dc9c63009 ) ) -game ( - name "Gremlins - Stripe vs Gizmo (Europe) (En,Fr,De,Es,It,Pt)" - description "Gremlins - Stripe vs Gizmo (Europe) (En,Fr,De,Es,It,Pt)" - rom ( name "Gremlins - Stripe vs Gizmo (Europe) (En,Fr,De,Es,It,Pt).gba" size 4194304 crc b6225186 sha1 a2c4bf97785e717ef45e4b73a6c66a2d4ae18192 ) -) - game ( name "Gremlins - Stripe vs Gizmo (USA)" description "Gremlins - Stripe vs Gizmo (USA)" rom ( name "Gremlins - Stripe vs Gizmo (USA).gba" size 4194304 crc 5e72899a sha1 ee32e704598d2b6a21b3db271f9cf94578b94744 ) ) +game ( + name "Gremlins - Stripe vs Gizmo (Europe) (En,Fr,De,Es,It,Pt)" + description "Gremlins - Stripe vs Gizmo (Europe) (En,Fr,De,Es,It,Pt)" + rom ( name "Gremlins - Stripe vs Gizmo (Europe) (En,Fr,De,Es,It,Pt).gba" size 4194304 crc b6225186 sha1 a2c4bf97785e717ef45e4b73a6c66a2d4ae18192 ) +) + game ( name "Grim Adventures of Billy & Mandy, The (USA)" description "Grim Adventures of Billy & Mandy, The (USA)" @@ -7497,7 +7623,7 @@ game ( game ( name "GT Advance 3 - Pro Concept Racing (Europe)" description "GT Advance 3 - Pro Concept Racing (Europe)" - rom ( name "GT Advance 3 - Pro Concept Racing (Europe).gba" size 8388608 crc 03898e7f sha1 1e81d7ad7a9d8c179ef9f1a2e334a155799fe788 ) + rom ( name "GT Advance 3 - Pro Concept Racing (Europe).gba" size 8388608 crc 03898e7f sha1 1e81d7ad7a9d8c179ef9f1a2e334a155799fe788 flags verified ) ) game ( @@ -7530,18 +7656,6 @@ game ( rom ( name "Gu Huo Lang 4 (Taiwan) (Unl).gba" size 33554432 crc 1608f6db sha1 8c40ce7a06f741fb11aa717b7ce2f151279fa2e2 ) ) -game ( - name "Guilty Gear X - Advance Edition (Japan) (Beta)" - description "Guilty Gear X - Advance Edition (Japan) (Beta)" - rom ( name "Guilty Gear X - Advance Edition (Japan) (Beta).gba" size 8388608 crc 4506ada8 sha1 85915ecf10ce73afe9fffbbc8cd7a449dfe802c4 ) -) - -game ( - name "Guilty Gear X - Advance Edition (USA)" - description "Guilty Gear X - Advance Edition (USA)" - rom ( name "Guilty Gear X - Advance Edition (USA).gba" size 8388608 crc 70db3f96 sha1 bb064410c57324b25de96d297338cc5e73262fe6 ) -) - game ( name "Guilty Gear X - Advance Edition (Japan)" description "Guilty Gear X - Advance Edition (Japan)" @@ -7554,6 +7668,18 @@ game ( rom ( name "Guilty Gear X - Advance Edition (Europe).gba" size 8388608 crc ba95861d sha1 8236a650a18dfedc22da7c00b5affd3e752ec5de ) ) +game ( + name "Guilty Gear X - Advance Edition (USA)" + description "Guilty Gear X - Advance Edition (USA)" + rom ( name "Guilty Gear X - Advance Edition (USA).gba" size 8388608 crc 70db3f96 sha1 bb064410c57324b25de96d297338cc5e73262fe6 ) +) + +game ( + name "Guilty Gear X - Advance Edition (Japan) (Beta)" + description "Guilty Gear X - Advance Edition (Japan) (Beta)" + rom ( name "Guilty Gear X - Advance Edition (Japan) (Beta).gba" size 8388608 crc 4506ada8 sha1 85915ecf10ce73afe9fffbbc8cd7a449dfe802c4 ) +) + game ( name "Gumby vs. the Astrobots (USA)" description "Gumby vs. the Astrobots (USA)" @@ -7591,9 +7717,9 @@ game ( ) game ( - name "Guru Logic Champ (Japan)" - description "Guru Logic Champ (Japan)" - rom ( name "Guru Logic Champ (Japan).gba" size 4194304 crc 30d04ad9 sha1 77588b6e802de57d1d826c4d43e4c3b0e3aebdae ) + name "Guru Logichamp (Japan)" + description "Guru Logichamp (Japan)" + rom ( name "Guru Logichamp (Japan).gba" size 4194304 crc 30d04ad9 sha1 77588b6e802de57d1d826c4d43e4c3b0e3aebdae ) ) game ( @@ -7758,6 +7884,12 @@ game ( rom ( name "Hamtaro - Rainbow Rescue (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc 5d051081 sha1 b6446397744c10eb08f112f005e995dd9954a675 ) ) +game ( + name "Hamtaro - Rainbow Rescue (USA) (Proto) (2003-07-29)" + description "Hamtaro - Rainbow Rescue (USA) (Proto) (2003-07-29)" + rom ( name "Hamtaro - Rainbow Rescue (USA) (Proto) (2003-07-29).gba" size 8388608 crc 5c5b934d sha1 b081395415fae9cd59963a5b85bc7cc0d5623cb9 ) +) + game ( name "Hanabi Hyakkei Advance (Japan)" description "Hanabi Hyakkei Advance (Japan)" @@ -7773,13 +7905,13 @@ game ( game ( name "Happy Feet (Europe) (En,Fr,De,Es,It)" description "Happy Feet (Europe) (En,Fr,De,Es,It)" - rom ( name "Happy Feet (Europe) (En,Fr,De,Es,It).gba" size 33554432 crc 7a53173c sha1 cbccce77bb727efa7ab4805509773121239faf13 ) + rom ( name "Happy Feet (Europe) (En,Fr,De,Es,It).gba" size 33554432 crc b8653e59 sha1 1eabcfe84bd7558f64197e890a0eda8e76cdbc2c ) ) game ( name "Happy Feet (USA) (En,Fr)" description "Happy Feet (USA) (En,Fr)" - rom ( name "Happy Feet (USA) (En,Fr).gba" size 33554432 crc 682617cf sha1 e7c95cbc076e97ed2a414abc9f8d419e47174505 ) + rom ( name "Happy Feet (USA) (En,Fr).gba" size 33554432 crc 98235433 sha1 be8373ca6b9969af85303b1ec910ceb28b4f59f6 flags verified ) ) game ( @@ -7863,7 +7995,7 @@ game ( game ( name "Harry Potter Collection (Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da)" description "Harry Potter Collection (Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da)" - rom ( name "Harry Potter Collection (Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da).gba" size 33554432 crc ffa9f4fb sha1 a0e1a8f0c31ffd6e82ef99c95f903347a6eae623 ) + rom ( name "Harry Potter Collection (Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da).gba" size 33554432 crc 4f39c174 sha1 1af909d2e9604501b094da95dd3e4d96e72778e8 ) ) game ( @@ -8016,6 +8148,12 @@ game ( rom ( name "Hi Hi Puffy AmiYumi - Kaznapped! (Europe) (En,De).gba" size 8388608 crc e5531d04 sha1 4060be81c5a0bc741d759f75cd83823106e5b6b9 ) ) +game ( + name "Hi Hi Puffy AmiYumi - Puffy Ami Yumi and the Manga Madman! (USA) (Proto)" + description "Hi Hi Puffy AmiYumi - Puffy Ami Yumi and the Manga Madman! (USA) (Proto)" + rom ( name "Hi Hi Puffy AmiYumi - Puffy Ami Yumi and the Manga Madman! (USA) (Proto).gba" size 8388608 crc d048ec49 sha1 f0a5e83593a3dd2c32166e6a6e48d550d7de9ecb ) +) + game ( name "Higanbana (Japan) (Rev 1)" description "Higanbana (Japan) (Rev 1)" @@ -8077,9 +8215,9 @@ game ( ) game ( - name "Himawari Doubutsu Byouin - Pet no Oishasan Ikusei Game (Japan)" - description "Himawari Doubutsu Byouin - Pet no Oishasan Ikusei Game (Japan)" - rom ( name "Himawari Doubutsu Byouin - Pet no Oishasan Ikusei Game (Japan).gba" size 8388608 crc 8ea9afcc sha1 fefc7a73ddceaf28ebb95b88f5f39a5489024d4e ) + name "Hikaru no Go 3 - Senyou Joy Carry Cartridge (Japan) (Rewritable Cartridge)" + description "Hikaru no Go 3 - Senyou Joy Carry Cartridge (Japan) (Rewritable Cartridge)" + rom ( name "Hikaru no Go 3 - Senyou Joy Carry Cartridge (Japan) (Rewritable Cartridge).gba" size 33554432 crc 5bfbc276 sha1 e064ceecae66f7eb0b6ba4f19424a52e504f4bf2 ) ) game ( @@ -8088,6 +8226,12 @@ game ( rom ( name "Himawari Doubutsu Byouin - Pet no Oishasan Ikusei Game (Japan) (Rev 1).gba" size 8388608 crc 526fdfff sha1 93b98fcf585483722240e56c01826ae5c31930e4 ) ) +game ( + name "Himawari Doubutsu Byouin - Pet no Oishasan Ikusei Game (Japan)" + description "Himawari Doubutsu Byouin - Pet no Oishasan Ikusei Game (Japan)" + rom ( name "Himawari Doubutsu Byouin - Pet no Oishasan Ikusei Game (Japan).gba" size 8388608 crc 8ea9afcc sha1 fefc7a73ddceaf28ebb95b88f5f39a5489024d4e ) +) + game ( name "Hime Kishi Monogatari - Princess Blue (Japan)" description "Hime Kishi Monogatari - Princess Blue (Japan)" @@ -8118,10 +8262,16 @@ game ( rom ( name "Hobbit, The - The Prelude to the Lord of the Rings (USA).gba" size 8388608 crc d3f654b3 sha1 70d04d6d3ab8a1bfc4fa1a26d55cd4f73f84d479 ) ) +game ( + name "Holy Bible, The - World English Bible (USA) (Proto)" + description "Holy Bible, The - World English Bible (USA) (Proto)" + rom ( name "Holy Bible, The - World English Bible (USA) (Proto).gba" size 4194304 crc 0152a619 sha1 807d0b3dcf5ea7e972a0ecf0cecb03a040befb91 ) +) + game ( name "Home on the Range (USA) (En,Fr)" description "Home on the Range (USA) (En,Fr)" - rom ( name "Home on the Range (USA) (En,Fr).gba" size 8388608 crc dbd4a6cb sha1 321bce711714f718ac3882acdc3c0f659db5191d ) + rom ( name "Home on the Range (USA) (En,Fr).gba" size 8388608 crc dbd4a6cb sha1 321bce711714f718ac3882acdc3c0f659db5191d flags verified ) ) game ( @@ -8304,18 +8454,18 @@ game ( rom ( name "Hugo 2 in 1 (Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi,Pl).gba" size 8388608 crc 8eae8860 sha1 ba780a01415ac4b814e5376c077fda21d493f396 ) ) -game ( - name "Hunter X Hunter - Minna Tomodachi Daisakusen!! (Japan)" - description "Hunter X Hunter - Minna Tomodachi Daisakusen!! (Japan)" - rom ( name "Hunter X Hunter - Minna Tomodachi Daisakusen!! (Japan).gba" size 16777216 crc af22a5ea sha1 e752cad1fa3ffec56c9f6ca5886f37da0dc74240 ) -) - game ( name "Hunter X Hunter - Minna Tomodachi Daisakusen!! (Japan) (Rev 1)" description "Hunter X Hunter - Minna Tomodachi Daisakusen!! (Japan) (Rev 1)" rom ( name "Hunter X Hunter - Minna Tomodachi Daisakusen!! (Japan) (Rev 1).gba" size 16777216 crc 86c21aeb sha1 5a327073c67ee6a29bdd595f0c4031f055804e32 ) ) +game ( + name "Hunter X Hunter - Minna Tomodachi Daisakusen!! (Japan)" + description "Hunter X Hunter - Minna Tomodachi Daisakusen!! (Japan)" + rom ( name "Hunter X Hunter - Minna Tomodachi Daisakusen!! (Japan).gba" size 16777216 crc af22a5ea sha1 e752cad1fa3ffec56c9f6ca5886f37da0dc74240 ) +) + game ( name "Huo-Wen Zhanji - Fengyin Zhi Jian (China) (Proto)" description "Huo-Wen Zhanji - Fengyin Zhi Jian (China) (Proto)" @@ -8334,6 +8484,12 @@ game ( rom ( name "I Spy Challenger! (USA).gba" size 8388608 crc 946d2cbb sha1 532934239ea1151927fd45298d918e0646a6bea4 ) ) +game ( + name "I-Ninja (USA) (Proto)" + description "I-Ninja (USA) (Proto)" + rom ( name "I-Ninja (USA) (Proto).gba" size 8388608 crc 8f31e9c6 sha1 c5ca0f7d1d836285202fbd674ef914a7da87b024 ) +) + game ( name "Ice Age (USA) (En,Fr,Es)" description "Ice Age (USA) (En,Fr,Es)" @@ -8514,12 +8670,6 @@ game ( rom ( name "iQue Video & Audio (China).gba" size 16777216 crc 92852a72 sha1 79c7494c116e276f85a5f62d59f3a4588bd88391 ) ) -game ( - name "Iridion 3D (USA) (Aftermarket) (Unl)" - description "Iridion 3D (USA) (Aftermarket) (Unl)" - rom ( name "Iridion 3D (USA) (Aftermarket) (Unl).gba" size 4194304 crc 4c7ebe42 sha1 6f1c77ab88351d2d50da412e4788fc7ca8a6714d ) -) - game ( name "Iridion 3D (USA, Europe)" description "Iridion 3D (USA, Europe)" @@ -8535,7 +8685,7 @@ game ( game ( name "Iridion II (Europe) (En,Fr,De)" description "Iridion II (Europe) (En,Fr,De)" - rom ( name "Iridion II (Europe) (En,Fr,De).gba" size 8388608 crc 57930c6a sha1 661442c24404cc0727e4343f9ce570c87c797661 ) + rom ( name "Iridion II (Europe) (En,Fr,De).gba" size 8388608 crc 57930c6a sha1 661442c24404cc0727e4343f9ce570c87c797661 flags verified ) ) game ( @@ -8544,12 +8694,6 @@ game ( rom ( name "Iridion II (USA) (Beta).gba" size 8388608 crc 9c63d17c sha1 3e951fd97bacd4f258bf30785af22934f7697a91 ) ) -game ( - name "Iridion II (USA) (Aftermarket) (Unl)" - description "Iridion II (USA) (Aftermarket) (Unl)" - rom ( name "Iridion II (USA) (Aftermarket) (Unl).gba" size 8388608 crc b371f070 sha1 cc788b38a047ff5ec8c445ce11efcd1852ad7c4d ) -) - game ( name "Iron Kid (Korea)" description "Iron Kid (Korea)" @@ -8559,7 +8703,7 @@ game ( game ( name "Island Xtreme Stunts (USA, Europe) (En,Fr,De,Es,It,Nl,Sv,Da)" description "Island Xtreme Stunts (USA, Europe) (En,Fr,De,Es,It,Nl,Sv,Da)" - rom ( name "Island Xtreme Stunts (USA, Europe) (En,Fr,De,Es,It,Nl,Sv,Da).gba" size 4194304 crc 3beb5446 sha1 4eec876994bdea873188fe10033c48c924d129ec ) + rom ( name "Island Xtreme Stunts (USA, Europe) (En,Fr,De,Es,It,Nl,Sv,Da).gba" size 4194304 crc 3beb5446 sha1 4eec876994bdea873188fe10033c48c924d129ec flags verified ) ) game ( @@ -8574,18 +8718,18 @@ game ( rom ( name "It's Mr. Pants (USA, Europe).gba" size 4194304 crc 757a4efb sha1 c49742f964a698ccce0520e24368a9d425a29b4d flags verified ) ) -game ( - name "J.League Pocket (Japan)" - description "J.League Pocket (Japan)" - rom ( name "J.League Pocket (Japan).gba" size 8388608 crc 51be73b8 sha1 b4cd024b10d740f3525dddfbcc613c04a8d4c166 ) -) - game ( name "J.League Pocket (Japan) (Rev 1)" description "J.League Pocket (Japan) (Rev 1)" rom ( name "J.League Pocket (Japan) (Rev 1).gba" size 8388608 crc 0524e9ef sha1 64c6b3f0113d91daf41e63b2755d26b9ed0cea3a ) ) +game ( + name "J.League Pocket (Japan)" + description "J.League Pocket (Japan)" + rom ( name "J.League Pocket (Japan).gba" size 8388608 crc 51be73b8 sha1 b4cd024b10d740f3525dddfbcc613c04a8d4c166 ) +) + game ( name "J.League Pocket 2 (Japan)" description "J.League Pocket 2 (Japan)" @@ -8673,7 +8817,7 @@ game ( game ( name "Jimmy Neutron - Boy Genius (USA)" description "Jimmy Neutron - Boy Genius (USA)" - rom ( name "Jimmy Neutron - Boy Genius (USA).gba" size 4194304 crc d3ee0c51 sha1 31ed7659e2e072d1c00baf95c0ee9c770e949900 ) + rom ( name "Jimmy Neutron - Boy Genius (USA).gba" size 4194304 crc d3ee0c51 sha1 31ed7659e2e072d1c00baf95c0ee9c770e949900 flags verified ) ) game ( @@ -8826,18 +8970,18 @@ game ( rom ( name "Justice League - Injustice for All (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc d71c4382 sha1 7385169111585230ba62007397802a7197653447 ) ) -game ( - name "Justice League - Injustice for All (USA) (Beta)" - description "Justice League - Injustice for All (USA) (Beta)" - rom ( name "Justice League - Injustice for All (USA) (Beta).gba" size 8388608 crc c41081cf sha1 e3302c2aa5cd14bf5546a3069bc6757363ee38b4 ) -) - game ( name "Justice League - Injustice for All (USA)" description "Justice League - Injustice for All (USA)" rom ( name "Justice League - Injustice for All (USA).gba" size 8388608 crc b2477b72 sha1 f7d774f3d1f1436c18b044c65e574dc327ad6437 ) ) +game ( + name "Justice League - Injustice for All (USA) (Beta)" + description "Justice League - Injustice for All (USA) (Beta)" + rom ( name "Justice League - Injustice for All (USA) (Beta).gba" size 8388608 crc c41081cf sha1 e3302c2aa5cd14bf5546a3069bc6757363ee38b4 ) +) + game ( name "Justice League Heroes - The Flash (USA)" description "Justice League Heroes - The Flash (USA)" @@ -9066,6 +9210,12 @@ game ( rom ( name "Kien (USA) (Proto).gba" size 8388608 crc 185c2eca sha1 da1673ec5ec35f8ececa3f04cb6a92d61237ce72 ) ) +game ( + name "Kien (World) (Proto) (Incub8 Games)" + description "Kien (World) (Proto) (Incub8 Games)" + rom ( name "Kien (World) (Proto) (Incub8 Games).gba" size 8350032 crc 5a64b473 sha1 3cf07cd95e5a83b65c773111051a50d9bef367eb flags verified ) +) + game ( name "Kikaika Guntai - Mech Platoon (Japan)" description "Kikaika Guntai - Mech Platoon (Japan)" @@ -9126,18 +9276,18 @@ game ( rom ( name "Kim Possible - Revenge of Monkey Fist (USA).gba" size 8388608 crc 1a56efbd sha1 64ef958beae876d3a6c295d0351d671b6991774b ) ) -game ( - name "Kim Possible 2 - Drakken's Demise (USA) (En,Fr)" - description "Kim Possible 2 - Drakken's Demise (USA) (En,Fr)" - rom ( name "Kim Possible 2 - Drakken's Demise (USA) (En,Fr).gba" size 8388608 crc fa946fc6 sha1 d2baaec3c20b48bebe79ebe27761cd107fd067bf flags verified ) -) - game ( name "Kim Possible 2 - Drakken's Demise (Europe) (En,Fr,De,Es)" description "Kim Possible 2 - Drakken's Demise (Europe) (En,Fr,De,Es)" rom ( name "Kim Possible 2 - Drakken's Demise (Europe) (En,Fr,De,Es).gba" size 8388608 crc 71c505c8 sha1 eb4099911dbd28073c554f4d4fa35cbeed82bc6b ) ) +game ( + name "Kim Possible 2 - Drakken's Demise (USA) (En,Fr)" + description "Kim Possible 2 - Drakken's Demise (USA) (En,Fr)" + rom ( name "Kim Possible 2 - Drakken's Demise (USA) (En,Fr).gba" size 8388608 crc fa946fc6 sha1 d2baaec3c20b48bebe79ebe27761cd107fd067bf flags verified ) +) + game ( name "Kim Possible 3 - Team Possible (USA) (En,Fr)" description "Kim Possible 3 - Team Possible (USA) (En,Fr)" @@ -9321,7 +9471,7 @@ game ( game ( name "Klonoa - Empire of Dreams (Europe)" description "Klonoa - Empire of Dreams (Europe)" - rom ( name "Klonoa - Empire of Dreams (Europe).gba" size 4194304 crc 69492530 sha1 e4a81713b134e0b7409708843dad2a4948b903ef ) + rom ( name "Klonoa - Empire of Dreams (Europe).gba" size 4194304 crc 69492530 sha1 e4a81713b134e0b7409708843dad2a4948b903ef flags verified ) ) game ( @@ -9531,7 +9681,7 @@ game ( game ( name "Korokoro Puzzle - Happy Panecchu! (Japan)" description "Korokoro Puzzle - Happy Panecchu! (Japan)" - rom ( name "Korokoro Puzzle - Happy Panecchu! (Japan).gba" size 4194304 crc 0bfe46e9 sha1 40cb751d119a49be0cd44cf0491c93ebc8795ef0 ) + rom ( name "Korokoro Puzzle - Happy Panecchu! (Japan).gba" size 4194304 crc 0bfe46e9 sha1 40cb751d119a49be0cd44cf0491c93ebc8795ef0 flags verified ) ) game ( @@ -9717,13 +9867,13 @@ game ( game ( name "Legend of Spyro, The - The Eternal Night (USA) (En,Fr)" description "Legend of Spyro, The - The Eternal Night (USA) (En,Fr)" - rom ( name "Legend of Spyro, The - The Eternal Night (USA) (En,Fr).gba" size 33554432 crc bd2751e6 sha1 4bc88f2c7325937bbe0f16dfebda10f279d5ed20 ) + rom ( name "Legend of Spyro, The - The Eternal Night (USA) (En,Fr).gba" size 33554432 crc 8d780224 sha1 6cfa38d08b735e8b6b1c3763aee8a8ed5da52977 ) ) game ( name "Legend of Spyro, The - The Eternal Night (Europe) (En,Fr,De,Es,It,Nl)" description "Legend of Spyro, The - The Eternal Night (Europe) (En,Fr,De,Es,It,Nl)" - rom ( name "Legend of Spyro, The - The Eternal Night (Europe) (En,Fr,De,Es,It,Nl).gba" size 33554432 crc 93b18353 sha1 4bce80310b43882f57c7bb5b202e09ce23687473 ) + rom ( name "Legend of Spyro, The - The Eternal Night (Europe) (En,Fr,De,Es,It,Nl).gba" size 33554432 crc a3eed091 sha1 0fced99190bce676e83bed31134e2f165ef997b8 ) ) game ( @@ -9942,10 +10092,16 @@ game ( rom ( name "Lilo & Stitch 2 - Haemsterviel Havoc (USA).gba" size 8388608 crc 021a5755 sha1 70e0dc5a8dcdf876b5dd87a4c1bbca03b6e30148 ) ) +game ( + name "Lindsi Luna Blast (World) (v1.01) (Unl)" + description "Lindsi Luna Blast (World) (v1.01) (Unl)" + rom ( name "Lindsi Luna Blast (World) (v1.01) (Unl).gba" size 4981720 crc e6fadd1a sha1 6786c08957251b3a5ab2534b15f5b2def2ee9d86 ) +) + game ( name "Lion King 1 1-2, The (USA)" description "Lion King 1 1-2, The (USA)" - rom ( name "Lion King 1 1-2, The (USA).gba" size 8388608 crc ea5ed4c0 sha1 382de6da61c5dc5c2844f5ffa28a1827d15319b1 ) + rom ( name "Lion King 1 1-2, The (USA).gba" size 8388608 crc ea5ed4c0 sha1 382de6da61c5dc5c2844f5ffa28a1827d15319b1 flags verified ) ) game ( @@ -9999,7 +10155,7 @@ game ( game ( name "Lizzie McGuire 2 - Lizzie Diaries (USA) (En,Fr)" description "Lizzie McGuire 2 - Lizzie Diaries (USA) (En,Fr)" - rom ( name "Lizzie McGuire 2 - Lizzie Diaries (USA) (En,Fr).gba" size 4194304 crc f11009f9 sha1 7ace37aec21c058aa98e3de12140cb691c070e00 ) + rom ( name "Lizzie McGuire 2 - Lizzie Diaries (USA) (En,Fr).gba" size 4194304 crc f11009f9 sha1 7ace37aec21c058aa98e3de12140cb691c070e00 flags verified ) ) game ( @@ -10417,9 +10573,9 @@ game ( ) game ( - name "Mandrake the Magician (Italy) (It) (Proto)" - description "Mandrake the Magician (Italy) (It) (Proto)" - rom ( name "Mandrake the Magician (Italy) (It) (Proto).gba" size 8388608 crc 7cfe1889 sha1 ddb5f0cdd5db80c22a448650c1b05d02feb0b831 ) + name "Mandrake the Magician (Italy) (Proto)" + description "Mandrake the Magician (Italy) (Proto)" + rom ( name "Mandrake the Magician (Italy) (Proto).gba" size 8388608 crc 7cfe1889 sha1 ddb5f0cdd5db80c22a448650c1b05d02feb0b831 ) ) game ( @@ -10470,6 +10626,12 @@ game ( rom ( name "Marie, Elie & Anis no Atelier - Soyokaze kara no Dengon (Japan).gba" size 8388608 crc 1b70a454 sha1 0dbde8bcaa9e4bdc201674a0d66c6ce64242eb4b ) ) +game ( + name "Mario & Luigi (USA) (Demo) (Kiosk, E3 2003)" + description "Mario & Luigi (USA) (Demo) (Kiosk, E3 2003)" + rom ( name "Mario & Luigi (USA) (Demo) (Kiosk, E3 2003).gba" size 8388608 crc 2d01a8df sha1 4265af33441ad7b16566ea6c6a2803dc8e9cdf9b ) +) + game ( name "Mario & Luigi - Superstar Saga (USA) (Demo) (Kiosk)" description "Mario & Luigi - Superstar Saga (USA) (Demo) (Kiosk)" @@ -10767,13 +10929,13 @@ game ( game ( name "Mary-Kate and Ashley - Girls Night Out (USA, Europe)" description "Mary-Kate and Ashley - Girls Night Out (USA, Europe)" - rom ( name "Mary-Kate and Ashley - Girls Night Out (USA, Europe).gba" size 4194304 crc 8af3f3ad sha1 4b46751b6deb8064d58a0786d62b37206c9529ac ) + rom ( name "Mary-Kate and Ashley - Girls Night Out (USA, Europe).gba" size 4194304 crc 8af3f3ad sha1 4b46751b6deb8064d58a0786d62b37206c9529ac flags verified ) ) game ( name "Mary-Kate and Ashley - Sweet 16 - Licensed to Drive (USA, Europe)" description "Mary-Kate and Ashley - Sweet 16 - Licensed to Drive (USA, Europe)" - rom ( name "Mary-Kate and Ashley - Sweet 16 - Licensed to Drive (USA, Europe).gba" size 4194304 crc 5fe092c6 sha1 284059f03f0dda9ce511d3c57bf0607706b9fca3 ) + rom ( name "Mary-Kate and Ashley - Sweet 16 - Licensed to Drive (USA, Europe).gba" size 4194304 crc 5fe092c6 sha1 284059f03f0dda9ce511d3c57bf0607706b9fca3 flags verified ) ) game ( @@ -10812,18 +10974,6 @@ game ( rom ( name "Matantei Loki Ragnarok - Gensou no Labyrinth (Japan) (Rev 1).gba" size 8388608 crc d647ab18 sha1 3489569fa8a3c6a750c5cb0048915da78c5f40ab ) ) -game ( - name "Matchbox Cross Town Heroes (USA)" - description "Matchbox Cross Town Heroes (USA)" - rom ( name "Matchbox Cross Town Heroes (USA).gba" size 4194304 crc 0fffb458 sha1 6baa6bfe76b077f365bedffa52346b94689b61d7 ) -) - -game ( - name "Matchbox Cross Town Heroes (Europe)" - description "Matchbox Cross Town Heroes (Europe)" - rom ( name "Matchbox Cross Town Heroes (Europe).gba" size 4194304 crc c9ea02f5 sha1 13310b7f25a0332a8e09e722587ec79aee11c373 ) -) - game ( name "Math Patrol - The Kleptoid Threat (USA)" description "Math Patrol - The Kleptoid Threat (USA)" @@ -10896,6 +11046,12 @@ game ( rom ( name "Medabots - Metabee (Europe).gba" size 8388608 crc 50927f3e sha1 cd3d674e88f40a0707b150c4293588a659001d29 ) ) +game ( + name "Medabots - Metabee (USA)" + description "Medabots - Metabee (USA)" + rom ( name "Medabots - Metabee (USA).gba" size 8388608 crc 59f208fc sha1 ca185b65ab50ef89a10c8db00d9cd76626b81610 ) +) + game ( name "Medabots - Metabee (Spain)" description "Medabots - Metabee (Spain)" @@ -10909,15 +11065,9 @@ game ( ) game ( - name "Medabots - Metabee (USA)" - description "Medabots - Metabee (USA)" - rom ( name "Medabots - Metabee (USA).gba" size 8388608 crc 59f208fc sha1 ca185b65ab50ef89a10c8db00d9cd76626b81610 ) -) - -game ( - name "Medabots - Rokusho (USA)" - description "Medabots - Rokusho (USA)" - rom ( name "Medabots - Rokusho (USA).gba" size 8388608 crc e144ded2 sha1 c4572428ea97b302f699a3b4eba2a1f0e87c1c9c ) + name "Medabots - Rokusho (Spain)" + description "Medabots - Rokusho (Spain)" + rom ( name "Medabots - Rokusho (Spain).gba" size 8388608 crc 046d86c4 sha1 90fe7f2927c592aabc9b33d0df00d92046c5cb92 ) ) game ( @@ -10939,15 +11089,9 @@ game ( ) game ( - name "Medabots - Rokusho (Spain)" - description "Medabots - Rokusho (Spain)" - rom ( name "Medabots - Rokusho (Spain).gba" size 8388608 crc 046d86c4 sha1 90fe7f2927c592aabc9b33d0df00d92046c5cb92 ) -) - -game ( - name "Medabots AX - Metabee Ver. (USA)" - description "Medabots AX - Metabee Ver. (USA)" - rom ( name "Medabots AX - Metabee Ver. (USA).gba" size 8388608 crc 03294511 sha1 80c024df6d40e499776665d7f0c494a252973048 ) + name "Medabots - Rokusho (USA)" + description "Medabots - Rokusho (USA)" + rom ( name "Medabots - Rokusho (USA).gba" size 8388608 crc e144ded2 sha1 c4572428ea97b302f699a3b4eba2a1f0e87c1c9c ) ) game ( @@ -10956,6 +11100,12 @@ game ( rom ( name "Medabots AX - Metabee Ver. (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 5f1e5a48 sha1 130c908d24ba3e422fd8db84e683bacc87235e78 flags verified ) ) +game ( + name "Medabots AX - Metabee Ver. (USA)" + description "Medabots AX - Metabee Ver. (USA)" + rom ( name "Medabots AX - Metabee Ver. (USA).gba" size 8388608 crc 03294511 sha1 80c024df6d40e499776665d7f0c494a252973048 ) +) + game ( name "Medabots AX - Metabee Ver. (USA) (Virtual Console)" description "Medabots AX - Metabee Ver. (USA) (Virtual Console)" @@ -10998,12 +11148,6 @@ game ( rom ( name "Medal of Honor - Infiltrator (USA, Europe) (En,Fr,De).gba" size 16777216 crc f23150a4 sha1 47761911475e9548c81fed78e3d3336ddae89a58 flags verified ) ) -game ( - name "Medal of Honor - Underground (Europe) (En,Fr,Es,It) (Zoo Digital)" - description "Medal of Honor - Underground (Europe) (En,Fr,Es,It) (Zoo Digital)" - rom ( name "Medal of Honor - Underground (Europe) (En,Fr,Es,It) (Zoo Digital).gba" size 8388608 crc 72b4cf20 sha1 abb26d759ef729d21e41a913fc6c1ce4ab77149f ) -) - game ( name "Medal of Honor - Underground (USA)" description "Medal of Honor - Underground (USA)" @@ -11016,6 +11160,12 @@ game ( rom ( name "Medal of Honor - Underground (Europe) (En,Fr,Es,It) (Ubi Soft).gba" size 8388608 crc 9db145b8 sha1 e43aaba3f925443cfccf9294b870024a9c71a9a9 ) ) +game ( + name "Medal of Honor - Underground (Europe) (En,Fr,Es,It) (Zoo Digital)" + description "Medal of Honor - Underground (Europe) (En,Fr,Es,It) (Zoo Digital)" + rom ( name "Medal of Honor - Underground (Europe) (En,Fr,Es,It) (Zoo Digital).gba" size 8388608 crc 72b4cf20 sha1 abb26d759ef729d21e41a913fc6c1ce4ab77149f ) +) + game ( name "Medal of Honor Advance (Japan)" description "Medal of Honor Advance (Japan)" @@ -11253,7 +11403,7 @@ game ( game ( name "Megaman - Battle Network 4 - Blue Moon (Europe)" description "Megaman - Battle Network 4 - Blue Moon (Europe)" - rom ( name "Megaman - Battle Network 4 - Blue Moon (Europe).gba" size 8388608 crc 48758316 sha1 a05e8dce26b5134001337e193d49958be2081598 ) + rom ( name "Megaman - Battle Network 4 - Blue Moon (Europe).gba" size 8388608 crc 48758316 sha1 a05e8dce26b5134001337e193d49958be2081598 flags verified ) ) game ( @@ -11304,18 +11454,6 @@ game ( rom ( name "Megaman - Battle Network 5 - Team Colonel (Europe) (Virtual Console).gba" size 8388608 crc 5247772c sha1 061c291b29629d5ce44011d2d83931f2e35044ed ) ) -game ( - name "Megaman - Battle Network 5 - Team Protoman (Europe)" - description "Megaman - Battle Network 5 - Team Protoman (Europe)" - rom ( name "Megaman - Battle Network 5 - Team Protoman (Europe).gba" size 8388608 crc 79f45ed8 sha1 3d017ed23535e42174299ff89fff44678eb553c3 ) -) - -game ( - name "Megaman - Battle Network 5 - Team Protoman (USA)" - description "Megaman - Battle Network 5 - Team Protoman (USA)" - rom ( name "Megaman - Battle Network 5 - Team Protoman (USA).gba" size 8388608 crc a73e83a4 sha1 b3774e96b1f107bb8b1db79b216be41b9bc5bac0 ) -) - game ( name "Megaman - Battle Network 5 - Team Protoman (USA) (Virtual Console)" description "Megaman - Battle Network 5 - Team Protoman (USA) (Virtual Console)" @@ -11328,6 +11466,18 @@ game ( rom ( name "Megaman - Battle Network 5 - Team Protoman (Europe) (Virtual Console).gba" size 8388608 crc 7e5bc83d sha1 b68b310e3106e7fa6a47d4155239be2e43959da4 ) ) +game ( + name "Megaman - Battle Network 5 - Team Protoman (Europe)" + description "Megaman - Battle Network 5 - Team Protoman (Europe)" + rom ( name "Megaman - Battle Network 5 - Team Protoman (Europe).gba" size 8388608 crc 79f45ed8 sha1 3d017ed23535e42174299ff89fff44678eb553c3 ) +) + +game ( + name "Megaman - Battle Network 5 - Team Protoman (USA)" + description "Megaman - Battle Network 5 - Team Protoman (USA)" + rom ( name "Megaman - Battle Network 5 - Team Protoman (USA).gba" size 8388608 crc a73e83a4 sha1 b3774e96b1f107bb8b1db79b216be41b9bc5bac0 ) +) + game ( name "Megaman - Battle Network 6 - Cybeast Falzar (Europe)" description "Megaman - Battle Network 6 - Cybeast Falzar (Europe)" @@ -11382,12 +11532,6 @@ game ( rom ( name "Megaman & Bass (USA) (Virtual Console).gba" size 8388608 crc b61f99d4 sha1 37db963a52aecec8018057cef3811860c3e889ed ) ) -game ( - name "Megaman & Bass (Europe)" - description "Megaman & Bass (Europe)" - rom ( name "Megaman & Bass (Europe).gba" size 8388608 crc 01b4d95e sha1 5d6f8fb1f52803a54e9857e53d0b88173cf8f48a flags verified ) -) - game ( name "Megaman & Bass (Europe) (Virtual Console)" description "Megaman & Bass (Europe) (Virtual Console)" @@ -11401,9 +11545,9 @@ game ( ) game ( - name "Megaman Zero (USA, Europe)" - description "Megaman Zero (USA, Europe)" - rom ( name "Megaman Zero (USA, Europe).gba" size 8388608 crc 9707d2a1 sha1 193b14120119162518a73c70876f0b8bffdbd96e flags verified ) + name "Megaman & Bass (Europe)" + description "Megaman & Bass (Europe)" + rom ( name "Megaman & Bass (Europe).gba" size 8388608 crc 01b4d95e sha1 5d6f8fb1f52803a54e9857e53d0b88173cf8f48a flags verified ) ) game ( @@ -11413,9 +11557,9 @@ game ( ) game ( - name "Megaman Zero 2 (USA) (Virtual Console)" - description "Megaman Zero 2 (USA) (Virtual Console)" - rom ( name "Megaman Zero 2 (USA) (Virtual Console).gba" size 8388608 crc 30d051fe sha1 d7a1edd912f8e01bc442809b922bceaf5a1f0176 ) + name "Megaman Zero (USA, Europe)" + description "Megaman Zero (USA, Europe)" + rom ( name "Megaman Zero (USA, Europe).gba" size 8388608 crc 9707d2a1 sha1 193b14120119162518a73c70876f0b8bffdbd96e flags verified ) ) game ( @@ -11437,9 +11581,9 @@ game ( ) game ( - name "Megaman Zero 3 (Europe) (Virtual Console)" - description "Megaman Zero 3 (Europe) (Virtual Console)" - rom ( name "Megaman Zero 3 (Europe) (Virtual Console).gba" size 8388608 crc 87e8656e sha1 8245ecb895caf0e0a2914f46bb79e4c9c5ba8c4a ) + name "Megaman Zero 2 (USA) (Virtual Console)" + description "Megaman Zero 2 (USA) (Virtual Console)" + rom ( name "Megaman Zero 2 (USA) (Virtual Console).gba" size 8388608 crc 30d051fe sha1 d7a1edd912f8e01bc442809b922bceaf5a1f0176 ) ) game ( @@ -11460,6 +11604,12 @@ game ( rom ( name "Megaman Zero 3 (USA).gba" size 8388608 crc 2784f3f2 sha1 403a78f2cad93d41e4b0f2e520ce08026531664b ) ) +game ( + name "Megaman Zero 3 (Europe) (Virtual Console)" + description "Megaman Zero 3 (Europe) (Virtual Console)" + rom ( name "Megaman Zero 3 (Europe) (Virtual Console).gba" size 8388608 crc 87e8656e sha1 8245ecb895caf0e0a2914f46bb79e4c9c5ba8c4a ) +) + game ( name "Megaman Zero 4 (Europe) (Virtual Console)" description "Megaman Zero 4 (Europe) (Virtual Console)" @@ -11538,6 +11688,12 @@ game ( rom ( name "Mermaid Melody - Pichi Pichi Pitch - Pichi Pichitto Live Start! (Japan).gba" size 33554432 crc 7a4fdec3 sha1 d6bd3140b83fb9b1c2d84b6faf21c7286e29d129 ) ) +game ( + name "Metal Gear Solid 2D - Sensible (World) (v0.31) (Demo) (Unl)" + description "Metal Gear Solid 2D - Sensible (World) (v0.31) (Demo) (Unl)" + rom ( name "Metal Gear Solid 2D - Sensible (World) (v0.31) (Demo) (Unl).gba" size 149668 crc c797641c sha1 e8a32fbd80f644e9828369603c1a926392a4c105 ) +) + game ( name "Metal Max 2 Kai (Japan)" description "Metal Max 2 Kai (Japan)" @@ -11586,6 +11742,12 @@ game ( rom ( name "Metalgun Slinger (Japan).gba" size 8388608 crc 8dfb7a2f sha1 dbf9e8515d9993c6fbab921af65cbbdeabd4aa93 ) ) +game ( + name "Metroid - Zero Mission (Japan) (Virtual Console)" + description "Metroid - Zero Mission (Japan) (Virtual Console)" + rom ( name "Metroid - Zero Mission (Japan) (Virtual Console).gba" size 8388608 crc 220b68f5 sha1 24d99f32875464dbcef5ca8ec231ec42073ff1e8 ) +) + game ( name "Metroid - Zero Mission (USA)" description "Metroid - Zero Mission (USA)" @@ -11629,9 +11791,27 @@ game ( ) game ( - name "Metroid - Zero Mission (Japan) (Virtual Console)" - description "Metroid - Zero Mission (Japan) (Virtual Console)" - rom ( name "Metroid - Zero Mission (Japan) (Virtual Console).gba" size 8388608 crc 220b68f5 sha1 24d99f32875464dbcef5ca8ec231ec42073ff1e8 ) + name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-11)" + description "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-11)" + rom ( name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-11).gba" size 16777216 crc 3acbd239 sha1 a45b539becbf10f3913255d6d624ee954dcc5593 ) +) + +game ( + name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-16)" + description "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-16)" + rom ( name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-16).gba" size 8388608 crc 1605e4f7 sha1 f688f2d3186a0a90040abb214efd1e8e93a424cd ) +) + +game ( + name "Metroid Fusion (USA) (Virtual Console)" + description "Metroid Fusion (USA) (Virtual Console)" + rom ( name "Metroid Fusion (USA) (Virtual Console).gba" size 8388608 crc 162a46b8 sha1 c63419a4ee7c2a5e412fa16645ee04cb24027724 ) +) + +game ( + name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Virtual Console)" + description "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Virtual Console)" + rom ( name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Virtual Console).gba" size 8388608 crc eee01b78 sha1 82e507863f647dc566bbf45227e8cd284052ecba ) ) game ( @@ -11658,30 +11838,6 @@ game ( rom ( name "Metroid Fusion (Japan).gba" size 8388608 crc 817a7e9e sha1 5d21c668baa84da4a5b745be56809bb277f947a3 flags verified ) ) -game ( - name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-11)" - description "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-11)" - rom ( name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-11).gba" size 16777216 crc 3acbd239 sha1 a45b539becbf10f3913255d6d624ee954dcc5593 ) -) - -game ( - name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-16)" - description "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-16)" - rom ( name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Beta) (2002-09-16).gba" size 8388608 crc 1605e4f7 sha1 f688f2d3186a0a90040abb214efd1e8e93a424cd ) -) - -game ( - name "Metroid Fusion (USA) (Virtual Console)" - description "Metroid Fusion (USA) (Virtual Console)" - rom ( name "Metroid Fusion (USA) (Virtual Console).gba" size 8388608 crc 162a46b8 sha1 c63419a4ee7c2a5e412fa16645ee04cb24027724 ) -) - -game ( - name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Virtual Console)" - description "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Virtual Console)" - rom ( name "Metroid Fusion (Europe) (En,Fr,De,Es,It) (Virtual Console).gba" size 8388608 crc eee01b78 sha1 82e507863f647dc566bbf45227e8cd284052ecba ) -) - game ( name "Mezase! Koushien (Japan)" description "Mezase! Koushien (Japan)" @@ -11784,12 +11940,6 @@ game ( rom ( name "Mini Moni. - Onegai Ohoshi-sama! (Japan).gba" size 8388608 crc f11c35cc sha1 d34795cf3679c6f259177db52a138c0d6e9fcdfd ) ) -game ( - name "Minicraft (World) (Aftermarket) (Unl)" - description "Minicraft (World) (Aftermarket) (Unl)" - rom ( name "Minicraft (World) (Aftermarket) (Unl).gba" size 131072 crc e852c9e9 sha1 06faa5be11978666db6995d8fce40ce2c3641ce8 ) -) - game ( name "Minna de Puyo Puyo (Japan) (En,Ja)" description "Minna de Puyo Puyo (Japan) (En,Ja)" @@ -11898,12 +12048,6 @@ game ( rom ( name "Mirakuru! Panzou - 7-tsu no Hoshi no Uchuu Kaizoku (Japan).gba" size 4194304 crc 3a87f78b sha1 ad916495bbb9c3ee34b68c13f118a4cbcdb18b3b ) ) -game ( - name "Misfortune Advance (World) (Aftermarket) (Unl)" - description "Misfortune Advance (World) (Aftermarket) (Unl)" - rom ( name "Misfortune Advance (World) (Aftermarket) (Unl).gba" size 5125100 crc 18f2166d sha1 68e215025ac963220f16ea3c100e51698f97c4eb ) -) - game ( name "Mission Impossible - Operation Surma (Europe) (En,Fr,De,Es,It)" description "Mission Impossible - Operation Surma (Europe) (En,Fr,De,Es,It)" @@ -12156,18 +12300,6 @@ game ( rom ( name "Monsters, Inc. (Europe) (En,Es,Nl).gba" size 4194304 crc d13177e0 sha1 36645b8de074f0b27dbe61528e70ae3af28fb3b9 ) ) -game ( - name "Mooncat's Trio (World) (Aftermarket) (Unl)" - description "Mooncat's Trio (World) (Aftermarket) (Unl)" - rom ( name "Mooncat's Trio (World) (Aftermarket) (Unl).gba" size 1175680 crc b05d5339 sha1 890de7d73723d235d9762e4866d569d3554d1480 flags verified ) -) - -game ( - name "Mooncat's Trio (World) (Beta) (Aftermarket) (Unl)" - description "Mooncat's Trio (World) (Beta) (Aftermarket) (Unl)" - rom ( name "Mooncat's Trio (World) (Beta) (Aftermarket) (Unl).gba" size 504220 crc cd3328ee sha1 c3ea5247f32c428bbcfd5c087218fc56779e3106 ) -) - game ( name "Moorhen 3 - The Chicken Chase! (Europe) (En,Fr,De,Es,It)" description "Moorhen 3 - The Chicken Chase! (Europe) (En,Fr,De,Es,It)" @@ -12240,6 +12372,18 @@ game ( rom ( name "Mother 3 (Japan) (Virtual Console).gba" size 33554432 crc c704a567 sha1 a9fb9c36df3b0fb24b266826f5853c56122f9d36 ) ) +game ( + name "Moto Racer Advance (USA) (En,Fr,De,Es,It)" + description "Moto Racer Advance (USA) (En,Fr,De,Es,It)" + rom ( name "Moto Racer Advance (USA) (En,Fr,De,Es,It).gba" size 4194304 crc 2fdbe7a8 sha1 351414650e6969c270b1339ada7b3565ce80374c ) +) + +game ( + name "Moto Racer Advance (Europe) (En,Fr,De,Es,It)" + description "Moto Racer Advance (Europe) (En,Fr,De,Es,It)" + rom ( name "Moto Racer Advance (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 8cb19da0 sha1 b91bad8ee04652d71e0610f8d1a5deaebd4c1fd0 flags verified ) +) + game ( name "Motocross Challenge (USA) (Proto)" description "Motocross Challenge (USA) (Proto)" @@ -12282,18 +12426,6 @@ game ( rom ( name "MotoGP (Europe) (Beta).gba" size 4194304 crc 508bf8dc sha1 25554ecf8c3b534e0a70c6d4e402fa8f721da7d8 ) ) -game ( - name "Motoracer Advance (USA) (En,Fr,De,Es,It)" - description "Motoracer Advance (USA) (En,Fr,De,Es,It)" - rom ( name "Motoracer Advance (USA) (En,Fr,De,Es,It).gba" size 4194304 crc 2fdbe7a8 sha1 351414650e6969c270b1339ada7b3565ce80374c ) -) - -game ( - name "Motoracer Advance (Europe) (En,Fr,De,Es,It)" - description "Motoracer Advance (Europe) (En,Fr,De,Es,It)" - rom ( name "Motoracer Advance (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 8cb19da0 sha1 b91bad8ee04652d71e0610f8d1a5deaebd4c1fd0 flags verified ) -) - game ( name "Mr Nutz (Europe) (En,Fr,De,Es,It)" description "Mr Nutz (Europe) (En,Fr,De,Es,It)" @@ -12312,12 +12444,6 @@ game ( rom ( name "Mr. Driller 2 (USA).gba" size 4194304 crc 02f51696 sha1 e7009dd8418303343c4aac2558538b8caa28b694 ) ) -game ( - name "Mr. Driller 2 (Japan)" - description "Mr. Driller 2 (Japan)" - rom ( name "Mr. Driller 2 (Japan).gba" size 4194304 crc 5264c730 sha1 0373318ef431b1d02708941af261c91de1677d9d ) -) - game ( name "Mr. Driller 2 (USA) (Virtual Console)" description "Mr. Driller 2 (USA) (Virtual Console)" @@ -12337,9 +12463,9 @@ game ( ) game ( - name "Mr. Driller A - Fushigi na Pacteria (Japan) (Virtual Console)" - description "Mr. Driller A - Fushigi na Pacteria (Japan) (Virtual Console)" - rom ( name "Mr. Driller A - Fushigi na Pacteria (Japan) (Virtual Console).gba" size 8388608 crc 5f595157 sha1 d51a4ef35205cb61a242db65be6a7807d49dec5c ) + name "Mr. Driller 2 (Japan)" + description "Mr. Driller 2 (Japan)" + rom ( name "Mr. Driller 2 (Japan).gba" size 4194304 crc 5264c730 sha1 0373318ef431b1d02708941af261c91de1677d9d ) ) game ( @@ -12348,6 +12474,12 @@ game ( rom ( name "Mr. Driller A - Fushigi na Pacteria (Japan).gba" size 8388608 crc 529f06a4 sha1 ccfb5f3051b4d3bdec38f0085f2a585ecf249f20 ) ) +game ( + name "Mr. Driller A - Fushigi na Pacteria (Japan) (Virtual Console)" + description "Mr. Driller A - Fushigi na Pacteria (Japan) (Virtual Console)" + rom ( name "Mr. Driller A - Fushigi na Pacteria (Japan) (Virtual Console).gba" size 8388608 crc 5f595157 sha1 d51a4ef35205cb61a242db65be6a7807d49dec5c ) +) + game ( name "Mr. Incredible (Japan)" description "Mr. Incredible (Japan)" @@ -12396,18 +12528,18 @@ game ( rom ( name "Mummy, The (USA) (En,Fr,De,Es,It).gba" size 4194304 crc 55bf350b sha1 cc833b1398a6ea87d31712806757c2fe52fadd31 ) ) -game ( - name "Muppet Pinball Mayhem (Europe)" - description "Muppet Pinball Mayhem (Europe)" - rom ( name "Muppet Pinball Mayhem (Europe).gba" size 4194304 crc 8d5034d7 sha1 1c45790873605defc999b45ee145013e7e406a5d ) -) - game ( name "Muppet Pinball Mayhem (USA)" description "Muppet Pinball Mayhem (USA)" rom ( name "Muppet Pinball Mayhem (USA).gba" size 4194304 crc 58575f65 sha1 cbf381536ab8d8ea02814a77f46db13cb625c72f ) ) +game ( + name "Muppet Pinball Mayhem (Europe)" + description "Muppet Pinball Mayhem (Europe)" + rom ( name "Muppet Pinball Mayhem (Europe).gba" size 4194304 crc 8d5034d7 sha1 1c45790873605defc999b45ee145013e7e406a5d ) +) + game ( name "Muppets, The - On with the Show! (USA, Europe) (En,Fr,De,Es,It,Nl)" description "Muppets, The - On with the Show! (USA, Europe) (En,Fr,De,Es,It,Nl)" @@ -12435,7 +12567,7 @@ game ( game ( name "My Animal Centre in Africa (Europe) (En,Fr,De,Es,It)" description "My Animal Centre in Africa (Europe) (En,Fr,De,Es,It)" - rom ( name "My Animal Centre in Africa (Europe) (En,Fr,De,Es,It).gba" size 33554432 crc 16c0e028 sha1 e85cea8428d51e40cf1b7a90643e94604973679f ) + rom ( name "My Animal Centre in Africa (Europe) (En,Fr,De,Es,It).gba" size 33554432 crc d4f6c94d sha1 0f4f86e0c2243d847d16488e42b07e26679dc0ae ) ) game ( @@ -12501,7 +12633,7 @@ game ( game ( name "Namco Museum (Europe)" description "Namco Museum (Europe)" - rom ( name "Namco Museum (Europe).gba" size 4194304 crc bb82460a sha1 3e84508a0d2362a0abf31dede1d55b865566213c ) + rom ( name "Namco Museum (Europe).gba" size 4194304 crc bb82460a sha1 3e84508a0d2362a0abf31dede1d55b865566213c flags verified ) ) game ( @@ -12636,6 +12768,18 @@ game ( rom ( name "NBA Jam 2002 (USA, Europe).gba" size 4194304 crc ca428a7a sha1 38de98758669b120b895661bec3882c3474cf47e ) ) +game ( + name "Nebulus (World) (v1.2) (Unl)" + description "Nebulus (World) (v1.2) (Unl)" + rom ( name "Nebulus (World) (v1.2) (Unl).gba" size 557936 crc 77e2d5f0 sha1 086f7d7e86cfbaff43a4ce35c179e43adbccc4f6 ) +) + +game ( + name "Nebulus (World) (GBAX 2004) (Unl)" + description "Nebulus (World) (GBAX 2004) (Unl)" + rom ( name "Nebulus (World) (GBAX 2004) (Unl).gba" size 544372 crc fb414ccc sha1 4c25014b29e87dd53f3677339f89dd18d316d2f0 ) +) + game ( name "Need for Speed - Carbon - Own the City (USA, Europe) (En,Fr,De,Es,It)" description "Need for Speed - Carbon - Own the City (USA, Europe) (En,Fr,De,Es,It)" @@ -12672,12 +12816,6 @@ game ( rom ( name "Need for Speed - Underground 2 (USA, Europe) (En,Fr,De,It).gba" size 8388608 crc 9a0c5090 sha1 f772000fbdfb84d8d5de9f69bd9c0de551389929 flags verified ) ) -game ( - name "Nekketsu Monogatari Advance (Japan) (Demo) (Aftermarket) (Unl)" - description "Nekketsu Monogatari Advance (Japan) (Demo) (Aftermarket) (Unl)" - rom ( name "Nekketsu Monogatari Advance (Japan) (Demo) (Aftermarket) (Unl).gba" size 508972 crc 55a0734d sha1 79d6977803cd7ee6b1c97ee149cc1bc037c50fb2 ) -) - game ( name "Neoromance Game - Harukanaru Toki no Naka de (Japan) (Rev 1)" description "Neoromance Game - Harukanaru Toki no Naka de (Japan) (Rev 1)" @@ -12744,12 +12882,6 @@ game ( rom ( name "Nicktoons - Freeze Frame Frenzy (USA).gba" size 4194304 crc a8b6766e sha1 a200cdaf66606bd724ce7073fd7990ea3fe6bcdd ) ) -game ( - name "Nicktoons Racing (USA) (Beta)" - description "Nicktoons Racing (USA) (Beta)" - rom ( name "Nicktoons Racing (USA) (Beta).gba" size 4194304 crc 4ed6e860 sha1 d553a265d1405bb073034e16ea97e1a2df899025 ) -) - game ( name "Nicktoons Racing (USA)" description "Nicktoons Racing (USA)" @@ -12762,6 +12894,12 @@ game ( rom ( name "Nicktoons Racing (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc babccefd sha1 55b145de1810a4a6a8b5716ef4c9e9333a93e3ba ) ) +game ( + name "Nicktoons Racing (USA) (Beta)" + description "Nicktoons Racing (USA) (Beta)" + rom ( name "Nicktoons Racing (USA) (Beta).gba" size 4194304 crc 4ed6e860 sha1 d553a265d1405bb073034e16ea97e1a2df899025 ) +) + game ( name "Nicktoons Unite! (USA)" description "Nicktoons Unite! (USA)" @@ -12978,18 +13116,18 @@ game ( rom ( name "Oriental Blue - Ao no Tengai (Japan).gba" size 16777216 crc 05e80ecc sha1 414cad1aee67ab20f3c133f0259da7e8c3073bbc flags verified ) ) -game ( - name "Oshaberi Inko Club (Japan)" - description "Oshaberi Inko Club (Japan)" - rom ( name "Oshaberi Inko Club (Japan).gba" size 8388608 crc df6901f0 sha1 82e48090b9615282c58747a1f7b105196866f8c9 ) -) - game ( name "Oshaberi Inko Club (Japan) (Beta)" description "Oshaberi Inko Club (Japan) (Beta)" rom ( name "Oshaberi Inko Club (Japan) (Beta).gba" size 8388608 crc f896bb9e sha1 e293d18a8a0fb856edafafa03b33454b2d04efd9 ) ) +game ( + name "Oshaberi Inko Club (Japan)" + description "Oshaberi Inko Club (Japan)" + rom ( name "Oshaberi Inko Club (Japan).gba" size 8388608 crc df6901f0 sha1 82e48090b9615282c58747a1f7b105196866f8c9 ) +) + game ( name "Oshare Princess (Japan)" description "Oshare Princess (Japan)" @@ -13197,7 +13335,7 @@ game ( game ( name "Paws & Claws - Pet Vet (USA)" description "Paws & Claws - Pet Vet (USA)" - rom ( name "Paws & Claws - Pet Vet (USA).gba" size 8388608 crc efee1ddf sha1 c121eea8f816c4f8cbab32058d6b9bac57f0d7e3 ) + rom ( name "Paws & Claws - Pet Vet (USA).gba" size 8388608 crc efee1ddf sha1 c121eea8f816c4f8cbab32058d6b9bac57f0d7e3 flags verified ) ) game ( @@ -13333,9 +13471,9 @@ game ( ) game ( - name "Phantom, The (Italy) (It) (Proto)" - description "Phantom, The (Italy) (It) (Proto)" - rom ( name "Phantom, The (Italy) (It) (Proto).gba" size 8388608 crc 5833169c sha1 ccd8e9d092a9ded9c3785ac776d40df66512b9b5 ) + name "Phantom, The (Italy) (Proto)" + description "Phantom, The (Italy) (Proto)" + rom ( name "Phantom, The (Italy) (Proto).gba" size 8388608 crc 5833169c sha1 ccd8e9d092a9ded9c3785ac776d40df66512b9b5 ) ) game ( @@ -13626,6 +13764,12 @@ game ( rom ( name "Pocket Monsters - Sapphire (Japan) (Rev 1).gba" size 8388608 crc 01bd60e3 sha1 01f509671445965236ac4c6b5a354fe2f1e69f13 flags verified ) ) +game ( + name "Pocket Monsters Diamond - Pocket Monsters Pearl - Manaphy Present Campaign Senyou Cartridge (Japan) (En)" + description "Pocket Monsters Diamond - Pocket Monsters Pearl - Manaphy Present Campaign Senyou Cartridge (Japan) (En)" + rom ( name "Pocket Monsters Diamond - Pocket Monsters Pearl - Manaphy Present Campaign Senyou Cartridge (Japan) (En).gba" size 2097152 crc e31566cf sha1 3fbbd166bacdc668844e38b0ca35d6e29d11da7a ) +) + game ( name "Pocket Monsters Diamond - Tomodachi to Issho ni! - Present Campaign Senyou Cartridge (Japan) [b]" description "Pocket Monsters Diamond - Tomodachi to Issho ni! - Present Campaign Senyou Cartridge (Japan) [b]" @@ -13902,12 +14046,6 @@ game ( rom ( name "Pokemon - Sapphire Version - Gotta Catch 'em All! (USA) (Unl).gba" size 33554432 crc 86a602ab sha1 14051d159d7a1266b5bfecbfd52722fd3e0711bf ) ) -game ( - name "Pokemon - Slot 2 Distribution (Japan) (En) (B5DJ)" - description "Pokemon - Slot 2 Distribution (Japan) (En) (B5DJ)" - rom ( name "Pokemon - Slot 2 Distribution (Japan) (En) (B5DJ).gba" size 2097152 crc e31566cf sha1 3fbbd166bacdc668844e38b0ca35d6e29d11da7a ) -) - game ( name "Pokemon - Slot 2 Distribution (Japan) (Proto)" description "Pokemon - Slot 2 Distribution (Japan) (Proto)" @@ -13947,7 +14085,7 @@ game ( game ( name "Pokemon - Version Saphir (France)" description "Pokemon - Version Saphir (France)" - rom ( name "Pokemon - Version Saphir (France).gba" size 16777216 crc 3581a05f sha1 c269b5692b2d0e5800ba1ddf117fda95ac648634 ) + rom ( name "Pokemon - Version Saphir (France).gba" size 16777216 crc 3581a05f sha1 c269b5692b2d0e5800ba1ddf117fda95ac648634 flags verified ) ) game ( @@ -14424,6 +14562,12 @@ game ( rom ( name "Punch King - Arcade Boxing (USA).gba" size 8388608 crc 540b6cc1 sha1 021fdd9420a81a3aa8f37de884ac2b8f42e691ed ) ) +game ( + name "Punch King - Arcade Boxing (World) (Evercade) (Unl)" + description "Punch King - Arcade Boxing (World) (Evercade) (Unl)" + rom ( name "Punch King - Arcade Boxing (World) (Evercade) (Unl).gba" size 8388608 crc 2afd6ff9 sha1 9e145758d3727c664c0612407f4b4d04f7b1733d ) +) + game ( name "Puppy Luv - Spa and Resort (USA)" description "Puppy Luv - Spa and Resort (USA)" @@ -14527,15 +14671,15 @@ game ( ) game ( - name "Racing Fever (Europe) (En,De,Es,It)" - description "Racing Fever (Europe) (En,De,Es,It)" - rom ( name "Racing Fever (Europe) (En,De,Es,It).gba" size 4194304 crc e40ec737 sha1 9bb5c036bca8f0d2e06013cac7ea6148a4f7f512 ) + name "Racing Fever (World) (En,De,Es,It) (Evercade) (Unl)" + description "Racing Fever (World) (En,De,Es,It) (Evercade) (Unl)" + rom ( name "Racing Fever (World) (En,De,Es,It) (Evercade) (Unl).gba" size 4194304 crc dbd09923 sha1 b10861c12a08826c58dffdbd3071ff72f753b76e ) ) game ( - name "Racing Gears Advance (USA) (Beta)" - description "Racing Gears Advance (USA) (Beta)" - rom ( name "Racing Gears Advance (USA) (Beta).gba" size 16777216 crc 86a05f93 sha1 d258526ce1dcfbed51b745a762f148c9bea01154 ) + name "Racing Fever (Europe) (En,De,Es,It)" + description "Racing Fever (Europe) (En,De,Es,It)" + rom ( name "Racing Fever (Europe) (En,De,Es,It).gba" size 4194304 crc e40ec737 sha1 9bb5c036bca8f0d2e06013cac7ea6148a4f7f512 ) ) game ( @@ -14550,6 +14694,12 @@ game ( rom ( name "Racing Gears Advance (USA).gba" size 8388608 crc bf648e5c sha1 3f053865f9a687a75927172cd281390b2560201c ) ) +game ( + name "Racing Gears Advance (USA) (Beta)" + description "Racing Gears Advance (USA) (Beta)" + rom ( name "Racing Gears Advance (USA) (Beta).gba" size 8388608 crc 7a3820b3 sha1 ff18dfe7d75a8154c0dcc3970e5d0d4cb75c3568 ) +) + game ( name "Rampage - Puzzle Attack (USA, Europe)" description "Rampage - Puzzle Attack (USA, Europe)" @@ -14562,6 +14712,12 @@ game ( rom ( name "Rapala Pro Fishing (USA, Europe).gba" size 4194304 crc 964d39a7 sha1 e3df6fe7a447ab30faf6fd7d4c57e88f987a5639 ) ) +game ( + name "Ratatouille (Australia, Greece) (En)" + description "Ratatouille (Australia, Greece) (En)" + rom ( name "Ratatouille (Australia, Greece) (En).gba" size 8388608 crc 3e1711c7 sha1 58f2fa1d7e531c7345b11db268e1bbc10372bebc flags verified ) +) + game ( name "Ratatouille (USA)" description "Ratatouille (USA)" @@ -14586,12 +14742,6 @@ game ( rom ( name "Ratatouille (Europe) (En,It,Sv,No,Da).gba" size 8388608 crc 82f9c596 sha1 a5c4a636979c06670a81428c778ff76ed2c65eee ) ) -game ( - name "Ratatouille (Greece) (En)" - description "Ratatouille (Greece) (En)" - rom ( name "Ratatouille (Greece) (En).gba" size 8388608 crc 3e1711c7 sha1 58f2fa1d7e531c7345b11db268e1bbc10372bebc ) -) - game ( name "Rave Master - Special Attack Force! (USA)" description "Rave Master - Special Attack Force! (USA)" @@ -14667,7 +14817,7 @@ game ( game ( name "Rayman Advance (Europe) (En,Fr,De,Es,It)" description "Rayman Advance (Europe) (En,Fr,De,Es,It)" - rom ( name "Rayman Advance (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc b43783b4 sha1 6a32d270848ae302a3e4fb873e53b663c2db4811 ) + rom ( name "Rayman Advance (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc b43783b4 sha1 6a32d270848ae302a3e4fb873e53b663c2db4811 flags verified ) ) game ( @@ -14730,12 +14880,6 @@ game ( rom ( name "Ready 2 Rumble Boxing - Round 2 (Europe) (En,Fr,De).gba" size 4194304 crc e418e962 sha1 57d06e405b281f68800b986bd9ff1257e4466939 flags verified ) ) -game ( - name "Rebelstar - Tactical Command (Europe) (En,Fr,De,Es,It) (Beta)" - description "Rebelstar - Tactical Command (Europe) (En,Fr,De,Es,It) (Beta)" - rom ( name "Rebelstar - Tactical Command (Europe) (En,Fr,De,Es,It) (Beta).gba" size 4194304 crc 2189021c sha1 b6e2167272a68bd4e3833cccd68929d50a27a426 ) -) - game ( name "Rebelstar - Tactical Command (USA)" description "Rebelstar - Tactical Command (USA)" @@ -14748,6 +14892,12 @@ game ( rom ( name "Rebelstar - Tactical Command (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc e448c5d4 sha1 669c47e62f2388ce0ba676f3dc641b5ad2ddb5c5 flags verified ) ) +game ( + name "Rebelstar - Tactical Command (Europe) (En,Fr,De,Es,It) (Beta)" + description "Rebelstar - Tactical Command (Europe) (En,Fr,De,Es,It) (Beta)" + rom ( name "Rebelstar - Tactical Command (Europe) (En,Fr,De,Es,It) (Beta).gba" size 4194304 crc 2189021c sha1 b6e2167272a68bd4e3833cccd68929d50a27a426 ) +) + game ( name "Recca no Honoo - The Game (Japan)" description "Recca no Honoo - The Game (Japan)" @@ -14772,12 +14922,6 @@ game ( rom ( name "Relaxuma na Mainichi (Japan).gba" size 4194304 crc 9f333017 sha1 e6e649605603dc84b20934ac00f99a13dc8ff8cc ) ) -game ( - name "Remute - Unity (World) (Aftermarket) (Unl)" - description "Remute - Unity (World) (Aftermarket) (Unl)" - rom ( name "Remute - Unity (World) (Aftermarket) (Unl).gba" size 33554432 crc 6cd42a32 sha1 d8001b07885557ee32608c661e202a257d3e8c3d ) -) - game ( name "Renzhe Shen Gui 2 (Taiwan) (Unl)" description "Renzhe Shen Gui 2 (Taiwan) (Unl)" @@ -14928,6 +15072,12 @@ game ( rom ( name "Robot Wars - Advanced Destruction (USA).gba" size 4194304 crc e6cb567d sha1 952adf4e17865abc2b983c79ad4080e9b4867370 ) ) +game ( + name "Robot Wars - Advanced Destruction (USA) (Beta) (2001-03-20)" + description "Robot Wars - Advanced Destruction (USA) (Beta) (2001-03-20)" + rom ( name "Robot Wars - Advanced Destruction (USA) (Beta) (2001-03-20).gba" size 585104 crc ce95bbd6 sha1 e045c21b0fef1959c1207bb46e509089b03fd6db ) +) + game ( name "Robot Wars - Extreme Destruction (Europe) (En,Fr,De,Es,It,Nl)" description "Robot Wars - Extreme Destruction (Europe) (En,Fr,De,Es,It,Nl)" @@ -14940,6 +15090,12 @@ game ( rom ( name "Robotech - The Macross Saga (USA, Europe) (En,Fr,De,Es,It,Nl).gba" size 8388608 crc 325a6596 sha1 3dbfe433a2376589a24754bb7337306c43176b34 flags verified ) ) +game ( + name "Robots (Japan)" + description "Robots (Japan)" + rom ( name "Robots (Japan).gba" size 16777216 crc 1beb9e91 sha1 b1a670daf53d47f237a4078388178c16c843d4dc ) +) + game ( name "Robots (USA)" description "Robots (USA)" @@ -14952,12 +15108,6 @@ game ( rom ( name "Robots (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc 2acbdb64 sha1 26be826817f35433b3609d13ee75a3872e94d616 flags verified ) ) -game ( - name "Robots (Japan)" - description "Robots (Japan)" - rom ( name "Robots (Japan).gba" size 16777216 crc 1beb9e91 sha1 b1a670daf53d47f237a4078388178c16c843d4dc ) -) - game ( name "Rock 'N Roll Racing (USA)" description "Rock 'N Roll Racing (USA)" @@ -15009,7 +15159,7 @@ game ( game ( name "Rocket Power - Zero Gravity Zone (USA)" description "Rocket Power - Zero Gravity Zone (USA)" - rom ( name "Rocket Power - Zero Gravity Zone (USA).gba" size 8388608 crc 26d62d32 sha1 2e8fcf7afe49b57c2527f31288198a4b93df8bec ) + rom ( name "Rocket Power - Zero Gravity Zone (USA).gba" size 8388608 crc 26d62d32 sha1 2e8fcf7afe49b57c2527f31288198a4b93df8bec flags verified ) ) game ( @@ -15048,6 +15198,12 @@ game ( rom ( name "Rockman EXE 4 - Tournament Blue Moon (Japan) (Rev 1) (Virtual Console).gba" size 8388608 crc 0a27789e sha1 bfded71514df71d0449f9c972a4f6356970796a1 ) ) +game ( + name "Rockman EXE 4 - Tournament Blue Moon (Japan) (Rev 1)" + description "Rockman EXE 4 - Tournament Blue Moon (Japan) (Rev 1)" + rom ( name "Rockman EXE 4 - Tournament Blue Moon (Japan) (Rev 1).gba" size 8388608 crc 709bbf07 sha1 c46305f0398f75230b7f6f62d39167dfcc7b1778 ) +) + game ( name "Rockman EXE 4 - Tournament Blue Moon (Japan)" description "Rockman EXE 4 - Tournament Blue Moon (Japan)" @@ -15222,6 +15378,30 @@ game ( rom ( name "Rugrats - Travesuras en el Castillo (Spain).gba" size 4194304 crc 0bcab7d0 sha1 89448f91091a46deaebaddbaaada43522f387465 ) ) +game ( + name "S World 3 (World) (Beta 4) (Unl)" + description "S World 3 (World) (Beta 4) (Unl)" + rom ( name "S World 3 (World) (Beta 4) (Unl).gba" size 265800 crc 9d5e128c sha1 243555734e942b3ddba2d7834805e56eb72403c4 ) +) + +game ( + name "S World 3 (World) (Beta 3) (Unl)" + description "S World 3 (World) (Beta 3) (Unl)" + rom ( name "S World 3 (World) (Beta 3) (Unl).gba" size 43296 crc 3bc15e46 sha1 830f34779783f645dc88c4b00f8d85ca5f87f904 ) +) + +game ( + name "S World 3 (World) (Beta 2) (Unl)" + description "S World 3 (World) (Beta 2) (Unl)" + rom ( name "S World 3 (World) (Beta 2) (Unl).gba" size 12844 crc 34ad13fe sha1 5de0d42c33c616d8b27bb32050b10853cdea232d ) +) + +game ( + name "S World 3 (World) (Beta 1) (Unl)" + description "S World 3 (World) (Beta 1) (Unl)" + rom ( name "S World 3 (World) (Beta 1) (Unl).gba" size 10144 crc 6b1a6173 sha1 201d6c313fed6b263ba31872be7032cfe874c50b ) +) + game ( name "Sabre Wulf (Europe) (En,Fr,De)" description "Sabre Wulf (Europe) (En,Fr,De)" @@ -15459,7 +15639,7 @@ game ( game ( name "Scorpion King, The - Sword of Osiris (Europe) (En,Fr,De,Es,It)" description "Scorpion King, The - Sword of Osiris (Europe) (En,Fr,De,Es,It)" - rom ( name "Scorpion King, The - Sword of Osiris (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc d5410d32 sha1 9a483e98d72b1d7d8579511cc9344e5d27bcee61 ) + rom ( name "Scorpion King, The - Sword of Osiris (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc d5410d32 sha1 9a483e98d72b1d7d8579511cc9344e5d27bcee61 flags verified ) ) game ( @@ -15681,7 +15861,7 @@ game ( game ( name "Shamu's Deep Sea Adventures (USA)" description "Shamu's Deep Sea Adventures (USA)" - rom ( name "Shamu's Deep Sea Adventures (USA).gba" size 33554432 crc 4e9426eb sha1 0bca9c4dd35d02c52a5db98b2097a50ef159de32 ) + rom ( name "Shamu's Deep Sea Adventures (USA).gba" size 33554432 crc 7ecb7529 sha1 1927b344bba21bcd80544a55734234610972f373 flags verified ) ) game ( @@ -16305,7 +16485,7 @@ game ( game ( name "Smuggler's Run (Europe) (En,Fr,De,Es,It)" description "Smuggler's Run (Europe) (En,Fr,De,Es,It)" - rom ( name "Smuggler's Run (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 3ae0afc8 sha1 e87067719da93f0d7c8136cdf5717612a6c15034 ) + rom ( name "Smuggler's Run (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 3ae0afc8 sha1 e87067719da93f0d7c8136cdf5717612a6c15034 flags verified ) ) game ( @@ -16323,7 +16503,7 @@ game ( game ( name "Snood (USA)" description "Snood (USA)" - rom ( name "Snood (USA).gba" size 4194304 crc f1f1f148 sha1 2c09548ae924ac0c1a3e15412d9a7aae7707a753 ) + rom ( name "Snood (USA).gba" size 4194304 crc f1f1f148 sha1 2c09548ae924ac0c1a3e15412d9a7aae7707a753 flags verified ) ) game ( @@ -16398,6 +16578,18 @@ game ( rom ( name "Sonic Advance (Japan) (En,Ja) (Rev 1).gba" size 8388608 crc 85957a24 sha1 f43faca5d8df354a63471aebfea3be125e797e51 ) ) +game ( + name "Sonic Advance 2 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console)" + description "Sonic Advance 2 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console)" + rom ( name "Sonic Advance 2 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console).gba" size 16777216 crc 6c6c65a3 sha1 2aa6ee2cf2b0ebfafbea6d6d24165b252a7e329e ) +) + +game ( + name "Sonic Advance 2 (USA) (Beta) (2002-10-25)" + description "Sonic Advance 2 (USA) (Beta) (2002-10-25)" + rom ( name "Sonic Advance 2 (USA) (Beta) (2002-10-25).gba" size 16777216 crc 95ab3867 sha1 3368642fc4157824af63367e2a685b7d6ee9b09d ) +) + game ( name "Sonic Advance 2 (Japan) (En,Ja,Fr,De,Es,It)" description "Sonic Advance 2 (Japan) (En,Ja,Fr,De,Es,It)" @@ -16416,30 +16608,6 @@ game ( rom ( name "Sonic Advance 2 (Europe) (En,Ja,Fr,De,Es,It).gba" size 16777216 crc 89509891 sha1 b0f64bdca097f2de8f05ac4c8caea2b80c5faeb1 flags verified ) ) -game ( - name "Sonic Advance 2 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console)" - description "Sonic Advance 2 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console)" - rom ( name "Sonic Advance 2 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console).gba" size 16777216 crc 6c6c65a3 sha1 2aa6ee2cf2b0ebfafbea6d6d24165b252a7e329e ) -) - -game ( - name "Sonic Advance 2 (USA) (Beta) (2002-10-25)" - description "Sonic Advance 2 (USA) (Beta) (2002-10-25)" - rom ( name "Sonic Advance 2 (USA) (Beta) (2002-10-25).gba" size 16777216 crc 95ab3867 sha1 3368642fc4157824af63367e2a685b7d6ee9b09d ) -) - -game ( - name "Sonic Advance 3 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console)" - description "Sonic Advance 3 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console)" - rom ( name "Sonic Advance 3 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console).gba" size 16777216 crc 1f36892f sha1 9fc8e926fc5472a1e34e3251c5d316526dc7a7a9 ) -) - -game ( - name "Sonic Advance 3 (Japan) (Demo) (Kiosk, GameCube)" - description "Sonic Advance 3 (Japan) (Demo) (Kiosk, GameCube)" - rom ( name "Sonic Advance 3 (Japan) (Demo) (Kiosk, GameCube).gba" size 16777216 crc 0594d496 sha1 9c3f18112c126ca08403408a844a3a83967eb4dc flags verified ) -) - game ( name "Sonic Advance 3 (Europe) (En,Ja,Fr,De,Es,It) (Beta)" description "Sonic Advance 3 (Europe) (En,Ja,Fr,De,Es,It) (Beta)" @@ -16464,6 +16632,18 @@ game ( rom ( name "Sonic Advance 3 (Europe) (En,Ja,Fr,De,Es,It).gba" size 16777216 crc 5bf83456 sha1 685af3a2dc0f1b3f8922e73ec42c1dc92e210e39 flags verified ) ) +game ( + name "Sonic Advance 3 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console)" + description "Sonic Advance 3 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console)" + rom ( name "Sonic Advance 3 (Japan) (En,Ja,Fr,De,Es,It) (Virtual Console).gba" size 16777216 crc 1f36892f sha1 9fc8e926fc5472a1e34e3251c5d316526dc7a7a9 ) +) + +game ( + name "Sonic Advance 3 (Japan) (Demo) (Kiosk, GameCube)" + description "Sonic Advance 3 (Japan) (Demo) (Kiosk, GameCube)" + rom ( name "Sonic Advance 3 (Japan) (Demo) (Kiosk, GameCube).gba" size 16777216 crc 0594d496 sha1 9c3f18112c126ca08403408a844a3a83967eb4dc flags verified ) +) + game ( name "Sonic Battle (Japan) (En,Ja)" description "Sonic Battle (Japan) (En,Ja)" @@ -16473,7 +16653,7 @@ game ( game ( name "Sonic Battle (USA) (En,Ja,Fr,De,Es,It)" description "Sonic Battle (USA) (En,Ja,Fr,De,Es,It)" - rom ( name "Sonic Battle (USA) (En,Ja,Fr,De,Es,It).gba" size 16777216 crc 9ec9d86f sha1 8cf4fbbe73f6b1907ab9997caab4c4e7d9708937 ) + rom ( name "Sonic Battle (USA) (En,Ja,Fr,De,Es,It).gba" size 16777216 crc 9ec9d86f sha1 8cf4fbbe73f6b1907ab9997caab4c4e7d9708937 flags verified ) ) game ( @@ -16554,6 +16734,12 @@ game ( rom ( name "Space Invaders EX (Japan) (En).gba" size 4194304 crc 297b9854 sha1 ae8cace77baccdb8f25c9b44ea3cf64d881b91a8 ) ) +game ( + name "Space Twins (World) (Proto) (Unl)" + description "Space Twins (World) (Proto) (Unl)" + rom ( name "Space Twins (World) (Proto) (Unl).gba" size 1350536 crc 0edc97d9 sha1 4a9848cc2262b30aba7e87013c0a197e01cc9617 ) +) + game ( name "Speedball 2 (Europe) (En,Fr,De,Es,It)" description "Speedball 2 (Europe) (En,Fr,De,Es,It)" @@ -16662,18 +16848,18 @@ game ( rom ( name "Spider-Man 3 (USA) (Unl).gba" size 33554432 crc 3e1b693a sha1 54d22c0fe81e78380fc2d839aa800f36fc1ef311 ) ) -game ( - name "Spirit - Der Wilde Mustang - Auf der Suche nach Homeland (Germany) (Beta)" - description "Spirit - Der Wilde Mustang - Auf der Suche nach Homeland (Germany) (Beta)" - rom ( name "Spirit - Der Wilde Mustang - Auf der Suche nach Homeland (Germany) (Beta).gba" size 4183576 crc caaaefb6 sha1 53c4bb950d9b92918f26aeb7b0105604d0263ba1 ) -) - game ( name "Spirit - Der Wilde Mustang - Auf der Suche nach Homeland (Germany)" description "Spirit - Der Wilde Mustang - Auf der Suche nach Homeland (Germany)" rom ( name "Spirit - Der Wilde Mustang - Auf der Suche nach Homeland (Germany).gba" size 4194304 crc 4785eee0 sha1 ce8f271e143456616a9649fee7d47ef1602ee497 ) ) +game ( + name "Spirit - Der Wilde Mustang - Auf der Suche nach Homeland (Germany) (Beta)" + description "Spirit - Der Wilde Mustang - Auf der Suche nach Homeland (Germany) (Beta)" + rom ( name "Spirit - Der Wilde Mustang - Auf der Suche nach Homeland (Germany) (Beta).gba" size 4183576 crc caaaefb6 sha1 53c4bb950d9b92918f26aeb7b0105604d0263ba1 ) +) + game ( name "Spirit - L'Etalon des Plaines - A la Recherche de la Terre Natale (France)" description "Spirit - L'Etalon des Plaines - A la Recherche de la Terre Natale (France)" @@ -16740,6 +16926,18 @@ game ( rom ( name "SpongeBob SquarePants - Lights, Camera, Pants! (Europe) (En,Fr,De,Es,It,Nl,Sv).gba" size 8388608 crc c189013d sha1 09d945acc251000c49539a3f18b21e48520ec8ad flags verified ) ) +game ( + name "SpongeBob SquarePants - Lights, Camera, Pants! (USA) (Beta) (2005-08-03)" + description "SpongeBob SquarePants - Lights, Camera, Pants! (USA) (Beta) (2005-08-03)" + rom ( name "SpongeBob SquarePants - Lights, Camera, Pants! (USA) (Beta) (2005-08-03).gba" size 4291500 crc 52fd3771 sha1 72d84f52c796cbb06c2cd9291ca7952093d9b7dc ) +) + +game ( + name "SpongeBob SquarePants - Lights, Camera, Pants! (USA) (Beta) (2005-08-05)" + description "SpongeBob SquarePants - Lights, Camera, Pants! (USA) (Beta) (2005-08-05)" + rom ( name "SpongeBob SquarePants - Lights, Camera, Pants! (USA) (Beta) (2005-08-05).gba" size 4519932 crc e1461b58 sha1 b30dc120107a70796250b831e7174fc4c03ae58a ) +) + game ( name "SpongeBob SquarePants - Revenge of the Flying Dutchman (USA) (Beta)" description "SpongeBob SquarePants - Revenge of the Flying Dutchman (USA) (Beta)" @@ -16836,6 +17034,24 @@ game ( rom ( name "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-07-31).gba" size 4194304 crc f2f67f40 sha1 bb298d490ec9d8657cbd2fc402ae1e0a5792d406 ) ) +game ( + name "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-03-28)" + description "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-03-28)" + rom ( name "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-03-28).gba" size 4646712 crc 1407d86e sha1 2608c985c8ab5bffeae0687421bb21a46e34b681 ) +) + +game ( + name "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-04-03)" + description "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-04-03)" + rom ( name "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-04-03).gba" size 5477108 crc 0bc6dfaf sha1 c617321d405f4a5bb07c4fa769321df46a944bb8 ) +) + +game ( + name "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-04-04)" + description "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-04-04)" + rom ( name "SpongeBob SquarePants - SuperSponge (USA, Europe) (Beta) (2001-04-04).gba" size 5477244 crc 23d7ba77 sha1 0177808f1bcd65738c10fd0fba477ecdd46a791f ) +) + game ( name "SpongeBob SquarePants and Friends - Battle for Volcano Island (Europe) (En,Fr,De,Es,It,Nl)" description "SpongeBob SquarePants and Friends - Battle for Volcano Island (Europe) (En,Fr,De,Es,It,Nl)" @@ -16947,7 +17163,7 @@ game ( game ( name "Spyro - Season of Ice (Europe) (En,Fr,De,Es,It)" description "Spyro - Season of Ice (Europe) (En,Fr,De,Es,It)" - rom ( name "Spyro - Season of Ice (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc afd25827 sha1 854e788e5e1316b7d5cdf6b961d0969e5cd62119 ) + rom ( name "Spyro - Season of Ice (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc afd25827 sha1 854e788e5e1316b7d5cdf6b961d0969e5cd62119 flags verified ) ) game ( @@ -17019,7 +17235,7 @@ game ( game ( name "SSX 3 (USA, Europe)" description "SSX 3 (USA, Europe)" - rom ( name "SSX 3 (USA, Europe).gba" size 8388608 crc 8232f58a sha1 4f2bd55bcd3118e10520179e285aae897aa21898 ) + rom ( name "SSX 3 (USA, Europe).gba" size 8388608 crc 8232f58a sha1 4f2bd55bcd3118e10520179e285aae897aa21898 flags verified ) ) game ( @@ -17055,7 +17271,7 @@ game ( game ( name "Star Wars - Episode III - Revenge of the Sith (Europe) (En,Fr,De,Es,It,Nl)" description "Star Wars - Episode III - Revenge of the Sith (Europe) (En,Fr,De,Es,It,Nl)" - rom ( name "Star Wars - Episode III - Revenge of the Sith (Europe) (En,Fr,De,Es,It,Nl).gba" size 8388608 crc fd49236b sha1 4ba5e5a6174bad9369f088f801c743f88616c5f4 ) + rom ( name "Star Wars - Episode III - Revenge of the Sith (Europe) (En,Fr,De,Es,It,Nl).gba" size 8388608 crc fd49236b sha1 4ba5e5a6174bad9369f088f801c743f88616c5f4 flags verified ) ) game ( @@ -17109,7 +17325,7 @@ game ( game ( name "Star Wars Trilogy - Apprentice of the Force (Europe) (En,Fr,De,Es,It,Nl)" description "Star Wars Trilogy - Apprentice of the Force (Europe) (En,Fr,De,Es,It,Nl)" - rom ( name "Star Wars Trilogy - Apprentice of the Force (Europe) (En,Fr,De,Es,It,Nl).gba" size 8388608 crc c9f0c492 sha1 51ffd3684d9bd8140d8c7969d7eb2096dd2424a5 ) + rom ( name "Star Wars Trilogy - Apprentice of the Force (Europe) (En,Fr,De,Es,It,Nl).gba" size 8388608 crc c9f0c492 sha1 51ffd3684d9bd8140d8c7969d7eb2096dd2424a5 flags verified ) ) game ( @@ -17220,12 +17436,6 @@ game ( rom ( name "Street Racing Syndicate (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc ac24888b sha1 0536c9d6b0732337eaa6764d918f3b314b96c063 ) ) -game ( - name "Strike Force Hydra (USA)" - description "Strike Force Hydra (USA)" - rom ( name "Strike Force Hydra (USA).gba" size 4194304 crc 5aeea1de sha1 39fcdd20cb253d9a0292208902994381a3ba7c27 ) -) - game ( name "Strike Force Hydra (Europe)" description "Strike Force Hydra (Europe)" @@ -17233,15 +17443,9 @@ game ( ) game ( - name "Stuart Little 2 (USA, Europe)" - description "Stuart Little 2 (USA, Europe)" - rom ( name "Stuart Little 2 (USA, Europe).gba" size 8388608 crc 6eb7c688 sha1 fdb6d8098340966456cd05c7babe77b5a204608c ) -) - -game ( - name "Stuart Little 2 (France)" - description "Stuart Little 2 (France)" - rom ( name "Stuart Little 2 (France).gba" size 8388608 crc 0827d896 sha1 59ab956ef920bdf2a75b36448f557df8538d558a ) + name "Strike Force Hydra (USA)" + description "Strike Force Hydra (USA)" + rom ( name "Strike Force Hydra (USA).gba" size 4194304 crc 5aeea1de sha1 39fcdd20cb253d9a0292208902994381a3ba7c27 ) ) game ( @@ -17250,6 +17454,18 @@ game ( rom ( name "Stuart Little 2 (Europe) (Rev 1).gba" size 8388608 crc 34e4f8c5 sha1 1435574b92777a633cec0722300601dcbb5f84ce ) ) +game ( + name "Stuart Little 2 (USA, Europe)" + description "Stuart Little 2 (USA, Europe)" + rom ( name "Stuart Little 2 (USA, Europe).gba" size 8388608 crc 6eb7c688 sha1 fdb6d8098340966456cd05c7babe77b5a204608c flags verified ) +) + +game ( + name "Stuart Little 2 (France)" + description "Stuart Little 2 (France)" + rom ( name "Stuart Little 2 (France).gba" size 8388608 crc 0827d896 sha1 59ab956ef920bdf2a75b36448f557df8538d558a ) +) + game ( name "Stuntman (Europe) (En,Fr,De,Es,It)" description "Stuntman (Europe) (En,Fr,De,Es,It)" @@ -17346,6 +17562,12 @@ game ( rom ( name "Super Bubble Pop (Europe) (En,Fr,De,Es,It,Nl,Pt,Sv).gba" size 4194304 crc 25123d97 sha1 f62396b5502437651d26e1ad27a8ec8c18b4268e ) ) +game ( + name "Super Bubble Pop (World) (Evercade) (Unl)" + description "Super Bubble Pop (World) (Evercade) (Unl)" + rom ( name "Super Bubble Pop (World) (Evercade) (Unl).gba" size 4194304 crc 940f385e sha1 fa2c3b84014a84143f519609a8808d13ca33bf22 ) +) + game ( name "Super Bust-A-Move (Europe) (En,Fr,De,Es,It)" description "Super Bust-A-Move (Europe) (En,Fr,De,Es,It)" @@ -17371,15 +17593,9 @@ game ( ) game ( - name "Super Dodge Ball Advance (USA)" - description "Super Dodge Ball Advance (USA)" - rom ( name "Super Dodge Ball Advance (USA).gba" size 4194304 crc 1d31dc6b sha1 5fc95814ea7695d1301df4b545614a1ffae95218 ) -) - -game ( - name "Super Dodge Ball Advance (Europe)" - description "Super Dodge Ball Advance (Europe)" - rom ( name "Super Dodge Ball Advance (Europe).gba" size 4194304 crc 4ca4f528 sha1 a0ac6be19f385eef6bc48bca8d54520d4e8a00e7 flags verified ) + name "Super Dodge Ball Advance (USA) (Rev 1)" + description "Super Dodge Ball Advance (USA) (Rev 1)" + rom ( name "Super Dodge Ball Advance (USA) (Rev 1).gba" size 4194304 crc 63ca5050 sha1 29561789fcb3bcd106a5d27dea47f29b393191f6 ) ) game ( @@ -17389,9 +17605,15 @@ game ( ) game ( - name "Super Dodge Ball Advance (USA) (Rev 1)" - description "Super Dodge Ball Advance (USA) (Rev 1)" - rom ( name "Super Dodge Ball Advance (USA) (Rev 1).gba" size 4194304 crc 63ca5050 sha1 29561789fcb3bcd106a5d27dea47f29b393191f6 ) + name "Super Dodge Ball Advance (USA)" + description "Super Dodge Ball Advance (USA)" + rom ( name "Super Dodge Ball Advance (USA).gba" size 4194304 crc 1d31dc6b sha1 5fc95814ea7695d1301df4b545614a1ffae95218 ) +) + +game ( + name "Super Dodge Ball Advance (Europe)" + description "Super Dodge Ball Advance (Europe)" + rom ( name "Super Dodge Ball Advance (Europe).gba" size 4194304 crc 4ca4f528 sha1 a0ac6be19f385eef6bc48bca8d54520d4e8a00e7 flags verified ) ) game ( @@ -17445,7 +17667,7 @@ game ( game ( name "Super Hornet FA 18F (USA, Europe)" description "Super Hornet FA 18F (USA, Europe)" - rom ( name "Super Hornet FA 18F (USA, Europe).gba" size 4194304 crc 9653bac5 sha1 038b533bb09845ade7b0a13c7ca9923348eb1100 ) + rom ( name "Super Hornet FA 18F (USA, Europe).gba" size 4194304 crc 9653bac5 sha1 038b533bb09845ade7b0a13c7ca9923348eb1100 flags verified ) ) game ( @@ -17814,6 +18036,12 @@ game ( rom ( name "Superman Returns - Fortress of Solitude (USA, Europe) (En,Fr,De,Es,It).gba" size 16777216 crc 68215047 sha1 1ff9d19032466227ae7aaebb0161c531aaf60428 ) ) +game ( + name "Superman Returns - Fortress of Solitude (USA, Europe) (Beta)" + description "Superman Returns - Fortress of Solitude (USA, Europe) (Beta)" + rom ( name "Superman Returns - Fortress of Solitude (USA, Europe) (Beta).gba" size 16777216 crc a0fb8e93 sha1 fd4585fc39ef54e1eb901e463d8e6d45ab40fccf ) +) + game ( name "Surf's Up (USA) (En,Fr,Es)" description "Surf's Up (USA) (En,Fr,Es)" @@ -17832,6 +18060,12 @@ game ( rom ( name "Surf's Up (Europe) (En,Fr,Es).gba" size 8388608 crc 317326b0 sha1 b0a2ba2a7d042cc9426ec1abdbd912613c4ae191 ) ) +game ( + name "Sushi the Cat (World) (Unl)" + description "Sushi the Cat (World) (Unl)" + rom ( name "Sushi the Cat (World) (Unl).gba" size 540296 crc 6f019a88 sha1 f6d523a073c21639e15d615947167bba3871c67a ) +) + game ( name "Sutakomi - Star Communicator (Japan)" description "Sutakomi - Star Communicator (Japan)" @@ -17844,12 +18078,6 @@ game ( rom ( name "Sweet Cookie Pie (Japan).gba" size 4194304 crc 63f45849 sha1 96610003fdb49a14b35aeedf0c8cebf5f80d8e4a ) ) -game ( - name "Sword of Mana (Europe)" - description "Sword of Mana (Europe)" - rom ( name "Sword of Mana (Europe).gba" size 16777216 crc 88e64a8a sha1 129712ce98646c89136cee01902dd20ef6541978 flags verified ) -) - game ( name "Sword of Mana (USA, Australia)" description "Sword of Mana (USA, Australia)" @@ -17868,6 +18096,12 @@ game ( rom ( name "Sword of Mana (Europe) (Es,It).gba" size 16777216 crc 11a0af49 sha1 390dff3ec37d24a5d00165deb17eb64c0ace32b1 ) ) +game ( + name "Sword of Mana (Europe)" + description "Sword of Mana (Europe)" + rom ( name "Sword of Mana (Europe).gba" size 16777216 crc 88e64a8a sha1 129712ce98646c89136cee01902dd20ef6541978 flags verified ) +) + game ( name "Sylvanian Families - Fashion Designer ni Naritai! - Kurumi-risu no Onnanoko (Japan)" description "Sylvanian Families - Fashion Designer ni Naritai! - Kurumi-risu no Onnanoko (Japan)" @@ -17907,7 +18141,7 @@ game ( game ( name "Tak - The Great Juju Challenge (USA, Europe)" description "Tak - The Great Juju Challenge (USA, Europe)" - rom ( name "Tak - The Great Juju Challenge (USA, Europe).gba" size 8388608 crc 881c8416 sha1 0999a8ee2bae78a223c992408e987422ba0c0af9 ) + rom ( name "Tak - The Great Juju Challenge (USA, Europe).gba" size 8388608 crc 881c8416 sha1 0999a8ee2bae78a223c992408e987422ba0c0af9 flags verified ) ) game ( @@ -17919,7 +18153,7 @@ game ( game ( name "Tak 2 - The Staff of Dreams (USA)" description "Tak 2 - The Staff of Dreams (USA)" - rom ( name "Tak 2 - The Staff of Dreams (USA).gba" size 8388608 crc 8f7eb026 sha1 f90219db6359332eb997a2717986a8c66eaded2b ) + rom ( name "Tak 2 - The Staff of Dreams (USA).gba" size 8388608 crc 8f7eb026 sha1 f90219db6359332eb997a2717986a8c66eaded2b flags verified ) ) game ( @@ -18096,12 +18330,6 @@ game ( rom ( name "Teenage Mutant Ninja Turtles Double Pack (USA) (En,Fr,De,Es,It).gba" size 16777216 crc 176a42e5 sha1 15cbff45ce0cb35f3e6a6059ada2710f0cec05c3 ) ) -game ( - name "Tekken Advance (Europe)" - description "Tekken Advance (Europe)" - rom ( name "Tekken Advance (Europe).gba" size 8388608 crc 4628c1b8 sha1 0a8665fe4e1f33427f710793db2937485a1c9418 flags verified ) -) - game ( name "Tekken Advance (Japan)" description "Tekken Advance (Japan)" @@ -18114,6 +18342,12 @@ game ( rom ( name "Tekken Advance (USA).gba" size 8388608 crc c59ea73b sha1 8b21cd57cacf172f963dfc7ead4fa127a8a63870 ) ) +game ( + name "Tekken Advance (Europe)" + description "Tekken Advance (Europe)" + rom ( name "Tekken Advance (Europe).gba" size 8388608 crc 4628c1b8 sha1 0a8665fe4e1f33427f710793db2937485a1c9418 flags verified ) +) + game ( name "Ten Pin Alley 2 (USA)" description "Ten Pin Alley 2 (USA)" @@ -18180,6 +18414,12 @@ game ( rom ( name "Tetris Worlds (Europe) (En,Es,It).gba" size 4194304 crc 4a834fc2 sha1 2de4d4c3d239b2e56ad4cc3000bb1ad2fdddd987 ) ) +game ( + name "Tetris Worlds (Japan) (Rev 1)" + description "Tetris Worlds (Japan) (Rev 1)" + rom ( name "Tetris Worlds (Japan) (Rev 1).gba" size 4194304 crc fcf2d471 sha1 be44036e39f95fb9feb93630720d46570ba1a42f ) +) + game ( name "Tetris Worlds (USA)" description "Tetris Worlds (USA)" @@ -18189,7 +18429,7 @@ game ( game ( name "Tetris Worlds (Europe) (En,Fr,De,Nl)" description "Tetris Worlds (Europe) (En,Fr,De,Nl)" - rom ( name "Tetris Worlds (Europe) (En,Fr,De,Nl).gba" size 4194304 crc ad97eb3f sha1 4a1297b44208366a178cc1f2541f5ea8386f6f3e ) + rom ( name "Tetris Worlds (Europe) (En,Fr,De,Nl).gba" size 4194304 crc ad97eb3f sha1 4a1297b44208366a178cc1f2541f5ea8386f6f3e flags verified ) ) game ( @@ -18199,9 +18439,9 @@ game ( ) game ( - name "Tetris Worlds (Japan) (Rev 1)" - description "Tetris Worlds (Japan) (Rev 1)" - rom ( name "Tetris Worlds (Japan) (Rev 1).gba" size 4194304 crc fcf2d471 sha1 be44036e39f95fb9feb93630720d46570ba1a42f ) + name "Texas Hold 'em Poker (USA)" + description "Texas Hold 'em Poker (USA)" + rom ( name "Texas Hold 'em Poker (USA).gba" size 4194304 crc 78b59aac sha1 5fcc9958210d8bde94a429516b15ca669427fe6d flags verified ) ) game ( @@ -18210,12 +18450,6 @@ game ( rom ( name "Texas Hold 'em Poker (Europe) (Rev 1).gba" size 4194304 crc 1a13df6b sha1 f6d018d9174bf04fd8c90b3173570391f2d11b19 ) ) -game ( - name "Texas Hold 'em Poker (USA)" - description "Texas Hold 'em Poker (USA)" - rom ( name "Texas Hold 'em Poker (USA).gba" size 4194304 crc 78b59aac sha1 5fcc9958210d8bde94a429516b15ca669427fe6d ) -) - game ( name "TG Rally (Europe)" description "TG Rally (Europe)" @@ -18267,13 +18501,13 @@ game ( game ( name "Thunder Alley (USA)" description "Thunder Alley (USA)" - rom ( name "Thunder Alley (USA).gba" size 4194304 crc 25e8e649 sha1 d63aaf9ac4468f1d0ead35606d9a4f56327b2537 ) + rom ( name "Thunder Alley (USA).gba" size 4194304 crc 25e8e649 sha1 d63aaf9ac4468f1d0ead35606d9a4f56327b2537 flags verified ) ) game ( name "Thunderbirds (USA, Europe)" description "Thunderbirds (USA, Europe)" - rom ( name "Thunderbirds (USA, Europe).gba" size 4194304 crc f09b7bb0 sha1 08c4b9b924f5cf0404cab5cd7fb6064fca872250 ) + rom ( name "Thunderbirds (USA, Europe).gba" size 4194304 crc f09b7bb0 sha1 08c4b9b924f5cf0404cab5cd7fb6064fca872250 flags verified ) ) game ( @@ -18291,7 +18525,7 @@ game ( game ( name "Tiger Woods PGA Tour Golf (USA, Europe)" description "Tiger Woods PGA Tour Golf (USA, Europe)" - rom ( name "Tiger Woods PGA Tour Golf (USA, Europe).gba" size 8388608 crc f3f26acc sha1 88b204b7b51995e41459b532580b3956d7db55ad ) + rom ( name "Tiger Woods PGA Tour Golf (USA, Europe).gba" size 8388608 crc f3f26acc sha1 88b204b7b51995e41459b532580b3956d7db55ad flags verified ) ) game ( @@ -18324,36 +18558,36 @@ game ( rom ( name "Tiny Toon Adventures - Scary Dreams (USA).gba" size 4194304 crc fcd7a7c0 sha1 305c6cf66e47508deee4b9fc12c8917302f2ed39 ) ) -game ( - name "Tiny Toon Adventures - Wacky Stackers (Europe) (En,Fr,De,Es,It)" - description "Tiny Toon Adventures - Wacky Stackers (Europe) (En,Fr,De,Es,It)" - rom ( name "Tiny Toon Adventures - Wacky Stackers (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 4ac770b6 sha1 cd9d810b29070d9f37df219bfd7e52ce9d52d2b0 ) -) - game ( name "Tiny Toon Adventures - Wacky Stackers (USA)" description "Tiny Toon Adventures - Wacky Stackers (USA)" rom ( name "Tiny Toon Adventures - Wacky Stackers (USA).gba" size 4194304 crc e03c633e sha1 fd9d10006bd29945ac16c6f88608a27e15f8f7da ) ) +game ( + name "Tiny Toon Adventures - Wacky Stackers (Europe) (En,Fr,De,Es,It)" + description "Tiny Toon Adventures - Wacky Stackers (Europe) (En,Fr,De,Es,It)" + rom ( name "Tiny Toon Adventures - Wacky Stackers (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 4ac770b6 sha1 cd9d810b29070d9f37df219bfd7e52ce9d52d2b0 flags verified ) +) + game ( name "Tir et But - Edition Champions du Monde (France)" description "Tir et But - Edition Champions du Monde (France)" rom ( name "Tir et But - Edition Champions du Monde (France).gba" size 4194304 crc 7782a204 sha1 e097aa37ab67146d544ae1438a19f8cd9e3a8f7c ) ) -game ( - name "Titeuf - Mega Compet (France)" - description "Titeuf - Mega Compet (France)" - rom ( name "Titeuf - Mega Compet (France).gba" size 4194304 crc ffd0a045 sha1 ff59a9810adc3270295763282c9d86d549f58a6f ) -) - game ( name "Titeuf - Mega Compet (France) (Beta)" description "Titeuf - Mega Compet (France) (Beta)" rom ( name "Titeuf - Mega Compet (France) (Beta).gba" size 4194304 crc c9be7fcf sha1 1ed43c7419b22b1147bd7e3198de52f4c8d3003d ) ) +game ( + name "Titeuf - Mega Compet (France)" + description "Titeuf - Mega Compet (France)" + rom ( name "Titeuf - Mega Compet (France).gba" size 4194304 crc ffd0a045 sha1 ff59a9810adc3270295763282c9d86d549f58a6f ) +) + game ( name "Titeuf - Ze Gag Machine (France)" description "Titeuf - Ze Gag Machine (France)" @@ -18456,24 +18690,30 @@ game ( rom ( name "Tom Clancy's Rainbow Six - Rogue Spear (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 6863ce1a sha1 092179cd51657a4572fa855eb3e5bc3f46c1d76f ) ) +game ( + name "Tom Clancy's Rainbow Six - Rogue Spear (USA, Europe) (En,Fr,De,Es,It) (Beta) (2001-10-25)" + description "Tom Clancy's Rainbow Six - Rogue Spear (USA, Europe) (En,Fr,De,Es,It) (Beta) (2001-10-25)" + rom ( name "Tom Clancy's Rainbow Six - Rogue Spear (USA, Europe) (En,Fr,De,Es,It) (Beta) (2001-10-25).gba" size 7963152 crc 666e31b5 sha1 d8426022537149670871817ff9336261b31172b5 ) +) + game ( name "Tom Clancy's Splinter Cell (USA) (En,Fr,Es)" description "Tom Clancy's Splinter Cell (USA) (En,Fr,Es)" rom ( name "Tom Clancy's Splinter Cell (USA) (En,Fr,Es).gba" size 8388608 crc 308ba69c sha1 dbd089cbdd79c26b2f0b651f74df59b6cbfafbcb ) ) -game ( - name "Tom Clancy's Splinter Cell (Europe) (En,Fr,De,Es,It,Nl)" - description "Tom Clancy's Splinter Cell (Europe) (En,Fr,De,Es,It,Nl)" - rom ( name "Tom Clancy's Splinter Cell (Europe) (En,Fr,De,Es,It,Nl).gba" size 8388608 crc 7ecd29ce sha1 d623cbd1019665eee78846a2a60d17adaf8ec0fe flags verified ) -) - game ( name "Tom Clancy's Splinter Cell (Europe) (En,Fr,De,Es,It,Nl) (Beta)" description "Tom Clancy's Splinter Cell (Europe) (En,Fr,De,Es,It,Nl) (Beta)" rom ( name "Tom Clancy's Splinter Cell (Europe) (En,Fr,De,Es,It,Nl) (Beta).gba" size 16777216 crc e07ba799 sha1 3a55f6ed66a3ec7c019221fa2660e2f85954ebae ) ) +game ( + name "Tom Clancy's Splinter Cell (Europe) (En,Fr,De,Es,It,Nl)" + description "Tom Clancy's Splinter Cell (Europe) (En,Fr,De,Es,It,Nl)" + rom ( name "Tom Clancy's Splinter Cell (Europe) (En,Fr,De,Es,It,Nl).gba" size 8388608 crc 7ecd29ce sha1 d623cbd1019665eee78846a2a60d17adaf8ec0fe flags verified ) +) + game ( name "Tom Clancy's Splinter Cell - Pandora Tomorrow (Europe) (En,Fr,De,Es,It,Nl)" description "Tom Clancy's Splinter Cell - Pandora Tomorrow (Europe) (En,Fr,De,Es,It,Nl)" @@ -18567,7 +18807,7 @@ game ( game ( name "Tony Hawk's Pro Skater 3 (France)" description "Tony Hawk's Pro Skater 3 (France)" - rom ( name "Tony Hawk's Pro Skater 3 (France).gba" size 8388608 crc 8d132067 sha1 62ba6f28f5bbd8fe42ecabecdcff4d6b96ae4f21 ) + rom ( name "Tony Hawk's Pro Skater 3 (France).gba" size 8388608 crc 8d132067 sha1 62ba6f28f5bbd8fe42ecabecdcff4d6b96ae4f21 flags verified ) ) game ( @@ -18705,7 +18945,13 @@ game ( game ( name "Tottoko Hamutarou - Hamu-Hamu Sports (Japan) (Demo) (Kiosk, GameCube)" description "Tottoko Hamutarou - Hamu-Hamu Sports (Japan) (Demo) (Kiosk, GameCube)" - rom ( name "Tottoko Hamutarou - Hamu-Hamu Sports (Japan) (Demo) (Kiosk, GameCube).gba" size 16777216 crc 7cd6839c sha1 ace1d3587636d17fd9ebfe7a7cfd3ee36bc51b43 flags verified ) + rom ( name "Tottoko Hamutarou - Hamu-Hamu Sports (Japan) (Demo) (Kiosk, GameCube).gba" size 16777216 crc 7cd6839c sha1 ace1d3587636d17fd9ebfe7a7cfd3ee36bc51b43 ) +) + +game ( + name "Tottoko Hamutarou 3 - Love Love Daibouken Dechu (Japan) (Beta) (2002-05-29)" + description "Tottoko Hamutarou 3 - Love Love Daibouken Dechu (Japan) (Beta) (2002-05-29)" + rom ( name "Tottoko Hamutarou 3 - Love Love Daibouken Dechu (Japan) (Beta) (2002-05-29).gba" size 8388608 crc 782e25ae sha1 3f1a1448db7a48fe99428bb94b7b04382fd67aad ) ) game ( @@ -18756,6 +19002,12 @@ game ( rom ( name "Travis Pastrana's Pro MotoX (USA) (Proto) (2002-12-12).gba" size 4194304 crc ecfe5f96 sha1 64e356f495fd58a862f272124798ecf61e20cfb7 ) ) +game ( + name "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl) (Rev 1)" + description "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl) (Rev 1)" + rom ( name "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl) (Rev 1).gba" size 8388608 crc 794b2602 sha1 c703edaee8a2bad09c2298e2c92a14d459fe664a ) +) + game ( name "Treasure Planet (USA)" description "Treasure Planet (USA)" @@ -18765,37 +19017,7 @@ game ( game ( name "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl)" description "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl)" - rom ( name "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl).gba" size 8388608 crc d52ddce1 sha1 d89a2515f4fe0d0ac90b20e4633a80a2549175fc ) -) - -game ( - name "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl) (Rev 1)" - description "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl) (Rev 1)" - rom ( name "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl) (Rev 1).gba" size 8388608 crc 794b2602 sha1 c703edaee8a2bad09c2298e2c92a14d459fe664a ) -) - -game ( - name "Tremblay Island (World) (En) (v.1.10) (Aftermarket) (Unl)" - description "Tremblay Island (World) (En) (v.1.10) (Aftermarket) (Unl)" - rom ( name "Tremblay Island (World) (En) (v.1.10) (Aftermarket) (Unl).gba" size 16239516 crc ce85ba07 sha1 b09b600bfc222c2d92829d8883feab700b013953 ) -) - -game ( - name "Tremblay Island (World) (En) (v.1.10) (Solid State Version) (Aftermarket) (Unl)" - description "Tremblay Island (World) (En) (v.1.10) (Solid State Version) (Aftermarket) (Unl)" - rom ( name "Tremblay Island (World) (En) (v.1.10) (Solid State Version) (Aftermarket) (Unl).gba" size 16229600 crc bd57344d sha1 a2fcfe94c9b8b0feff31c1245c8b033222c9f668 ) -) - -game ( - name "Tremblay Island (World) (Fr) (v.1.10) (Solid State Version) (Aftermarket) (Unl)" - description "Tremblay Island (World) (Fr) (v.1.10) (Solid State Version) (Aftermarket) (Unl)" - rom ( name "Tremblay Island (World) (Fr) (v.1.10) (Solid State Version) (Aftermarket) (Unl).gba" size 16204024 crc fa43669e sha1 a57392fa7cee61913b20a840fe8b2ee27f11d808 ) -) - -game ( - name "Tremblay Island (World) (En) (Kickstarter Edition) (Aftermarket) (Unl)" - description "Tremblay Island (World) (En) (Kickstarter Edition) (Aftermarket) (Unl)" - rom ( name "Tremblay Island (World) (En) (Kickstarter Edition) (Aftermarket) (Unl).gba" size 16777216 crc ff5d64ab sha1 645ab8d4dacb6666d8eb549d491f77d8cd63ce97 ) + rom ( name "Treasure Planet (Europe) (En,Fr,De,Es,It,Nl).gba" size 8388608 crc d52ddce1 sha1 d89a2515f4fe0d0ac90b20e4633a80a2549175fc flags verified ) ) game ( @@ -19107,7 +19329,7 @@ game ( game ( name "Unfabulous (USA)" description "Unfabulous (USA)" - rom ( name "Unfabulous (USA).gba" size 4194304 crc 2547f3a1 sha1 a56e96a46ed7264bddbfc132925d291e3e8f0e38 ) + rom ( name "Unfabulous (USA).gba" size 4194304 crc 2547f3a1 sha1 a56e96a46ed7264bddbfc132925d291e3e8f0e38 flags verified ) ) game ( @@ -19140,6 +19362,36 @@ game ( rom ( name "Uno 52 (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 315360d0 sha1 f85709ec7a97c8b40504f2097497bd961531272d ) ) +game ( + name "Uranus (World) (Unl)" + description "Uranus (World) (Unl)" + rom ( name "Uranus (World) (Unl).gba" size 4194304 crc 8152384d sha1 2c99b0c66cea1ce8d203aaa0985baa43fcdd82bd ) +) + +game ( + name "Uranus 2 - Sun Tear (World) (En,Fr) (Unl)" + description "Uranus 2 - Sun Tear (World) (En,Fr) (Unl)" + rom ( name "Uranus 2 - Sun Tear (World) (En,Fr) (Unl).gba" size 4194304 crc f1c63552 sha1 7c68363212a7fb424429281a658cbadfe37de035 ) +) + +game ( + name "Uranus Zero - Sun Tear (World) (En,Fr) (Unl)" + description "Uranus Zero - Sun Tear (World) (En,Fr) (Unl)" + rom ( name "Uranus Zero - Sun Tear (World) (En,Fr) (Unl).gba" size 8388608 crc 117183cc sha1 258058fb9ca44a93478220e19d0cf09cde527003 ) +) + +game ( + name "Uranus Zero EV (World) (En,Fr) (v1.1) (Unl)" + description "Uranus Zero EV (World) (En,Fr) (v1.1) (Unl)" + rom ( name "Uranus Zero EV (World) (En,Fr) (v1.1) (Unl).gba" size 7609632 crc 1b463c9e sha1 bb2536ae8c6b625f3abfb66add7c1b3b74b942ee ) +) + +game ( + name "Uranus Zero EV (World) (En,Fr) (Unl)" + description "Uranus Zero EV (World) (En,Fr) (Unl)" + rom ( name "Uranus Zero EV (World) (En,Fr) (Unl).gba" size 7610684 crc adbcba92 sha1 405fb8cefb7ab0262a5f3bb7d290b9b60128db9b ) +) + game ( name "Urban Yeti! (USA, Europe)" description "Urban Yeti! (USA, Europe)" @@ -19257,7 +19509,7 @@ game ( game ( name "W.i.t.c.h. (Europe) (En,Fr,De,Es,It)" description "W.i.t.c.h. (Europe) (En,Fr,De,Es,It)" - rom ( name "W.i.t.c.h. (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc ca4f6d5d sha1 dce3603206745f3d9288f35eab33cc0f890c3751 ) + rom ( name "W.i.t.c.h. (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc ca4f6d5d sha1 dce3603206745f3d9288f35eab33cc0f890c3751 flags verified ) ) game ( @@ -19590,18 +19842,18 @@ game ( rom ( name "WinX Club - Quest for the Codex (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 9eb09c77 sha1 84951f8baabc405eee8a1fb94d420397623265ad ) ) -game ( - name "Wizardry Summoner (Japan)" - description "Wizardry Summoner (Japan)" - rom ( name "Wizardry Summoner (Japan).gba" size 4194304 crc 71695a71 sha1 c9ba4742d494d61a215f6e8068fdaeed12d19cdc ) -) - game ( name "Wizardry Summoner (Japan) (Rev 1)" description "Wizardry Summoner (Japan) (Rev 1)" rom ( name "Wizardry Summoner (Japan) (Rev 1).gba" size 4194304 crc b3c77a61 sha1 c4ddb35319b8ed0f2e3d281ad93e42a0db757cd5 flags verified ) ) +game ( + name "Wizardry Summoner (Japan)" + description "Wizardry Summoner (Japan)" + rom ( name "Wizardry Summoner (Japan).gba" size 4194304 crc 71695a71 sha1 c9ba4742d494d61a215f6e8068fdaeed12d19cdc ) +) + game ( name "Wolfenstein 3D (USA, Europe)" description "Wolfenstein 3D (USA, Europe)" @@ -19639,15 +19891,15 @@ game ( ) game ( - name "World Championship Poker (Europe) (En,Fr,De,Es,It)" - description "World Championship Poker (Europe) (En,Fr,De,Es,It)" - rom ( name "World Championship Poker (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 4776f86e sha1 731ef2646ad83750aff729cb2286de6ee60f8260 ) + name "World Championship Poker (USA)" + description "World Championship Poker (USA)" + rom ( name "World Championship Poker (USA).gba" size 4194304 crc 07f15152 sha1 1d72864021f88f8db2686c57cfc5176b33ce2015 flags verified ) ) game ( - name "World Championship Poker (USA)" - description "World Championship Poker (USA)" - rom ( name "World Championship Poker (USA).gba" size 4194304 crc 07f15152 sha1 1d72864021f88f8db2686c57cfc5176b33ce2015 ) + name "World Championship Poker (Europe) (En,Fr,De,Es,It)" + description "World Championship Poker (Europe) (En,Fr,De,Es,It)" + rom ( name "World Championship Poker (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 4776f86e sha1 731ef2646ad83750aff729cb2286de6ee60f8260 ) ) game ( @@ -19668,12 +19920,6 @@ game ( rom ( name "World Reborn (USA) (Proto).gba" size 4194304 crc 4c48ebb3 sha1 91899433556c14bbe3bb043e95c3549bf3346e5a ) ) -game ( - name "World Reborn (USA) (Aftermarket) (Unl)" - description "World Reborn (USA) (Aftermarket) (Unl)" - rom ( name "World Reborn (USA) (Aftermarket) (Unl).gba" size 4194304 crc eefb32ff sha1 c7ec2f8d7d3dec40a893cdfe2a41a8ed43ed71c4 ) -) - game ( name "World Tennis Stars (Europe)" description "World Tennis Stars (Europe)" @@ -19704,6 +19950,12 @@ game ( rom ( name "Worms Blast (Europe) (En,Fr,De,Es,It).gba" size 4194304 crc 5223f5aa sha1 0da4ff24b61ae8b6d67ef59377770fd958517f2f ) ) +game ( + name "Worms Blast (World) (En,Fr,De,Es,It) (Evercade) (Unl)" + description "Worms Blast (World) (En,Fr,De,Es,It) (Evercade) (Unl)" + rom ( name "Worms Blast (World) (En,Fr,De,Es,It) (Evercade) (Unl).gba" size 4194304 crc 55c25c4a sha1 da4e430b5fef43bdb8a4c52a8fdec5ae98243ddb ) +) + game ( name "WTA Tour Tennis (USA)" description "WTA Tour Tennis (USA)" @@ -19728,18 +19980,18 @@ game ( rom ( name "WWE - Survivor Series (USA, Europe).gba" size 4194304 crc 6694f94d sha1 bb61e289f2a09e7ce0e193267430dbc6f5583a49 flags verified ) ) -game ( - name "WWF - Road to WrestleMania (USA, Europe) (Beta)" - description "WWF - Road to WrestleMania (USA, Europe) (Beta)" - rom ( name "WWF - Road to WrestleMania (USA, Europe) (Beta).gba" size 4194304 crc 8314421b sha1 13c1965b62849873738417830e142182782430fe ) -) - game ( name "WWF - Road to WrestleMania (USA, Europe)" description "WWF - Road to WrestleMania (USA, Europe)" rom ( name "WWF - Road to WrestleMania (USA, Europe).gba" size 4194304 crc 8d3b116e sha1 e9334fd4b7a8acf2256a8e2e97f0ab3dd91d6abb ) ) +game ( + name "WWF - Road to WrestleMania (USA, Europe) (Beta)" + description "WWF - Road to WrestleMania (USA, Europe) (Beta)" + rom ( name "WWF - Road to WrestleMania (USA, Europe) (Beta).gba" size 4194304 crc 8314421b sha1 13c1965b62849873738417830e142182782430fe ) +) + game ( name "X Zhan Jing (Taiwan) (Unl)" description "X Zhan Jing (Taiwan) (Unl)" @@ -19845,19 +20097,19 @@ game ( game ( name "Yggdra Union (Japan)" description "Yggdra Union (Japan)" - rom ( name "Yggdra Union (Japan).gba" size 33554432 crc a86f844a sha1 4ac5874b98f0fa3c3aad4c3ebe927f7fbc5b3267 ) + rom ( name "Yggdra Union (Japan).gba" size 33554432 crc bf53a3d2 sha1 b55d786fd8f80e71d24097ae45f5fcc5948f395b ) ) game ( name "Yggdra Union - We'll Never Fight Alone (USA)" description "Yggdra Union - We'll Never Fight Alone (USA)" - rom ( name "Yggdra Union - We'll Never Fight Alone (USA).gba" size 33554432 crc 3bfa68f7 sha1 b289083b01f2f8fc726c664cf872d72b3f4986e3 ) + rom ( name "Yggdra Union - We'll Never Fight Alone (USA).gba" size 33554432 crc 84b5666c sha1 75697060a9c262fd00552ddd06faec82fc310282 ) ) game ( name "Yggdra Union - We'll Never Fight Alone (Europe)" description "Yggdra Union - We'll Never Fight Alone (Europe)" - rom ( name "Yggdra Union - We'll Never Fight Alone (Europe).gba" size 33554432 crc 3e0df130 sha1 e419c835200457f67d5ab7e3c236583980b922d9 ) + rom ( name "Yggdra Union - We'll Never Fight Alone (Europe).gba" size 33554432 crc 2931d6a8 sha1 7b65074cb5d75d8f12692a21e2be77fa963f10e2 ) ) game ( @@ -19896,6 +20148,12 @@ game ( rom ( name "Youkaidou (Japan).gba" size 8388608 crc 2a4a92b4 sha1 ed6578bb6a4f201ae5b269df5ce842158a34a421 ) ) +game ( + name "Yu Yu Hakusho - Ghostfiles - Spirit Detective (USA) (Beta)" + description "Yu Yu Hakusho - Ghostfiles - Spirit Detective (USA) (Beta)" + rom ( name "Yu Yu Hakusho - Ghostfiles - Spirit Detective (USA) (Beta).gba" size 16777216 crc 8cbfa66b sha1 d3906650386872a94b83c417ecef2369ece5b978 ) +) + game ( name "Yu Yu Hakusho - Ghostfiles - Spirit Detective (USA)" description "Yu Yu Hakusho - Ghostfiles - Spirit Detective (USA)" @@ -19908,12 +20166,6 @@ game ( rom ( name "Yu Yu Hakusho - Ghostfiles - Spirit Detective (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc 208d77ec sha1 66dc426b71195c11761f7ce58ffef231e8e227b1 ) ) -game ( - name "Yu Yu Hakusho - Ghostfiles - Spirit Detective (USA) (Beta)" - description "Yu Yu Hakusho - Ghostfiles - Spirit Detective (USA) (Beta)" - rom ( name "Yu Yu Hakusho - Ghostfiles - Spirit Detective (USA) (Beta).gba" size 16777216 crc 8cbfa66b sha1 d3906650386872a94b83c417ecef2369ece5b978 ) -) - game ( name "Yu Yu Hakusho - Ghostfiles - Tournament Tactics (USA, Europe)" description "Yu Yu Hakusho - Ghostfiles - Tournament Tactics (USA, Europe)" @@ -19944,6 +20196,12 @@ game ( rom ( name "Yu-Gi-Oh! - Destiny Board Traveler (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc ae1a8e9d sha1 96fd0e583ab49258b194f578e29e9a5d55122b50 ) ) +game ( + name "Yu-Gi-Oh! - Dungeon Dice Monsters (Europe) (En,Fr,De,Es,It)" + description "Yu-Gi-Oh! - Dungeon Dice Monsters (Europe) (En,Fr,De,Es,It)" + rom ( name "Yu-Gi-Oh! - Dungeon Dice Monsters (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc ee317f69 sha1 3ded1227698fbdb2ba47f03025cd1934fc184b99 flags verified ) +) + game ( name "Yu-Gi-Oh! - Dungeon Dice Monsters (Japan)" description "Yu-Gi-Oh! - Dungeon Dice Monsters (Japan)" @@ -19956,12 +20214,6 @@ game ( rom ( name "Yu-Gi-Oh! - Dungeon Dice Monsters (USA) (En,Es).gba" size 8388608 crc 8b5e0a27 sha1 fdd69455a072b2f74e6c5c50b96daa0438156b27 flags verified ) ) -game ( - name "Yu-Gi-Oh! - Dungeon Dice Monsters (Europe) (En,Fr,De,Es,It)" - description "Yu-Gi-Oh! - Dungeon Dice Monsters (Europe) (En,Fr,De,Es,It)" - rom ( name "Yu-Gi-Oh! - Dungeon Dice Monsters (Europe) (En,Fr,De,Es,It).gba" size 8388608 crc ee317f69 sha1 3ded1227698fbdb2ba47f03025cd1934fc184b99 flags verified ) -) - game ( name "Yu-Gi-Oh! - Reshef of Destruction (USA)" description "Yu-Gi-Oh! - Reshef of Destruction (USA)" @@ -19971,7 +20223,7 @@ game ( game ( name "Yu-Gi-Oh! - Reshef of Destruction (Europe) (En,Fr,De,Es,It)" description "Yu-Gi-Oh! - Reshef of Destruction (Europe) (En,Fr,De,Es,It)" - rom ( name "Yu-Gi-Oh! - Reshef of Destruction (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc 460e073f sha1 1d33877dcc5ec94cc0d68460163208c7ebfb6ad3 ) + rom ( name "Yu-Gi-Oh! - Reshef of Destruction (Europe) (En,Fr,De,Es,It).gba" size 16777216 crc 460e073f sha1 1d33877dcc5ec94cc0d68460163208c7ebfb6ad3 flags verified ) ) game ( @@ -20115,7 +20367,7 @@ game ( game ( name "Yu-Gi-Oh! GX - Duel Academy (USA)" description "Yu-Gi-Oh! GX - Duel Academy (USA)" - rom ( name "Yu-Gi-Oh! GX - Duel Academy (USA).gba" size 33554432 crc 3b8a00fe sha1 57d6bb789833b62b360072902982d5f1011b3640 ) + rom ( name "Yu-Gi-Oh! GX - Duel Academy (USA).gba" size 33554432 crc 3b8a00fe sha1 57d6bb789833b62b360072902982d5f1011b3640 flags verified ) ) game ( @@ -20292,18 +20544,18 @@ game ( rom ( name "Zoids Saga II (Japan).gba" size 8388608 crc 0c039503 sha1 6014ca7c7af931d62634be4baa992a2fe187413f ) ) -game ( - name "Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan)" - description "Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan)" - rom ( name "Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan).gba" size 16777216 crc 2804e589 sha1 54a4dcdeca2ee9a22559eb104b88586386639097 ) -) - game ( name "Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan) (Rev 1)" description "Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan) (Rev 1)" rom ( name "Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan) (Rev 1).gba" size 16777216 crc 71e2cd01 sha1 1a81843c3070decea4cbca20c4563541400b2437 ) ) +game ( + name "Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan)" + description "Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan)" + rom ( name "Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan).gba" size 16777216 crc 2804e589 sha1 54a4dcdeca2ee9a22559eb104b88586386639097 ) +) + game ( name "Zone of the Enders - The Fist of Mars (USA)" description "Zone of the Enders - The Fist of Mars (USA)" @@ -20349,7 +20601,7 @@ game ( clrmamepro ( name "Nintendo - Game Boy Advance (Multiboot)" description "Nintendo - Game Boy Advance (Multiboot)" - version 20220808-164416 + version 20240221-035028 author "Arctic Circle System, C. V. Reynolds, chillerecke, DeriLoko3, Hiccup, hking0036, niemand, norkmetnoil577, omonim2007, relax" homepage No-Intro url "https://www.no-intro.org" @@ -20939,8 +21191,8 @@ game ( clrmamepro ( name "Nintendo - Game Boy Advance (Video)" description "Nintendo - Game Boy Advance (Video)" - version 20230301-094141 - author "BigFred, C. V. Reynolds, DeadSkullzJr, Hiccup, kazumi213, omonim2007, relax, SonGoku, xuom2" + version 20240727-194101 + author "BigFred, C. V. Reynolds, DeadSkullzJr, Hiccup, kazumi213, omonim2007, Psychofox11, psykopat, relax, SonGoku, xuom2" homepage No-Intro url "https://www.no-intro.org" forcenodump required @@ -20998,6 +21250,12 @@ game ( rom ( name "Game Boy Advance Video - Cartoon Network Collection - Special Edition (USA, Europe).gba" size 33554432 crc e9b7b8a4 sha1 5f17d2ec1a3ba1d605d486b6f6abcde6d82df767 ) ) +game ( + name "Game Boy Advance Video - Cartoon Network Collection - Special Edition (USA) (Rev 5)" + description "Game Boy Advance Video - Cartoon Network Collection - Special Edition (USA) (Rev 5)" + rom ( name "Game Boy Advance Video - Cartoon Network Collection - Special Edition (USA) (Rev 5).gba" size 33554432 crc 1baf372d sha1 86f257c7b8d8feaee0a7e7dd5f5ba48053fd633e flags verified ) +) + game ( name "Game Boy Advance Video - Cartoon Network Collection - Volume 1 (USA, Europe)" description "Game Boy Advance Video - Cartoon Network Collection - Volume 1 (USA, Europe)" @@ -21055,7 +21313,7 @@ game ( game ( name "Game Boy Advance Video - Nicktoons Collection - Volume 2 (USA)" description "Game Boy Advance Video - Nicktoons Collection - Volume 2 (USA)" - rom ( name "Game Boy Advance Video - Nicktoons Collection - Volume 2 (USA).gba" size 33554432 crc 65deeeb6 sha1 03a767124f034b1eea51ab84ba6e80ec76f7f50c ) + rom ( name "Game Boy Advance Video - Nicktoons Collection - Volume 2 (USA).gba" size 33554432 crc 65deeeb6 sha1 03a767124f034b1eea51ab84ba6e80ec76f7f50c flags verified ) ) game ( @@ -21091,7 +21349,7 @@ game ( game ( name "Game Boy Advance Video - Shark Tale (USA) (Rev 5)" description "Game Boy Advance Video - Shark Tale (USA) (Rev 5)" - rom ( name "Game Boy Advance Video - Shark Tale (USA) (Rev 5).gba" size 67108864 crc 01468820 sha1 6128a476edb10e6839ac5bd2697e83b9b7a9b234 ) + rom ( name "Game Boy Advance Video - Shark Tale (USA) (Rev 5).gba" size 67108864 crc 01468820 sha1 6128a476edb10e6839ac5bd2697e83b9b7a9b234 flags verified ) ) game ( @@ -21196,23 +21454,1203 @@ game ( rom ( name "Game Boy Advance Video - The Proud Family - Volume 1 (USA).gba" size 33554432 crc c6a91365 sha1 31a2cbb9b1b5adf7de399eecf2a9cec4f5412767 ) ) -game ( - name "Game Boy Advance Video - Yu-Gi-Oh! - Yugi vs. Joey (France)" - description "Game Boy Advance Video - Yu-Gi-Oh! - Yugi vs. Joey (France)" - rom ( name "Game Boy Advance Video - Yu-Gi-Oh! - Yugi vs. Joey (France).gba" size 33554432 crc c9b6ccf1 sha1 8fb43e5018cf2d4b1a2aa2d1693862ce248ab6b0 ) -) - game ( name "Game Boy Advance Video - Yu-Gi-Oh! - Yugi vs. Joey (USA, Europe)" description "Game Boy Advance Video - Yu-Gi-Oh! - Yugi vs. Joey (USA, Europe)" rom ( name "Game Boy Advance Video - Yu-Gi-Oh! - Yugi vs. Joey (USA, Europe).gba" size 33554432 crc 8d631f4e sha1 6daf15bb61a10d1bbf94009886d6a76f9c937f8b flags verified ) ) +game ( + name "Game Boy Advance Video - Yu-Gi-Oh! - Yugi vs. Joey (France)" + description "Game Boy Advance Video - Yu-Gi-Oh! - Yugi vs. Joey (France)" + rom ( name "Game Boy Advance Video - Yu-Gi-Oh! - Yugi vs. Joey (France).gba" size 33554432 crc c9b6ccf1 sha1 8fb43e5018cf2d4b1a2aa2d1693862ce248ab6b0 flags verified ) +) + +clrmamepro ( + name "Nintendo - Game Boy Advance (Aftermarket)" + description "Nintendo - Game Boy Advance (Aftermarket)" + version 20240807-214821 + author "aci68, Arctic Circle System, Aringon, Bent, BigFred, bikerspade, C. V. Reynolds, chillerecke, DeadSkullzJr, Densetsu, DeriLoko3, einstein95, ElBarto, Enker, FakeShemp, Flashfire42, fuzzball, Gefflon, Hiccup, hking0036, hydr0x, InternalLoss, Jack, jimmsu, Just001Kim, kazumi213, Larsenv, Lesserkuma, Madeline, MeguCocoa, Money_114, NESBrew12, niemand, nnssxx, norkmetnoil577, NovaAurora, omonim2007, Powerpuff, PPLToast, Prominos, Psychofox11, psykopat, rarenight, relax, RetroGamer, Rifu, sCZther, SonGoku, Tauwasser, Tescu, togemet2, ufocrossing, Vallaine01, Whovian9369, xprism, xuom2, zg" + homepage No-Intro + url "https://www.no-intro.org" + forcenodump required +) + +emulator ( + name "datafile" +) + +game ( + name "2-in-1 - Smickeonn the Game + Smickeonn the Game Deluxe (World) (Demo) (Aftermarket) (Unl)" + description "2-in-1 - Smickeonn the Game + Smickeonn the Game Deluxe (World) (Demo) (Aftermarket) (Unl)" + rom ( name "2-in-1 - Smickeonn the Game + Smickeonn the Game Deluxe (World) (Demo) (Aftermarket) (Unl).gba" size 1648884 crc 8ad5b73f sha1 eb85e372f15299cde6fefa8a2967e7e2886c9c56 ) +) + +game ( + name "2048 Pool (World) (Aftermarket) (Unl)" + description "2048 Pool (World) (Aftermarket) (Unl)" + rom ( name "2048 Pool (World) (Aftermarket) (Unl).gba" size 203440 crc 9df6ae4f sha1 c93a9cf3502237b474e70de8dee274901ee7ecb2 ) +) + +game ( + name "Advanced Ghost Wranglin' (World) (Demo) (Aftermarket) (Unl)" + description "Advanced Ghost Wranglin' (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Advanced Ghost Wranglin' (World) (Demo) (Aftermarket) (Unl).gba" size 354992 crc 739eb5ce sha1 9cf53301404407aae24ac7735006f594ca0fe969 ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (v0.95) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (v0.95) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (v0.95) (Aftermarket) (Unl).gba" size 1710888 crc 3346891f sha1 270c426705df767a4ad2dc69d039842442f779b2 flags verified ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (2021-02-28) (Patreon) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (2021-02-28) (Patreon) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (2021-02-28) (Patreon) (Aftermarket) (Unl).gba" size 1729120 crc a354d555 sha1 d7cd0ab9d622187d4ce55bf0c7f14a24ee781710 ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (v0.95) (Itch.io) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (v0.95) (Itch.io) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (v0.95) (Itch.io) (Aftermarket) (Unl).gba" size 1775856 crc 41ea5b0b sha1 e351bc6a9046ec002fc2dfdee061047908bd4350 ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (Retro-Bit Generations) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (Retro-Bit Generations) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (Retro-Bit Generations) (Aftermarket) (Unl).gba" size 1775660 crc a234813c sha1 ad904624bf198a164ba580eea326cd30fffebac8 ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (Demo) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (Demo) (Aftermarket) (Unl).gba" size 597104 crc 0a9098b4 sha1 0992fb6f38e49426adc834fb3831748a1caa1bc0 ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (v2.0) (Demo) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (v2.0) (Demo) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (v2.0) (Demo) (Aftermarket) (Unl).gba" size 811840 crc 63c1cc2c sha1 faca8225ee20b8e5edb14e005af77b63c6f51446 ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (v0.91) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (v0.91) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (v0.91) (Aftermarket) (Unl).gba" size 1714000 crc eebb016f sha1 008a9d06f78bccc540ca4ece4d1982de76f95901 ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (v0.92) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (v0.92) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (v0.92) (Aftermarket) (Unl).gba" size 1710624 crc ba271987 sha1 04f1e79e79e894d8f45ed1ea2ff5aa67053f0ab3 ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl).gba" size 1710624 crc df7108e3 sha1 bd267fd7e762acb8cd595e54bfd51a139864759e ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl) (Alt)" + description "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl) (Alt)" + rom ( name "Anguna - Warriors of Virtue (World) (v0.93) (Aftermarket) (Unl) (Alt).gba" size 1714000 crc 54ff2e56 sha1 0386315fc140db2a43a6f927c04de658bd800da9 ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (v0.94) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (v0.94) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (v0.94) (Aftermarket) (Unl).gba" size 1710952 crc cb4e2768 sha1 a7297cf4ecffc1f93f86edde68e1ff42e8099f3b ) +) + +game ( + name "Anguna - Warriors of Virtue (World) (Evercade) (Aftermarket) (Unl)" + description "Anguna - Warriors of Virtue (World) (Evercade) (Aftermarket) (Unl)" + rom ( name "Anguna - Warriors of Virtue (World) (Evercade) (Aftermarket) (Unl).gba" size 1693656 crc 7d8c00d3 sha1 9fffd28c933ac88a441a2e262156c66a3a763829 ) +) + +game ( + name "Apotris (World) (v3.4.5) (Aftermarket) (Unl)" + description "Apotris (World) (v3.4.5) (Aftermarket) (Unl)" + rom ( name "Apotris (World) (v3.4.5) (Aftermarket) (Unl).gba" size 4194304 crc 55ae4312 sha1 fb7142bcc30f71f187cc51b7fcbc5a3958374c6c ) +) + +game ( + name "Armadillo Run (World) (Demo) (Aftermarket) (Unl)" + description "Armadillo Run (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Armadillo Run (World) (Demo) (Aftermarket) (Unl).gba" size 1260068 crc 5151babd sha1 dfb706257d598a5ae845ddf6485e59a88c16d210 ) +) + +game ( + name "Attack on Voxelburg (World) (Demo) (GBA Jam 2022) (Aftermarket) (Unl)" + description "Attack on Voxelburg (World) (Demo) (GBA Jam 2022) (Aftermarket) (Unl)" + rom ( name "Attack on Voxelburg (World) (Demo) (GBA Jam 2022) (Aftermarket) (Unl).gba" size 827676 crc 941c1fe0 sha1 cb3823420a6e2399db7fa4805fefd1b5366c778e ) +) + +game ( + name "Battery Chad - Shock the World (World) (Demo) (Aftermarket) (Unl)" + description "Battery Chad - Shock the World (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Battery Chad - Shock the World (World) (Demo) (Aftermarket) (Unl).gba" size 609400 crc e0a4bc38 sha1 3274c915fb78d10541efa69dfbb8f9391f974ffe ) +) + +game ( + name "Blender Bros. (World) (Aftermarket) (Unl)" + description "Blender Bros. (World) (Aftermarket) (Unl)" + rom ( name "Blender Bros. (World) (Aftermarket) (Unl).gba" size 8388608 crc 440f2f06 sha1 8f9ca62306b7ab56d8da45673d7b7d0eb4c349c5 ) +) + +game ( + name "Blind Jump (World) (En,Ja,Fr,It,Ru) (v2021.11.20.0) (Proto) (Aftermarket) (Unl)" + description "Blind Jump (World) (En,Ja,Fr,It,Ru) (v2021.11.20.0) (Proto) (Aftermarket) (Unl)" + rom ( name "Blind Jump (World) (En,Ja,Fr,It,Ru) (v2021.11.20.0) (Proto) (Aftermarket) (Unl).gba" size 16565008 crc 2342e91e sha1 2e5758789f7e109839ea302424c385c1247eab38 ) +) + +game ( + name "Blood Drive (World) (GBA Jam Week) (Aftermarket) (Unl)" + description "Blood Drive (World) (GBA Jam Week) (Aftermarket) (Unl)" + rom ( name "Blood Drive (World) (GBA Jam Week) (Aftermarket) (Unl).gba" size 1523780 crc 3444a7ae sha1 12a3c114563684fdca4a4ee1b3fea43ceaf226c0 ) +) + +game ( + name "Broken Circle (World) (En,It) (Aftermarket) (Unl)" + description "Broken Circle (World) (En,It) (Aftermarket) (Unl)" + rom ( name "Broken Circle (World) (En,It) (Aftermarket) (Unl).gba" size 16777216 crc 3212c09b sha1 e04a71dbe7b640cc53e81f447856e60666e64aa3 ) +) + +game ( + name "Brush Rush (World) (Proto) (GBA WinterJam 2023) (Aftermarket) (Unl)" + description "Brush Rush (World) (Proto) (GBA WinterJam 2023) (Aftermarket) (Unl)" + rom ( name "Brush Rush (World) (Proto) (GBA WinterJam 2023) (Aftermarket) (Unl).gba" size 371136 crc afdf2c03 sha1 d36f7bd6d0420597ba0f12f746f8ec8a628b3658 ) +) + +game ( + name "Butano Fighter (World) (Aftermarket) (Unl)" + description "Butano Fighter (World) (Aftermarket) (Unl)" + rom ( name "Butano Fighter (World) (Aftermarket) (Unl).gba" size 3482456 crc 3c31501c sha1 36efe397badf199c0339222dc825013c06b86423 ) +) + +game ( + name "Cat's Curse (World) (Aftermarket) (Unl)" + description "Cat's Curse (World) (Aftermarket) (Unl)" + rom ( name "Cat's Curse (World) (Aftermarket) (Unl).gba" size 353052 crc a35d87de sha1 4a149baad17840948c2d4ffdf068bfaf1116a024 ) +) + +game ( + name "CCCP (World) (Aftermarket) (Unl)" + description "CCCP (World) (Aftermarket) (Unl)" + rom ( name "CCCP (World) (Aftermarket) (Unl).gba" size 499440 crc ad634c54 sha1 324f0375e3f4f89455122e2663b831917013bfc3 ) +) + +game ( + name "Celeste Classic (World) (v1.0) (Aftermarket) (Unl)" + description "Celeste Classic (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "Celeste Classic (World) (v1.0) (Aftermarket) (Unl).gba" size 5416932 crc f79b0d53 sha1 756f02396a150698e695ad4afd24445e2af70576 ) +) + +game ( + name "Celeste Classic (World) (v1.1) (Aftermarket) (Unl)" + description "Celeste Classic (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Celeste Classic (World) (v1.1) (Aftermarket) (Unl).gba" size 5418248 crc f5d36ad2 sha1 95a86dff641b11b4c2ed0d0fe8152c33b462d927 ) +) + +game ( + name "Celeste Classic (World) (v1.2) (Aftermarket) (Unl)" + description "Celeste Classic (World) (v1.2) (Aftermarket) (Unl)" + rom ( name "Celeste Classic (World) (v1.2) (Aftermarket) (Unl).gba" size 5418424 crc ff0e8ada sha1 08512605e5c02e81a72e24c2c8d4959d8e84e1f4 ) +) + +game ( + name "Codename Hacker (World) (En,Fr) (Aftermarket) (Unl)" + description "Codename Hacker (World) (En,Fr) (Aftermarket) (Unl)" + rom ( name "Codename Hacker (World) (En,Fr) (Aftermarket) (Unl).gba" size 4058684 crc 1ccfbe29 sha1 fbc6a366f773204b031b589aab4125e15a70dc9b ) +) + +game ( + name "Collie Defense (World) (Demo) (Aftermarket) (Unl)" + description "Collie Defense (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Collie Defense (World) (Demo) (Aftermarket) (Unl).gba" size 3714268 crc 08feb1ed sha1 4dce7b29bca3f8588cccb548c698d5d2ba53e188 ) +) + +game ( + name "DCPR (World) (Demo) (Aftermarket) (Unl)" + description "DCPR (World) (Demo) (Aftermarket) (Unl)" + rom ( name "DCPR (World) (Demo) (Aftermarket) (Unl).gba" size 107512 crc 6c27348a sha1 43d11a2e42aa56fa8851bb00a5467211ac195feb ) +) + +game ( + name "Donsol (World) (Aftermarket) (Unl)" + description "Donsol (World) (Aftermarket) (Unl)" + rom ( name "Donsol (World) (Aftermarket) (Unl).gba" size 52520 crc aec144b3 sha1 751675b0d77c341f2265b0edd38858b0dbdb7b50 ) +) + +game ( + name "Drawing a Leviathan (World) (Aftermarket) (Unl)" + description "Drawing a Leviathan (World) (Aftermarket) (Unl)" + rom ( name "Drawing a Leviathan (World) (Aftermarket) (Unl).gba" size 9437768 crc 1eb0f64d sha1 745636d636b44a67ad078dae5416636fa58236ab ) +) + +game ( + name "Eliminator GBA (World) (v0.91) (Proto) (Aftermarket) (Unl)" + description "Eliminator GBA (World) (v0.91) (Proto) (Aftermarket) (Unl)" + rom ( name "Eliminator GBA (World) (v0.91) (Proto) (Aftermarket) (Unl).gba" size 747872 crc 637dc1aa sha1 13a4d5c2c647945cbbf17423afd45a25c4057527 ) +) + +game ( + name "Elite AGB (World) (v1.4.1) (Aftermarket) (Unl)" + description "Elite AGB (World) (v1.4.1) (Aftermarket) (Unl)" + rom ( name "Elite AGB (World) (v1.4.1) (Aftermarket) (Unl).gba" size 960088 crc 28985872 sha1 803095500e47772452433144f2cd7630d515a41b ) +) + +game ( + name "Elite AGB (World) (v0.5.2) (Beta) (Aftermarket) (Unl)" + description "Elite AGB (World) (v0.5.2) (Beta) (Aftermarket) (Unl)" + rom ( name "Elite AGB (World) (v0.5.2) (Beta) (Aftermarket) (Unl).gba" size 327360 crc f00c939f sha1 ce5a236608c629c99d4ec7b35e3ccaf211e6bb60 ) +) + +game ( + name "Feline (World) (GBA Jam 2021) (Aftermarket) (Unl)" + description "Feline (World) (GBA Jam 2021) (Aftermarket) (Unl)" + rom ( name "Feline (World) (GBA Jam 2021) (Aftermarket) (Unl).gba" size 1504920 crc 09b777ea sha1 34b5aff6a7a3d752027ea1d2fd53e03bb8964529 ) +) + +game ( + name "Flappy Bird (World) (Aftermarket) (Unl)" + description "Flappy Bird (World) (Aftermarket) (Unl)" + rom ( name "Flappy Bird (World) (Aftermarket) (Unl).gba" size 575204 crc 4d099541 sha1 55f611567e7ac2ad8f96529f4d7eac70ad283601 ) +) + +game ( + name "GBA Tactics (World) (Proto) (NEO Coding Compo 2006) (Aftermarket) (Unl)" + description "GBA Tactics (World) (Proto) (NEO Coding Compo 2006) (Aftermarket) (Unl)" + rom ( name "GBA Tactics (World) (Proto) (NEO Coding Compo 2006) (Aftermarket) (Unl).gba" size 251816 crc 81b449a6 sha1 803834d8843a6689fe43c77921eaaea6bdaf6ed4 ) +) + +game ( + name "Glacia Dungeon (World) (En,Es,Ru,Ro) (v1.5.2) (Aftermarket) (Unl)" + description "Glacia Dungeon (World) (En,Es,Ru,Ro) (v1.5.2) (Aftermarket) (Unl)" + rom ( name "Glacia Dungeon (World) (En,Es,Ru,Ro) (v1.5.2) (Aftermarket) (Unl).gba" size 1210608 crc ab5ae65b sha1 e35037ff9cc24f8a7043d9a9d378e86d2ef80f9b ) +) + +game ( + name "Goldrunner (World) (Aftermarket) (Unl)" + description "Goldrunner (World) (Aftermarket) (Unl)" + rom ( name "Goldrunner (World) (Aftermarket) (Unl).gba" size 527040 crc 53f4cac1 sha1 517a400150a6ebca126b0a95aa3497c637cc8161 ) +) + +game ( + name "Goodboy Galaxy (World) (En,Ja,Fr,De,Es,Pt-BR,Zh,Ar) (Evercade) (Aftermarket) (Unl)" + description "Goodboy Galaxy (World) (En,Ja,Fr,De,Es,Pt-BR,Zh,Ar) (Evercade) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy (World) (En,Ja,Fr,De,Es,Pt-BR,Zh,Ar) (Evercade) (Aftermarket) (Unl).gba" size 32524164 crc ebb81069 sha1 273bae3d794f2b5a6bea637f67f7d5163ae4bb62 ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (En) (v1.0.6) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (En) (v1.0.6) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (En) (v1.0.6) (Demo) (Aftermarket) (Unl).gba" size 13224124 crc 19ba7d80 sha1 1bf95f8730ecdfa6665b85bea8764f42a88e8e3d ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Ja) (v1.0.6) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Ja) (v1.0.6) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Ja) (v1.0.6) (Demo) (Aftermarket) (Unl).gba" size 13219728 crc d4621e3e sha1 5bd59fac58c5f9a375216e9d1cf85fa5262f21f7 ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Fr) (v1.0.6) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Fr) (v1.0.6) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Fr) (v1.0.6) (Demo) (Aftermarket) (Unl).gba" size 13225068 crc 21512022 sha1 8832d38f787f3e1da620fcae7514d7387445ccf2 ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Es) (v1.0.6) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Es) (v1.0.6) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Es) (v1.0.6) (Demo) (Aftermarket) (Unl).gba" size 13223944 crc c1811c9b sha1 9d413bce82708df137215a2968306a5196b1638b ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Zh) (v1.0.6) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Zh) (v1.0.6) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Zh) (v1.0.6) (Demo) (Aftermarket) (Unl).gba" size 13269108 crc 3360e114 sha1 50186922ff77714b9ac638948b464cdbf80ab5fb ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Pt) (v1.0.6) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Pt) (v1.0.6) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Pt) (v1.0.6) (Demo) (Aftermarket) (Unl).gba" size 13223696 crc 3477ef15 sha1 4b447de09a23fbfdaa6d640824f8ceb5bbe56fab ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Ar) (v1.0.6) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Ar) (v1.0.6) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Ar) (v1.0.6) (Demo) (Aftermarket) (Unl).gba" size 13250016 crc a4054c2b sha1 c3cd833b9bdf87a8481c9b05251bba782bc3527e ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (En) (v1.0.7) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (En) (v1.0.7) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (En) (v1.0.7) (Demo) (Aftermarket) (Unl).gba" size 13220676 crc ab179d6e sha1 2ad1c4840f2f6c2138ed44b1a7aa36071c227a0a ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Fr) (v1.0.7) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Fr) (v1.0.7) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Fr) (v1.0.7) (Demo) (Aftermarket) (Unl).gba" size 13221620 crc 3aa591f1 sha1 2548615eeaecd7498e32d02b5c758b713ada27f4 ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (De) (v1.0.7) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (De) (v1.0.7) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (De) (v1.0.7) (Demo) (Aftermarket) (Unl).gba" size 13221368 crc d02cdb6a sha1 1e579e15bdc8dc1def99bcb3c30acfc185e0476b ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Es) (v1.0.7) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Es) (v1.0.7) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Es) (v1.0.7) (Demo) (Aftermarket) (Unl).gba" size 13220496 crc 906717a5 sha1 31857a9ab4daa537322f80faa77482a4b8120483 ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Pt) (v1.0.7) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Pt) (v1.0.7) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Pt) (v1.0.7) (Demo) (Aftermarket) (Unl).gba" size 13220252 crc d12372bd sha1 89ea5ea41133419c317fd28e7c7f172f5bb53ec3 ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Ja) (v1.0.7) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Ja) (v1.0.7) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Ja) (v1.0.7) (Demo) (Aftermarket) (Unl).gba" size 13216280 crc d3c8dffd sha1 c41c0596a4c52b0e26bb9ffe5c9f7f1c064e0be6 ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Zh) (v1.0.7) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Zh) (v1.0.7) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Zh) (v1.0.7) (Demo) (Aftermarket) (Unl).gba" size 13265660 crc 119f9ddc sha1 d6c23ff47b21a7bf2f8238ac916aeea3866042b5 ) +) + +game ( + name "Goodboy Galaxy - Chapter Zero (World) (Ar) (v1.0.7) (Demo) (Aftermarket) (Unl)" + description "Goodboy Galaxy - Chapter Zero (World) (Ar) (v1.0.7) (Demo) (Aftermarket) (Unl)" + rom ( name "Goodboy Galaxy - Chapter Zero (World) (Ar) (v1.0.7) (Demo) (Aftermarket) (Unl).gba" size 13246576 crc b14cd1b4 sha1 0d15bd0584148b1658f7d47a2dda604a936ea166 ) +) + +game ( + name "Google Dino Advance (World) (v1.0.1) (Aftermarket) (Unl)" + description "Google Dino Advance (World) (v1.0.1) (Aftermarket) (Unl)" + rom ( name "Google Dino Advance (World) (v1.0.1) (Aftermarket) (Unl).gba" size 109072 crc 6534185e sha1 33cc0afc7fbac8948deb75c66b8e097c1d05b2e3 ) +) + +game ( + name "Green Memories (World) (v1.2.0) (Aftermarket) (Unl)" + description "Green Memories (World) (v1.2.0) (Aftermarket) (Unl)" + rom ( name "Green Memories (World) (v1.2.0) (Aftermarket) (Unl).gba" size 6639328 crc 78b81bbc sha1 fb090890bd767a22afe07b3323dd0992d698c906 ) +) + +game ( + name "Green Memories (World) (v1.4.2) (Aftermarket) (Unl)" + description "Green Memories (World) (v1.4.2) (Aftermarket) (Unl)" + rom ( name "Green Memories (World) (v1.4.2) (Aftermarket) (Unl).gba" size 6937384 crc 9fa9f00f sha1 005f4dc0d615d36d32bbe36e9cc9007b22be2ecd ) +) + +game ( + name "Green Memories (World) (v1.4.4) (Aftermarket) (Unl)" + description "Green Memories (World) (v1.4.4) (Aftermarket) (Unl)" + rom ( name "Green Memories (World) (v1.4.4) (Aftermarket) (Unl).gba" size 6937812 crc 702b46c6 sha1 61f8ff01247e45888b8fd5da791176ff2c88f7f5 ) +) + +game ( + name "Hero Core (World) (Aftermarket) (Unl)" + description "Hero Core (World) (Aftermarket) (Unl)" + rom ( name "Hero Core (World) (Aftermarket) (Unl).gba" size 23642396 crc a58bfa21 sha1 fa96ba52c2573add583cb051b387f6bbb3edf02e ) +) + +game ( + name "Hero Core (World) (v0.1.2) (Beta) (GBA Jam 2022) (Aftermarket) (Unl)" + description "Hero Core (World) (v0.1.2) (Beta) (GBA Jam 2022) (Aftermarket) (Unl)" + rom ( name "Hero Core (World) (v0.1.2) (Beta) (GBA Jam 2022) (Aftermarket) (Unl).gba" size 22209300 crc 0a3fcad6 sha1 3b7b91c474a225d96118c4a4263007218a8ee2de ) +) + +game ( + name "Hexa Virus (World) (Aftermarket) (Unl)" + description "Hexa Virus (World) (Aftermarket) (Unl)" + rom ( name "Hexa Virus (World) (Aftermarket) (Unl).gba" size 1414244 crc 92243509 sha1 358640dc9972dd839d0b527177e05d030ec12d79 ) +) + +game ( + name "Hexes (World) (Aftermarket) (Unl)" + description "Hexes (World) (Aftermarket) (Unl)" + rom ( name "Hexes (World) (Aftermarket) (Unl).gba" size 10436680 crc d8d17420 sha1 d5686671caa7ec17b811476c982f81147073f0ed ) +) + +game ( + name "Holy Hell (World) (Proto) (NEO Coding Compo 2012) (Aftermarket) (Unl)" + description "Holy Hell (World) (Proto) (NEO Coding Compo 2012) (Aftermarket) (Unl)" + rom ( name "Holy Hell (World) (Proto) (NEO Coding Compo 2012) (Aftermarket) (Unl).gba" size 5956804 crc 09e21865 sha1 98db9220dffb07fc14a729931e7197a678d92d21 ) +) + +game ( + name "Inheritors of the Oubliette (World) (v1.2) (Aftermarket) (Unl)" + description "Inheritors of the Oubliette (World) (v1.2) (Aftermarket) (Unl)" + rom ( name "Inheritors of the Oubliette (World) (v1.2) (Aftermarket) (Unl).gba" size 10592124 crc a9014760 sha1 2430c6c0784912ad2f0b51e633bf577f087f189f ) +) + +game ( + name "Inheritors of the Oubliette (World) (GBA Jam 2021) (Aftermarket) (Unl)" + description "Inheritors of the Oubliette (World) (GBA Jam 2021) (Aftermarket) (Unl)" + rom ( name "Inheritors of the Oubliette (World) (GBA Jam 2021) (Aftermarket) (Unl).gba" size 25516708 crc 965a1a75 sha1 ae23cfba1f53a9bbde025490f3d7bdf52c3970e4 ) +) + +game ( + name "Inky and the Alien Aquarium (World) (Demo 1) (Aftermarket) (Unl)" + description "Inky and the Alien Aquarium (World) (Demo 1) (Aftermarket) (Unl)" + rom ( name "Inky and the Alien Aquarium (World) (Demo 1) (Aftermarket) (Unl).gba" size 3145728 crc 7ee7ae7f sha1 73d870fad3caa86b6f659e13b57eddac80db2f37 ) +) + +game ( + name "Inky and the Alien Aquarium (World) (Demo 2) (Aftermarket) (Unl)" + description "Inky and the Alien Aquarium (World) (Demo 2) (Aftermarket) (Unl)" + rom ( name "Inky and the Alien Aquarium (World) (Demo 2) (Aftermarket) (Unl).gba" size 3145728 crc 36f8ba9c sha1 3c05e1b3f40d9c16b85b05315472267b94e76471 ) +) + +game ( + name "Iridion 3D (USA) (Aftermarket) (Unl)" + description "Iridion 3D (USA) (Aftermarket) (Unl)" + rom ( name "Iridion 3D (USA) (Aftermarket) (Unl).gba" size 4194304 crc 4c7ebe42 sha1 6f1c77ab88351d2d50da412e4788fc7ca8a6714d ) +) + +game ( + name "Iridion II (USA) (Aftermarket) (Unl)" + description "Iridion II (USA) (Aftermarket) (Unl)" + rom ( name "Iridion II (USA) (Aftermarket) (Unl).gba" size 8388608 crc b371f070 sha1 cc788b38a047ff5ec8c445ce11efcd1852ad7c4d ) +) + +game ( + name "Join 4 Together (World) (Proto) (Aftermarket) (Unl)" + description "Join 4 Together (World) (Proto) (Aftermarket) (Unl)" + rom ( name "Join 4 Together (World) (Proto) (Aftermarket) (Unl).gba" size 1048576 crc 97d3c875 sha1 f9ffabd386d4d76d09e147f87f73de2638f875bb ) +) + +game ( + name "Luggage Retrieval Officer (World) (Aftermarket) (Unl)" + description "Luggage Retrieval Officer (World) (Aftermarket) (Unl)" + rom ( name "Luggage Retrieval Officer (World) (Aftermarket) (Unl).gba" size 3336260 crc 5aa30d90 sha1 84c9b2d50c8af74b8b04f88af367d9fac1a24ef6 ) +) + +game ( + name "Magic & Legend - Time Knights (World) (Beta) (Aftermarket) (Unl)" + description "Magic & Legend - Time Knights (World) (Beta) (Aftermarket) (Unl)" + rom ( name "Magic & Legend - Time Knights (World) (Beta) (Aftermarket) (Unl).gba" size 533996 crc 17af9e42 sha1 616342e07fa4c18a21e6b5de46b032c93bbbf34d ) +) + +game ( + name "Mandarin 2, The - Limoncello's Revenge (World) (Aftermarket) (Unl)" + description "Mandarin 2, The - Limoncello's Revenge (World) (Aftermarket) (Unl)" + rom ( name "Mandarin 2, The - Limoncello's Revenge (World) (Aftermarket) (Unl).gba" size 213684 crc cc2cb6a8 sha1 1937d06c2282152d6a9748c0e741c41c09583b77 ) +) + +game ( + name "MazezaM (World) (v1.1) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + description "MazezaM (World) (v1.1) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + rom ( name "MazezaM (World) (v1.1) (NEO Coding Compo 2013) (Aftermarket) (Unl).gba" size 569944 crc f7bc9db0 sha1 4517fbb7c44e9e93b0f5e89661e5cf979c624658 ) +) + +game ( + name "MazezaM (World) (v1.0) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + description "MazezaM (World) (v1.0) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + rom ( name "MazezaM (World) (v1.0) (NEO Coding Compo 2013) (Aftermarket) (Unl).gba" size 569704 crc 7c200ed5 sha1 46053717cf638c428ce92186e6a51a4a08e15ffd ) +) + +game ( + name "Metal Warrior 4 - Agents of Metal (World) (v1.3) (Aftermarket) (Unl)" + description "Metal Warrior 4 - Agents of Metal (World) (v1.3) (Aftermarket) (Unl)" + rom ( name "Metal Warrior 4 - Agents of Metal (World) (v1.3) (Aftermarket) (Unl).gba" size 524288 crc 7ec3485e sha1 729592141bc160ead0af51d4322c7f9f17da0b82 ) +) + +game ( + name "Metal Warrior 4 - Agents of Metal (World) (v1.1) (Aftermarket) (Unl)" + description "Metal Warrior 4 - Agents of Metal (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Metal Warrior 4 - Agents of Metal (World) (v1.1) (Aftermarket) (Unl).gba" size 524288 crc 5be69b8d sha1 5252dd4b67b56f591e9f8559d328433d5cf08f31 ) +) + +game ( + name "Minicraft (World) (v1.0) (Aftermarket) (Unl)" + description "Minicraft (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "Minicraft (World) (v1.0) (Aftermarket) (Unl).gba" size 131072 crc e852c9e9 sha1 06faa5be11978666db6995d8fce40ce2c3641ce8 ) +) + +game ( + name "Minicraft (World) (v1.1) (Aftermarket) (Unl)" + description "Minicraft (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Minicraft (World) (v1.1) (Aftermarket) (Unl).gba" size 131072 crc 07595773 sha1 fee5cfa5b9e1f3383780432772f29764ac0fc443 ) +) + +game ( + name "Minicraft (World) (v1.2) (Aftermarket) (Unl)" + description "Minicraft (World) (v1.2) (Aftermarket) (Unl)" + rom ( name "Minicraft (World) (v1.2) (Aftermarket) (Unl).gba" size 131072 crc 37e7ee7d sha1 dc7faa4952986d5c5f0e3b32203936cd717f97eb ) +) + +game ( + name "Minicraft (World) (v1.3) (Aftermarket) (Unl)" + description "Minicraft (World) (v1.3) (Aftermarket) (Unl)" + rom ( name "Minicraft (World) (v1.3) (Aftermarket) (Unl).gba" size 131072 crc cc48e03a sha1 7fe080bf9cc110aa78ce7248ff92ff3185083247 ) +) + +game ( + name "Misfortune Advance (World) (Aftermarket) (Unl)" + description "Misfortune Advance (World) (Aftermarket) (Unl)" + rom ( name "Misfortune Advance (World) (Aftermarket) (Unl).gba" size 5125100 crc 18f2166d sha1 68e215025ac963220f16ea3c100e51698f97c4eb ) +) + +game ( + name "Mooncat's Trio (World) (Aftermarket) (Unl)" + description "Mooncat's Trio (World) (Aftermarket) (Unl)" + rom ( name "Mooncat's Trio (World) (Aftermarket) (Unl).gba" size 1175680 crc b05d5339 sha1 890de7d73723d235d9762e4866d569d3554d1480 flags verified ) +) + +game ( + name "Mooncat's Trio (World) (Beta) (Aftermarket) (Unl)" + description "Mooncat's Trio (World) (Beta) (Aftermarket) (Unl)" + rom ( name "Mooncat's Trio (World) (Beta) (Aftermarket) (Unl).gba" size 504220 crc cd3328ee sha1 c3ea5247f32c428bbcfd5c087218fc56779e3106 ) +) + +game ( + name "Nekketsu Monogatari Advance (Japan) (Demo) (Aftermarket) (Unl)" + description "Nekketsu Monogatari Advance (Japan) (Demo) (Aftermarket) (Unl)" + rom ( name "Nekketsu Monogatari Advance (Japan) (Demo) (Aftermarket) (Unl).gba" size 508972 crc 55a0734d sha1 79d6977803cd7ee6b1c97ee149cc1bc037c50fb2 ) +) + +game ( + name "Notebook Adventure (World) (v1.3) (Aftermarket) (Unl)" + description "Notebook Adventure (World) (v1.3) (Aftermarket) (Unl)" + rom ( name "Notebook Adventure (World) (v1.3) (Aftermarket) (Unl).gba" size 476392 crc cc110502 sha1 b730e401214fb348edcd2908cc9842e720f908d1 ) +) + +game ( + name "notenogram (World) (v1.1) (Aftermarket) (Unl)" + description "notenogram (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "notenogram (World) (v1.1) (Aftermarket) (Unl).gba" size 807876 crc 28108d5e sha1 426a19598624132356ff5d63a48eb874f19ead6b ) +) + +game ( + name "notenogram (World) (GBA Jam 2022) (Aftermarket) (Unl)" + description "notenogram (World) (GBA Jam 2022) (Aftermarket) (Unl)" + rom ( name "notenogram (World) (GBA Jam 2022) (Aftermarket) (Unl).gba" size 784216 crc 3b936e97 sha1 fb2fadad0d41979df75e49ff09b67fa42b54fc79 ) +) + +game ( + name "Ping-Pong Diplomacy Advance (World) (Aftermarket) (Unl)" + description "Ping-Pong Diplomacy Advance (World) (Aftermarket) (Unl)" + rom ( name "Ping-Pong Diplomacy Advance (World) (Aftermarket) (Unl).gba" size 1048576 crc 9ec140d3 sha1 9e19e8f97e8619a4755c3ceb482fa3e2ad5a4529 ) +) + +game ( + name "Pipe Spin (World) (GBA Jam 2021) (Aftermarket) (Unl)" + description "Pipe Spin (World) (GBA Jam 2021) (Aftermarket) (Unl)" + rom ( name "Pipe Spin (World) (GBA Jam 2021) (Aftermarket) (Unl).gba" size 3126100 crc 09d723e2 sha1 d4b4b99e644ca1d8202147a8c7ae0309a6f07e74 ) +) + +game ( + name "Pocket Meat (World) (Proto) (Aftermarket) (Unl)" + description "Pocket Meat (World) (Proto) (Aftermarket) (Unl)" + rom ( name "Pocket Meat (World) (Proto) (Aftermarket) (Unl).gba" size 861952 crc 0b029da3 sha1 9958d9a66742cc00e234a96c311b2acec40f69d1 ) +) + +game ( + name "Powder (World) (v1.18) (Aftermarket) (Unl)" + description "Powder (World) (v1.18) (Aftermarket) (Unl)" + rom ( name "Powder (World) (v1.18) (Aftermarket) (Unl).gba" size 2278832 crc 44ea10fa sha1 3e0addefc22440c76b0eed06c91bc855f59838bf ) +) + +game ( + name "Powerpig (World) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + description "Powerpig (World) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + rom ( name "Powerpig (World) (NEO Coding Compo 2013) (Aftermarket) (Unl).gba" size 2308528 crc 318f1504 sha1 af5e459df42d5317ce552bdb3062fcff53a9da8e ) +) + +game ( + name "Rick Dangerous (World) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + description "Rick Dangerous (World) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + rom ( name "Rick Dangerous (World) (NEO Coding Compo 2013) (Aftermarket) (Unl).gba" size 4238368 crc 7edb6e6e sha1 62c9b12c3790a7c1a28edd2043ef61706357ed41 ) +) + +game ( + name "Rick Dangerous (World) (Aftermarket) (Unl)" + description "Rick Dangerous (World) (Aftermarket) (Unl)" + rom ( name "Rick Dangerous (World) (Aftermarket) (Unl).gba" size 4237460 crc 53d4f7c5 sha1 ed5a9eb155388f19c28a7f5069d32532a5c9a494 ) +) + +game ( + name "Rick Dangerous 2 (World) (Aftermarket) (Unl)" + description "Rick Dangerous 2 (World) (Aftermarket) (Unl)" + rom ( name "Rick Dangerous 2 (World) (Aftermarket) (Unl).gba" size 4934608 crc 65a8d986 sha1 5dd0cff0f112c43ee44db642b4bfdb38ca6355b7 ) +) + +game ( + name "Rushed Hack Job, A (World) (GBA Jam 2022) (Aftermarket) (Unl)" + description "Rushed Hack Job, A (World) (GBA Jam 2022) (Aftermarket) (Unl)" + rom ( name "Rushed Hack Job, A (World) (GBA Jam 2022) (Aftermarket) (Unl).gba" size 332724 crc 730a5dd6 sha1 d8e03f4b1a12cf7a26813fb07aae2c4b503e2970 ) +) + +game ( + name "Shadow - A Parable (World) (Audio) (Aftermarket) (Unl)" + description "Shadow - A Parable (World) (Audio) (Aftermarket) (Unl)" + rom ( name "Shadow - A Parable (World) (Audio) (Aftermarket) (Unl).gba" size 1352899 crc 3178488f sha1 dd90e7d76b751a0e748aae83777d449d963b774b ) +) + +game ( + name "Shoot for the Moon (World) (Aftermarket) (Unl)" + description "Shoot for the Moon (World) (Aftermarket) (Unl)" + rom ( name "Shoot for the Moon (World) (Aftermarket) (Unl).gba" size 7374924 crc f3bd4f90 sha1 cf99dd8670a3af704b6994898fa521667aba09a6 ) +) + +game ( + name "Sips (World) (GBA WinterJam 2023) (Aftermarket) (Unl)" + description "Sips (World) (GBA WinterJam 2023) (Aftermarket) (Unl)" + rom ( name "Sips (World) (GBA WinterJam 2023) (Aftermarket) (Unl).gba" size 6235380 crc 5c1fb22d sha1 bb725df7226307d55df04365f85e5698b199c3c9 ) +) + +game ( + name "Skyland (World) (v2023.5.5.0) (Proto) (Aftermarket) (Unl)" + description "Skyland (World) (v2023.5.5.0) (Proto) (Aftermarket) (Unl)" + rom ( name "Skyland (World) (v2023.5.5.0) (Proto) (Aftermarket) (Unl).gba" size 15887876 crc c798529d sha1 ea4a6494bcec25757f657c69550c91190e46cebd ) +) + +game ( + name "Skyland (World) (v2023.5.15.0) (Proto) (Aftermarket) (Unl)" + description "Skyland (World) (v2023.5.15.0) (Proto) (Aftermarket) (Unl)" + rom ( name "Skyland (World) (v2023.5.15.0) (Proto) (Aftermarket) (Unl).gba" size 15894868 crc af572de8 sha1 997bf192369d48433a7c35187c7e1d0b5fcc16e0 ) +) + +game ( + name "Skyland (World) (v2023.5.26.0) (Proto) (Aftermarket) (Unl)" + description "Skyland (World) (v2023.5.26.0) (Proto) (Aftermarket) (Unl)" + rom ( name "Skyland (World) (v2023.5.26.0) (Proto) (Aftermarket) (Unl).gba" size 15900084 crc df05edff sha1 1328d17668480b4e9bea338662532ace332c74a9 ) +) + +game ( + name "Skyland (World) (v2023.8.1.1) (Proto) (Aftermarket) (Unl)" + description "Skyland (World) (v2023.8.1.1) (Proto) (Aftermarket) (Unl)" + rom ( name "Skyland (World) (v2023.8.1.1) (Proto) (Aftermarket) (Unl).gba" size 16075456 crc d271c516 sha1 0dbdf16b23afb70229eff2de269fd5d73659d745 ) +) + +game ( + name "Skyland (World) (v2024.5.24.0) (Proto) (Aftermarket) (Unl)" + description "Skyland (World) (v2024.5.24.0) (Proto) (Aftermarket) (Unl)" + rom ( name "Skyland (World) (v2024.5.24.0) (Proto) (Aftermarket) (Unl).gba" size 16250380 crc 4cfb40d2 sha1 d9936c4a776ce61ede6241a018683e3efc0fe12b ) +) + +game ( + name "Spout GBA (World) (Aftermarket) (Unl)" + description "Spout GBA (World) (Aftermarket) (Unl)" + rom ( name "Spout GBA (World) (Aftermarket) (Unl).gba" size 752448 crc ab42f086 sha1 87654f792d847bb8f642c0fc754eb70419a57859 ) +) + +game ( + name "Tiger Rescue (World) (Aftermarket) (Unl)" + description "Tiger Rescue (World) (Aftermarket) (Unl)" + rom ( name "Tiger Rescue (World) (Aftermarket) (Unl).gba" size 1575852 crc 34e118e5 sha1 8cc652cb0aee8649643386c8ffcc77fe6e5b0126 ) +) + +game ( + name "Toadally Awesome (World) (GBA Jam 2021) (Aftermarket) (Unl)" + description "Toadally Awesome (World) (GBA Jam 2021) (Aftermarket) (Unl)" + rom ( name "Toadally Awesome (World) (GBA Jam 2021) (Aftermarket) (Unl).gba" size 964504 crc fa6f976c sha1 098f9e2ba7ba15225768eae3585591b9b09ef2d6 ) +) + +game ( + name "Toadally Awesome (World) (GBA Jam 2021) (Unlocked) (Aftermarket) (Unl)" + description "Toadally Awesome (World) (GBA Jam 2021) (Unlocked) (Aftermarket) (Unl)" + rom ( name "Toadally Awesome (World) (GBA Jam 2021) (Unlocked) (Aftermarket) (Unl).gba" size 964520 crc 11044eb3 sha1 ac83f9815f4bf3a9c6690c4437d7f2256b36dd40 ) +) + +game ( + name "Tremblay Island (World) (En) (v1.1) (Aftermarket) (Unl)" + description "Tremblay Island (World) (En) (v1.1) (Aftermarket) (Unl)" + rom ( name "Tremblay Island (World) (En) (v1.1) (Aftermarket) (Unl).gba" size 16239516 crc ce85ba07 sha1 b09b600bfc222c2d92829d8883feab700b013953 ) +) + +game ( + name "Tremblay Island (World) (En) (v1.1) (Solid State Version) (Aftermarket) (Unl)" + description "Tremblay Island (World) (En) (v1.1) (Solid State Version) (Aftermarket) (Unl)" + rom ( name "Tremblay Island (World) (En) (v1.1) (Solid State Version) (Aftermarket) (Unl).gba" size 16229600 crc bd57344d sha1 a2fcfe94c9b8b0feff31c1245c8b033222c9f668 ) +) + +game ( + name "Tremblay Island (World) (Fr) (v1.1) (Solid State Version) (Aftermarket) (Unl)" + description "Tremblay Island (World) (Fr) (v1.1) (Solid State Version) (Aftermarket) (Unl)" + rom ( name "Tremblay Island (World) (Fr) (v1.1) (Solid State Version) (Aftermarket) (Unl).gba" size 16204024 crc fa43669e sha1 a57392fa7cee61913b20a840fe8b2ee27f11d808 ) +) + +game ( + name "Tremblay Island (World) (En) (v1.1) (Kickstarter Edition) (Aftermarket) (Unl)" + description "Tremblay Island (World) (En) (v1.1) (Kickstarter Edition) (Aftermarket) (Unl)" + rom ( name "Tremblay Island (World) (En) (v1.1) (Kickstarter Edition) (Aftermarket) (Unl).gba" size 16777216 crc ff5d64ab sha1 645ab8d4dacb6666d8eb549d491f77d8cd63ce97 ) +) + +game ( + name "Tremblay Island (World) (Aftermarket) (Unl)" + description "Tremblay Island (World) (Aftermarket) (Unl)" + rom ( name "Tremblay Island (World) (Aftermarket) (Unl).gba" size 16225608 crc 95503690 sha1 634ea6be3df5ebd85c9c60871e34fc3c72ae5140 ) +) + +game ( + name "Tristam Island (World) (v9) (Digital) (Aftermarket) (Unl)" + description "Tristam Island (World) (v9) (Digital) (Aftermarket) (Unl)" + rom ( name "Tristam Island (World) (v9) (Digital) (Aftermarket) (Unl).gba" size 286184 crc 4baa947c sha1 4a90a81991d38ce08ded5da017d0567ecd00c1df flags verified ) +) + +game ( + name "uCity Advance (World) (v1.0.1) (GBA Jam 2021) (Aftermarket) (Unl)" + description "uCity Advance (World) (v1.0.1) (GBA Jam 2021) (Aftermarket) (Unl)" + rom ( name "uCity Advance (World) (v1.0.1) (GBA Jam 2021) (Aftermarket) (Unl).gba" size 1925124 crc a6e47443 sha1 c3e8f7fe01e05eda8bdb52a35db0d6dc92554e42 ) +) + +game ( + name "Varooom 3D (World) (GBA Jam 2021) (Aftermarket) (Unl)" + description "Varooom 3D (World) (GBA Jam 2021) (Aftermarket) (Unl)" + rom ( name "Varooom 3D (World) (GBA Jam 2021) (Aftermarket) (Unl).gba" size 7957428 crc 3f127891 sha1 cc7e45a680f9a8701fe35a64c764d5e106bd9096 ) +) + +game ( + name "Waimanu - Grinding Blocks Adventure (World) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + description "Waimanu - Grinding Blocks Adventure (World) (NEO Coding Compo 2013) (Aftermarket) (Unl)" + rom ( name "Waimanu - Grinding Blocks Adventure (World) (NEO Coding Compo 2013) (Aftermarket) (Unl).gba" size 1739504 crc 0fe153c5 sha1 c4ce156b04fb257875bc5f539f3d64accbc08451 ) +) + +game ( + name "Werewolf Tale, A (World) (Proto) (NEO Coding Compo 2012) (Aftermarket) (Unl)" + description "Werewolf Tale, A (World) (Proto) (NEO Coding Compo 2012) (Aftermarket) (Unl)" + rom ( name "Werewolf Tale, A (World) (Proto) (NEO Coding Compo 2012) (Aftermarket) (Unl).gba" size 7359860 crc fa1a22d3 sha1 631fa1b513e1e4a45a5a60b10b7822b47832b866 ) +) + +game ( + name "With the Last Moonbeam (World) (v1.0.0) (Aftermarket) (Unl)" + description "With the Last Moonbeam (World) (v1.0.0) (Aftermarket) (Unl)" + rom ( name "With the Last Moonbeam (World) (v1.0.0) (Aftermarket) (Unl).gba" size 1449956 crc 4ffa611d sha1 89bbeb3fbce1533acf2f2113642ebe2a4f9f79a8 ) +) + +game ( + name "With the Last Moonbeam (World) (v1.0.1) (Aftermarket) (Unl)" + description "With the Last Moonbeam (World) (v1.0.1) (Aftermarket) (Unl)" + rom ( name "With the Last Moonbeam (World) (v1.0.1) (Aftermarket) (Unl).gba" size 1449956 crc 27055186 sha1 b9ce91d55870e07434509f6e2e91c2f90b4afc97 ) +) + +game ( + name "World Reborn (USA) (Aftermarket) (Unl)" + description "World Reborn (USA) (Aftermarket) (Unl)" + rom ( name "World Reborn (USA) (Aftermarket) (Unl).gba" size 4194304 crc eefb32ff sha1 c7ec2f8d7d3dec40a893cdfe2a41a8ed43ed71c4 ) +) + +game ( + name "xniq (World) (Proto) (GBA Jam 2021) (Aftermarket) (Unl)" + description "xniq (World) (Proto) (GBA Jam 2021) (Aftermarket) (Unl)" + rom ( name "xniq (World) (Proto) (GBA Jam 2021) (Aftermarket) (Unl).gba" size 1436448 crc ddb5205d sha1 47dabc2d526aefc41cc82eeec315c986e3a9b8bc ) +) + +clrmamepro ( + name "Nintendo - Game Boy Advance (Video) (Aftermarket)" + description "Nintendo - Game Boy Advance (Video) (Aftermarket)" + version 20240727-194101 + author "BigFred, C. V. Reynolds, DeadSkullzJr, Hiccup, kazumi213, omonim2007, Psychofox11, psykopat, relax, SonGoku, xuom2" + homepage No-Intro + url "https://www.no-intro.org" + forcenodump required +) + +emulator ( + name "datafile" +) + +game ( + name "Dinosaur Office (World) (Aftermarket) (Unl)" + description "Dinosaur Office (World) (Aftermarket) (Unl)" + rom ( name "Dinosaur Office (World) (Aftermarket) (Unl).gba" size 15237120 crc d8aae820 sha1 24feb8a0f36428461be8ecbb7add65f43dc1366e ) +) + +game ( + name "Dinosaur Office - Bring Your Child to Work Day (World) (Aftermarket) (Unl)" + description "Dinosaur Office - Bring Your Child to Work Day (World) (Aftermarket) (Unl)" + rom ( name "Dinosaur Office - Bring Your Child to Work Day (World) (Aftermarket) (Unl).gba" size 12222464 crc 3de24b84 sha1 63938be2d2e357b9644de8dc452f6f4195911618 ) +) + +game ( + name "Dinosaur Office - Computer Problems (World) (Aftermarket) (Unl)" + description "Dinosaur Office - Computer Problems (World) (Aftermarket) (Unl)" + rom ( name "Dinosaur Office - Computer Problems (World) (Aftermarket) (Unl).gba" size 15990784 crc 8a05677f sha1 664c1568e601bf6e51920bca85d096aa6e06f5e2 ) +) + +game ( + name "Dinosaur Office - Gym (World) (Aftermarket) (Unl)" + description "Dinosaur Office - Gym (World) (Aftermarket) (Unl)" + rom ( name "Dinosaur Office - Gym (World) (Aftermarket) (Unl).gba" size 12419072 crc 9dc8f035 sha1 062fcb78d9f9058ff9427f123fbb36db77fca20b ) +) + +game ( + name "Dinosaur Office - Office Party (World) (Aftermarket) (Unl)" + description "Dinosaur Office - Office Party (World) (Aftermarket) (Unl)" + rom ( name "Dinosaur Office - Office Party (World) (Aftermarket) (Unl).gba" size 12484608 crc 34c1df88 sha1 9ee6ca14c78a7e1949d8af9d52e6bfa4d09b7f9f ) +) + +game ( + name "Dinosaur Office - Office Romance (World) (Aftermarket) (Unl)" + description "Dinosaur Office - Office Romance (World) (Aftermarket) (Unl)" + rom ( name "Dinosaur Office - Office Romance (World) (Aftermarket) (Unl).gba" size 13828096 crc c202e426 sha1 4a66f3db5bde55a33f4b9ca55ba231f806c8d2b9 ) +) + +game ( + name "Dinosaur Office - Team Building (World) (Aftermarket) (Unl)" + description "Dinosaur Office - Team Building (World) (Aftermarket) (Unl)" + rom ( name "Dinosaur Office - Team Building (World) (Aftermarket) (Unl).gba" size 17334272 crc 9cd0566e sha1 9dc93f4c8d25a0e5d52deb8c7edf656b8f0c059d ) +) + +game ( + name "Dinosaur Office - Traffic (World) (Aftermarket) (Unl)" + description "Dinosaur Office - Traffic (World) (Aftermarket) (Unl)" + rom ( name "Dinosaur Office - Traffic (World) (Aftermarket) (Unl).gba" size 13107200 crc 96d90be9 sha1 879d9c7f0951235607cedb9c8fd85e4fc9a1d452 ) +) + +game ( + name "Dinosaur Office - Viral Videos (World) (Aftermarket) (Unl)" + description "Dinosaur Office - Viral Videos (World) (Aftermarket) (Unl)" + rom ( name "Dinosaur Office - Viral Videos (World) (Aftermarket) (Unl).gba" size 13139968 crc e7338b7c sha1 e6f089034f30757f8dce2eb6568e8f5d2d122d49 ) +) + +game ( + name "Eek! The Cat - A Sharkwork Orange (World) (Aftermarket) (Unl)" + description "Eek! The Cat - A Sharkwork Orange (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - A Sharkwork Orange (World) (Aftermarket) (Unl).gba" size 31129600 crc 4feab397 sha1 0bb061759804b46f201c39ccf9e7722a4407909e ) +) + +game ( + name "Eek! The Cat - Chariots of Fur (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Chariots of Fur (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Chariots of Fur (World) (Aftermarket) (Unl).gba" size 30998528 crc 5ea13d5a sha1 7022193f78fcb89988483cca1bacb8e66182ac55 ) +) + +game ( + name "Eek! The Cat - Eek Space-9 (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Eek Space-9 (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Eek Space-9 (World) (Aftermarket) (Unl).gba" size 30801920 crc cfbb43d3 sha1 1b056d1449282c08eae0ed49ffc33f56346304fe ) +) + +game ( + name "Eek! The Cat - Eek's Funny Thing That He Does (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Eek's Funny Thing That He Does (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Eek's Funny Thing That He Does (World) (Aftermarket) (Unl).gba" size 31064064 crc 3773b28d sha1 b13c1d3ae7f993deee10542390ac416b6c5cd1c6 ) +) + +game ( + name "Eek! The Cat - Eekscaliber (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Eekscaliber (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Eekscaliber (World) (Aftermarket) (Unl).gba" size 31227904 crc ed5792d4 sha1 2a903b53a371ef4132291452f5d192dace6dc5e8 ) +) + +game ( + name "Eek! The Cat - Eekstremely Dull (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Eekstremely Dull (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Eekstremely Dull (World) (Aftermarket) (Unl).gba" size 31162368 crc 28f73fe4 sha1 3ea9bfa0d937150574affdb8de271cf7873ab042 ) +) + +game ( + name "Eek! The Cat - Eeksy Rider (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Eeksy Rider (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Eeksy Rider (World) (Aftermarket) (Unl).gba" size 31096832 crc ec1f5d37 sha1 1359f5e802862b0a6f01e37fd5843a5b12edb7d4 ) +) + +game ( + name "Eek! The Cat - Fatal Eektraction (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Fatal Eektraction (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Fatal Eektraction (World) (Aftermarket) (Unl).gba" size 31096832 crc 494997c3 sha1 52e63ca7e162fe3a0296709b924b0dc4b19ce693 ) +) + +game ( + name "Eek! The Cat - Honey I Shrunk the Cat (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Honey I Shrunk the Cat (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Honey I Shrunk the Cat (World) (Aftermarket) (Unl).gba" size 15597568 crc 8bae90ef sha1 8ee80c6e4f54081c6b796983ab51d8c03e36c2d0 ) +) + +game ( + name "Eek! The Cat - Natural Bored Kittens (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Natural Bored Kittens (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Natural Bored Kittens (World) (Aftermarket) (Unl).gba" size 31129600 crc 941da25e sha1 8fa3d5d5f305ac32653527860caf153c97d20a24 ) +) + +game ( + name "Eek! The Cat - OutbrEek (World) (Aftermarket) (Unl)" + description "Eek! The Cat - OutbrEek (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - OutbrEek (World) (Aftermarket) (Unl).gba" size 30834688 crc 4fea7a72 sha1 344cdff52d4820932c3ba8ad5c57c91d61d93751 ) +) + +game ( + name "Eek! The Cat - Rock-Eek 6 (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Rock-Eek 6 (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Rock-Eek 6 (World) (Aftermarket) (Unl).gba" size 31096832 crc 7a05eb25 sha1 6b3789fd599bf7d30788be38872f5832cb5edfaa ) +) + +game ( + name "Eek! The Cat - Shark Doggy Dog (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Shark Doggy Dog (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Shark Doggy Dog (World) (Aftermarket) (Unl).gba" size 30965760 crc f8f2e313 sha1 f169a86d11602d84181fd0161bc7ec6747d5c750 ) +) + +game ( + name "Eek! The Cat - Shark Therapy (World) (Aftermarket) (Unl)" + description "Eek! The Cat - Shark Therapy (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - Shark Therapy (World) (Aftermarket) (Unl).gba" size 30998528 crc 81bc6107 sha1 9cca9b282e9441364e5acd7379c251674165eb13 ) +) + +game ( + name "Eek! The Cat - The Sound of MusEek (World) (Aftermarket) (Unl)" + description "Eek! The Cat - The Sound of MusEek (World) (Aftermarket) (Unl)" + rom ( name "Eek! The Cat - The Sound of MusEek (World) (Aftermarket) (Unl).gba" size 31129600 crc 923aafde sha1 1f1071ba3a6e056357c04f653cc48d2333a6bff1 ) +) + +game ( + name "GBA Groove - LoFi Lullabies (World) (Aftermarket) (Unl)" + description "GBA Groove - LoFi Lullabies (World) (Aftermarket) (Unl)" + rom ( name "GBA Groove - LoFi Lullabies (World) (Aftermarket) (Unl).gba" size 33128448 crc ff858ea8 sha1 e42166ed389ba80a38b91019b80b00fdca3252bd ) +) + +game ( + name "Legend of Lofi - High Quality - Part 1 (World) (v2.0) (Aftermarket) (Unl)" + description "Legend of Lofi - High Quality - Part 1 (World) (v2.0) (Aftermarket) (Unl)" + rom ( name "Legend of Lofi - High Quality - Part 1 (World) (v2.0) (Aftermarket) (Unl).gba" size 33095680 crc a29a4d08 sha1 5c5ba15aef8cf86fbfee102dd3d667c09a024215 ) +) + +game ( + name "Legend of Lofi - High Quality - Part 2 (World) (v2.0) (Aftermarket) (Unl)" + description "Legend of Lofi - High Quality - Part 2 (World) (v2.0) (Aftermarket) (Unl)" + rom ( name "Legend of Lofi - High Quality - Part 2 (World) (v2.0) (Aftermarket) (Unl).gba" size 33292288 crc d30b0a69 sha1 1d0f5640c62823100802a9d99991c81321fd6a7e ) +) + +game ( + name "Legend of Lofi - High Quality - Part 3 (World) (v2.0) (Aftermarket) (Unl)" + description "Legend of Lofi - High Quality - Part 3 (World) (v2.0) (Aftermarket) (Unl)" + rom ( name "Legend of Lofi - High Quality - Part 3 (World) (v2.0) (Aftermarket) (Unl).gba" size 33226752 crc 5514a608 sha1 0b942ca93b86a61710e437995fbe9b051b49f33b ) +) + +game ( + name "Legend of Lofi - High Quality - Part 4 (World) (v2.0) (Aftermarket) (Unl)" + description "Legend of Lofi - High Quality - Part 4 (World) (v2.0) (Aftermarket) (Unl)" + rom ( name "Legend of Lofi - High Quality - Part 4 (World) (v2.0) (Aftermarket) (Unl).gba" size 33226752 crc 996086fb sha1 cdae6017134b235c4b939c3718fef5c68c932046 ) +) + +game ( + name "Legend of Lofi - High Quality - Part 5 (World) (v2.1) (Aftermarket) (Unl)" + description "Legend of Lofi - High Quality - Part 5 (World) (v2.1) (Aftermarket) (Unl)" + rom ( name "Legend of Lofi - High Quality - Part 5 (World) (v2.1) (Aftermarket) (Unl).gba" size 33062912 crc 30394a33 sha1 677e3fbd22eac9661365f798e141844628869f09 ) +) + +game ( + name "Legend of Lofi - Low Quality - Part 1 (World) (Aftermarket) (Unl)" + description "Legend of Lofi - Low Quality - Part 1 (World) (Aftermarket) (Unl)" + rom ( name "Legend of Lofi - Low Quality - Part 1 (World) (Aftermarket) (Unl).gba" size 33456128 crc ec98d515 sha1 02d89347e83d030168916b1d5b5cb39f436564cf ) +) + +game ( + name "Legend of Lofi - Low Quality - Part 2 (World) (Aftermarket) (Unl)" + description "Legend of Lofi - Low Quality - Part 2 (World) (Aftermarket) (Unl)" + rom ( name "Legend of Lofi - Low Quality - Part 2 (World) (Aftermarket) (Unl).gba" size 33488896 crc 9a3ad572 sha1 90a4fefd48cc5024b88591a29a79c5a720593dcf ) +) + +game ( + name "Lizard of Aaaahs (World) (Aftermarket) (Unl)" + description "Lizard of Aaaahs (World) (Aftermarket) (Unl)" + rom ( name "Lizard of Aaaahs (World) (Aftermarket) (Unl).gba" size 30801920 crc 45d496d3 sha1 65b0a763932517d504abb0e39e9db316b2500c0a ) +) + +game ( + name "Lofi Radio (World) (Aftermarket) (Unl)" + description "Lofi Radio (World) (Aftermarket) (Unl)" + rom ( name "Lofi Radio (World) (Aftermarket) (Unl).gba" size 30965760 crc 4643636f sha1 7657efc85a8414a2d2065549e66bc0e0804a0153 ) +) + +game ( + name "Popeye The Sailor Meets Ali Baba's Forty Thieves (World) (Aftermarket) (Unl)" + description "Popeye The Sailor Meets Ali Baba's Forty Thieves (World) (Aftermarket) (Unl)" + rom ( name "Popeye The Sailor Meets Ali Baba's Forty Thieves (World) (Aftermarket) (Unl).gba" size 25067520 crc 3d2b7e9a sha1 7ed0b27ce1537610d62e3265ee1d8e7aa09ac649 ) +) + +game ( + name "Sleepy Time (World) (Aftermarket) (Unl)" + description "Sleepy Time (World) (Aftermarket) (Unl)" + rom ( name "Sleepy Time (World) (Aftermarket) (Unl).gba" size 33554432 crc b4a8e893 sha1 ba0a790b18de15009d711474aa25f29875e7f9fd ) +) + +game ( + name "Sonic Boom - Aim Low (World) (Aftermarket) (Unl)" + description "Sonic Boom - Aim Low (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Aim Low (World) (Aftermarket) (Unl).gba" size 32899072 crc a4b992a4 sha1 321716a5cc8035d2f3c834db70e21024b26e01ec ) +) + +game ( + name "Sonic Boom - Anything You Can Do, I Can Do Worse-er (World) (Aftermarket) (Unl)" + description "Sonic Boom - Anything You Can Do, I Can Do Worse-er (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Anything You Can Do, I Can Do Worse-er (World) (Aftermarket) (Unl).gba" size 32669696 crc 3e19389e sha1 bd9e8e22ddde7426d8eb77772480c822a099044f ) +) + +game ( + name "Sonic Boom - Blue with Envy (World) (Aftermarket) (Unl)" + description "Sonic Boom - Blue with Envy (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Blue with Envy (World) (Aftermarket) (Unl).gba" size 33488896 crc c847a712 sha1 44c4d7a6ba6b3bea7f452f22ec7c419cf6cf6965 ) +) + +game ( + name "Sonic Boom - Cabin Fever (World) (Aftermarket) (Unl)" + description "Sonic Boom - Cabin Fever (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Cabin Fever (World) (Aftermarket) (Unl).gba" size 32145408 crc 6a916ed9 sha1 e422c79d1b85942fcd9bae26105151c4e8a8352c ) +) + +game ( + name "Sonic Boom - Curse of the Cross Eyed Moose (World) (Aftermarket) (Unl)" + description "Sonic Boom - Curse of the Cross Eyed Moose (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Curse of the Cross Eyed Moose (World) (Aftermarket) (Unl).gba" size 32636928 crc 751a7c3c sha1 393a023540a261e14ab96ee341505fd6852e5040 ) +) + +game ( + name "Sonic Boom - Double Doomsday (World) (Aftermarket) (Unl)" + description "Sonic Boom - Double Doomsday (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Double Doomsday (World) (Aftermarket) (Unl).gba" size 33095680 crc e43df55f sha1 b0f7feb5f1b012ce4a486e6ad1331d83372a52e8 ) +) + +game ( + name "Sonic Boom - Eggheads (World) (Aftermarket) (Unl)" + description "Sonic Boom - Eggheads (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Eggheads (World) (Aftermarket) (Unl).gba" size 32964608 crc 7be59036 sha1 6afd6a0e39a792422767f40d96d28683fe3f010b ) +) + +game ( + name "Sonic Boom - Fortress of Squalitude (World) (Aftermarket) (Unl)" + description "Sonic Boom - Fortress of Squalitude (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Fortress of Squalitude (World) (Aftermarket) (Unl).gba" size 32964608 crc 2732961a sha1 db37f535660f66d947ccd2fdb05631d6c3b53157 ) +) + +game ( + name "Sonic Boom - Guilt Tripping (World) (Aftermarket) (Unl)" + description "Sonic Boom - Guilt Tripping (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Guilt Tripping (World) (Aftermarket) (Unl).gba" size 33095680 crc eb433ebc sha1 29648e120e9fd97f9c8b279b29246f165df3b9e6 ) +) + +game ( + name "Sonic Boom - It Takes a Village to Defeat a Hedgehog (World) (Aftermarket) (Unl)" + description "Sonic Boom - It Takes a Village to Defeat a Hedgehog (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - It Takes a Village to Defeat a Hedgehog (World) (Aftermarket) (Unl).gba" size 33062912 crc 087a17bf sha1 5cfd8eb8d832d21d64fc150bcc6d26b52da86911 ) +) + +game ( + name "Sonic Boom - Let's Play Musical Friends (World) (Aftermarket) (Unl)" + description "Sonic Boom - Let's Play Musical Friends (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Let's Play Musical Friends (World) (Aftermarket) (Unl).gba" size 33226752 crc 4f7e8a97 sha1 ad7d4f4833878ccc7055e65efbcb62fba20cd340 ) +) + +game ( + name "Sonic Boom - Nutwork (World) (Aftermarket) (Unl)" + description "Sonic Boom - Nutwork (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - Nutwork (World) (Aftermarket) (Unl).gba" size 32768000 crc ed3ead6a sha1 f89d6acee3095419d2eda71c1d79e73ba3dcf5e4 ) +) + +game ( + name "Sonic Boom - The Evil Dr. Orbot (World) (Aftermarket) (Unl)" + description "Sonic Boom - The Evil Dr. Orbot (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - The Evil Dr. Orbot (World) (Aftermarket) (Unl).gba" size 33095680 crc e8c0b3b3 sha1 175126d3946e61295993982cb04758a5761233b1 ) +) + +game ( + name "Sonic Boom - The Meteor (World) (Aftermarket) (Unl)" + description "Sonic Boom - The Meteor (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - The Meteor (World) (Aftermarket) (Unl).gba" size 32931840 crc d3c8e3bc sha1 84a91ed46f4e055ef075b4e110091dd1510c6bab ) +) + +game ( + name "Sonic Boom - The Sidekick (World) (Aftermarket) (Unl)" + description "Sonic Boom - The Sidekick (World) (Aftermarket) (Unl)" + rom ( name "Sonic Boom - The Sidekick (World) (Aftermarket) (Unl).gba" size 32964608 crc bca89ca3 sha1 93d24392e31fa7fa1b017eae2efbbb3d198739b7 ) +) + +game ( + name "Super Mario World - Episode 1 - Fire Sale (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 1 - Fire Sale (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 1 - Fire Sale (World) (Aftermarket) (Unl).gba" size 31522816 crc 5af74124 sha1 c715e8adff312d3ade93185d6cebcb2d493cc41e ) +) + +game ( + name "Super Mario World - Episode 10 - Rock TV (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 10 - Rock TV (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 10 - Rock TV (World) (Aftermarket) (Unl).gba" size 30179328 crc ccb80716 sha1 3f05bfc29688ab70cc728bbe609d5b976730490e ) +) + +game ( + name "Super Mario World - Episode 11 - The Yoshi Shuffle (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 11 - The Yoshi Shuffle (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 11 - The Yoshi Shuffle (World) (Aftermarket) (Unl).gba" size 31129600 crc 733bb9b0 sha1 45875207d24653aa81c2bdd60bde639783c5c387 ) +) + +game ( + name "Super Mario World - Episode 12 - A Little Learning (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 12 - A Little Learning (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 12 - A Little Learning (World) (Aftermarket) (Unl).gba" size 31227904 crc dd8717c1 sha1 26fcf34d2fd9f87f287d14fdeda9d8e234306db5 ) +) + +game ( + name "Super Mario World - Episode 13 - Mama Luigi (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 13 - Mama Luigi (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 13 - Mama Luigi (World) (Aftermarket) (Unl).gba" size 32112640 crc 3d2bf1b0 sha1 4a897d3de60f1bd3991803196f5b96c5916f9e8c ) +) + +game ( + name "Super Mario World - Episode 2 - The Wheel Thing (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 2 - The Wheel Thing (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 2 - The Wheel Thing (World) (Aftermarket) (Unl).gba" size 32145408 crc 9c5140d6 sha1 30b6b51d60ba9213e5c472bf52070eab98b43c74 ) +) + +game ( + name "Super Mario World - Episode 3 - Send in the Clown (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 3 - Send in the Clown (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 3 - Send in the Clown (World) (Aftermarket) (Unl).gba" size 32112640 crc 88888a8c sha1 26c791180a1b35d8ab9cf7947d8db6c0367d7eb9 ) +) + +game ( + name "Super Mario World - Episode 4 - Ghosts 'R' Us (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 4 - Ghosts 'R' Us (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 4 - Ghosts 'R' Us (World) (Aftermarket) (Unl).gba" size 32079872 crc ca0d9b45 sha1 a15fb94a371d783f78c069038c350e569ea9c370 ) +) + +game ( + name "Super Mario World - Episode 5 - The Night Before Cave Christmas (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 5 - The Night Before Cave Christmas (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 5 - The Night Before Cave Christmas (World) (Aftermarket) (Unl).gba" size 31981568 crc 564582fa sha1 ce8b3589a67dcd930d2e437efa0bf754f438cfa7 ) +) + +game ( + name "Super Mario World - Episode 6 - King Scoopa Koopa (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 6 - King Scoopa Koopa (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 6 - King Scoopa Koopa (World) (Aftermarket) (Unl).gba" size 32112640 crc edcb04de sha1 1e8e89daf7faed9660f2dc3b6aa113df6de527c0 ) +) + +game ( + name "Super Mario World - Episode 7 - Born to Ride (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 7 - Born to Ride (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 7 - Born to Ride (World) (Aftermarket) (Unl).gba" size 32145408 crc 0044466e sha1 105f0d0a500ea542f87b10b7c671b6c93e312f4a ) +) + +game ( + name "Super Mario World - Episode 8 - Party Line (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 8 - Party Line (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 8 - Party Line (World) (Aftermarket) (Unl).gba" size 28672000 crc ed103f04 sha1 df5e947880b634482081ee82f79f37d5ff7d009c ) +) + +game ( + name "Super Mario World - Episode 9 - Gopher Bash (World) (Aftermarket) (Unl)" + description "Super Mario World - Episode 9 - Gopher Bash (World) (Aftermarket) (Unl)" + rom ( name "Super Mario World - Episode 9 - Gopher Bash (World) (Aftermarket) (Unl).gba" size 31031296 crc 3a8f46ad sha1 160895e7953a3323647c0c9d2d00eeff17b57db5 ) +) + clrmamepro ( name "Nintendo - Game Boy" description "Nintendo - Game Boy" - version 20230422-225330 - author "aci68, akubi, Arctic Circle System, Aringon, baldjared, Bent, BigFred, BitLooter, buckwheat, C. V. Reynolds, chillerecke, darthcloud, DeadSkullzJr, Densetsu, DeriLoko3, ElBarto, foxe, fuzzball, Gefflon, Hiccup, hking0036, InternalLoss, jimmsu, kazumi213, leekindo, Lesserkuma, Madeline, NESBrew12, NGEfreak, nnssxx, norkmetnoil577, NovaAurora, omonim2007, Powerpuff, PPLToast, rarenight, relax, RetroUprising, rpg2813, sCZther, SonGoku, Tauwasser, togemet2, UnlockerPT, xNo, xuom2" + version 20240809-004429 + author "aci68, akubi, Arctic Circle System, Aringon, baldjared, Bent, BigFred, BitLooter, buckwheat, C. V. Reynolds, chillerecke, darthcloud, DeadSkullzJr, Densetsu, DeriLoko3, ElBarto, foxe, fuzzball, Gefflon, Hiccup, hking0036, InternalLoss, Jack, jimmsu, Just001Kim, kazumi213, leekindo, Lesserkuma, Madeline, NESBrew12, NGEfreak, nnssxx, norkmetnoil577, NovaAurora, omonim2007, Powerpuff, PPLToast, Psychofox11, psykopat, rarenight, relax, RetroUprising, rpg2813, sCZther, SonGoku, Tauwasser, togemet2, UnlockerPT, xNo, xprism, xuom2" homepage No-Intro url "https://www.no-intro.org" forcenodump required @@ -21252,24 +22690,6 @@ game ( rom ( name "10-Pin Bowling (USA) (Proto).gb" size 131072 crc 9a024415 sha1 952d154dd2c6189ef4b786ae37bd7887c8ca9037 ) ) -game ( - name "2097 ROM Pack II (USA) (Test Program)" - description "2097 ROM Pack II (USA) (Test Program)" - rom ( name "2097 ROM Pack II (USA) (Test Program).gb" size 32768 crc 0a9ab6e7 sha1 68968d1b1fc84b2381159c0938675d2048c57ee2 ) -) - -game ( - name "2420 ROM Pack V (USA) (Test Program)" - description "2420 ROM Pack V (USA) (Test Program)" - rom ( name "2420 ROM Pack V (USA) (Test Program).gb" size 32768 crc 97561d80 sha1 a55a5fd97ca1be3fa129f744f81fc972e29418ac ) -) - -game ( - name "2440 ROM Pack (USA) (Test Program)" - description "2440 ROM Pack (USA) (Test Program)" - rom ( name "2440 ROM Pack (USA) (Test Program).gb" size 32768 crc 7a9359ea sha1 c15325e2e0ad2c8bd4323ef2390df28e578dcdb8 ) -) - game ( name "3 Choume no Tama - Tama and Friends - 3 Choume Obake Panic!! (Japan)" description "3 Choume no Tama - Tama and Friends - 3 Choume Obake Panic!! (Japan)" @@ -21373,9 +22793,9 @@ game ( ) game ( - name "Action Replay Pro (World)" - description "Action Replay Pro (World)" - rom ( name "Action Replay Pro (World).gb" size 16384 crc 2ea05daa sha1 e947b9264092168950ad1ce23bbe3d8ccfed765e ) + name "Action Replay Pro (World) (Unl)" + description "Action Replay Pro (World) (Unl)" + rom ( name "Action Replay Pro (World) (Unl).gb" size 16384 crc 2ea05daa sha1 e947b9264092168950ad1ce23bbe3d8ccfed765e ) ) game ( @@ -21402,18 +22822,6 @@ game ( rom ( name "Addams Family, The - Pugsley's Scavenger Hunt (USA, Europe).gb" size 131072 crc 7e054a88 sha1 f9020e3d104cb5c5347e28f45ed9e24e6c0ebddd flags verified ) ) -game ( - name "Adulting! (World) (v2.0) (Aftermarket) (Unl)" - description "Adulting! (World) (v2.0) (Aftermarket) (Unl)" - rom ( name "Adulting! (World) (v2.0) (Aftermarket) (Unl).gb" size 524288 crc e56d1244 sha1 d107bd8bf32d0d94a988466885fe1a44aae32c9a ) -) - -game ( - name "Adulting! Soundtrack (World) (Aftermarket) (Unl)" - description "Adulting! Soundtrack (World) (Aftermarket) (Unl)" - rom ( name "Adulting! Soundtrack (World) (Aftermarket) (Unl).gb" size 131072 crc 1b5b9e64 sha1 c5dad32be800c36814a0f9b940e99b5eada34150 ) -) - game ( name "Adventure Island (USA, Europe)" description "Adventure Island (USA, Europe)" @@ -21576,12 +22984,6 @@ game ( rom ( name "Alien vs Predator - The Last of His Clan (USA).gb" size 131072 crc 4bbcf652 sha1 c0d39ee87b908cdbd68c59f73e5dc2a7a6ccbedc ) ) -game ( - name "All Humans Must Die! (World) (Aftermarket) (Unl)" - description "All Humans Must Die! (World) (Aftermarket) (Unl)" - rom ( name "All Humans Must Die! (World) (Aftermarket) (Unl).gb" size 524288 crc b4d50eed sha1 f4513fc525cbcfa4a2804b55ce20c809e01d1c87 ) -) - game ( name "All-Star Baseball 99 (USA)" description "All-Star Baseball 99 (USA)" @@ -21594,12 +22996,6 @@ game ( rom ( name "Alleyway (World).gb" size 32768 crc 5cc01586 sha1 0cf2b8d0428f389f5361f67a0cd1ace05a1c75cc flags verified ) ) -game ( - name "Alphamax (World) (Aftermarket) (Unl)" - description "Alphamax (World) (Aftermarket) (Unl)" - rom ( name "Alphamax (World) (Aftermarket) (Unl).gb" size 131072 crc 8b493b41 sha1 798dda34d04a06dcee32f44f8a4a045caf734927 ) -) - game ( name "Altered Space - A 3-D Alien Adventure (Europe)" description "Altered Space - A 3-D Alien Adventure (Europe)" @@ -21624,6 +23020,12 @@ game ( rom ( name "Amazing Penguin (USA, Europe).gb" size 65536 crc 3011d5ca sha1 84cc6452823eb05ee38679aec86e3cc6e4a50e6f ) ) +game ( + name "Amazing Penguin (World) (Limited Run Games)" + description "Amazing Penguin (World) (Limited Run Games)" + rom ( name "Amazing Penguin (World) (Limited Run Games).gb" size 65536 crc 82d4664c sha1 01f11e0746a511b35b2c873d6a190f6e10204676 ) +) + game ( name "Amazing Spider-Man, The (USA, Europe)" description "Amazing Spider-Man, The (USA, Europe)" @@ -21690,12 +23092,6 @@ game ( rom ( name "Animaniacs (USA) (SGB Enhanced).gb" size 262144 crc 673c815d sha1 a0732f81e0c4f1bba592563bdc0eaae9d759ef28 flags verified ) ) -game ( - name "Another Adventure (World) (En,Es) (Aftermarket) (Unl)" - description "Another Adventure (World) (En,Es) (Aftermarket) (Unl)" - rom ( name "Another Adventure (World) (En,Es) (Aftermarket) (Unl).gb" size 1048576 crc dfcd02ef sha1 041473b2381dd9e11b3cbda5858f9841324327af ) -) - game ( name "Another Bible (Japan) (SGB Enhanced)" description "Another Bible (Japan) (SGB Enhanced)" @@ -21768,30 +23164,6 @@ game ( rom ( name "Aretha III (Japan).gb" size 262144 crc 430d3d6b sha1 f57ff26d31283c88cc4c414b18ef6f182d07da9d ) ) -game ( - name "Art School Pocket (World) (Aftermarket) (Unl)" - description "Art School Pocket (World) (Aftermarket) (Unl)" - rom ( name "Art School Pocket (World) (Aftermarket) (Unl).gb" size 1048576 crc b4eab528 sha1 c482cfc6ec40b1f33c4ba48ecdc45fef4730b653 ) -) - -game ( - name "Art School Pocket (Spain) (Aftermarket) (Unl)" - description "Art School Pocket (Spain) (Aftermarket) (Unl)" - rom ( name "Art School Pocket (Spain) (Aftermarket) (Unl).gb" size 1048576 crc 240067df sha1 c8a75895c87b11f9493f629c19c54d0c607505bd ) -) - -game ( - name "Art School Pocket (France) (Aftermarket) (Unl)" - description "Art School Pocket (France) (Aftermarket) (Unl)" - rom ( name "Art School Pocket (France) (Aftermarket) (Unl).gb" size 1048576 crc 49a5b74d sha1 73ecffaee185eb2caf1db385d04b863676c777fb ) -) - -game ( - name "Art School Pocket (Germany) (Aftermarket) (Unl)" - description "Art School Pocket (Germany) (Aftermarket) (Unl)" - rom ( name "Art School Pocket (Germany) (Aftermarket) (Unl).gb" size 1048576 crc 82b73e5b sha1 7772e2b9d5e722e54d19fc6283ccb1fa5d19b641 ) -) - game ( name "Asmik-kun World 2 (Japan)" description "Asmik-kun World 2 (Japan)" @@ -21858,18 +23230,6 @@ game ( rom ( name "Astro Rabby (Japan).gb" size 65536 crc 61e48eef sha1 3e53fd25f350c78a29e0642ee6de80208930d469 ) ) -game ( - name "Astro-Jump (World) (Aftermarket) (Unl)" - description "Astro-Jump (World) (Aftermarket) (Unl)" - rom ( name "Astro-Jump (World) (Aftermarket) (Unl).gb" size 262144 crc c35a3b39 sha1 1bcb4be684626ce061aad105701548fa3a77e254 ) -) - -game ( - name "Astro-Jump - The Sequel (World) (Aftermarket) (Unl)" - description "Astro-Jump - The Sequel (World) (Aftermarket) (Unl)" - rom ( name "Astro-Jump - The Sequel (World) (Aftermarket) (Unl).gb" size 131072 crc e6a96130 sha1 2cd0ef086c4b89497d9497a17d871a6568a9e2d3 ) -) - game ( name "Atomic Punk (USA)" description "Atomic Punk (USA)" @@ -21888,18 +23248,6 @@ game ( rom ( name "Attack of the Killer Tomatoes (USA, Europe).gb" size 131072 crc b5b38860 sha1 cbbba5d4f80f2b4ab3e882ceb4f79c293a17904f flags verified ) ) -game ( - name "Auto Zone (World) (Aftermarket) (Unl)" - description "Auto Zone (World) (Aftermarket) (Unl)" - rom ( name "Auto Zone (World) (Aftermarket) (Unl).gb" size 524288 crc cee73c14 sha1 3070ec215014633dac5dbbb487aade2e2993c049 ) -) - -game ( - name "Autumn With You, An (World) (Aftermarket) (Unl)" - description "Autumn With You, An (World) (Aftermarket) (Unl)" - rom ( name "Autumn With You, An (World) (Aftermarket) (Unl).gb" size 262144 crc eac459fa sha1 68a5520be76c52a4936ad1756ea274667f2ac0e3 ) -) - game ( name "Avenging Spirit (USA, Europe)" description "Avenging Spirit (USA, Europe)" @@ -22029,7 +23377,7 @@ game ( game ( name "Bases Loaded (USA)" description "Bases Loaded (USA)" - rom ( name "Bases Loaded (USA).gb" size 131072 crc d37a2fdf sha1 5220db2e87622648caeacdfb8d4f564c9bf479fc ) + rom ( name "Bases Loaded (USA).gb" size 131072 crc d37a2fdf sha1 5220db2e87622648caeacdfb8d4f564c9bf479fc flags verified ) ) game ( @@ -22212,12 +23560,6 @@ game ( rom ( name "Battletoads-Double Dragon (USA).gb" size 262144 crc a727f9cd sha1 ce68df4dc2d604625164430266017b237b72303d ) ) -game ( - name "Batty Zabella (World) (Aftermarket) (Unl)" - description "Batty Zabella (World) (Aftermarket) (Unl)" - rom ( name "Batty Zabella (World) (Aftermarket) (Unl).gb" size 1048576 crc dfa3c64c sha1 2361d5f87bd525964e61bd39765a6fa843fa4c43 ) -) - game ( name "Beavis and Butt-head (USA, Europe)" description "Beavis and Butt-head (USA, Europe)" @@ -22267,9 +23609,9 @@ game ( ) game ( - name "Bill & Ted's Excellent Portable Adventure - A Bogus Journey! (World) (Aftermarket) (Unl)" - description "Bill & Ted's Excellent Portable Adventure - A Bogus Journey! (World) (Aftermarket) (Unl)" - rom ( name "Bill & Ted's Excellent Portable Adventure - A Bogus Journey! (World) (Aftermarket) (Unl).gb" size 131072 crc 7b5e19ca sha1 c6e606cb5e17f7530a529387ad2fb703a94b205a ) + name "Bill & Ted's Excellent Portable Adventure - A Bogus Journey! (World) (Retro Collection)" + description "Bill & Ted's Excellent Portable Adventure - A Bogus Journey! (World) (Retro Collection)" + rom ( name "Bill & Ted's Excellent Portable Adventure - A Bogus Journey! (World) (Retro Collection).gb" size 131072 crc 7b5e19ca sha1 c6e606cb5e17f7530a529387ad2fb703a94b205a flags verified ) ) game ( @@ -22278,6 +23620,12 @@ game ( rom ( name "Bill Elliott's NASCAR Fast Tracks (USA).gb" size 131072 crc 71cf43ce sha1 ebc2ca8b4503f0b05e00749d693462a54f2f95eb ) ) +game ( + name "Binary Monsters II - Adventure of Hell (Taiwan) (En) (Unl)" + description "Binary Monsters II - Adventure of Hell (Taiwan) (En) (Unl)" + rom ( name "Binary Monsters II - Adventure of Hell (Taiwan) (En) (Unl).gb" size 131072 crc 3bf1e911 sha1 5a7ea252cc344f239e48eee0eba6a9ba97d799ea ) +) + game ( name "Bionic Battler (USA)" description "Bionic Battler (USA)" @@ -22320,18 +23668,6 @@ game ( rom ( name "Black Bass - Lure Fishing (USA).gb" size 262144 crc 2db3dace sha1 d9524ac9f7788172a55cc8ceb6e199f8a12e033d ) ) -game ( - name "Black Castle GB (World) (Aftermarket) (Unl)" - description "Black Castle GB (World) (Aftermarket) (Unl)" - rom ( name "Black Castle GB (World) (Aftermarket) (Unl).gb" size 65536 crc 10f577c7 sha1 45d979be572bb820835d2ecd4e990cd1eadbf5a6 ) -) - -game ( - name "Black Tape (World) (Aftermarket) (Unl)" - description "Black Tape (World) (Aftermarket) (Unl)" - rom ( name "Black Tape (World) (Aftermarket) (Unl).gb" size 524288 crc 45c5f990 sha1 ec8c467e955d69b2084805f11a954e0d90855461 ) -) - game ( name "Blade Warrior (Europe) (Proto)" description "Blade Warrior (Europe) (Proto)" @@ -22368,24 +23704,12 @@ game ( rom ( name "Blaster Master Jr. (Europe).gb" size 131072 crc e9f9016f sha1 6a6deae1942e7cf048ce35d18e9540363c226727 ) ) -game ( - name "Blitz Bomber (World) (Aftermarket) (Unl)" - description "Blitz Bomber (World) (Aftermarket) (Unl)" - rom ( name "Blitz Bomber (World) (Aftermarket) (Unl).gb" size 262144 crc 5e9956de sha1 b72cbc6bfa6ceef940f49c9c82024071c6f82b90 ) -) - game ( name "Block Kuzushi GB (Japan) (SGB Enhanced)" description "Block Kuzushi GB (Japan) (SGB Enhanced)" rom ( name "Block Kuzushi GB (Japan) (SGB Enhanced).gb" size 131072 crc 54b67501 sha1 7540fe9af69d8c7d48f50c2d5fe6d3ce07421f74 ) ) -game ( - name "Blockade (World) (Aftermarket) (Unl)" - description "Blockade (World) (Aftermarket) (Unl)" - rom ( name "Blockade (World) (Aftermarket) (Unl).gb" size 262144 crc b8cfab16 sha1 9e753048a0eb036ac17c08f5a64d860abd1aaaf5 ) -) - game ( name "Blodia (Japan)" description "Blodia (Japan)" @@ -22434,18 +23758,6 @@ game ( rom ( name "Boggle Plus (USA).gb" size 131072 crc 70c8c799 sha1 d6cf512f7301ccdc2d802f34fbbde2d0ba2cf3cd ) ) -game ( - name "BOING! (World) (Aftermarket) (Unl)" - description "BOING! (World) (Aftermarket) (Unl)" - rom ( name "BOING! (World) (Aftermarket) (Unl).gb" size 2097152 crc 91961796 sha1 09fde4065941784bab4cf8f624a0398049ed4add ) -) - -game ( - name "Bokujou Monogatari GB (Japan) (SGB Enhanced) (NP)" - description "Bokujou Monogatari GB (Japan) (SGB Enhanced) (NP)" - rom ( name "Bokujou Monogatari GB (Japan) (SGB Enhanced) (NP).gb" size 524288 crc 0424df85 sha1 551df2021d0e433e7f07cf881c7b1d534f54f6ad ) -) - game ( name "Bokujou Monogatari GB (Japan) (SGB Enhanced)" description "Bokujou Monogatari GB (Japan) (SGB Enhanced)" @@ -22459,9 +23771,9 @@ game ( ) game ( - name "Bomb Jack (Europe)" - description "Bomb Jack (Europe)" - rom ( name "Bomb Jack (Europe).gb" size 32768 crc 9bd8815e sha1 a2b2799e867777a5a19155ed1f2245630fc03560 ) + name "Bokujou Monogatari GB (Japan) (SGB Enhanced) (NP)" + description "Bokujou Monogatari GB (Japan) (SGB Enhanced) (NP)" + rom ( name "Bokujou Monogatari GB (Japan) (SGB Enhanced) (NP).gb" size 524288 crc 0424df85 sha1 551df2021d0e433e7f07cf881c7b1d534f54f6ad ) ) game ( @@ -22476,6 +23788,12 @@ game ( rom ( name "Bomb Jack (Europe) (Beta 2).gb" size 32768 crc 7ca8e543 sha1 6fc3794149f5e75ad82b4a7d47ad5497e1ee4e6a ) ) +game ( + name "Bomb Jack (Europe)" + description "Bomb Jack (Europe)" + rom ( name "Bomb Jack (Europe).gb" size 32768 crc 9bd8815e sha1 a2b2799e867777a5a19155ed1f2245630fc03560 ) +) + game ( name "Bomber Boy (Japan)" description "Bomber Boy (Japan)" @@ -22548,12 +23866,6 @@ game ( rom ( name "Boomer's Adventure in ASMIK World (USA).gb" size 65536 crc 105bc1c0 sha1 3d8a6fcc644290c9d88fe2918bfa6007ee811de8 flags verified ) ) -game ( - name "Borbo's Quest (World) (Aftermarket) (Unl)" - description "Borbo's Quest (World) (Aftermarket) (Unl)" - rom ( name "Borbo's Quest (World) (Aftermarket) (Unl).gb" size 1048576 crc e92ce3d4 sha1 1ddf864188dfd741ccda0b0715e75e162d212605 ) -) - game ( name "Bouken! Puzzle Road (Japan)" description "Bouken! Puzzle Road (Japan)" @@ -22572,18 +23884,6 @@ game ( rom ( name "Boulder Dash (Japan).gb" size 65536 crc b5b3f85b sha1 f5a4a5ccda4f559ce85567c4b68f758216aee2d4 ) ) -game ( - name "Bounce (World) (v1.1) (Aftermarket) (Unl)" - description "Bounce (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Bounce (World) (v1.1) (Aftermarket) (Unl).gb" size 32768 crc 827f2bd5 sha1 e9abf64de3faeb48151003ac8bb77dea61e838b5 ) -) - -game ( - name "Bouncing Ball, The (World) (Aftermarket)" - description "Bouncing Ball, The (World) (Aftermarket)" - rom ( name "Bouncing Ball, The (World) (Aftermarket).gb" size 65536 crc 42ddf53e sha1 5d331f2e66d7d3f4b4b0fcbaf6ab4b1a0147db3e ) -) - game ( name "Boxing (Japan)" description "Boxing (Japan)" @@ -22627,9 +23927,9 @@ game ( ) game ( - name "Brain Drain (Japan) (SGB Enhanced)" - description "Brain Drain (Japan) (SGB Enhanced)" - rom ( name "Brain Drain (Japan) (SGB Enhanced).gb" size 131072 crc e558aacd sha1 225c25d94854f509611b8c0b4b415daf48d51310 ) + name "Brain Drain (Japan) (En) (SGB Enhanced)" + description "Brain Drain (Japan) (En) (SGB Enhanced)" + rom ( name "Brain Drain (Japan) (En) (SGB Enhanced).gb" size 131072 crc e558aacd sha1 225c25d94854f509611b8c0b4b415daf48d51310 ) ) game ( @@ -22788,12 +24088,6 @@ game ( rom ( name "Buster Bros. (USA).gb" size 131072 crc b4245ca3 sha1 0d1692ff60ef1f6a97bbfd2bf8c1548f1f7439ed ) ) -game ( - name "Busty Bunny the Bounty Babe (World) (v1.02) (Aftermarket) (Unl)" - description "Busty Bunny the Bounty Babe (World) (v1.02) (Aftermarket) (Unl)" - rom ( name "Busty Bunny the Bounty Babe (World) (v1.02) (Aftermarket) (Unl).gb" size 1048576 crc d0ed199c sha1 a1cbaacdf32cb8fb9a9c59fcb624c729e0ca17bf ) -) - game ( name "Cadillac II (Japan)" description "Cadillac II (Japan)" @@ -22815,13 +24109,13 @@ game ( game ( name "Caesars Palace (USA)" description "Caesars Palace (USA)" - rom ( name "Caesars Palace (USA).gb" size 131072 crc d9f901a9 sha1 c1ed80f33fc3603edaba1bdf5c317f1a205da3dc ) + rom ( name "Caesars Palace (USA).gb" size 131072 crc d9f901a9 sha1 c1ed80f33fc3603edaba1bdf5c317f1a205da3dc flags verified ) ) game ( name "Caesars Palace (USA) (Rev 1)" description "Caesars Palace (USA) (Rev 1)" - rom ( name "Caesars Palace (USA) (Rev 1).gb" size 131072 crc 87a9d605 sha1 126e9ef9e975bbbc6303d5d62a379d4dbd404cf0 ) + rom ( name "Caesars Palace (USA) (Rev 1).gb" size 131072 crc 87a9d605 sha1 126e9ef9e975bbbc6303d5d62a379d4dbd404cf0 flags verified ) ) game ( @@ -22962,18 +24256,6 @@ game ( rom ( name "Castlevania Legends (USA, Europe) (SGB Enhanced).gb" size 262144 crc ad9c17fb sha1 91a8e49bf6eac5fe62ec2cc5e6decbd08ce9b515 flags verified ) ) -game ( - name "Cat Boy's Stellar Journey (World) (Aftermarket) (Unl)" - description "Cat Boy's Stellar Journey (World) (Aftermarket) (Unl)" - rom ( name "Cat Boy's Stellar Journey (World) (Aftermarket) (Unl).gb" size 262144 crc 280937cc sha1 9ec53942f0136076b6468671562764e1ab9dee3b ) -) - -game ( - name "Catrap (USA)" - description "Catrap (USA)" - rom ( name "Catrap (USA).gb" size 32768 crc adb96150 sha1 171e4d54f22f8dc137d12828fcc2da9874c56970 ) -) - game ( name "Catrap (USA) (Beta)" description "Catrap (USA) (Beta)" @@ -22981,9 +24263,9 @@ game ( ) game ( - name "Cave Fighter (World) (Aftermarket) (Unl)" - description "Cave Fighter (World) (Aftermarket) (Unl)" - rom ( name "Cave Fighter (World) (Aftermarket) (Unl).gb" size 262144 crc e8f91f6a sha1 290048717d0a8cabb3cc591161339550eb53c161 ) + name "Catrap (USA)" + description "Catrap (USA)" + rom ( name "Catrap (USA).gb" size 32768 crc adb96150 sha1 171e4d54f22f8dc137d12828fcc2da9874c56970 ) ) game ( @@ -23034,12 +24316,6 @@ game ( rom ( name "Chase H.Q. (USA, Europe).gb" size 131072 crc 67a45d19 sha1 cbcd6254b1b0227ba6aa8d95c979abb7fe8e4d38 flags verified ) ) -game ( - name "Cherry Rescue! (World) (Aftermarket) (Unl)" - description "Cherry Rescue! (World) (Aftermarket) (Unl)" - rom ( name "Cherry Rescue! (World) (Aftermarket) (Unl).gb" size 524288 crc ba65812a sha1 740dba1827c730cc5d8bf67495bcede3a5352643 ) -) - game ( name "Chessmaster, The (Europe)" description "Chessmaster, The (Europe)" @@ -23160,54 +24436,18 @@ game ( rom ( name "Chousoku Spinner (Japan) (SGB Enhanced).gb" size 524288 crc b4fa9cf2 sha1 057a3251bbb7eb4e04b01f786bd2986af5eabc58 ) ) -game ( - name "Christmas Carols (World) (Aftermarket) (Unl)" - description "Christmas Carols (World) (Aftermarket) (Unl)" - rom ( name "Christmas Carols (World) (Aftermarket) (Unl).gb" size 262144 crc a00bb310 sha1 e19b0a698d8194467d57c00664f00f9898ee5368 ) -) - game ( name "Chuck Rock (USA, Europe)" description "Chuck Rock (USA, Europe)" rom ( name "Chuck Rock (USA, Europe).gb" size 131072 crc c5951d9e sha1 601453f98ba7d92ebe71f3e86952a584cbea090c ) ) -game ( - name "Ciao Nonna (World) (v1.1) (Aftermarket) (Unl)" - description "Ciao Nonna (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Ciao Nonna (World) (v1.1) (Aftermarket) (Unl).gb" size 1048576 crc 2165f2e4 sha1 f8e5020298183c3f47836da3890b6bb398e2ecab ) -) - -game ( - name "Ciao Nonna (World) (v2.0) (Aftermarket) (Unl)" - description "Ciao Nonna (World) (v2.0) (Aftermarket) (Unl)" - rom ( name "Ciao Nonna (World) (v2.0) (Aftermarket) (Unl).gb" size 1048576 crc 6afee818 sha1 602709c8655febb42899881a8ef598fb4b3da0c9 ) -) - -game ( - name "Ciao Nonna (World) (v2.1) (Aftermarket) (Unl)" - description "Ciao Nonna (World) (v2.1) (Aftermarket) (Unl)" - rom ( name "Ciao Nonna (World) (v2.1) (Aftermarket) (Unl).gb" size 1048576 crc 225ce296 sha1 45aebfe4e7f5382a4b31c3db270b75d2c458d1b2 ) -) - -game ( - name "Ciao Nonna (World) (v1.0) (Aftermarket) (Unl)" - description "Ciao Nonna (World) (v1.0) (Aftermarket) (Unl)" - rom ( name "Ciao Nonna (World) (v1.0) (Aftermarket) (Unl).gb" size 1048576 crc dd7576d6 sha1 0556eb6160fdca6e7959bba1a619b8e34d974375 ) -) - game ( name "Cliffhanger (USA, Europe)" description "Cliffhanger (USA, Europe)" rom ( name "Cliffhanger (USA, Europe).gb" size 131072 crc aa133439 sha1 c74f85035842f8a2d9560066d7065ff86d9107e2 flags verified ) ) -game ( - name "Clockmaker's Tale, A (World) (Aftermarket) (Unl)" - description "Clockmaker's Tale, A (World) (Aftermarket) (Unl)" - rom ( name "Clockmaker's Tale, A (World) (Aftermarket) (Unl).gb" size 1048576 crc c4b00adb sha1 07e4254c7f74b9d4caa6a1231558b2430dff163a ) -) - game ( name "Collection Pocket (Japan) (SGB Enhanced)" description "Collection Pocket (Japan) (SGB Enhanced)" @@ -23220,12 +24460,6 @@ game ( rom ( name "College Slam (USA).gb" size 524288 crc a549a572 sha1 84dc6269fbe4ee4c157f940b0a9630412e099cc6 ) ) -game ( - name "Commando (World) (Aftermarket) (Unl)" - description "Commando (World) (Aftermarket) (Unl)" - rom ( name "Commando (World) (Aftermarket) (Unl).gb" size 262144 crc 48173941 sha1 c861858e9f2cf7470e739c26ae9f17d3834ce464 ) -) - game ( name "Contra (World) (Contra Anniversary Collection)" description "Contra (World) (Contra Anniversary Collection)" @@ -23250,12 +24484,6 @@ game ( rom ( name "Contra Spirits (Japan) (SGB Enhanced).gb" size 131072 crc 7fc22df5 sha1 72213c5d8af05cad5f17a42566f7383066612eee ) ) -game ( - name "Cookie's Bakery (World) (v1.0.3) (Aftermarket) (Unl)" - description "Cookie's Bakery (World) (v1.0.3) (Aftermarket) (Unl)" - rom ( name "Cookie's Bakery (World) (v1.0.3) (Aftermarket) (Unl).gb" size 524288 crc c53ace00 sha1 02fdc52bc934b80aa41520d92cf0340753d8f668 ) -) - game ( name "Cool Ball (USA)" description "Cool Ball (USA)" @@ -23292,18 +24520,6 @@ game ( rom ( name "Cool World (USA, Europe).gb" size 131072 crc a193c0d0 sha1 1919495cc83c4126c90d6cfa2e14427b6364da3a flags verified ) ) -game ( - name "Coria and the Sunken City (World) (Demo) (Aftermarket) (Unl)" - description "Coria and the Sunken City (World) (Demo) (Aftermarket) (Unl)" - rom ( name "Coria and the Sunken City (World) (Demo) (Aftermarket) (Unl).gb" size 131072 crc fe1bdae6 sha1 00d86bbdbc228ff3ea0684984a261cadbed5fb0a ) -) - -game ( - name "Cosmic Courier - Trapped in Limbo (World) (Aftermarket) (Unl)" - description "Cosmic Courier - Trapped in Limbo (World) (Aftermarket) (Unl)" - rom ( name "Cosmic Courier - Trapped in Limbo (World) (Aftermarket) (Unl).gb" size 262144 crc fd304687 sha1 7df11ec2946099d49dd62928118b6d76703dc57c ) -) - game ( name "Cosmo Tank (Japan) (Beta)" description "Cosmo Tank (Japan) (Beta)" @@ -23328,18 +24544,6 @@ game ( rom ( name "Cosmo Tank (USA).gb" size 131072 crc 2e767d25 sha1 48a8f5c50a237f11c8e18efd03a5282f493312bc ) ) -game ( - name "Coucou (World) (Aftermarket) (Unl)" - description "Coucou (World) (Aftermarket) (Unl)" - rom ( name "Coucou (World) (Aftermarket) (Unl).gb" size 32768 crc e6aabd72 sha1 5283268e3640e2924d00aea3b12b2d3930bef43c ) -) - -game ( - name "Counting Sheep (World) (Aftermarket) (Unl)" - description "Counting Sheep (World) (Aftermarket) (Unl)" - rom ( name "Counting Sheep (World) (Aftermarket) (Unl).GB" size 65536 crc 6e97c837 sha1 e7e251ad86fa00803837cf871de62d3f100c83ce ) -) - game ( name "Crayon Shin-chan - Ora no Gokigen Collection (Japan) (SGB Enhanced)" description "Crayon Shin-chan - Ora no Gokigen Collection (Japan) (SGB Enhanced)" @@ -23388,12 +24592,6 @@ game ( rom ( name "Cult Master - Ultraman ni Miserarete (Japan).gb" size 262144 crc c3eb82ef sha1 f0e63a0a4e7b576c7460e810eb6f50d4c5b68769 ) ) -game ( - name "Cuthbert in the Cooler (World) (Aftermarket) (Unl)" - description "Cuthbert in the Cooler (World) (Aftermarket) (Unl)" - rom ( name "Cuthbert in the Cooler (World) (Aftermarket) (Unl).gb" size 262144 crc 10838580 sha1 c740bc995adf2bb638bb125a36edc416558fd4c6 ) -) - game ( name "CutThroat Island (Japan) (En) (Proto)" description "CutThroat Island (Japan) (En) (Proto)" @@ -23460,24 +24658,6 @@ game ( rom ( name "Daisenryaku (Japan).gb" size 131072 crc c8f80d90 sha1 79e724619d21ebb3cd5de5438535a7ee25009de0 ) ) -game ( - name "Dangan (World) (v1.1) (Aftermarket) (Unl)" - description "Dangan (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Dangan (World) (v1.1) (Aftermarket) (Unl).gb" size 262144 crc 5359d6db sha1 10029774046dabec2d8c0533caf94091f6e19071 ) -) - -game ( - name "Dangan (World) (v1.0) (Aftermarket) (Unl)" - description "Dangan (World) (v1.0) (Aftermarket) (Unl)" - rom ( name "Dangan (World) (v1.0) (Aftermarket) (Unl).gb" size 262144 crc daa59c9c sha1 8375d845fcfe4c236cd68f3d56a290f8c7b76c06 ) -) - -game ( - name "Dark Winter Wander, A (World) (Aftermarket) (Unl)" - description "Dark Winter Wander, A (World) (Aftermarket) (Unl)" - rom ( name "Dark Winter Wander, A (World) (Aftermarket) (Unl).gb" size 1048576 crc df19aa9f sha1 412f18ba08f2f2a2afbf3bfb5281e360d7aba31d ) -) - game ( name "Darkman (USA, Europe)" description "Darkman (USA, Europe)" @@ -23496,12 +24676,6 @@ game ( rom ( name "Darkwing Duck (USA).gb" size 131072 crc 238b9646 sha1 cc1f12f3ec3852657a14d11c13d1ef91fbdda5bb ) ) -game ( - name "Darkwing Duck (USA) (Beta)" - description "Darkwing Duck (USA) (Beta)" - rom ( name "Darkwing Duck (USA) (Beta).gb" size 131072 crc 311ade03 sha1 2883b8854529369cce4d473e71fa0193c7df02b6 ) -) - game ( name "Darkwing Duck (Germany)" description "Darkwing Duck (Germany)" @@ -23515,9 +24689,15 @@ game ( ) game ( - name "Dash (World) (Aftermarket) (Unl)" - description "Dash (World) (Aftermarket) (Unl)" - rom ( name "Dash (World) (Aftermarket) (Unl).gb" size 262144 crc 73868683 sha1 c1ffe7c25a34d65ed166293bc7d2b48b65ca922b ) + name "Darkwing Duck (USA) (Beta)" + description "Darkwing Duck (USA) (Beta)" + rom ( name "Darkwing Duck (USA) (Beta).gb" size 131072 crc 311ade03 sha1 2883b8854529369cce4d473e71fa0193c7df02b6 ) +) + +game ( + name "David Crane's The Rescue of Princess Blobette (World) (Limited Run Games)" + description "David Crane's The Rescue of Princess Blobette (World) (Limited Run Games)" + rom ( name "David Crane's The Rescue of Princess Blobette (World) (Limited Run Games).gb" size 65536 crc 0c24923e sha1 e1f391102aba5ea75572b04180b31bcaaa47e593 ) ) game ( @@ -23532,12 +24712,6 @@ game ( rom ( name "David Crane's The Rescue of Princess Blobette (USA).gb" size 65536 crc 8210a03f sha1 0a45d1b98646fd7832b5119b04bc8d6d6d0f657a ) ) -game ( - name "Dawn Will Come (World) (Aftermarket) (Unl)" - description "Dawn Will Come (World) (Aftermarket) (Unl)" - rom ( name "Dawn Will Come (World) (Aftermarket) (Unl).gb" size 2097152 crc bb64f51c sha1 1611ddfdb9af72f20ddeca4133d8eebd0f14e424 ) -) - game ( name "Days of Thunder (USA, Europe)" description "Days of Thunder (USA, Europe)" @@ -23556,18 +24730,6 @@ game ( rom ( name "Dead Heat Scramble (USA).gb" size 65536 crc 9e3e3656 sha1 71e560dd2b5f5c4f4dcca0837c74bb1b843a15aa ) ) -game ( - name "Deadeus (World) (v1.3.8) (Aftermarket) (Unl)" - description "Deadeus (World) (v1.3.8) (Aftermarket) (Unl)" - rom ( name "Deadeus (World) (v1.3.8) (Aftermarket) (Unl).gb" size 1048576 crc 7da95971 sha1 23cff594ef4b0bb21883b422940526c7fe81f1fd flags verified ) -) - -game ( - name "Deadeus (World) (v1.2.5) (Aftermarket) (Unl)" - description "Deadeus (World) (v1.2.5) (Aftermarket) (Unl)" - rom ( name "Deadeus (World) (v1.2.5) (Aftermarket) (Unl).gb" size 1048576 crc 9e2bf649 sha1 3feeba5c438880f70cdfdc4ea7e29f77e645e9be flags verified ) -) - game ( name "Death Track (Europe) (Proto)" description "Death Track (Europe) (Proto)" @@ -23575,9 +24737,9 @@ game ( ) game ( - name "Deep Forest (World) (v1.1) (Aftermarket) (Unl)" - description "Deep Forest (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Deep Forest (World) (v1.1) (Aftermarket) (Unl).gb" size 1048576 crc 3ddf177d sha1 517302d20cb5140975e6cd1b3c495786b6390aaf ) + name "Dennis (Europe) (Beta) (1993-09-13)" + description "Dennis (Europe) (Beta) (1993-09-13)" + rom ( name "Dennis (Europe) (Beta) (1993-09-13).gb" size 131072 crc 807d34a4 sha1 fab382a28f9d7fefae7dc9a16bf86f309d89e037 ) ) game ( @@ -23586,12 +24748,6 @@ game ( rom ( name "Dennis (Europe).gb" size 131072 crc 896a30a8 sha1 9b5c289f25829534020951f84732177036837aea ) ) -game ( - name "Dennis (Europe) (Beta) (1993-09-13)" - description "Dennis (Europe) (Beta) (1993-09-13)" - rom ( name "Dennis (Europe) (Beta) (1993-09-13).gb" size 131072 crc 807d34a4 sha1 fab382a28f9d7fefae7dc9a16bf86f309d89e037 ) -) - game ( name "Dennis the Menace (USA)" description "Dennis the Menace (USA)" @@ -23622,12 +24778,6 @@ game ( rom ( name "Diablo (USA) (Proto).gb" size 131072 crc aaaad0b6 sha1 8982410ac627618628a8b823c0608cc8b5653f41 ) ) -game ( - name "DiaMaze (World) (Aftermarket) (Unl)" - description "DiaMaze (World) (Aftermarket) (Unl)" - rom ( name "DiaMaze (World) (Aftermarket) (Unl).gb" size 262144 crc 956fa901 sha1 f41b98ac4669920ffede1736ddbd9e1f62d4cb0d ) -) - game ( name "Dick Tracy (USA)" description "Dick Tracy (USA)" @@ -23664,12 +24814,6 @@ game ( rom ( name "Dino Breeder 2 (Japan) (SGB Enhanced).gb" size 524288 crc 05a3ab7a sha1 ac4b1fe0e917298d81725d7a9bdf46c285502ac7 flags verified ) ) -game ( - name "Dino's Offline Adventure (World) (Aftermarket) (Unl)" - description "Dino's Offline Adventure (World) (Aftermarket) (Unl)" - rom ( name "Dino's Offline Adventure (World) (Aftermarket) (Unl).gb" size 32768 crc d6bd0e6a sha1 6d11c145606f8e7ab25b2b07c299e36c8b442d23 ) -) - game ( name "Dirty Racing (Europe) (Proto)" description "Dirty Racing (Europe) (Proto)" @@ -23682,48 +24826,6 @@ game ( rom ( name "Dirty Racing (Japan).gb" size 131072 crc 43af45b1 sha1 5b58b4d02987ce3a16774bc4a6707d12ac404c1c ) ) -game ( - name "Disco Elysium - Game Boy Edition (World) (Aftermarket) (Unl)" - description "Disco Elysium - Game Boy Edition (World) (Aftermarket) (Unl)" - rom ( name "Disco Elysium - Game Boy Edition (World) (Aftermarket) (Unl).gb" size 1048576 crc ef349515 sha1 06fe25086432c82f1e4b4c44473dd5b487a8af05 ) -) - -game ( - name "DMG Deals Damage (World) (Aftermarket) (Unl)" - description "DMG Deals Damage (World) (Aftermarket) (Unl)" - rom ( name "DMG Deals Damage (World) (Aftermarket) (Unl).gb" size 32768 crc 250e0cbd sha1 a15539199e4b6bd2a71d1ac0e7c61ae4f19a65e7 ) -) - -game ( - name "Do I Pass (World) (Demo) (Aftermarket) (Unl)" - description "Do I Pass (World) (Demo) (Aftermarket) (Unl)" - rom ( name "Do I Pass (World) (Demo) (Aftermarket) (Unl).gb" size 1048576 crc f339fa82 sha1 bdbc082017bdf2e4caa84e7d00dad9707727e9d4 ) -) - -game ( - name "Do I Pass (World) (v1.4) (Aftermarket) (Unl)" - description "Do I Pass (World) (v1.4) (Aftermarket) (Unl)" - rom ( name "Do I Pass (World) (v1.4) (Aftermarket) (Unl).gb" size 1048576 crc cfb44d68 sha1 6dde71bbec8b807af5132d1ef2e99c6bb6af3a1c ) -) - -game ( - name "Do I Pass (World) (v1.4) (Web) (Aftermarket) (Unl)" - description "Do I Pass (World) (v1.4) (Web) (Aftermarket) (Unl)" - rom ( name "Do I Pass (World) (v1.4) (Web) (Aftermarket) (Unl).gb" size 1048576 crc 62e0c3a2 sha1 e1b516e472e0c681b4ad1c7f4aeda55c91e7f340 ) -) - -game ( - name "Do I Pass (World) (Fr) (v1.4.2) (Aftermarket) (Unl)" - description "Do I Pass (World) (Fr) (v1.4.2) (Aftermarket) (Unl)" - rom ( name "Do I Pass (World) (Fr) (v1.4.2) (Aftermarket) (Unl).gb" size 1048576 crc e393d4aa sha1 d45dfcab4a76b62ea1e10730d01f755e12137484 ) -) - -game ( - name "Do I Pass (World) (v1.5) (Aftermarket) (Unl)" - description "Do I Pass (World) (v1.5) (Aftermarket) (Unl)" - rom ( name "Do I Pass (World) (v1.5) (Aftermarket) (Unl).gb" size 1048576 crc 3890e0a4 sha1 6998e1bbf2ccb9db3d661ddac2d7edf7571d0af7 ) -) - game ( name "Doctor GB Card 16M Loader (World) (Unl)" description "Doctor GB Card 16M Loader (World) (Unl)" @@ -23754,30 +24856,6 @@ game ( rom ( name "Dodge Boy (Japan).gb" size 131072 crc f58dc358 sha1 b48eb2bdc34588847728936491dadda67394f9b7 ) ) -game ( - name "Dog's Muck Island (World) (Aftermarket) (Unl)" - description "Dog's Muck Island (World) (Aftermarket) (Unl)" - rom ( name "Dog's Muck Island (World) (Aftermarket) (Unl).gb" size 262144 crc 79a7a06c sha1 eb4cea3b9db770bf3b586578af1ad7427d88ee8e ) -) - -game ( - name "Don't Forget About Me (World) (v1.0) (Aftermarket) (Unl)" - description "Don't Forget About Me (World) (v1.0) (Aftermarket) (Unl)" - rom ( name "Don't Forget About Me (World) (v1.0) (Aftermarket) (Unl).gb" size 524288 crc 52cf7153 sha1 74e6246405dd52d4c5c2eabc417946550c637164 ) -) - -game ( - name "Don't Forget About Me (World) (v1.2) (Aftermarket) (Unl)" - description "Don't Forget About Me (World) (v1.2) (Aftermarket) (Unl)" - rom ( name "Don't Forget About Me (World) (v1.2) (Aftermarket) (Unl).gb" size 1048576 crc 3d87efd8 sha1 83201c43e9fc89f4393678ade8c6107b4cfdb628 ) -) - -game ( - name "Don't Forget About Me (World) (v1.1) (Aftermarket) (Unl)" - description "Don't Forget About Me (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Don't Forget About Me (World) (v1.1) (Aftermarket) (Unl).gb" size 1048576 crc 8ca9dbe0 sha1 cf6eaac37c4ae1b3cfc4ed8d2ce73a143635b525 ) -) - game ( name "Donkey Kong (Japan, USA) (En) (SGB Enhanced)" description "Donkey Kong (Japan, USA) (En) (SGB Enhanced)" @@ -24084,18 +25162,6 @@ game ( rom ( name "Dragon's Lair - The Legend (USA).gb" size 131072 crc 7a38b5c3 sha1 4e947908fde7ef9892c59021c6eea0607771f6d2 ) ) -game ( - name "Dragonborne (World) (Aftermarket) (Unl)" - description "Dragonborne (World) (Aftermarket) (Unl)" - rom ( name "Dragonborne (World) (Aftermarket) (Unl).gb" size 2097152 crc 0ae28712 sha1 e3cd09069ee59ed3f7915a79af0667de4ebd7d50 ) -) - -game ( - name "Dragonborne (World) (Demo) (Aftermarket) (Unl)" - description "Dragonborne (World) (Demo) (Aftermarket) (Unl)" - rom ( name "Dragonborne (World) (Demo) (Aftermarket) (Unl).gb" size 2097152 crc eda66890 sha1 3a5bcd9daa830842da60d8ebf35fa7036a259d76 ) -) - game ( name "DragonHeart (France)" description "DragonHeart (France)" @@ -24204,6 +25270,12 @@ game ( rom ( name "Earthworm Jim (USA).gb" size 262144 crc 259ff267 sha1 f5d3085de17a5181c07739e49be7637faa5ff932 ) ) +game ( + name "Eclipse (Europe) (Proto)" + description "Eclipse (Europe) (Proto)" + rom ( name "Eclipse (Europe) (Proto).gb" size 65536 crc 6b507efd sha1 de02a34675a57d450284103681951436a4c830cd ) +) + game ( name "Edd the Duck (Europe) (Proto)" description "Edd the Duck (Europe) (Proto)" @@ -24234,12 +25306,6 @@ game ( rom ( name "Elite Soccer (USA) (SGB Enhanced).gb" size 131072 crc f54158a6 sha1 4576881ea25e29ebba91c49c89f8e70e105fbc60 ) ) -game ( - name "Empire of Dreams, The (World) (Aftermarket) (Unl)" - description "Empire of Dreams, The (World) (Aftermarket) (Unl)" - rom ( name "Empire of Dreams, The (World) (Aftermarket) (Unl).gb" size 524288 crc d87e5e68 sha1 92b2da6bd10337950ddcb8bb372cabccdce4f6bd ) -) - game ( name "Exodus - Journey to the Promised Land (USA) (Unl)" description "Exodus - Journey to the Promised Land (USA) (Unl)" @@ -24282,12 +25348,6 @@ game ( rom ( name "F-15 Strike Eagle II (USA, Europe) (Beta) (July, 1992).gb" size 131072 crc d80bdbba sha1 298c07ef596ab3a3c4a320b2f2d7e2c0dbaf764d ) ) -game ( - name "F-Zero - Project (World) (Aftermarket) (Unl)" - description "F-Zero - Project (World) (Aftermarket) (Unl)" - rom ( name "F-Zero - Project (World) (Aftermarket) (Unl).gb" size 1048576 crc 4c707059 sha1 5b823ee17691d286a45f0667cddd59ccaaab5d8b ) -) - game ( name "F1 Boy (Japan)" description "F1 Boy (Japan)" @@ -24342,12 +25402,6 @@ game ( rom ( name "Famista 3 (Japan).gb" size 262144 crc bdc4ccc3 sha1 ac4b03e11e2ba135d0427c8b1da7de57c006b4a6 ) ) -game ( - name "Farm, The (World) (Aftermarket) (Unl)" - description "Farm, The (World) (Aftermarket) (Unl)" - rom ( name "Farm, The (World) (Aftermarket) (Unl).gb" size 524288 crc fbc1b5e8 sha1 d0fe06920f7e771d76507f60881904370ffbc145 ) -) - game ( name "Fastest Lap (USA)" description "Fastest Lap (USA)" @@ -24486,12 +25540,6 @@ game ( rom ( name "Final Reverse (Japan).gb" size 65536 crc e94a6942 sha1 e4b08e702f3b6c575b31dbd62615619126e03af5 ) ) -game ( - name "Finders Keepers (World) (Aftermarket) (Unl)" - description "Finders Keepers (World) (Aftermarket) (Unl)" - rom ( name "Finders Keepers (World) (Aftermarket) (Unl).gb" size 524288 crc 6a98ac61 sha1 e40dd804388df8c08d3890d79eeafd8542cc8805 ) -) - game ( name "Fire Fighter (Europe)" description "Fire Fighter (Europe)" @@ -24511,9 +25559,9 @@ game ( ) game ( - name "Fix My Heart (World) (Aftermarket) (Unl)" - description "Fix My Heart (World) (Aftermarket) (Unl)" - rom ( name "Fix My Heart (World) (Aftermarket) (Unl).gb" size 524288 crc 507f9ea2 sha1 28ad64e379dc60d6e1c2617e073f6361c0feb475 ) + name "Flappy Special (Japan)" + description "Flappy Special (Japan)" + rom ( name "Flappy Special (Japan).gb" size 32768 crc 3b6cdda4 sha1 6517aee7caa2fa60750005ef1dacaeaecee7c2f6 ) ) game ( @@ -24522,24 +25570,12 @@ game ( rom ( name "Flappy Special (USA) (Proto).gb" size 32768 crc 617d0d9f sha1 75347d9f708da85487b779ed79b9c1e84954020d ) ) -game ( - name "Flappy Special (Japan)" - description "Flappy Special (Japan)" - rom ( name "Flappy Special (Japan).gb" size 32768 crc 3b6cdda4 sha1 6517aee7caa2fa60750005ef1dacaeaecee7c2f6 ) -) - game ( name "Flash, The (USA, Europe)" description "Flash, The (USA, Europe)" rom ( name "Flash, The (USA, Europe).gb" size 131072 crc 6deb1f06 sha1 f7e5701e6fa8fe4440988d1207517668c35088c6 ) ) -game ( - name "Flashin' (World) (v3.0) (Aftermarket) (Unl)" - description "Flashin' (World) (v3.0) (Aftermarket) (Unl)" - rom ( name "Flashin' (World) (v3.0) (Aftermarket) (Unl).gb" size 1048576 crc fcc05ec4 sha1 64d31f34e189b3af08bf0c659a93f71dbf83ef71 ) -) - game ( name "Fleet Commander VS. (Japan)" description "Fleet Commander VS. (Japan)" @@ -24576,12 +25612,6 @@ game ( rom ( name "Flipull - An Exciting Cube Game (Japan).gb" size 32768 crc 198f147d sha1 090c88ae19892c35608f4fa844a6e9efcbe23893 ) ) -game ( - name "Flooder (World) (Aftermarket) (Unl)" - description "Flooder (World) (Aftermarket) (Unl)" - rom ( name "Flooder (World) (Aftermarket) (Unl).gb" size 32768 crc 253dcbe0 sha1 8fdcd8b02604ac5259fb6aa80e5ba67a03c861fb ) -) - game ( name "Football International (Europe)" description "Football International (Europe)" @@ -24600,18 +25630,6 @@ game ( rom ( name "Foreman for Real (USA, Europe).gb" size 262144 crc 77083ae0 sha1 7b088c7b3a0ad275d340ca27f64a99c1bd6c34e6 ) ) -game ( - name "Forest of Fallen Knights (World) (Aftermarket) (Unl)" - description "Forest of Fallen Knights (World) (Aftermarket) (Unl)" - rom ( name "Forest of Fallen Knights (World) (Aftermarket) (Unl).gb" size 524288 crc fa2d92a1 sha1 24f02d116aafb7b55d6cfd6d263b7595986af843 ) -) - -game ( - name "Forest of Fallen Knights (World) (Beta) (Aftermarket) (Unl)" - description "Forest of Fallen Knights (World) (Beta) (Aftermarket) (Unl)" - rom ( name "Forest of Fallen Knights (World) (Beta) (Aftermarket) (Unl).gb" size 524288 crc 4c21e563 sha1 f6f84f1a44d41fa7d26a9195ddf791fae53dfcdf ) -) - game ( name "Fortified Zone (USA, Europe)" description "Fortified Zone (USA, Europe)" @@ -24630,12 +25648,6 @@ game ( rom ( name "Franky, Joe & Dirk - On the Tiles (Europe) (En,Fr,De,Es,It,Nl).gb" size 131072 crc caf5b372 sha1 b7e292cfd34d64546f158e548afa92efaf8c2acd ) ) -game ( - name "Friday the 13th - The GB Game (World) (Aftermarket) (Unl)" - description "Friday the 13th - The GB Game (World) (Aftermarket) (Unl)" - rom ( name "Friday the 13th - The GB Game (World) (Aftermarket) (Unl).gb" size 1048576 crc 7543586a sha1 397821751ac6464582f61566f3a7c731a46b24ba ) -) - game ( name "Frisky Tom (Japan) (SGB Enhanced)" description "Frisky Tom (Japan) (SGB Enhanced)" @@ -24690,18 +25702,6 @@ game ( rom ( name "G Arms - Operation Gundam (Japan).gb" size 131072 crc 39058153 sha1 7d8011636fe36266b5f716e78e3e29006f024992 ) ) -game ( - name "G-Man (World) (Aftermarket) (Unl)" - description "G-Man (World) (Aftermarket) (Unl)" - rom ( name "G-Man (World) (Aftermarket) (Unl).gb" size 524288 crc 7296da69 sha1 fdc9933d46a063575c175453b1da8042fd28b135 ) -) - -game ( - name "G-ZERO (World) (v2.6) (Aftermarket) (Unl)" - description "G-ZERO (World) (v2.6) (Aftermarket) (Unl)" - rom ( name "G-ZERO (World) (v2.6) (Aftermarket) (Unl).gb" size 65536 crc 7dd0c878 sha1 929d25a612308614ac3ac2ee5a19a9cd4a9968d6 ) -) - game ( name "Galaga & Galaxian (Japan) (SGB Enhanced)" description "Galaga & Galaxian (Japan) (SGB Enhanced)" @@ -24723,7 +25723,7 @@ game ( game ( name "Game & Watch Gallery (USA) (Rev 1) (SGB Enhanced)" description "Game & Watch Gallery (USA) (Rev 1) (SGB Enhanced)" - rom ( name "Game & Watch Gallery (USA) (Rev 1) (SGB Enhanced).gb" size 262144 crc 9e6cdc96 sha1 4e4da0ed89c2baaed64600f7eaca90aeeadc084e ) + rom ( name "Game & Watch Gallery (USA) (Rev 1) (SGB Enhanced).gb" size 262144 crc 9e6cdc96 sha1 4e4da0ed89c2baaed64600f7eaca90aeeadc084e flags verified ) ) game ( @@ -24738,12 +25738,6 @@ game ( rom ( name "Game Boy Camera (USA, Europe) (SGB Enhanced).gb" size 1048576 crc 4640909f sha1 461c3c37ed270681e3e94053efb21504b600aef5 flags verified ) ) -game ( - name "Game Boy Camera Gallery 2022, The (World) (Aftermarket) (Unl)" - description "Game Boy Camera Gallery 2022, The (World) (Aftermarket) (Unl)" - rom ( name "Game Boy Camera Gallery 2022, The (World) (Aftermarket) (Unl).gb" size 524288 crc f1948966 sha1 14849ab5831c71949ec3a1fe7657050057d2cf29 ) -) - game ( name "Game Boy Camera Gold (USA) (SGB Enhanced)" description "Game Boy Camera Gold (USA) (SGB Enhanced)" @@ -24936,12 +25930,6 @@ game ( rom ( name "GB Basketball (Japan).gb" size 131072 crc d9b24d21 sha1 65f73db2942d400a4c555fbcfd6313f07303d4e4 ) ) -game ( - name "GB Corp. (World) (Aftermarket) (Unl)" - description "GB Corp. (World) (Aftermarket) (Unl)" - rom ( name "GB Corp. (World) (Aftermarket) (Unl).gb" size 32768 crc fd2e40f4 sha1 e442316132506ff223a9e5f33d874b71ec09d71a ) -) - game ( name "GB Genjin (Japan)" description "GB Genjin (Japan)" @@ -24966,66 +25954,6 @@ game ( rom ( name "GB Pachi-Slot Hisshouhou! Jr. (Japan).gb" size 131072 crc a2e210e9 sha1 7636799f5a57d22cf579bb687be5bb9fedddd0ca ) ) -game ( - name "GB-Wordyl (World) (Pt-BR) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (Pt-BR) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (Pt-BR) (Aftermarket) (Unl).gb" size 32768 crc f20c0097 sha1 691af25434a09931a302ced52c757d28b9b06619 ) -) - -game ( - name "GB-Wordyl (World) (Ca) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (Ca) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (Ca) (Aftermarket) (Unl).gb" size 32768 crc 164999eb sha1 197d3d194d4cb6cae9a358f7fb53d6de649e7c5f ) -) - -game ( - name "GB-Wordyl (World) (De) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (De) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (De) (Aftermarket) (Unl).gb" size 32768 crc 60b075d1 sha1 0a66254b2327b48657de64d6102ac05f1e8700e7 ) -) - -game ( - name "GB-Wordyl (World) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (Aftermarket) (Unl).gb" size 32768 crc 8780e125 sha1 7163bfbaa2cae2f9d41c472128f69a4fa5879180 ) -) - -game ( - name "GB-Wordyl (World) (Es) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (Es) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (Es) (Aftermarket) (Unl).gb" size 32768 crc 1a169897 sha1 0636b968e8e24fe7c1910f61db6e94fa84824494 ) -) - -game ( - name "GB-Wordyl (World) (Fr) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (Fr) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (Fr) (Aftermarket) (Unl).gb" size 32768 crc 593965ff sha1 75d566045a680aaed4d40b83b6418cbfab5b4422 ) -) - -game ( - name "GB-Wordyl (World) (It) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (It) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (It) (Aftermarket) (Unl).gb" size 32768 crc d81ab567 sha1 1dfd3c4508ffb6598662bcf1b16ec109a9282dd5 ) -) - -game ( - name "GB-Wordyl (World) (Kw) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (Kw) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (Kw) (Aftermarket) (Unl).gb" size 32768 crc f795689c sha1 9a332127182e8155d1a3dc53e1382a6c9dde6aeb ) -) - -game ( - name "GB-Wordyl (World) (Es-XL) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (Es-XL) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (Es-XL) (Aftermarket) (Unl).gb" size 32768 crc 660ed37b sha1 0792fbef010cac21c12cbcb8b3c85b3af30faec4 ) -) - -game ( - name "GB-Wordyl (World) (Nl) (Aftermarket) (Unl)" - description "GB-Wordyl (World) (Nl) (Aftermarket) (Unl)" - rom ( name "GB-Wordyl (World) (Nl) (Aftermarket) (Unl).gb" size 32768 crc 6dc4faaa sha1 7617083f9b13b2f95bdf1b0b327ffb4f8ccbe3c9 ) -) - game ( name "GBKiss Mini Games (Japan)" description "GBKiss Mini Games (Japan)" @@ -25056,12 +25984,6 @@ game ( rom ( name "Gem Gem (Japan).gb" size 65536 crc a64a8710 sha1 90a29d7a56f64b596cda1c64c8998b63d12c321e ) ) -game ( - name "Genesis (World) (Aftermarket) (Unl)" - description "Genesis (World) (Aftermarket) (Unl)" - rom ( name "Genesis (World) (Aftermarket) (Unl).gb" size 65536 crc 74b3ec78 sha1 ca43f82d73ba0b3e43ec17f6bc6761c09ca23626 ) -) - game ( name "Genjin Collection (Japan) (SGB Enhanced)" description "Genjin Collection (Japan) (SGB Enhanced)" @@ -25098,12 +26020,6 @@ game ( rom ( name "Getaway, The - High Speed II (USA).gb" size 262144 crc 8f2bf517 sha1 a0ca7187b55135150f348d44544d3a6e6d51394e ) ) -game ( - name "Ghost Town (World) (Aftermarket) (Unl)" - description "Ghost Town (World) (Aftermarket) (Unl)" - rom ( name "Ghost Town (World) (Aftermarket) (Unl).gb" size 262144 crc 2d27cdf2 sha1 af526273cdaa6423b92d0484fb27af56fe355a5d ) -) - game ( name "Ghostbusters II (USA, Europe) (Beta)" description "Ghostbusters II (USA, Europe) (Beta)" @@ -25219,9 +26135,9 @@ game ( ) game ( - name "Gorf the Ghost Saves Halloween (World) (Aftermarket) (Unl)" - description "Gorf the Ghost Saves Halloween (World) (Aftermarket) (Unl)" - rom ( name "Gorf the Ghost Saves Halloween (World) (Aftermarket) (Unl).gb" size 262144 crc ab10cec6 sha1 9dcaa6824fab806683737bdf1c76609c68c451a5 ) + name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Joushiki no Sho (Japan) (Imagineer)" + description "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Joushiki no Sho (Japan) (Imagineer)" + rom ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Joushiki no Sho (Japan) (Imagineer).gb" size 1048576 crc 5d43a385 sha1 d367f2dab5eacb10e785a13a2550ca7cc3e54177 ) ) game ( @@ -25231,9 +26147,9 @@ game ( ) game ( - name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Joushiki no Sho (Japan) (Imagineer)" - description "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Joushiki no Sho (Japan) (Imagineer)" - rom ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Joushiki no Sho (Japan) (Imagineer).gb" size 1048576 crc 5d43a385 sha1 d367f2dab5eacb10e785a13a2550ca7cc3e54177 ) + name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Kanji no Tatsujin (Japan) (IE Institute)" + description "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Kanji no Tatsujin (Japan) (IE Institute)" + rom ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Kanji no Tatsujin (Japan) (IE Institute).gb" size 1048576 crc 180d54a7 sha1 7dce0adcbac61f0caae33646847fd06ced8c8b67 ) ) game ( @@ -25243,9 +26159,9 @@ game ( ) game ( - name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Kanji no Tatsujin (Japan) (IE Institute)" - description "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Kanji no Tatsujin (Japan) (IE Institute)" - rom ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Kanji no Tatsujin (Japan) (IE Institute).gb" size 1048576 crc 180d54a7 sha1 7dce0adcbac61f0caae33646847fd06ced8c8b67 ) + name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Keisan no Tatsujin (Japan) (Imagineer)" + description "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Keisan no Tatsujin (Japan) (Imagineer)" + rom ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Keisan no Tatsujin (Japan) (Imagineer).gb" size 1048576 crc 71acbb67 sha1 e2ac91493248869aba6b7d26a36e5ff6bd6d6f5a flags verified ) ) game ( @@ -25255,9 +26171,9 @@ game ( ) game ( - name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Keisan no Tatsujin (Japan) (Imagineer)" - description "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Keisan no Tatsujin (Japan) (Imagineer)" - rom ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Keisan no Tatsujin (Japan) (Imagineer).gb" size 1048576 crc 71acbb67 sha1 e2ac91493248869aba6b7d26a36e5ff6bd6d6f5a flags verified ) + name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Nanmon no Sho (Japan) (Proto) (IE Institute)" + description "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Nanmon no Sho (Japan) (Proto) (IE Institute)" + rom ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Nanmon no Sho (Japan) (Proto) (IE Institute).gb" size 1048576 crc 91ab959f sha1 2e1797646b2d3aa6fc9b2f5eaa248751133a0518 ) ) game ( @@ -25266,12 +26182,6 @@ game ( rom ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Nanmon no Sho (Japan) (Imagineer).gb" size 1048576 crc 3c907f2c sha1 fa7a40acd835676fbcae9507a8aaaf1191f9b1cd ) ) -game ( - name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Nanmon no Sho (Japan) (Proto) (IE Institute)" - description "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Nanmon no Sho (Japan) (Proto) (IE Institute)" - rom ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Nanmon no Sho (Japan) (Proto) (IE Institute).gb" size 1048576 crc 91ab959f sha1 2e1797646b2d3aa6fc9b2f5eaa248751133a0518 ) -) - game ( name "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Zukei no Tatsujin (Japan)" description "Goukaku Boy GOLD - Shikakui Atama o Maruku Suru - Zukei no Tatsujin (Japan)" @@ -25506,24 +26416,6 @@ game ( rom ( name "Gremlins 2 - The New Batch (World).gb" size 131072 crc 3579e297 sha1 0cb722d9d4e349bea1b1afa85d8d3b93f2dc2aad flags verified ) ) -game ( - name "Gun Law (World) (Aftermarket) (Unl)" - description "Gun Law (World) (Aftermarket) (Unl)" - rom ( name "Gun Law (World) (Aftermarket) (Unl).gb" size 262144 crc b0d53211 sha1 ef6e3d287e99bd61861a333165c92b306238a45f ) -) - -game ( - name "Gunman Clive (World) (Aftermarket) (Unl)" - description "Gunman Clive (World) (Aftermarket) (Unl)" - rom ( name "Gunman Clive (World) (Aftermarket) (Unl).gb" size 65536 crc 11f5fded sha1 ec03763db2c0d754e2eb7e98384ed92fc8aeeb1d ) -) - -game ( - name "Gunship (USA) (Aftermarket) (Unl)" - description "Gunship (USA) (Aftermarket) (Unl)" - rom ( name "Gunship (USA) (Aftermarket) (Unl).gb" size 131072 crc bd31eef8 sha1 a801977c3746799cfb4d8bdfd679e45cccd3b719 ) -) - game ( name "HAL Wrestling (USA)" description "HAL Wrestling (USA)" @@ -25548,12 +26440,6 @@ game ( rom ( name "Hammerin' Harry - Ghost Building Company (USA) (Proto).gb" size 262144 crc 6c4d0377 sha1 c5f73b09f001fc4d7eaa40ffee00234ca6a41a41 ) ) -game ( - name "Harbour Attack (World) (Aftermarket) (Unl)" - description "Harbour Attack (World) (Aftermarket) (Unl)" - rom ( name "Harbour Attack (World) (Aftermarket) (Unl).gb" size 262144 crc 4018ebf7 sha1 5bbbe727ebc6a489f1a498d067e4f05d0d69b60f ) -) - game ( name "Harvest Moon GB (USA) (SGB Enhanced)" description "Harvest Moon GB (USA) (SGB Enhanced)" @@ -25566,12 +26452,6 @@ game ( rom ( name "Hatris (Japan, USA) (En).gb" size 65536 crc 7635f28b sha1 e8002f226e90ed52e1675c003d3c8ce804b56b0e ) ) -game ( - name "Hauntsfield (World) (Aftermarket) (Unl)" - description "Hauntsfield (World) (Aftermarket) (Unl)" - rom ( name "Hauntsfield (World) (Aftermarket) (Unl).gb" size 1048576 crc 287afc75 sha1 42ccc76883c041bc5c6c25a2e61ccc939c14811f ) -) - game ( name "Hayaoshi Quiz - Ouza Ketteisen (Japan) (SGB Enhanced)" description "Hayaoshi Quiz - Ouza Ketteisen (Japan) (SGB Enhanced)" @@ -25584,12 +26464,6 @@ game ( rom ( name "Head On (Japan).gb" size 65536 crc 78830daf sha1 76261091adb7def20a4f76aa6c062c60c6d9761c ) ) -game ( - name "Heart Knight (World) (Aftermarket) (Unl)" - description "Heart Knight (World) (Aftermarket) (Unl)" - rom ( name "Heart Knight (World) (Aftermarket) (Unl).gb" size 32768 crc c7ecac73 sha1 dedcab41f58c58834e3534e877c494669a0d8952 ) -) - game ( name "Heavyweight Championship Boxing (USA)" description "Heavyweight Championship Boxing (USA)" @@ -25806,12 +26680,6 @@ game ( rom ( name "Hugo (Europe) (SGB Enhanced).gb" size 131072 crc 74aa5e0f sha1 d314dffcf5fb441d5d6d6419e01dc825e90cf0fc flags verified ) ) -game ( - name "Hugo (World) (Aftermarket) (Unl)" - description "Hugo (World) (Aftermarket) (Unl)" - rom ( name "Hugo (World) (Aftermarket) (Unl).gb" size 262144 crc 8cc87f60 sha1 53fac2774b29a32501788e1eac65db23bf5c7b8f ) -) - game ( name "Hugo 2 (Germany)" description "Hugo 2 (Germany)" @@ -25830,6 +26698,12 @@ game ( rom ( name "Humans, The (USA).gb" size 262144 crc 1df2e81d sha1 39b7f8f6abb213bb5727379b864106ca2947fe6f ) ) +game ( + name "Humans, The (USA) (QUByte Classics)" + description "Humans, The (USA) (QUByte Classics)" + rom ( name "Humans, The (USA) (QUByte Classics).gb" size 262144 crc 4580ec88 sha1 669f4645b426400a4853793c7070c53642f71556 ) +) + game ( name "Hunchback of Notre Dame, The - 5 Foolishly Fun Topsy Turvy Games (USA, Europe) (SGB Enhanced)" description "Hunchback of Notre Dame, The - 5 Foolishly Fun Topsy Turvy Games (USA, Europe) (SGB Enhanced)" @@ -25872,12 +26746,6 @@ game ( rom ( name "Hyper Lode Runner (Japan) (En) (Possible Proto).gb" size 32768 crc 3fc21b74 sha1 37d0f2cbac0f95af8b22dea0c882612681ec5cc8 ) ) -game ( - name "If (World) (Aftermarket) (Unl)" - description "If (World) (Aftermarket) (Unl)" - rom ( name "If (World) (Aftermarket) (Unl).gb" size 1048576 crc be7e4454 sha1 c11d8dc9ce96133f679678b07822a82f985e16f9 ) -) - game ( name "Ikari no Yousai (Japan)" description "Ikari no Yousai (Japan)" @@ -25890,12 +26758,6 @@ game ( rom ( name "Ikari no Yousai 2 (Japan).gb" size 131072 crc 6d4fd9aa sha1 ae437d4fb39d7438fc9eb98c91820aa2b5161b4f ) ) -game ( - name "In the Dark (World) (Aftermarket) (Unl)" - description "In the Dark (World) (Aftermarket) (Unl)" - rom ( name "In the Dark (World) (Aftermarket) (Unl).gb" size 1048576 crc 89ac8948 sha1 dfed92c906d9fd4e4ee405453ee391e0e9b174bf ) -) - game ( name "In Your Face (USA)" description "In Your Face (USA)" @@ -25908,12 +26770,6 @@ game ( rom ( name "Incredible Crash Dummies, The (USA, Europe).gb" size 131072 crc d81c08fa sha1 f62d369b576cfd2882f8e03a5a32238eb1599477 ) ) -game ( - name "IndestructoTank! (World) (Aftermarket) (Unl)" - description "IndestructoTank! (World) (Aftermarket) (Unl)" - rom ( name "IndestructoTank! (World) (Aftermarket) (Unl).gb" size 32768 crc aa176926 sha1 e70992f8598c489bd34c30bd3a4c3789dddb8057 ) -) - game ( name "Indiana Jones - Saigo no Seisen (Japan)" description "Indiana Jones - Saigo no Seisen (Japan)" @@ -25986,12 +26842,6 @@ game ( rom ( name "Initial D Gaiden (Japan) (SGB Enhanced).gb" size 262144 crc 6cc56612 sha1 1b3c4c1c4dfca46a009eb2e5cd45b343d7ee6681 ) ) -game ( - name "Interblocked (World) (Aftermarket) (Unl)" - description "Interblocked (World) (Aftermarket) (Unl)" - rom ( name "Interblocked (World) (Aftermarket) (Unl).gb" size 262144 crc 5c208855 sha1 8e46486533a3de9ee87cc07bf8efaf818752a61a ) -) - game ( name "International Superstar Soccer (USA, Europe) (SGB Enhanced)" description "International Superstar Soccer (USA, Europe) (SGB Enhanced)" @@ -26058,12 +26908,6 @@ game ( rom ( name "J.League Winning Goal (Japan).gb" size 131072 crc adb46f9c sha1 b8630f06e8b9682e667b7b1f2139162e2f022561 ) ) -game ( - name "Jabberwocky (World) (Aftermarket) (Unl)" - description "Jabberwocky (World) (Aftermarket) (Unl)" - rom ( name "Jabberwocky (World) (Aftermarket) (Unl).gb" size 1048576 crc cfc51717 sha1 b4e447f2197688c740a45dce27879a62c742fb96 ) -) - game ( name "Jack Nicklaus Golf (France)" description "Jack Nicklaus Golf (France)" @@ -26088,12 +26932,6 @@ game ( rom ( name "James Bond 007 (USA, Europe) (SGB Enhanced).gb" size 524288 crc ca3bc3ce sha1 e03754173a5d62cb9da7d2306bc41b0e23e3d519 flags verified ) ) -game ( - name "Jane in the Jungle (World) (Aftermarket) (Unl)" - description "Jane in the Jungle (World) (Aftermarket) (Unl)" - rom ( name "Jane in the Jungle (World) (Aftermarket) (Unl).gb" size 262144 crc c68e751a sha1 dfc65dcf700a26b273d705b7cfececbc44b80587 ) -) - game ( name "Jankenman (Japan)" description "Jankenman (Japan)" @@ -26178,12 +27016,6 @@ game ( rom ( name "Jet Pak Man (Europe) (Proto).gb" size 32768 crc e40dfc1b sha1 0080f76961164810d6c0543d951a465cfa1cab54 ) ) -game ( - name "Jet Set Willy (World) (Aftermarket) (Unl)" - description "Jet Set Willy (World) (Aftermarket) (Unl)" - rom ( name "Jet Set Willy (World) (Aftermarket) (Unl).gb" size 262144 crc 1686d7ed sha1 0e594224506fd087e36c66bb66905d4c91b02461 ) -) - game ( name "Jetsons, The - Robot Panic (USA, Europe)" description "Jetsons, The - Robot Panic (USA, Europe)" @@ -26191,9 +27023,9 @@ game ( ) game ( - name "Jetsons, The - Robot Panic (USA) (Rev 1) (Possible Proto)" - description "Jetsons, The - Robot Panic (USA) (Rev 1) (Possible Proto)" - rom ( name "Jetsons, The - Robot Panic (USA) (Rev 1) (Possible Proto).gb" size 131072 crc cc38cf0d sha1 38b5ec2c74316696b7731cd88e56be4519084168 ) + name "Jetsons, The - Robot Panic (USA, Europe) (Rev 1)" + description "Jetsons, The - Robot Panic (USA, Europe) (Rev 1)" + rom ( name "Jetsons, The - Robot Panic (USA, Europe) (Rev 1).gb" size 131072 crc cc38cf0d sha1 38b5ec2c74316696b7731cd88e56be4519084168 ) ) game ( @@ -26226,6 +27058,12 @@ game ( rom ( name "Jimmy Connors Tennis (USA, Europe) (Beta).gb" size 131072 crc eb50caf2 sha1 4ca04a3270e217d54d8c5fa7a254fdbcb48c5b87 ) ) +game ( + name "Jimmy Connors Tennis (USA, Europe) (1993-03-19) (Beta)" + description "Jimmy Connors Tennis (USA, Europe) (1993-03-19) (Beta)" + rom ( name "Jimmy Connors Tennis (USA, Europe) (1993-03-19) (Beta).gb" size 65536 crc 4ee3e02e sha1 06c9018f7943362f8b9571486b6412de11672718 ) +) + game ( name "Jinsei Game (Japan) (SGB Enhanced)" description "Jinsei Game (Japan) (SGB Enhanced)" @@ -26256,12 +27094,6 @@ game ( rom ( name "Joe & Mac - Caveman Ninja (Europe) (En,Fr,De,Es,It,Nl,Sv) (Beta).gb" size 262144 crc 381c62ee sha1 979e36765291153b82025b1f036c08fe9c23cfa5 ) ) -game ( - name "Joe Blade 2 (World) (Aftermarket) (Unl)" - description "Joe Blade 2 (World) (Aftermarket) (Unl)" - rom ( name "Joe Blade 2 (World) (Aftermarket) (Unl).gb" size 524288 crc 09f75c70 sha1 f001dffcd16be670c36a98dd9136f6f9fbf5b85d ) -) - game ( name "John Madden Football (USA) (Proto 2) (SGB Enhanced)" description "John Madden Football (USA) (Proto 2) (SGB Enhanced)" @@ -26478,12 +27310,6 @@ game ( rom ( name "Kenyuu Densetsu Yaiba (Japan).gb" size 262144 crc cc19768e sha1 c2b71ceee21f66f462df18233f7622d8ec95fcca ) ) -game ( - name "Kenzie's Birthday Dash (World) (Aftermarket) (Unl)" - description "Kenzie's Birthday Dash (World) (Aftermarket) (Unl)" - rom ( name "Kenzie's Birthday Dash (World) (Aftermarket) (Unl).gb" size 1048576 crc 986bfd75 sha1 6d15b5bc33d7c7771ba62d56ae7f25fa081bc564 ) -) - game ( name "Kick Attack (Japan) (Proto)" description "Kick Attack (Japan) (Proto)" @@ -26838,24 +27664,12 @@ game ( rom ( name "Lasama Chuanqi - Story of Lasama (Taiwan) (Unl) (Alt).gb" size 65536 crc 997fa9eb sha1 ded742d50ed553ffea524d7deec628c354c74cc4 ) ) -game ( - name "Laser Squad Alter (World) (Aftermarket) (Unl)" - description "Laser Squad Alter (World) (Aftermarket) (Unl)" - rom ( name "Laser Squad Alter (World) (Aftermarket) (Unl).gb" size 1048576 crc a39b3a5a sha1 1620e585e77a2457cffde82453bec0c7a04e07cf ) -) - game ( name "Last Action Hero (USA, Europe)" description "Last Action Hero (USA, Europe)" rom ( name "Last Action Hero (USA, Europe).gb" size 131072 crc 10499af6 sha1 010eb2cbab987ec242cd0792c789a07c00106f48 ) ) -game ( - name "Lawn Mower Land (World) (Aftermarket) (Unl)" - description "Lawn Mower Land (World) (Aftermarket) (Unl)" - rom ( name "Lawn Mower Land (World) (Aftermarket) (Unl).gb" size 32768 crc 11c62e39 sha1 1d6aa817ebf2a7e5d22285b906540272b67169da ) -) - game ( name "Lawnmower Man, The (USA) (Proto 1) (1993-10-11) (Not For Resale)" description "Lawnmower Man, The (USA) (Proto 1) (1993-10-11) (Not For Resale)" @@ -26880,12 +27694,6 @@ game ( rom ( name "Lazlos' Leap (USA).gb" size 65536 crc 31fb404b sha1 c111470fcdadf191cf843e50c8f3d3dbb995a5c5 ) ) -game ( - name "Leak, The (World) (Aftermarket) (Unl)" - description "Leak, The (World) (Aftermarket) (Unl)" - rom ( name "Leak, The (World) (Aftermarket) (Unl).GB" size 65536 crc ba3cfeae sha1 98de2d8be75e6d9cb4e87afe14b1380c033de797 ) -) - game ( name "Learn and Play - Blackjack & Solitaire (USA) (1994-08-09) (Proto)" description "Learn and Play - Blackjack & Solitaire (USA) (1994-08-09) (Proto)" @@ -26916,6 +27724,12 @@ game ( rom ( name "Legend of the River King GB (Australia) (SGB Enhanced).gb" size 524288 crc 51627213 sha1 87274e8c0d2daaac2e0dda94651c35d6a0617c0f ) ) +game ( + name "Legend of the Sea King GB (USA) (Proto) (SGB Enhanced)" + description "Legend of the Sea King GB (USA) (Proto) (SGB Enhanced)" + rom ( name "Legend of the Sea King GB (USA) (Proto) (SGB Enhanced).gb" size 1048576 crc a45ef889 sha1 26bebc2394b5da850be55e409b9efcb4d2d29d87 ) +) + game ( name "Legend of Zelda, The - Link's Awakening (Canada) (Fr)" description "Legend of Zelda, The - Link's Awakening (Canada) (Fr)" @@ -26952,6 +27766,18 @@ game ( rom ( name "Legend of Zelda, The - Link's Awakening (USA, Europe) (Rev 2).gb" size 524288 crc 34d08e7b sha1 5ab63def958728933571c3b4f6af54db14f3f8b2 flags verified ) ) +game ( + name "Legend of Zelda, The - Link's Awakening DX (France) (Proto) (1998-11-17)" + description "Legend of Zelda, The - Link's Awakening DX (France) (Proto) (1998-11-17)" + rom ( name "Legend of Zelda, The - Link's Awakening DX (France) (Proto) (1998-11-17).gb" size 524288 crc bfa800c0 sha1 3d48bcec56bf202d3362ba3e5e20233f996492c5 ) +) + +game ( + name "Legend of Zelda, The - Link's Awakening DX (USA, Europe) (Proto) (1998-11-08)" + description "Legend of Zelda, The - Link's Awakening DX (USA, Europe) (Proto) (1998-11-08)" + rom ( name "Legend of Zelda, The - Link's Awakening DX (USA, Europe) (Proto) (1998-11-08).gb" size 524288 crc d8ba6631 sha1 9d6da903a5481aadfb20d75954bd01917497a38d ) +) + game ( name "Legend of Zelda, The - Link's Awakening DX (Germany) (Proto) (1998-11-16)" description "Legend of Zelda, The - Link's Awakening DX (Germany) (Proto) (1998-11-16)" @@ -26991,13 +27817,7 @@ game ( game ( name "Lemmings 2 - The Tribes (Europe)" description "Lemmings 2 - The Tribes (Europe)" - rom ( name "Lemmings 2 - The Tribes (Europe).gb" size 524288 crc 9800bd49 sha1 76ccf9ac82faebc7f9c4a4c8b5cd47ddea46c486 ) -) - -game ( - name "Lethal Weapon (USA, Europe)" - description "Lethal Weapon (USA, Europe)" - rom ( name "Lethal Weapon (USA, Europe).gb" size 131072 crc 1f8d207c sha1 8b4621471b376a6262fbed70c1191416ab3be915 ) + rom ( name "Lemmings 2 - The Tribes (Europe).gb" size 524288 crc 9800bd49 sha1 76ccf9ac82faebc7f9c4a4c8b5cd47ddea46c486 flags verified ) ) game ( @@ -27006,6 +27826,12 @@ game ( rom ( name "Lethal Weapon (USA, Europe) (Beta).gb" size 131072 crc d585ab23 sha1 2221ba322acffc9d7ae5400752e16d0455fda3ef ) ) +game ( + name "Lethal Weapon (USA, Europe)" + description "Lethal Weapon (USA, Europe)" + rom ( name "Lethal Weapon (USA, Europe).gb" size 131072 crc 1f8d207c sha1 8b4621471b376a6262fbed70c1191416ab3be915 ) +) + game ( name "Lingo (Europe) (En,Fr,De,Nl)" description "Lingo (Europe) (En,Fr,De,Nl)" @@ -27067,9 +27893,9 @@ game ( ) game ( - name "Lock n' Chase ~ Lock 'n' Chase (World)" - description "Lock n' Chase ~ Lock 'n' Chase (World)" - rom ( name "Lock n' Chase ~ Lock 'n' Chase (World).gb" size 65536 crc dab91c7a sha1 643cbd566d35ce8dbe0f24627e4862c09805a04c flags verified ) + name "Lock n' Chase (World)" + description "Lock n' Chase (World)" + rom ( name "Lock n' Chase (World).gb" size 65536 crc dab91c7a sha1 643cbd566d35ce8dbe0f24627e4862c09805a04c flags verified ) ) game ( @@ -27144,12 +27970,6 @@ game ( rom ( name "Lucle (Japan, Europe) (En).gb" size 524288 crc a3d5c8d7 sha1 2fef16fac95ec4ffd252e9974eccfce538e5f797 ) ) -game ( - name "Lucy and the Gem Dungeon (World) (Aftermarket) (Unl)" - description "Lucy and the Gem Dungeon (World) (Aftermarket) (Unl)" - rom ( name "Lucy and the Gem Dungeon (World) (Aftermarket) (Unl).gb" size 524288 crc 1a5106a2 sha1 f56c1b324b8c1e17da86e40c5e9a887ec19b0c80 ) -) - game ( name "Lunar Chase (USA) (Proto 1)" description "Lunar Chase (USA) (Proto 1)" @@ -27174,12 +27994,6 @@ game ( rom ( name "Mach Go Go Go (Japan) (SGB Enhanced).gb" size 262144 crc 016d230b sha1 baea8b49ce2402c5c094ddae0320a382c0d95d86 ) ) -game ( - name "Machine, The (World) (Aftermarket) (Unl)" - description "Machine, The (World) (Aftermarket) (Unl)" - rom ( name "Machine, The (World) (Aftermarket) (Unl).gb" size 2097152 crc b06036a9 sha1 50c5d1eb7c8946ac2d7e2c566b1ea4a9b0d58e90 ) -) - game ( name "Madden 95 (USA, Europe) (SGB Enhanced)" description "Madden 95 (USA, Europe) (SGB Enhanced)" @@ -27228,18 +28042,6 @@ game ( rom ( name "Magical Taruruuto-kun 2 - Raibaa Zone Panic!! (Japan).gb" size 131072 crc 0aad5217 sha1 3be6c6b8cec80a0fe0f6edbbe40496f4d077c750 ) ) -game ( - name "Magipanels (World) (2022-02-09) (Demo) (Aftermarket) (Unl)" - description "Magipanels (World) (2022-02-09) (Demo) (Aftermarket) (Unl)" - rom ( name "Magipanels (World) (2022-02-09) (Demo) (Aftermarket) (Unl).gb" size 131072 crc 76fcbc30 sha1 7a759372bd013dcdb59c9131a2908085fc04d648 ) -) - -game ( - name "Magipanels (World) (Aftermarket) (Unl)" - description "Magipanels (World) (Aftermarket) (Unl)" - rom ( name "Magipanels (World) (Aftermarket) (Unl).gb" size 131072 crc 0b66561b sha1 c9513f6769098f2185f632f87386788f0f0b6ad8 ) -) - game ( name "Magnetic Soccer (Europe)" description "Magnetic Soccer (Europe)" @@ -27276,12 +28078,6 @@ game ( rom ( name "Makaimura Gaiden - The Demon Darkness (Japan).gb" size 262144 crc cfa358de sha1 961d05e91288d7ad1f2e6a1c996059d7ab96fe98 ) ) -game ( - name "Make Way (World) (Aftermarket) (Unl)" - description "Make Way (World) (Aftermarket) (Unl)" - rom ( name "Make Way (World) (Aftermarket) (Unl).gb" size 1048576 crc edeee5a8 sha1 19fd02e9318ed81ec968a2fca31ea0c3d8d94a7b ) -) - game ( name "Malibu Beach Volleyball (USA)" description "Malibu Beach Volleyball (USA)" @@ -27348,12 +28144,6 @@ game ( rom ( name "Marmalade Boy (Japan) (SGB Enhanced).gb" size 262144 crc 0f3ff7da sha1 60125690b7a354ff8e72f497c8a88ecd691e7e4b ) ) -game ( - name "Marron Helps a Friend (World) (Aftermarket) (Unl)" - description "Marron Helps a Friend (World) (Aftermarket) (Unl)" - rom ( name "Marron Helps a Friend (World) (Aftermarket) (Unl).gb" size 1048576 crc 08a3a987 sha1 adcd56fa3eba93edd20be25ae5cb349070cd0323 flags verified ) -) - game ( name "Maru's Mission (USA)" description "Maru's Mission (USA)" @@ -27558,12 +28348,6 @@ game ( rom ( name "Meitantei Conan - Giwaku no Gouka Ressha (Japan) (SGB Enhanced).gb" size 262144 crc 1dc5c31a sha1 125db863bad5d48033d0bf94ed808b2b8d34ca2f ) ) -game ( - name "Melanie and the Magic Forest (World) (Aftermarket) (Unl)" - description "Melanie and the Magic Forest (World) (Aftermarket) (Unl)" - rom ( name "Melanie and the Magic Forest (World) (Aftermarket) (Unl).gb" size 262144 crc f614bdff sha1 7e46c193f6566f620acf20ead3a1fca1d677c221 ) -) - game ( name "Mercenary Force (USA, Europe)" description "Mercenary Force (USA, Europe)" @@ -27583,9 +28367,9 @@ game ( ) game ( - name "Meteorite (World) (Aftermarket) (Unl)" - description "Meteorite (World) (Aftermarket) (Unl)" - rom ( name "Meteorite (World) (Aftermarket) (Unl).gb" size 262144 crc 50cf593d sha1 0e88a47faf3273f87c1ead7f789faeb06d5333f3 ) + name "Metal Masters (World) (Limited Run Games)" + description "Metal Masters (World) (Limited Run Games)" + rom ( name "Metal Masters (World) (Limited Run Games).gb" size 131072 crc 7de862fa sha1 9d4896a198904365ebc348c557b7c15f87b5e3c5 ) ) game ( @@ -27709,9 +28493,9 @@ game ( ) game ( - name "Midterm Moments (World) (Aftermarket) (Unl)" - description "Midterm Moments (World) (Aftermarket) (Unl)" - rom ( name "Midterm Moments (World) (Aftermarket) (Unl).gb" size 262144 crc f9a5ed4e sha1 8b3e18287d5adf3b5a711e28a896f843927f22a2 ) + name "Mighty Morphin Power Rangers (USA, Europe) (SGB Enhanced)" + description "Mighty Morphin Power Rangers (USA, Europe) (SGB Enhanced)" + rom ( name "Mighty Morphin Power Rangers (USA, Europe) (SGB Enhanced).gb" size 262144 crc c60d032a sha1 ef88476d9a1a26b67f3535ae7afcf5156578e38c flags verified ) ) game ( @@ -27720,12 +28504,6 @@ game ( rom ( name "Mighty Morphin Power Rangers (USA, Europe) (Beta) (SGB Enhanced).gb" size 262144 crc caab9ac9 sha1 be42f45d8038ce28461ed36ba9164854632aebe0 ) ) -game ( - name "Mighty Morphin Power Rangers (USA, Europe) (SGB Enhanced)" - description "Mighty Morphin Power Rangers (USA, Europe) (SGB Enhanced)" - rom ( name "Mighty Morphin Power Rangers (USA, Europe) (SGB Enhanced).gb" size 262144 crc c60d032a sha1 ef88476d9a1a26b67f3535ae7afcf5156578e38c flags verified ) -) - game ( name "Mighty Morphin Power Rangers - The Movie (USA, Europe) (SGB Enhanced)" description "Mighty Morphin Power Rangers - The Movie (USA, Europe) (SGB Enhanced)" @@ -27816,6 +28594,138 @@ game ( rom ( name "Mini-Putt (Japan).gb" size 65536 crc 33cd7550 sha1 e2a75fc09d8f9e56325449ca91cda9a68d058c1f ) ) +game ( + name "Minolta 2085 Adj. Program (USA) (Unl)" + description "Minolta 2085 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2085 Adj. Program (USA) (Unl).gb" size 32768 crc de660a82 sha1 d0e586988108b7238bebcac055cb7c6982abf81c ) +) + +game ( + name "Minolta 2097 Adj. Program (USA) (Unl)" + description "Minolta 2097 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2097 Adj. Program (USA) (Unl).gb" size 32768 crc 0a9ab6e7 sha1 68968d1b1fc84b2381159c0938675d2048c57ee2 flags verified ) +) + +game ( + name "Minolta 2098 Adj. Program (USA) (Unl)" + description "Minolta 2098 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2098 Adj. Program (USA) (Unl).gb" size 32768 crc 1b7eb836 sha1 dc0f429cc1eac8dd9009a9b30dab0803099be646 ) +) + +game ( + name "Minolta 2156 Adj. Program (USA) (Unl)" + description "Minolta 2156 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2156 Adj. Program (USA) (Unl).gb" size 32768 crc 3af37d46 sha1 c4b46446553bf6c25e3b3c1d5cd450a205ff6692 ) +) + +game ( + name "Minolta 2162 Adj. Program (USA) (Unl)" + description "Minolta 2162 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2162 Adj. Program (USA) (Unl).gb" size 32768 crc 54a6aec4 sha1 58202d2f8f823c52c09275df3fa63b4b2a630bdc ) +) + +game ( + name "Minolta 2162 Adj. Program (USA) (Unl) (Alt)" + description "Minolta 2162 Adj. Program (USA) (Unl) (Alt)" + rom ( name "Minolta 2162 Adj. Program (USA) (Unl) (Alt).gb" size 32768 crc 74ecd4bf sha1 6e0121c4cb9cb82ca7ee1004f90f9954f062d927 ) +) + +game ( + name "Minolta 2166 Adj. Program (USA) (Unl)" + description "Minolta 2166 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2166 Adj. Program (USA) (Unl).gb" size 32768 crc 711179d9 sha1 dd48d1cb7218bda09d59247f4b0eb6832a611e51 ) +) + +game ( + name "Minolta 2181 Adj. Program (USA) (Unl)" + description "Minolta 2181 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2181 Adj. Program (USA) (Unl).gb" size 32768 crc ac64f965 sha1 14d85a2943a2caedb559ccd48f3c3536b7c54a18 ) +) + +game ( + name "Minolta 2205 Adj. Program (USA) (Unl)" + description "Minolta 2205 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2205 Adj. Program (USA) (Unl).gb" size 32768 crc d70cc276 sha1 48a417f53bb7852d7278f37b4a75c8da695db5d6 ) +) + +game ( + name "Minolta 2419 Adj. Program (USA) (Unl)" + description "Minolta 2419 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2419 Adj. Program (USA) (Unl).gb" size 32768 crc f9373901 sha1 c4fdbdc3a2b7cdd4b494ece7f81d88f5d7564c3d ) +) + +game ( + name "Minolta 2420 Adj. Program (USA) (Unl)" + description "Minolta 2420 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2420 Adj. Program (USA) (Unl).gb" size 32768 crc 5bd13f4f sha1 b5994db5e190bef18bb7f3d1c25f8b14ef4b9b22 ) +) + +game ( + name "Minolta 2420 Adj. Program2 (USA) (Unl)" + description "Minolta 2420 Adj. Program2 (USA) (Unl)" + rom ( name "Minolta 2420 Adj. Program2 (USA) (Unl).gb" size 32768 crc 97561d80 sha1 a55a5fd97ca1be3fa129f744f81fc972e29418ac ) +) + +game ( + name "Minolta 2428 Adj. Program (USA) (Unl)" + description "Minolta 2428 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2428 Adj. Program (USA) (Unl).gb" size 32768 crc 4abf7bd2 sha1 6192d29c564441ca2b42a06ef15cc6f56e90f90f ) +) + +game ( + name "Minolta 2429 Adj. Program (USA) (Unl)" + description "Minolta 2429 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2429 Adj. Program (USA) (Unl).gb" size 32768 crc e0dc1323 sha1 f3a394cee80a1de435fd3c90e3ca31b0672665f9 ) +) + +game ( + name "Minolta 2440 Adj. Program (USA) (Unl) (Alt)" + description "Minolta 2440 Adj. Program (USA) (Unl) (Alt)" + rom ( name "Minolta 2440 Adj. Program (USA) (Unl) (Alt).gb" size 32768 crc 37c305dc sha1 494b8392c67a6e91ccf198b82b8f9e515dd7e02a ) +) + +game ( + name "Minolta 2440 Adj. Program (USA) (Unl)" + description "Minolta 2440 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2440 Adj. Program (USA) (Unl).gb" size 32768 crc 7a9359ea sha1 c15325e2e0ad2c8bd4323ef2390df28e578dcdb8 ) +) + +game ( + name "Minolta 2463 Adj. Program (USA) (Unl)" + description "Minolta 2463 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2463 Adj. Program (USA) (Unl).gb" size 32768 crc 7e5429d3 sha1 828f068b0fe5d8c88862f505e982e2cb1568689b ) +) + +game ( + name "Minolta 2468 Adj. Program (USA) (Unl)" + description "Minolta 2468 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2468 Adj. Program (USA) (Unl).gb" size 32768 crc cd622b15 sha1 51480e67f459b966bf2e18ec5092c135557c12d7 ) +) + +game ( + name "Minolta 2472-73 Adj. Program (USA) (Unl)" + description "Minolta 2472-73 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2472-73 Adj. Program (USA) (Unl).gb" size 32768 crc 15493e75 sha1 b242bcf33d46b5642392e526d7466e63f0b6a718 ) +) + +game ( + name "Minolta 2476 Adj. Program (USA) (Unl)" + description "Minolta 2476 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2476 Adj. Program (USA) (Unl).gb" size 32768 crc 6c3501df sha1 2ac3148a2593e062ffd8ed116da4eb749277c434 ) +) + +game ( + name "Minolta 2481 Adj. Program (USA) (Unl)" + description "Minolta 2481 Adj. Program (USA) (Unl)" + rom ( name "Minolta 2481 Adj. Program (USA) (Unl).gb" size 32768 crc 67e5a203 sha1 4d1a3176e4232984a14580382152ce5313a620e6 ) +) + +game ( + name "Minolta SLR Data Copy (USA) (Unl)" + description "Minolta SLR Data Copy (USA) (Unl)" + rom ( name "Minolta SLR Data Copy (USA) (Unl).gb" size 32768 crc 76f0ff74 sha1 a0ada0dd3cdfd1e0908e90cd512fa094f5396e1e ) +) + game ( name "Miracle Adventure of Esparks - Ushinawareta Seiseki Perivron (Japan)" description "Miracle Adventure of Esparks - Ushinawareta Seiseki Perivron (Japan)" @@ -27829,15 +28739,15 @@ game ( ) game ( - name "Mission to Mars (World) (Aftermarket) (Unl)" - description "Mission to Mars (World) (Aftermarket) (Unl)" - rom ( name "Mission to Mars (World) (Aftermarket) (Unl).gb" size 262144 crc cb3a9ab8 sha1 31625a90b61d28ac782909ed8b00b3a48df7742e ) + name "Mofa Qiu - Magic Ball (Taiwan) (Multicart Rip) (Unl)" + description "Mofa Qiu - Magic Ball (Taiwan) (Multicart Rip) (Unl)" + rom ( name "Mofa Qiu - Magic Ball (Taiwan) (Multicart Rip) (Unl).gb" size 131072 crc e2cb3b91 sha1 88ac96eb953d1c273896893c7d8e1597524da4a4 ) ) game ( - name "Mofa Qiu (Taiwan) (Unl)" - description "Mofa Qiu (Taiwan) (Unl)" - rom ( name "Mofa Qiu (Taiwan) (Unl).gb" size 131072 crc e2cb3b91 sha1 88ac96eb953d1c273896893c7d8e1597524da4a4 ) + name "Mofa Qiu - Magic Ball (Taiwan) (Unl)" + description "Mofa Qiu - Magic Ball (Taiwan) (Unl)" + rom ( name "Mofa Qiu - Magic Ball (Taiwan) (Unl).gb" size 65536 crc 38465864 sha1 50c0450b540bb338a71bf626f93005e991929f6e ) ) game ( @@ -27906,12 +28816,6 @@ game ( rom ( name "Momotarou Dentetsu jr. - Zenkoku Ramen Meguri no Maki (Japan) (SGB Enhanced).gb" size 524288 crc 218265b3 sha1 30edf17fc9ddd9db7613c8f78b0ebc340cc89eb0 ) ) -game ( - name "Mona and the Witch's Hat (World) (Aftermarket) (Unl)" - description "Mona and the Witch's Hat (World) (Aftermarket) (Unl)" - rom ( name "Mona and the Witch's Hat (World) (Aftermarket) (Unl).gb" size 65536 crc 32ed7f4a sha1 625d3664d99dee075021b03ea6ff074ae2e49204 ) -) - game ( name "Monde Perdu, Le - Jurassic Park (France) (En) (SGB Enhanced)" description "Monde Perdu, Le - Jurassic Park (France) (En) (SGB Enhanced)" @@ -28002,12 +28906,6 @@ game ( rom ( name "Montezuma's Return! (Europe) (En,Fr,De,Es,It).gb" size 262144 crc e7ac155b sha1 a6b90cc58aeb5b44ef674c503a55a58278b1b6fa flags verified ) ) -game ( - name "Monty on the Run (World) (Aftermarket) (Unl)" - description "Monty on the Run (World) (Aftermarket) (Unl)" - rom ( name "Monty on the Run (World) (Aftermarket) (Unl).gb" size 524288 crc e2ebb406 sha1 41ac5993fbff58be0712b554aae5e4367b68677b ) -) - game ( name "Mortal Kombat (USA, Europe) (Beta)" description "Mortal Kombat (USA, Europe) (Beta)" @@ -28086,12 +28984,6 @@ game ( rom ( name "Motocross Maniacs (Europe) (Rev 1).gb" size 32768 crc f867ee3b sha1 d21f2a4ddb69c408a370b6768f83914c11012c71 ) ) -game ( - name "Mountain Climber (World) (En,Es) (Aftermarket) (Unl)" - description "Mountain Climber (World) (En,Es) (Aftermarket) (Unl)" - rom ( name "Mountain Climber (World) (En,Es) (Aftermarket) (Unl).gb" size 262144 crc 362a84ba sha1 b4b3afa2379a07acab6965ae8fcf6d2ba82d6d7e ) -) - game ( name "Mouse Trap Hotel (USA)" description "Mouse Trap Hotel (USA)" @@ -28140,12 +29032,6 @@ game ( rom ( name "Ms. Pac-Man (USA).gb" size 65536 crc 0e5bb1c4 sha1 fcc05f0625d52ace28d21fd8270e71246229cbad ) ) -game ( - name "Mud Warriors (World) (Aftermarket) (Unl)" - description "Mud Warriors (World) (Aftermarket) (Unl)" - rom ( name "Mud Warriors (World) (Aftermarket) (Unl).gb" size 524288 crc 846afc79 sha1 dae84fbc60839da29878714cd845c3704b915323 ) -) - game ( name "Muhammad Ali Heavyweight Boxing (USA, Europe)" description "Muhammad Ali Heavyweight Boxing (USA, Europe)" @@ -28170,12 +29056,6 @@ game ( rom ( name "MVP Baseball (Japan).gb" size 262144 crc 38c126aa sha1 f0d921d13689d2afe7838eee127bf670439c8d8d ) ) -game ( - name "Mysterium (USA) (Beta)" - description "Mysterium (USA) (Beta)" - rom ( name "Mysterium (USA) (Beta).gb" size 131072 crc 004c1af7 sha1 82e058a7608a04a2837d0d8fe810270f804b43f3 ) -) - game ( name "Mysterium (Japan)" description "Mysterium (Japan)" @@ -28189,21 +29069,9 @@ game ( ) game ( - name "Mystic Quest (Europe)" - description "Mystic Quest (Europe)" - rom ( name "Mystic Quest (Europe).gb" size 262144 crc 57d95c92 sha1 3513310426c6ae88f9beb588f71c666e003273be flags verified ) -) - -game ( - name "Mystic Quest (France)" - description "Mystic Quest (France)" - rom ( name "Mystic Quest (France).gb" size 262144 crc b6e134af sha1 b52d82248849f1ead9bf22954b3cbf7bf8e02907 flags verified ) -) - -game ( - name "Mystic Quest (Germany)" - description "Mystic Quest (Germany)" - rom ( name "Mystic Quest (Germany).gb" size 262144 crc 0351b9a6 sha1 7cb65cb314e3f26b92549ddc7f4fc275186c6170 flags verified ) + name "Mysterium (USA) (Beta)" + description "Mysterium (USA) (Beta)" + rom ( name "Mysterium (USA) (Beta).gb" size 131072 crc 004c1af7 sha1 82e058a7608a04a2837d0d8fe810270f804b43f3 ) ) game ( @@ -28224,6 +29092,24 @@ game ( rom ( name "Mystic Quest (World) (De) (Collection of Mana).gb" size 262144 crc a9d7e152 sha1 69235c3494ea650db3b66d6393264f03f0022194 flags verified ) ) +game ( + name "Mystic Quest (Europe)" + description "Mystic Quest (Europe)" + rom ( name "Mystic Quest (Europe).gb" size 262144 crc 57d95c92 sha1 3513310426c6ae88f9beb588f71c666e003273be flags verified ) +) + +game ( + name "Mystic Quest (France)" + description "Mystic Quest (France)" + rom ( name "Mystic Quest (France).gb" size 262144 crc b6e134af sha1 b52d82248849f1ead9bf22954b3cbf7bf8e02907 flags verified ) +) + +game ( + name "Mystic Quest (Germany)" + description "Mystic Quest (Germany)" + rom ( name "Mystic Quest (Germany).gb" size 262144 crc 0351b9a6 sha1 7cb65cb314e3f26b92549ddc7f4fc275186c6170 flags verified ) +) + game ( name "Mystical Ninja Starring Goemon (Europe) (SGB Enhanced)" description "Mystical Ninja Starring Goemon (Europe) (SGB Enhanced)" @@ -28392,12 +29278,6 @@ game ( rom ( name "Nekketsu! Beach Volley Da yo Kunio-kun (Japan) (SGB Enhanced).gb" size 262144 crc abfb84df sha1 d3ad43c40c21d9825b4879dbf28ca58835da658a ) ) -game ( - name "Neko Can Dream (World) (Ja) (Demo) (Aftermarket) (Unl)" - description "Neko Can Dream (World) (Ja) (Demo) (Aftermarket) (Unl)" - rom ( name "Neko Can Dream (World) (Ja) (Demo) (Aftermarket) (Unl).gb" size 2097152 crc a0ad7a18 sha1 5fb1a09e04cf1704b059468de8855dfa7e23043b ) -) - game ( name "Nekojara Monogatari (Japan)" description "Nekojara Monogatari (Japan)" @@ -28728,36 +29608,18 @@ game ( rom ( name "Noobow (Japan).gb" size 262144 crc 8bbcc8bb sha1 b571d9051e3a9f1a55533b4f43941cae907aedff ) ) -game ( - name "Oblique Strategies (World) (Aftermarket) (Unl)" - description "Oblique Strategies (World) (Aftermarket) (Unl)" - rom ( name "Oblique Strategies (World) (Aftermarket) (Unl).gb" size 524288 crc 30eca8d3 sha1 6a09aabf30e2ebab2e31ae845cd2e8796c84797f ) -) - game ( name "Oddworld Adventures (USA, Europe)" description "Oddworld Adventures (USA, Europe)" rom ( name "Oddworld Adventures (USA, Europe).gb" size 524288 crc 6510c0e2 sha1 be3f69371b6959dab34014cb1d3672f4f3377c3a flags verified ) ) -game ( - name "Office Combat (World) (Aftermarket) (Unl)" - description "Office Combat (World) (Aftermarket) (Unl)" - rom ( name "Office Combat (World) (Aftermarket) (Unl).gb" size 262144 crc 9742276d sha1 cd8f18d6e5fabaa130a42e5618e29c5ff26f6a93 ) -) - game ( name "Oira Jajamaru! Sekai Daibouken (Japan)" description "Oira Jajamaru! Sekai Daibouken (Japan)" rom ( name "Oira Jajamaru! Sekai Daibouken (Japan).gb" size 131072 crc 2d08d27f sha1 5e13eeb635b41589689fc1b495ee077125b7e8c1 ) ) -game ( - name "Olympic Skier (World) (Aftermarket) (Unl)" - description "Olympic Skier (World) (Aftermarket) (Unl)" - rom ( name "Olympic Skier (World) (Aftermarket) (Unl).gb" size 524288 crc 93174431 sha1 7bcdf10533f8fe053e22534c4962ed4b1a5cf2e2 ) -) - game ( name "Olympic Summer Games (USA, Europe) (SGB Enhanced)" description "Olympic Summer Games (USA, Europe) (SGB Enhanced)" @@ -28866,12 +29728,6 @@ game ( rom ( name "Out of Gas (USA).gb" size 131072 crc 1b67e8b1 sha1 770ac35c0780cf432235593bd5674e72edd6cf7d ) ) -game ( - name "Out on a Limb (World) (Aftermarket) (Unl)" - description "Out on a Limb (World) (Aftermarket) (Unl)" - rom ( name "Out on a Limb (World) (Aftermarket) (Unl).gb" size 262144 crc be197f87 sha1 2ddc2378539316cf7a10e2cf8b562f17e1cf7a6a ) -) - game ( name "Outburst (Japan) (Demo)" description "Outburst (Japan) (Demo)" @@ -29103,7 +29959,7 @@ game ( game ( name "Pang (Europe)" description "Pang (Europe)" - rom ( name "Pang (Europe).gb" size 131072 crc ea9615b4 sha1 7ca64a45ea6a68770658ae39ef21c41f806988c5 ) + rom ( name "Pang (Europe).gb" size 131072 crc ea9615b4 sha1 7ca64a45ea6a68770658ae39ef21c41f806988c5 flags verified ) ) game ( @@ -29112,12 +29968,6 @@ game ( rom ( name "Pang (Europe) (Beta).gb" size 131072 crc 54d2754a sha1 b57d436d8a83f2fb1e42bad3150893ef8ffab0d4 ) ) -game ( - name "Panty Hunty (World) (v1.4) (Aftermarket) (Unl)" - description "Panty Hunty (World) (v1.4) (Aftermarket) (Unl)" - rom ( name "Panty Hunty (World) (v1.4) (Aftermarket) (Unl).gb" size 524288 crc ce707b9a sha1 b5757b268a09d9085d469eda0676991f7361ad8c ) -) - game ( name "Paperboy (USA, Europe)" description "Paperboy (USA, Europe)" @@ -29136,12 +29986,6 @@ game ( rom ( name "Parasol Henbee (Japan).gb" size 65536 crc ae97ec53 sha1 8f319d3d1929d953934e32ce900249ecf6b55fbd ) ) -game ( - name "Parasol Islands (World) (Aftermarket) (Unl)" - description "Parasol Islands (World) (Aftermarket) (Unl)" - rom ( name "Parasol Islands (World) (Aftermarket) (Unl).gb" size 1048576 crc b1d79c80 sha1 381f76af67f77e575beae2f45aefd21f079709e6 ) -) - game ( name "Parasol Stars - Rainbow Islands II (Europe)" description "Parasol Stars - Rainbow Islands II (Europe)" @@ -29196,18 +30040,6 @@ game ( rom ( name "Penta Dragon (Japan).gb" size 262144 crc 1e2efaee sha1 fd75d43258e79f14d104fb4756e219141882c837 ) ) -game ( - name "Perfect Blend (World) (v0.9) (Aftermarket) (Unl)" - description "Perfect Blend (World) (v0.9) (Aftermarket) (Unl)" - rom ( name "Perfect Blend (World) (v0.9) (Aftermarket) (Unl).gb" size 262144 crc 9b4bacaa sha1 09b0691f6823c54f1515dd3b66f135ac45a7dbc3 ) -) - -game ( - name "Perfect Blend (World) (v0.9) (Bugfix) (Aftermarket) (Unl)" - description "Perfect Blend (World) (v0.9) (Bugfix) (Aftermarket) (Unl)" - rom ( name "Perfect Blend (World) (v0.9) (Bugfix) (Aftermarket) (Unl).gb" size 262144 crc 1e8b2a29 sha1 a25dfc43408080ac116479fa55c9e7320e5cc82a ) -) - game ( name "PGA European Tour (USA, Europe) (SGB Enhanced)" description "PGA European Tour (USA, Europe) (SGB Enhanced)" @@ -29232,30 +30064,12 @@ game ( rom ( name "Phantom Air Mission (Europe).gb" size 131072 crc 8aced4a6 sha1 2a270597d7b814a1c8819a5698ab922200569206 flags verified ) ) -game ( - name "Phantom Fright (World) (Aftermarket) (Unl)" - description "Phantom Fright (World) (Aftermarket) (Unl)" - rom ( name "Phantom Fright (World) (Aftermarket) (Unl).gb" size 524288 crc 154cb547 sha1 3b217c595e6a5b115dc7130123a321049cf01d22 ) -) - game ( name "Philip & Marlowe in Bloomland (USA) (Proto)" description "Philip & Marlowe in Bloomland (USA) (Proto)" rom ( name "Philip & Marlowe in Bloomland (USA) (Proto).gb" size 131072 crc 32bae420 sha1 2f9e5cee29d0d578b2642ce8637f02fc567aebc5 ) ) -game ( - name "Phobos Dere .GB (World) (Aftermarket) (Unl)" - description "Phobos Dere .GB (World) (Aftermarket) (Unl)" - rom ( name "Phobos Dere .GB (World) (Aftermarket) (Unl).gb" size 1048576 crc ae97f4f8 sha1 e541505078ee5e7e5c897b4621cc693ce71e35ba flags verified ) -) - -game ( - name "Phobos Dere .GB (World) (2022-03-06) (Demo) (Aftermarket) (Unl)" - description "Phobos Dere .GB (World) (2022-03-06) (Demo) (Aftermarket) (Unl)" - rom ( name "Phobos Dere .GB (World) (2022-03-06) (Demo) (Aftermarket) (Unl).gb" size 262144 crc 58362b86 sha1 b4cc3c3735bc134e34b97e08ed24c57aef5c5ccf flags verified ) -) - game ( name "Picross 2 (Japan) (SGB Enhanced)" description "Picross 2 (Japan) (SGB Enhanced)" @@ -29310,12 +30124,6 @@ game ( rom ( name "Pinball Mania (Europe).gb" size 262144 crc edc8d122 sha1 0541161b4b93fffc3c75708aca86ea0873747ced ) ) -game ( - name "Pineapple Kid (World) (Aftermarket) (Unl)" - description "Pineapple Kid (World) (Aftermarket) (Unl)" - rom ( name "Pineapple Kid (World) (Aftermarket) (Unl).gb" size 131072 crc 9541488b sha1 fd574b5d407f3654db3227900a8ed7eff4fe48ae ) -) - game ( name "Pingu - Sekai de 1ban Genki na Penguin (Japan)" description "Pingu - Sekai de 1ban Genki na Penguin (Japan)" @@ -29337,7 +30145,7 @@ game ( game ( name "Pipe Dream (Japan)" description "Pipe Dream (Japan)" - rom ( name "Pipe Dream (Japan).gb" size 32768 crc d8b4aea4 sha1 64a58aafecb0aceed2dde843a19a28b2bb000b2f ) + rom ( name "Pipe Dream (Japan).gb" size 32768 crc d8b4aea4 sha1 64a58aafecb0aceed2dde843a19a28b2bb000b2f flags verified ) ) game ( @@ -29358,28 +30166,10 @@ game ( rom ( name "Pitman (Japan).gb" size 32768 crc a0b68136 sha1 a698d4bccd69d2ca51cb48877bde5d1f83d4317f ) ) -game ( - name "Pixel Who - The Lost Legions (World) (v1.0) (Aftermarket) (Unl)" - description "Pixel Who - The Lost Legions (World) (v1.0) (Aftermarket) (Unl)" - rom ( name "Pixel Who - The Lost Legions (World) (v1.0) (Aftermarket) (Unl).gb" size 1048576 crc f41cf2a7 sha1 c07378c774602060f1f93f18fbfd3f0d552fe2d2 ) -) - -game ( - name "Plants Eat My Zombies (World) (v1.1) (Aftermarket) (Unl)" - description "Plants Eat My Zombies (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Plants Eat My Zombies (World) (v1.1) (Aftermarket) (Unl).gb" size 524288 crc 60c84f2e sha1 c39ec5e6a9a0be0970b56e788c3f60e9821dbbd3 ) -) - game ( name "Play Action Football (USA)" description "Play Action Football (USA)" - rom ( name "Play Action Football (USA).gb" size 131072 crc 983caf46 sha1 dc2981baf1bb4d0a65ec45fb22d44a5ca4c06254 ) -) - -game ( - name "Pluto's Corner (World) (Aftermarket) (Unl)" - description "Pluto's Corner (World) (Aftermarket) (Unl)" - rom ( name "Pluto's Corner (World) (Aftermarket) (Unl).gb" size 65536 crc 21fc06b3 sha1 94e4a442205079d85d5ca37042eaec555f7f49db ) + rom ( name "Play Action Football (USA).gb" size 131072 crc 983caf46 sha1 dc2981baf1bb4d0a65ec45fb22d44a5ca4c06254 flags verified ) ) game ( @@ -29418,6 +30208,12 @@ game ( rom ( name "Pocket Camera (Japan) (Rev 1) (SGB Enhanced).gb" size 1048576 crc 73e8ef96 sha1 912205ea22e1dd735ed4f41d247039eebf39dddc flags verified ) ) +game ( + name "Pocket Camera - Debug Game Tester - Second Impact (Japan) (Test Program) (v10.24) (SGB Enhanced)" + description "Pocket Camera - Debug Game Tester - Second Impact (Japan) (Test Program) (v10.24) (SGB Enhanced)" + rom ( name "Pocket Camera - Debug Game Tester - Second Impact (Japan) (Test Program) (v10.24) (SGB Enhanced).gb" size 1048576 crc 15726d8c sha1 5ffcda6fa1a3d87c5cbb8ddf743ddbc18242443b ) +) + game ( name "Pocket Densha (Japan) (SGB Enhanced)" description "Pocket Densha (Japan) (SGB Enhanced)" @@ -29484,6 +30280,12 @@ game ( rom ( name "Pocket Monsters - Ao (Japan) (SGB Enhanced).gb" size 524288 crc e4468d14 sha1 0da501e3e5c51ab8fef55b092dcdd7e6b050e424 flags verified ) ) +game ( + name "Pocket Monsters - Green Version - English Edition (Taiwan) (En) (Pirate)" + description "Pocket Monsters - Green Version - English Edition (Taiwan) (En) (Pirate)" + rom ( name "Pocket Monsters - Green Version - English Edition (Taiwan) (En) (Pirate).gb" size 786432 crc 742357fc sha1 b8d1b89a82fbad0352f4a15dd1bcc91868717578 ) +) + game ( name "Pocket Monsters - Midori (Japan) (SGB Enhanced)" description "Pocket Monsters - Midori (Japan) (SGB Enhanced)" @@ -29571,7 +30373,7 @@ game ( game ( name "Pocket Sonar (Japan)" description "Pocket Sonar (Japan)" - rom ( name "Pocket Sonar (Japan).gb" size 524288 crc d68c9f79 sha1 788cdf148431b82b5308c68b3e45b133a7074196 ) + rom ( name "Pocket Sonar (Japan).gb" size 524288 crc d68c9f79 sha1 788cdf148431b82b5308c68b3e45b133a7074196 flags verified ) ) game ( @@ -29580,12 +30382,6 @@ game ( rom ( name "Pocket Stadium (Japan).gb" size 65536 crc c7bd9228 sha1 7ba422f2b48ff09673f7f1a258be6ecc1ff6a8d7 ) ) -game ( - name "Pogo Pete (World) (Aftermarket) (Unl)" - description "Pogo Pete (World) (Aftermarket) (Unl)" - rom ( name "Pogo Pete (World) (Aftermarket) (Unl).gb" size 262144 crc 185ce1d5 sha1 74021e84c1d095b2401302e26352e810dbc432d8 ) -) - game ( name "Pokemon - Blaue Edition (Germany) (SGB Enhanced)" description "Pokemon - Blaue Edition (Germany) (SGB Enhanced)" @@ -29649,7 +30445,7 @@ game ( game ( name "Pokemon - Version Bleue (France) (SGB Enhanced)" description "Pokemon - Version Bleue (France) (SGB Enhanced)" - rom ( name "Pokemon - Version Bleue (France) (SGB Enhanced).gb" size 1048576 crc 50e2fc1d sha1 47faa910d0e073c600665bf9c83b6bd17babdf8a ) + rom ( name "Pokemon - Version Bleue (France) (SGB Enhanced).gb" size 1048576 crc 50e2fc1d sha1 47faa910d0e073c600665bf9c83b6bd17babdf8a flags verified ) ) game ( @@ -29688,6 +30484,60 @@ game ( rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (CGB+SGB Enhanced).gb" size 1048576 crc 7d527d62 sha1 cc7d03262ebfaf2f06772c1a480c7d9d5f4a38e1 flags verified ) ) +game ( + name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-22) (Beta) (CGB+SGB Enhanced) (Alt)" + description "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-22) (Beta) (CGB+SGB Enhanced) (Alt)" + rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-22) (Beta) (CGB+SGB Enhanced) (Alt).gb" size 1048576 crc dbd0b8dc sha1 ad2ec0171cc731747adbe51b852a0bc6acd9471a ) +) + +game ( + name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-03) (Beta) (CGB+SGB Enhanced)" + description "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-03) (Beta) (CGB+SGB Enhanced)" + rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-03) (Beta) (CGB+SGB Enhanced).gb" size 1048576 crc d0b1e29b sha1 7c4ef696e2d0d965d5c6f33e745bbacc1715bba1 ) +) + +game ( + name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-03) (Beta) (CGB+SGB Enhanced) (Alt)" + description "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-03) (Beta) (CGB+SGB Enhanced) (Alt)" + rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-03) (Beta) (CGB+SGB Enhanced) (Alt).gb" size 1048576 crc 1116ae9f sha1 bfac8de19d04e859f64aaa52ffb1f3d5094417ff ) +) + +game ( + name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-18) (Beta) (CGB+SGB Enhanced)" + description "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-18) (Beta) (CGB+SGB Enhanced)" + rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-18) (Beta) (CGB+SGB Enhanced).gb" size 1048576 crc b539a028 sha1 53dcd8b02c7ad002a7c40edf758b19d3b393a9c4 ) +) + +game ( + name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-15) (Beta) (CGB+SGB Enhanced)" + description "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-15) (Beta) (CGB+SGB Enhanced)" + rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-15) (Beta) (CGB+SGB Enhanced).gb" size 1048576 crc 00787832 sha1 13ef81f63904d496c6d6acf6685750ecdb35357b ) +) + +game ( + name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-16) (Beta) (CGB+SGB Enhanced)" + description "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-16) (Beta) (CGB+SGB Enhanced)" + rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-16) (Beta) (CGB+SGB Enhanced).gb" size 1048576 crc 42c5430a sha1 d8a7d2ec6a8dd9f8e97cf02a27882a750650aa6c ) +) + +game ( + name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-22) (Beta) (CGB+SGB Enhanced)" + description "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-22) (Beta) (CGB+SGB Enhanced)" + rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-22) (Beta) (CGB+SGB Enhanced).gb" size 1048576 crc c83df319 sha1 490a925fe4e30dc0217c4a23ed9b4f41538277db ) +) + +game ( + name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-17) (Beta) (CGB+SGB Enhanced)" + description "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-17) (Beta) (CGB+SGB Enhanced)" + rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-17) (Beta) (CGB+SGB Enhanced).gb" size 1048576 crc 0dee0d87 sha1 bde79c92c801cc0c0e73a022bdf23f086b4da4c5 ) +) + +game ( + name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-10) (Beta) (CGB+SGB Enhanced)" + description "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-10) (Beta) (CGB+SGB Enhanced)" + rom ( name "Pokemon - Yellow Version - Special Pikachu Edition (USA, Europe) (1999-02-10) (Beta) (CGB+SGB Enhanced).gb" size 1048576 crc 2e63bc59 sha1 834e933256855403da07d88d375cdbe88d628f01 ) +) + game ( name "Pokonyan! - Yume no Daibouken (Japan) (SGB Enhanced)" description "Pokonyan! - Yume no Daibouken (Japan) (SGB Enhanced)" @@ -29712,12 +30562,6 @@ game ( rom ( name "Pop'n TwinBee (Europe).gb" size 131072 crc d07db274 sha1 0206230b55c15a8c18fbb85f852967e44b33a0a4 ) ) -game ( - name "Popcorn Caravan (World) (Aftermarket) (Unl)" - description "Popcorn Caravan (World) (Aftermarket) (Unl)" - rom ( name "Popcorn Caravan (World) (Aftermarket) (Unl).gb" size 65536 crc ead528f9 sha1 909d3421747d211a2dc70918d2c952db953e49b2 ) -) - game ( name "Popeye (Japan)" description "Popeye (Japan)" @@ -29772,18 +30616,6 @@ game ( rom ( name "Populous Gaiden (Japan).gb" size 131072 crc f327167e sha1 fde1789eb253309cae80faf4fe7241c6f9d72f29 ) ) -game ( - name "Porklike (World) (v1.0.3) (Aftermarket) (Unl)" - description "Porklike (World) (v1.0.3) (Aftermarket) (Unl)" - rom ( name "Porklike (World) (v1.0.3) (Aftermarket) (Unl).gb" size 65536 crc 6c57e55e sha1 143f31656a5007f65b19d6e32967698bb8f72a66 ) -) - -game ( - name "Porklike (World) (v1.0.9) (Aftermarket) (Unl)" - description "Porklike (World) (v1.0.9) (Aftermarket) (Unl)" - rom ( name "Porklike (World) (v1.0.9) (Aftermarket) (Unl).gb" size 65536 crc 7aaa853a sha1 0868bffd52b2bdc5601ab6cf1e25f40924ca643d ) -) - game ( name "Power Mission (Japan)" description "Power Mission (Japan)" @@ -29907,7 +30739,7 @@ game ( game ( name "Pro Mahjong Kiwame GB (Japan) (SGB Enhanced)" description "Pro Mahjong Kiwame GB (Japan) (SGB Enhanced)" - rom ( name "Pro Mahjong Kiwame GB (Japan) (SGB Enhanced).gb" size 131072 crc 6f5b6748 sha1 dc6b304ac4e9b679272f843411ba964b438a69b6 ) + rom ( name "Pro Mahjong Kiwame GB (Japan) (SGB Enhanced).gb" size 131072 crc 6f5b6748 sha1 dc6b304ac4e9b679272f843411ba964b438a69b6 flags verified ) ) game ( @@ -29994,18 +30826,6 @@ game ( rom ( name "Purikura Pocket 3 - Talent Debut Daisakusen (Japan) (Rev 1) (SGB Enhanced) (NP).gb" size 1048576 crc 458dd05d sha1 7779a103a7ae3e382c8ffa3a6830160af36bb3b4 ) ) -game ( - name "Purple Turtles (World) (Aftermarket) (Unl)" - description "Purple Turtles (World) (Aftermarket) (Unl)" - rom ( name "Purple Turtles (World) (Aftermarket) (Unl).gb" size 262144 crc f7041a97 sha1 d2d7eff063104c8f205c192a902a53092c0b5f4a ) -) - -game ( - name "Pushingo (World) (Aftermarket) (Unl)" - description "Pushingo (World) (Aftermarket) (Unl)" - rom ( name "Pushingo (World) (Aftermarket) (Unl).gb" size 262144 crc a8541ed0 sha1 1ac1e22b191a95fdfa00c34ccba7387c991c827b ) -) - game ( name "Puyo Puyo (Japan) (SGB Enhanced)" description "Puyo Puyo (Japan) (SGB Enhanced)" @@ -30090,12 +30910,6 @@ game ( rom ( name "QIX (World).gb" size 65536 crc 9185e89e sha1 fb9935ca821562966eafa8f60ec2f489ad33940a flags verified ) ) -game ( - name "Quartet (World) (Aftermarket) (Unl)" - description "Quartet (World) (Aftermarket) (Unl)" - rom ( name "Quartet (World) (Aftermarket) (Unl).gb" size 32768 crc 46743216 sha1 bf866b438a602af386f8fad02727b4084edf6047 ) -) - game ( name "Quarth (Japan)" description "Quarth (Japan)" @@ -30108,18 +30922,6 @@ game ( rom ( name "Quarth (USA, Europe).gb" size 65536 crc bfb112ad sha1 89448b17700a6016a3f81de09a15e097c060d103 flags verified ) ) -game ( - name "Quest Arrest (World) (v1.1) (Aftermarket) (Unl)" - description "Quest Arrest (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Quest Arrest (World) (v1.1) (Aftermarket) (Unl).gb" size 1048576 crc 9ac546d5 sha1 25b3a21135bfc7587c096b10f4a20d8b3095d721 ) -) - -game ( - name "Quick Draw (World) (Aftermarket) (Unl)" - description "Quick Draw (World) (Aftermarket) (Unl)" - rom ( name "Quick Draw (World) (Aftermarket) (Unl).gb" size 262144 crc 7704671f sha1 75f96ce54ed8739d58153780e9b573a65f1c5880 ) -) - game ( name "Quiz Nihon Mukashibanashi - Athena no Hatena (Japan)" description "Quiz Nihon Mukashibanashi - Athena no Hatena (Japan)" @@ -30204,12 +31006,6 @@ game ( rom ( name "Radar Mission (USA, Europe).gb" size 131072 crc 581da9c9 sha1 5ab5998a84eebc769f75c482cb0a5586ed97e888 ) ) -game ( - name "Raffles (World) (Aftermarket) (Unl)" - description "Raffles (World) (Aftermarket) (Unl)" - rom ( name "Raffles (World) (Aftermarket) (Unl).gb" size 262144 crc 0b400a91 sha1 aadfe3fd0720696547b73b272354b592b96f98f7 ) -) - game ( name "Raging Fighter (USA, Europe)" description "Raging Fighter (USA, Europe)" @@ -30276,12 +31072,6 @@ game ( rom ( name "Red October o Oe! (Japan).gb" size 131072 crc c2e7be35 sha1 48d5f02a126c32423569065f31d2c5695e39fd2f ) ) -game ( - name "Remute - Living Electronics (World) (Aftermarket) (Unl)" - description "Remute - Living Electronics (World) (Aftermarket) (Unl)" - rom ( name "Remute - Living Electronics (World) (Aftermarket) (Unl).gb" size 2097152 crc 1ced0a62 sha1 bc4bf12344d3b9d028a7013c84b94aea515be196 ) -) - game ( name "Ren & Stimpy Show, The - Space Cadet Adventures (USA)" description "Ren & Stimpy Show, The - Space Cadet Adventures (USA)" @@ -30312,24 +31102,6 @@ game ( rom ( name "Reservoir Rat (Europe) (En,Fr,De,Es,It).gb" size 262144 crc 2d33e175 sha1 08dad9ac1f045d1c9e403c4ea1368aee991e0094 ) ) -game ( - name "Rewind Time (World) (Aftermarket) (Unl)" - description "Rewind Time (World) (Aftermarket) (Unl)" - rom ( name "Rewind Time (World) (Aftermarket) (Unl).gb" size 262144 crc d8ad184a sha1 903ef8074e58a52bc98dcb9e3f2c88b52fc1335b ) -) - -game ( - name "Rhythm Land (World) (v1.0.0) (Aftermarket) (Unl)" - description "Rhythm Land (World) (v1.0.0) (Aftermarket) (Unl)" - rom ( name "Rhythm Land (World) (v1.0.0) (Aftermarket) (Unl).gb" size 131072 crc 4312c7ff sha1 c79f26ce187edea18cf92be8340ec0a0c8beec87 ) -) - -game ( - name "Rhythm Land (World) (v1.0.1) (Aftermarket) (Unl)" - description "Rhythm Land (World) (v1.0.1) (Aftermarket) (Unl)" - rom ( name "Rhythm Land (World) (v1.0.1) (Aftermarket) (Unl).gb" size 131072 crc fbf98400 sha1 1b831806d32e1ec35bc94a84384c6989433a274d ) -) - game ( name "Riddick Bowe Boxing (Europe)" description "Riddick Bowe Boxing (Europe)" @@ -30348,12 +31120,6 @@ game ( rom ( name "Riddick Bowe Boxing (USA) (Beta).gb" size 131072 crc a07512a6 sha1 69685eaffa523bf199be0c540d9eb561bb27d584 ) ) -game ( - name "Rig Attack (World) (Aftermarket) (Unl)" - description "Rig Attack (World) (Aftermarket) (Unl)" - rom ( name "Rig Attack (World) (Aftermarket) (Unl).gb" size 262144 crc dea8749d sha1 6f0fbac6b6c2e8f2d8df0a0a0e2f0c947e37b39a ) -) - game ( name "Ring Rage (Japan)" description "Ring Rage (Japan)" @@ -30384,12 +31150,6 @@ game ( rom ( name "Roadster (Japan).gb" size 131072 crc 04453e78 sha1 685c31496de738c27160d1f75408da6b95daaae8 ) ) -game ( - name "Robby's Day Out (World) (Aftermarket) (Unl)" - description "Robby's Day Out (World) (Aftermarket) (Unl)" - rom ( name "Robby's Day Out (World) (Aftermarket) (Unl).gb" size 262144 crc c3c89cd9 sha1 9d38b69ab9a4ff7bf387c88f2afed410d450f2e0 ) -) - game ( name "Robin Hood - Prince of Thieves (Europe)" description "Robin Hood - Prince of Thieves (Europe)" @@ -30618,12 +31378,6 @@ game ( rom ( name "Sakigake!! Otoko Juku - Meioutou Kessen (Japan).gb" size 131072 crc 2f0f7f63 sha1 c731f8be269d74748ae54fe5ce5faea89a825e0f ) ) -game ( - name "Sam Mallard - The Case of the Missing Swan (World) (Aftermarket) (Unl)" - description "Sam Mallard - The Case of the Missing Swan (World) (Aftermarket) (Unl)" - rom ( name "Sam Mallard - The Case of the Missing Swan (World) (Aftermarket) (Unl).gb" size 1048576 crc 994a2edd sha1 0132f0311d8478d4f45b3b8e2728698570091d69 ) -) - game ( name "Same Game (Japan) (SGB Enhanced)" description "Same Game (Japan) (SGB Enhanced)" @@ -30672,12 +31426,6 @@ game ( rom ( name "Sanrio Uranai Party (Japan) (Rev 1).gb" size 262144 crc d0687d9f sha1 72dfcc83dbd78ad2b5b43014fc9adf05431e230c flags verified ) ) -game ( - name "Sapphire & Shiny Kidnap the Crows (World) (v2) (Aftermarket) (Unl)" - description "Sapphire & Shiny Kidnap the Crows (World) (v2) (Aftermarket) (Unl)" - rom ( name "Sapphire & Shiny Kidnap the Crows (World) (v2) (Aftermarket) (Unl).gb" size 1048576 crc edb63c15 sha1 4617b71836c3ddabcfef46b33aa8a83803eaea90 ) -) - game ( name "Sarakon (Europe) (Proto)" description "Sarakon (Europe) (Proto)" @@ -30744,12 +31492,6 @@ game ( rom ( name "Sea Battle (Europe) (En,Fr,De,Es).gb" size 131072 crc ba091b91 sha1 560d62b96a1b9820e3fd953f76e33b4f5fdc9e2f ) ) -game ( - name "Sea King GB (USA) (Proto) (SGB Enhanced)" - description "Sea King GB (USA) (Proto) (SGB Enhanced)" - rom ( name "Sea King GB (USA) (Proto) (SGB Enhanced).gb" size 1048576 crc a45ef889 sha1 26bebc2394b5da850be55e409b9efcb4d2d29d87 ) -) - game ( name "seaQuest DSV (USA, Europe) (SGB Enhanced)" description "seaQuest DSV (USA, Europe) (SGB Enhanced)" @@ -30816,12 +31558,6 @@ game ( rom ( name "Serpent (USA).gb" size 32768 crc 74d466d7 sha1 3122b3c12c2580c3a81d70c5648f767bf3590aaf flags verified ) ) -game ( - name "Severen (World) (Demo) (Aftermarket) (Unl)" - description "Severen (World) (Demo) (Aftermarket) (Unl)" - rom ( name "Severen (World) (Demo) (Aftermarket) (Unl).gb" size 1048576 crc 642f2244 sha1 d9692aa569820db3f38458819cba21846a2e06f4 ) -) - game ( name "Shadow Warriors (Europe)" description "Shadow Warriors (Europe)" @@ -30852,31 +31588,12 @@ game ( rom ( name "Shanghai Pocket (Japan) (SGB Enhanced).gb" size 262144 crc 6b8eff2c sha1 82fe97442aa625fd36cf865d82f78b07108ede7f ) ) -game ( - name "Shapeshifter 2, The (World) (Aftermarket)" - description "Shapeshifter 2, The (World) (Aftermarket)" - rom ( name "Shapeshifter 2, The (World) (Aftermarket) (Cartridge 1).gb" size 2097152 crc 276125f1 sha1 b181b58984cb44c950fc56f88a4fb8112da8fcff ) - rom ( name "Shapeshifter 2, The (World) (Aftermarket) (Cartridge 2).gb" size 2097152 crc 5b45bce2 sha1 79d16ef5383ddc7ae299f825cd03268d00887500 ) -) - -game ( - name "Shapeshifter, The (World) (Aftermarket)" - description "Shapeshifter, The (World) (Aftermarket)" - rom ( name "Shapeshifter, The (World) (Aftermarket).gb" size 1048576 crc ef735794 sha1 179e69199f19b403b4c1a9675a3ee431ee570797 ) -) - game ( name "Shaq Fu (USA) (SGB Enhanced)" description "Shaq Fu (USA) (SGB Enhanced)" rom ( name "Shaq Fu (USA) (SGB Enhanced).gb" size 524288 crc 7ed43fe6 sha1 5e9e68d9235cf8149232b85fd6080ba8796cb85e ) ) -game ( - name "Shark Attack (World) (Aftermarket) (Unl)" - description "Shark Attack (World) (Aftermarket) (Unl)" - rom ( name "Shark Attack (World) (Aftermarket) (Unl).gb" size 262144 crc 3032025a sha1 6cc65bb719af53128bb04c9ee7c6abbf4ff1c3cf ) -) - game ( name "Shikinjou (Japan)" description "Shikinjou (Japan)" @@ -30943,24 +31660,6 @@ game ( rom ( name "Shisenshou - Match-Mania (Japan).gb" size 32768 crc 0cdd8b04 sha1 6e84a906f9e1ce43272db84c63f1b037096ac34f flags verified ) ) -game ( - name "Shock Lobster (World) (Aftermarket) (Unl)" - description "Shock Lobster (World) (Aftermarket) (Unl)" - rom ( name "Shock Lobster (World) (Aftermarket) (Unl).gb" size 32768 crc 7a0622e6 sha1 10c1816724cd6e332d2a5aeed4e546e7bd764ebf ) -) - -game ( - name "Shock Lobster (World) (v1.3) (Aftermarket) (Unl)" - description "Shock Lobster (World) (v1.3) (Aftermarket) (Unl)" - rom ( name "Shock Lobster (World) (v1.3) (Aftermarket) (Unl).gb" size 32768 crc 8f244e86 sha1 7b8c8a9ec4758c6880598b9d508bc5805293dd87 ) -) - -game ( - name "Shootris (World) (Aftermarket) (Unl)" - description "Shootris (World) (Aftermarket) (Unl)" - rom ( name "Shootris (World) (Aftermarket) (Unl).gb" size 262144 crc 50180f64 sha1 5d978e6fc4bd5d9717d022360122458e95fffc29 ) -) - game ( name "Shougi (Japan)" description "Shougi (Japan)" @@ -31045,18 +31744,6 @@ game ( rom ( name "Skate or Die - Tour de Thrash (USA).gb" size 131072 crc 02b77c09 sha1 6e1610450da0c836983a1c310524639fefcc304f ) ) -game ( - name "Sloth Story (World) (Aftermarket) (Unl)" - description "Sloth Story (World) (Aftermarket) (Unl)" - rom ( name "Sloth Story (World) (Aftermarket) (Unl).gb" size 262144 crc c873f232 sha1 369d2afec4ffb59d4f3a59ee684c5bfec0b34ff8 ) -) - -game ( - name "Sludge & Sorcery (World) (Aftermarket) (Unl)" - description "Sludge & Sorcery (World) (Aftermarket) (Unl)" - rom ( name "Sludge & Sorcery (World) (Aftermarket) (Unl).gb" size 1048576 crc c906c5af sha1 0e0d472b282e3ea590e0f126baf633ef0d9298fa ) -) - game ( name "Small Soldiers (USA, Europe) (SGB Enhanced)" description "Small Soldiers (USA, Europe) (SGB Enhanced)" @@ -31093,24 +31780,6 @@ game ( rom ( name "Smurfs, The (USA, Europe) (En,Fr,De) (Rev 1) (SGB Enhanced).gb" size 131072 crc 8b5bcde7 sha1 a0d6a85331fb034f68f05629a5ff85e13adab205 flags verified ) ) -game ( - name "Snail DX, The (World) (Aftermarket) (Unl)" - description "Snail DX, The (World) (Aftermarket) (Unl)" - rom ( name "Snail DX, The (World) (Aftermarket) (Unl).gb" size 262144 crc 1aecd096 sha1 8ce256d963a55badf71fd45047c173a74d76a92c ) -) - -game ( - name "Snail, The (World) (v1.3) (Aftermarket) (Unl)" - description "Snail, The (World) (v1.3) (Aftermarket) (Unl)" - rom ( name "Snail, The (World) (v1.3) (Aftermarket) (Unl).gb" size 262144 crc 422a7b44 sha1 776f7578d747f935ebccda93d6487ffa4dc4bce3 ) -) - -game ( - name "Snakebird (World) (Aftermarket) (Unl)" - description "Snakebird (World) (Aftermarket) (Unl)" - rom ( name "Snakebird (World) (Aftermarket) (Unl).gb" size 131072 crc 4627f98e sha1 99cc82279d65b86b4366bf61db9bf67a78e051dc ) -) - game ( name "Sneaky Snakes (USA, Europe)" description "Sneaky Snakes (USA, Europe)" @@ -31135,12 +31804,6 @@ game ( rom ( name "Snoopy's Magic Show (USA, Europe).gb" size 65536 crc 2b7a5034 sha1 bc21fb3aa1a58e2aef30fabe103b2e5bec02b535 flags verified ) ) -game ( - name "Snooze (World) (Aftermarket) (Unl)" - description "Snooze (World) (Aftermarket) (Unl)" - rom ( name "Snooze (World) (Aftermarket) (Unl).gb" size 262144 crc b246095f sha1 b7fdcc006c9c06dd391ee26d44b278d9d3793f6d ) -) - game ( name "Snow Bros. Jr. (Japan)" description "Snow Bros. Jr. (Japan)" @@ -31172,9 +31835,15 @@ game ( ) game ( - name "Soccer Boy (Japan)" - description "Soccer Boy (Japan)" - rom ( name "Soccer Boy (Japan).gb" size 65536 crc 23f64e82 sha1 7554b42d1c38508fd615828c96ab58ea8f41de4d ) + name "Soccer Boy (Japan) (En)" + description "Soccer Boy (Japan) (En)" + rom ( name "Soccer Boy (Japan) (En).gb" size 65536 crc 23f64e82 sha1 7554b42d1c38508fd615828c96ab58ea8f41de4d ) +) + +game ( + name "Soccer Boy (Japan) (En) (Beta)" + description "Soccer Boy (Japan) (En) (Beta)" + rom ( name "Soccer Boy (Japan) (En) (Beta).gb" size 65536 crc a46f98d1 sha1 22db7c6096f285222aefbfe413efa1d21de59731 ) ) game ( @@ -31351,12 +32020,6 @@ game ( rom ( name "Spider-Man 3 - Invasion of the Spider-Slayers (USA, Europe) (Beta 2) (1993-04-11).gb" size 131072 crc bf2d1f10 sha1 34740dc60663ef33c42573a26e7b207f2cfe4a16 ) ) -game ( - name "Spiky Harold (World) (Aftermarket) (Unl)" - description "Spiky Harold (World) (Aftermarket) (Unl)" - rom ( name "Spiky Harold (World) (Aftermarket) (Unl).gb" size 524288 crc 2ac1b945 sha1 b8f37a64524bde4c2b6e9a1938ed6e5c0a5aad7c ) -) - game ( name "Spirit of F-1, The (Europe)" description "Spirit of F-1, The (Europe)" @@ -31543,6 +32206,12 @@ game ( rom ( name "Star Wars (USA, Europe) (Rev 1).gb" size 131072 crc 5d8deb5b sha1 f6563f526fc786c8666d75dfba9e6d42d787ea89 flags verified ) ) +game ( + name "Star Wars (World) (Limited Run Games)" + description "Star Wars (World) (Limited Run Games)" + rom ( name "Star Wars (World) (Limited Run Games).gb" size 131072 crc 08838397 sha1 02bfb690ce171214bfee900069192e0daafc010d ) +) + game ( name "Star Wars - The Empire Strikes Back (USA, Europe)" description "Star Wars - The Empire Strikes Back (USA, Europe)" @@ -31556,9 +32225,9 @@ game ( ) game ( - name "StarFox - Grounded (World) (Aftermarket) (Unl)" - description "StarFox - Grounded (World) (Aftermarket) (Unl)" - rom ( name "StarFox - Grounded (World) (Aftermarket) (Unl).gb" size 524288 crc 82658661 sha1 dd45b0e3f346ce33668d49092b29a44597686061 ) + name "Star Wars - The Empire Strikes Back (World) (Limited Run Games)" + description "Star Wars - The Empire Strikes Back (World) (Limited Run Games)" + rom ( name "Star Wars - The Empire Strikes Back (World) (Limited Run Games).gb" size 131072 crc 799e4ae8 sha1 dc819b082f671699ac189a49075854d8ff7a2b8f ) ) game ( @@ -31579,6 +32248,12 @@ game ( rom ( name "StarHawk (Europe).gb" size 131072 crc e032e502 sha1 4c22e06cb98119923126f6500568ce9f136a33c5 flags verified ) ) +game ( + name "StarHawk (World) (Limited Run Games)" + description "StarHawk (World) (Limited Run Games)" + rom ( name "StarHawk (World) (Limited Run Games).gb" size 131072 crc 00da50e2 sha1 bf64c1b1071bd243417b6c29fd8a4dd559d3f63a ) +) + game ( name "Stop That Roach! (USA)" description "Stop That Roach! (USA)" @@ -31615,12 +32290,6 @@ game ( rom ( name "Street Racer (USA, Europe).gb" size 131072 crc fcfb4ce4 sha1 4e1d17772eb939cb0a3bce73e4378384d96836ce flags verified ) ) -game ( - name "Suicide Run (World) (Aftermarket) (Unl)" - description "Suicide Run (World) (Aftermarket) (Unl)" - rom ( name "Suicide Run (World) (Aftermarket) (Unl).gb" size 262144 crc d29ab1aa sha1 df373f58e51155e32fb81825a9082150f6d263c8 ) -) - game ( name "Sumo Fighter (USA)" description "Sumo Fighter (USA)" @@ -31747,12 +32416,6 @@ game ( rom ( name "Super Chinese Land 3 (Japan) (SGB Enhanced).gb" size 262144 crc e01caf0b sha1 6d8ef3fdd1702d629c679636698e1d483fc3723b flags verified ) ) -game ( - name "Super Covid Go Get Biscuits Adventure (World) (Aftermarket) (Unl)" - description "Super Covid Go Get Biscuits Adventure (World) (Aftermarket) (Unl)" - rom ( name "Super Covid Go Get Biscuits Adventure (World) (Aftermarket) (Unl).gb" size 262144 crc 51946e8d sha1 cac4917d56da02cf88ba68e0c5189a18c2c234ac ) -) - game ( name "Super Donkey Kong 3 (Taiwan) (Unl)" description "Super Donkey Kong 3 (Taiwan) (Unl)" @@ -31783,12 +32446,6 @@ game ( rom ( name "Super Hunchback (USA).gb" size 131072 crc 1a45706e sha1 9d53fbfeeec5a1a8352177c157ce615621c4b30c ) ) -game ( - name "Super Imposter Bros. (World) (Aftermarket) (Unl)" - description "Super Imposter Bros. (World) (Aftermarket) (Unl)" - rom ( name "Super Imposter Bros. (World) (Aftermarket) (Unl).gb" size 1048576 crc a38d702f sha1 301f93da4e5b0cd8dc3f1bf3e66e38176b8a909b ) -) - game ( name "Super James Pond (Europe)" description "Super James Pond (Europe)" @@ -31951,12 +32608,6 @@ game ( rom ( name "Superman (USA, Europe) (SGB Enhanced).gb" size 131072 crc 358e0091 sha1 3a987cb4ba6f33717ea70d7388ec1dfe6ab934e8 flags verified ) ) -game ( - name "Sushi Gun (World) (Aftermarket) (Unl)" - description "Sushi Gun (World) (Aftermarket) (Unl)" - rom ( name "Sushi Gun (World) (Aftermarket) (Unl).gb" size 262144 crc a9d405d6 sha1 c075856939d4fe3cd250083b527b3e09be70052d ) -) - game ( name "Sutte Hakkun (Japan) (Proto) (SGB Enhanced)" description "Sutte Hakkun (Japan) (Proto) (SGB Enhanced)" @@ -31981,12 +32632,6 @@ game ( rom ( name "Swamp Thing (USA, Europe).gb" size 131072 crc 76ae62c8 sha1 1ff322b5f44d21c951dcdf8d062d99ffa65827e3 flags verified ) ) -game ( - name "SWAPLATFORMER (World) (Aftermarket) (Unl)" - description "SWAPLATFORMER (World) (Aftermarket) (Unl)" - rom ( name "SWAPLATFORMER (World) (Aftermarket) (Unl).gb" size 1048576 crc babe7935 sha1 3df0c37862b7c391a0d091a55db0d305341529c2 ) -) - game ( name "Sword of Hope II, The (USA)" description "Sword of Hope II, The (USA)" @@ -32023,12 +32668,6 @@ game ( rom ( name "Sword of Hope, The (Europe) (Proto).gb" size 131072 crc c360f279 sha1 383ef07e04280f82da374852d04e7f98e9a00ae1 ) ) -game ( - name "Swordbird Song - The Iron Owl Tower (World) (v3.1) (Aftermarket) (Unl)" - description "Swordbird Song - The Iron Owl Tower (World) (v3.1) (Aftermarket) (Unl)" - rom ( name "Swordbird Song - The Iron Owl Tower (World) (v3.1) (Aftermarket) (Unl).gb" size 1048576 crc 64921bb1 sha1 b36ec89e0299c19767cc5c6467fa3664abbc3017 ) -) - game ( name "T2 - The Arcade Game (Japan)" description "T2 - The Arcade Game (Japan)" @@ -32053,6 +32692,12 @@ game ( rom ( name "Tail 'Gator (USA, Europe).gb" size 65536 crc c5acce7c sha1 ed5f1110a9db4c48d26d53af0973e8b46fe7e4e1 ) ) +game ( + name "Tail 'Gator (World) (Limited Run Games)" + description "Tail 'Gator (World) (Limited Run Games)" + rom ( name "Tail 'Gator (World) (Limited Run Games).gb" size 65536 crc e35cd748 sha1 203f6e20e4d44792c727fe78aaa65e354d014175 ) +) + game ( name "Taito Chase H.Q. (Japan)" description "Taito Chase H.Q. (Japan)" @@ -32095,12 +32740,6 @@ game ( rom ( name "Takeda Nobuhiro no Ace Striker (Japan).gb" size 262144 crc 7ff546df sha1 e354310c9946f48eb325c070e9c2c5ccb2e9f429 ) ) -game ( - name "Tales of Monsterland (World) (v2.83) (Aftermarket) (Unl)" - description "Tales of Monsterland (World) (v2.83) (Aftermarket) (Unl)" - rom ( name "Tales of Monsterland (World) (v2.83) (Aftermarket) (Unl).gb" size 2097152 crc a685f89a sha1 15a709d4300464b03ede4d774ce69cfb699c0fcf ) -) - game ( name "TaleSpin (Europe)" description "TaleSpin (Europe)" @@ -32167,12 +32806,6 @@ game ( rom ( name "Taz-Mania 2 (USA).gb" size 131072 crc 4ccb65e0 sha1 60116a304e85f04209dc7eb64d9649dc41c963f6 ) ) -game ( - name "Tech and Blood (World) (Aftermarket) (Unl)" - description "Tech and Blood (World) (Aftermarket) (Unl)" - rom ( name "Tech and Blood (World) (Aftermarket) (Unl).gb" size 262144 crc 3da2a358 sha1 40a00fce49b16cb36793df30e5156e5bf3e47778 ) -) - game ( name "Tecmo Bowl (USA)" description "Tecmo Bowl (USA)" @@ -32425,18 +33058,6 @@ game ( rom ( name "Tetris Plus (USA, Europe) (SGB Enhanced).gb" size 262144 crc dafc3bff sha1 dfab75ab6bdc0765ba9a5d33a93ffdb114a49cbf flags verified ) ) -game ( - name "There's Nothing To Do In This Town (World) (Aftermarket) (Unl)" - description "There's Nothing To Do In This Town (World) (Aftermarket) (Unl)" - rom ( name "There's Nothing To Do In This Town (World) (Aftermarket) (Unl).gb" size 1048576 crc 173b549a sha1 e000fbecda9ea6bbbd0c0370cf8c3faaa54bf64e ) -) - -game ( - name "Thin Ice Rescue, The (World) (Aftermarket) (Unl)" - description "Thin Ice Rescue, The (World) (Aftermarket) (Unl)" - rom ( name "Thin Ice Rescue, The (World) (Aftermarket) (Unl).gb" size 32768 crc 3e0483d6 sha1 b789ced0fe26785e7bce765a9d6ee783f9d967d8 ) -) - game ( name "Tintin - Prisoners of the Sun (Europe) (En,Fr,De)" description "Tintin - Prisoners of the Sun (Europe) (En,Fr,De)" @@ -32461,18 +33082,6 @@ game ( rom ( name "Tintin in Tibet (Europe) (En,Es,It,Sv) (Beta) (SGB Enhanced).gb" size 262144 crc 68b7fcf2 sha1 63070514f0a692cef70e9344ca0a973f6af510c9 ) ) -game ( - name "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.4) (Aftermarket) (Unl)" - description "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.4) (Aftermarket) (Unl)" - rom ( name "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.4) (Aftermarket) (Unl).gb" size 262144 crc af13e718 sha1 307e51664db2101755b6c617f3d81ee58676c485 ) -) - -game ( - name "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.2) (Aftermarket) (Unl)" - description "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.2) (Aftermarket) (Unl)" - rom ( name "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.2) (Aftermarket) (Unl).gb" size 262144 crc 0518f5aa sha1 85e5cd0cf7a6cc4a5946c93fa8665235a686e554 ) -) - game ( name "Tiny Toon Adventures (Japan)" description "Tiny Toon Adventures (Japan)" @@ -32539,12 +33148,6 @@ game ( rom ( name "Titus the Fox (USA, Europe).gb" size 262144 crc 814fa146 sha1 ba0037aeb21de0bbba3f9294a7861d90aefa5008 flags verified ) ) -game ( - name "Tobu Tobu Girl (World) (Aftermarket) (Unl)" - description "Tobu Tobu Girl (World) (Aftermarket) (Unl)" - rom ( name "Tobu Tobu Girl (World) (Aftermarket) (Unl).gb" size 262144 crc ed12be6c sha1 8a8f3c1f21f903ea5a7df8fc8b0a6aa5a602e150 ) -) - game ( name "Tokio Senki - Eiyuu Retsuden (Japan)" description "Tokio Senki - Eiyuu Retsuden (Japan)" @@ -32713,12 +33316,6 @@ game ( rom ( name "Trax (USA, Europe).gb" size 131072 crc 4a38be7d sha1 3f3a31ed7e47319c5815dd6e31ca27a52377423c flags verified ) ) -game ( - name "Treasure Island (World) (Aftermarket) (Unl)" - description "Treasure Island (World) (Aftermarket) (Unl)" - rom ( name "Treasure Island (World) (Aftermarket) (Unl).gb" size 262144 crc cbdec393 sha1 adeaba2723d286d143e0987f51ce9c8ad2f5e839 ) -) - game ( name "Trip World (Europe)" description "Trip World (Europe)" @@ -32731,6 +33328,12 @@ game ( rom ( name "Trip World (Japan).gb" size 262144 crc 11568e64 sha1 ac19d49906e72aaebeffa9ab7106eb346a5efa07 ) ) +game ( + name "Trip World (World) (Limited Run Games)" + description "Trip World (World) (Limited Run Games)" + rom ( name "Trip World (World) (Limited Run Games).gb" size 262144 crc ec67f1e6 sha1 16bb82fa8708cbd159388c55e702b9fb9ed5a41f ) +) + game ( name "TripleA (USA) (Proto)" description "TripleA (USA) (Proto)" @@ -32743,12 +33346,6 @@ game ( rom ( name "Triumph (USA) (Proto).gb" size 131072 crc 746159b2 sha1 90a40fc94709a3ec6945281bde2644d91bef28b5 ) ) -game ( - name "Trouble City - Pocket Mission (World) (Aftermarket) (Unl)" - description "Trouble City - Pocket Mission (World) (Aftermarket) (Unl)" - rom ( name "Trouble City - Pocket Mission (World) (Aftermarket) (Unl).gb" size 524288 crc 4b9143ad sha1 0e51e398d44aaad74a7c622f7818b56a3b34db56 ) -) - game ( name "True Lies (USA, Europe)" description "True Lies (USA, Europe)" @@ -32965,18 +33562,6 @@ game ( rom ( name "Undercover Cops Gaiden - Hakaishin Garumaa (Japan).gb" size 262144 crc b7af37f5 sha1 e391ea099ce371eef858d57e6c2da63a25944472 ) ) -game ( - name "Unearthed (World) (v1.3) (Aftermarket) (Unl)" - description "Unearthed (World) (v1.3) (Aftermarket) (Unl)" - rom ( name "Unearthed (World) (v1.3) (Aftermarket) (Unl).gb" size 2097152 crc 29bb9238 sha1 39fbfb220e9be0120090f770249049b3f3583f64 ) -) - -game ( - name "Ungrateful Son, The (World) (v1.1) (Aftermarket) (Unl)" - description "Ungrateful Son, The (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Ungrateful Son, The (World) (v1.1) (Aftermarket) (Unl).gb" size 262144 crc 977b54f4 sha1 016dde406896d827dcad682d40b52d0e9eeefa88 ) -) - game ( name "Universal Soldier (USA, Europe)" description "Universal Soldier (USA, Europe)" @@ -33019,12 +33604,6 @@ game ( rom ( name "V-Rally - Championship Edition (Europe) (En,Fr,De).gb" size 262144 crc d149652b sha1 67d2a6e41b6a1d8372808535ac8c8222d7c53480 flags verified ) ) -game ( - name "Vampire Night Shift (World) (Aftermarket) (Unl)" - description "Vampire Night Shift (World) (Aftermarket) (Unl)" - rom ( name "Vampire Night Shift (World) (Aftermarket) (Unl).gb" size 262144 crc 88acbc1a sha1 ef617803c2cdb14cfe3b3b2111aa239a3744e29e ) -) - game ( name "Vattle Giuce (Japan)" description "Vattle Giuce (Japan)" @@ -33079,12 +33658,6 @@ game ( rom ( name "VS Battler (Japan).gb" size 65536 crc 20ae389a sha1 5f99c7767cbbf5ad9164805214875d7054f49f14 ) ) -game ( - name "Waifu Clicker (World) (Aftermarket) (Unl)" - description "Waifu Clicker (World) (Aftermarket) (Unl)" - rom ( name "Waifu Clicker (World) (Aftermarket) (Unl).gb" size 65536 crc 155f85dc sha1 bb571ed69c3a33e45ba33fbb03a066ba98ae0b20 ) -) - game ( name "Wario Blast Featuring Bomberman! (USA, Europe) (SGB Enhanced)" description "Wario Blast Featuring Bomberman! (USA, Europe) (SGB Enhanced)" @@ -33103,24 +33676,6 @@ game ( rom ( name "Wario Land II (USA, Europe) (SGB Enhanced).gb" size 1048576 crc 9c54358d sha1 c65820b2e52d00e6ce60e0a432fab002fec4386f flags verified ) ) -game ( - name "Warp Coin Catastrophe, The (World) (v1.1) (Aftermarket) (Unl)" - description "Warp Coin Catastrophe, The (World) (v1.1) (Aftermarket) (Unl)" - rom ( name "Warp Coin Catastrophe, The (World) (v1.1) (Aftermarket) (Unl).gb" size 1048576 crc a381c914 sha1 adf37c5d2f706743b2a4946378df49ed19212039 ) -) - -game ( - name "Warp Coin Catastrophe, The (World) (v1.0) (Aftermarket) (Unl)" - description "Warp Coin Catastrophe, The (World) (v1.0) (Aftermarket) (Unl)" - rom ( name "Warp Coin Catastrophe, The (World) (v1.0) (Aftermarket) (Unl).gb" size 1048576 crc 1bfe1bf9 sha1 fae12dbbb75ae024e96a7ee21ad4077fdb5ed9a1 ) -) - -game ( - name "Warp Coin Catastrophe, The (World) (v1.1.2) (Aftermarket) (Unl)" - description "Warp Coin Catastrophe, The (World) (v1.1.2) (Aftermarket) (Unl)" - rom ( name "Warp Coin Catastrophe, The (World) (v1.1.2) (Aftermarket) (Unl).gb" size 1048576 crc 5519c167 sha1 04a53af6a77b884af91f8047d70fc0331bf23913 ) -) - game ( name "Waterworld (Europe)" description "Waterworld (Europe)" @@ -33163,16 +33718,10 @@ game ( rom ( name "Welcome Nakayoshi Park (Japan).gb" size 262144 crc f6e2baae sha1 8779a1557ba0de3c5c8b770413f30bd31717b2ef ) ) -game ( - name "What's Updog (World) (Aftermarket) (Unl)" - description "What's Updog (World) (Aftermarket) (Unl)" - rom ( name "What's Updog (World) (Aftermarket) (Unl).gb" size 262144 crc 2c3d5cbf sha1 a235c0915ac2b826eeb5884d0eccd321236fdb0c ) -) - game ( name "Wheel of Fortune (USA)" description "Wheel of Fortune (USA)" - rom ( name "Wheel of Fortune (USA).gb" size 131072 crc 8408fe48 sha1 43de94eda492bfabbdc6e232af9cbd9df080dfd5 ) + rom ( name "Wheel of Fortune (USA).gb" size 131072 crc 8408fe48 sha1 43de94eda492bfabbdc6e232af9cbd9df080dfd5 flags verified ) ) game ( @@ -33205,12 +33754,6 @@ game ( rom ( name "Wily & Right no Rockboard - That's Paradise (Japan) (Proto).gb" size 262144 crc af84dc97 sha1 cc917f113c5cdd1afc3340feb8bf2094d0902cec ) ) -game ( - name "Windows93 Adventure (World) (Aftermarket) (Unl)" - description "Windows93 Adventure (World) (Aftermarket) (Unl)" - rom ( name "Windows93 Adventure (World) (Aftermarket) (Unl).gb" size 1048576 crc e1ad0b6f sha1 3ad7327f6f94976c3d12054cf6deb2666ba9fa66 ) -) - game ( name "Winner's Horse (Japan)" description "Winner's Horse (Japan)" @@ -33235,12 +33778,6 @@ game ( rom ( name "Winter Olympic Games (USA) (Rev 1) (Beta).gb" size 131072 crc 1510305e sha1 6f66dc2ab6f302251591a1252be12367a8e8dfe4 ) ) -game ( - name "Wizard of Wor (World) (Aftermarket) (Unl)" - description "Wizard of Wor (World) (Aftermarket) (Unl)" - rom ( name "Wizard of Wor (World) (Aftermarket) (Unl).gb" size 524288 crc bfb1563e sha1 108eefa154412e3422dce4e63bf34f5826ec1baa ) -) - game ( name "Wizardry Gaiden I - Joou no Junan (Japan)" description "Wizardry Gaiden I - Joou no Junan (Japan)" @@ -33265,12 +33802,6 @@ game ( rom ( name "Wizards & Warriors X - The Fortress of Fear (USA, Europe).gb" size 65536 crc 104eb503 sha1 22a514056e58263dc08602778bc3bf2c0ca6e681 flags verified ) ) -game ( - name "Woolball's Backyard (World) (Aftermarket) (Unl)" - description "Woolball's Backyard (World) (Aftermarket) (Unl)" - rom ( name "Woolball's Backyard (World) (Aftermarket) (Unl).gb" size 65536 crc 69e26eb6 sha1 28795c4b829440549b3ac2afe3282d85a439f7d7 ) -) - game ( name "Wordtris (USA)" description "Wordtris (USA)" @@ -33481,6 +34012,18 @@ game ( rom ( name "Xenon 2 - Megablast (Japan).gb" size 131072 crc 2feb70d2 sha1 6b2f009b7a443e5ead48a2864bfb1d29096ed6a0 ) ) +game ( + name "Xin Nushen Zhuansheng Waizhuan - Zuihou de Shengjing (Taiwan) (Pirate)" + description "Xin Nushen Zhuansheng Waizhuan - Zuihou de Shengjing (Taiwan) (Pirate)" + rom ( name "Xin Nushen Zhuansheng Waizhuan - Zuihou de Shengjing (Taiwan) (Pirate).gb" size 524288 crc 2298585c sha1 f33091c0bfd840e0ce4c4f99c463cfb92f823a64 ) +) + +game ( + name "Xin Shuma Baobei Huang (China) (Pirate)" + description "Xin Shuma Baobei Huang (China) (Pirate)" + rom ( name "Xin Shuma Baobei Huang (China) (Pirate).gb" size 2097152 crc 86869520 sha1 b341efb4831b0fe066fd035ba9f7f876efa3cd50 ) +) + game ( name "Yakuman (Japan)" description "Yakuman (Japan)" @@ -33500,27 +34043,9 @@ game ( ) game ( - name "Year After, The (World) (Beta 2) (Aftermarket) (Unl)" - description "Year After, The (World) (Beta 2) (Aftermarket) (Unl)" - rom ( name "Year After, The (World) (Beta 2) (Aftermarket) (Unl).gb" size 1048576 crc 4e463a1a sha1 5d84f53f38aa24f54a6f897ca69ffc5d978805af ) -) - -game ( - name "Year After, The (World) (Beta) (Aftermarket) (Unl)" - description "Year After, The (World) (Beta) (Aftermarket) (Unl)" - rom ( name "Year After, The (World) (Beta) (Aftermarket) (Unl).gb" size 1048576 crc f15351c8 sha1 a78ff2eef780287bbdc37df122cfc1c504526662 ) -) - -game ( - name "Year After, The (World) (Pt) (Beta) (Aftermarket) (Unl)" - description "Year After, The (World) (Pt) (Beta) (Aftermarket) (Unl)" - rom ( name "Year After, The (World) (Pt) (Beta) (Aftermarket) (Unl).gb" size 1048576 crc b70c1c7f sha1 ce25cdf6a6264586423e76e34dc42779d39a1cb1 ) -) - -game ( - name "Year After, The (World) (Fr) (Beta) (Aftermarket) (Unl)" - description "Year After, The (World) (Fr) (Beta) (Aftermarket) (Unl)" - rom ( name "Year After, The (World) (Fr) (Beta) (Aftermarket) (Unl).gb" size 1048576 crc fbc50ee8 sha1 52c27e64fb37412c97a53d5dde52c3803fd1e4f7 ) + name "Yelu Wangzi (Prince Yeh Rude) (Taiwan) (En) (Unl)" + description "Yelu Wangzi (Prince Yeh Rude) (Taiwan) (En) (Unl)" + rom ( name "Yelu Wangzi (Prince Yeh Rude) (Taiwan) (En) (Unl).gb" size 65536 crc 76ab9719 sha1 e4a762ef26a40fb88b4e89b839da8baa6e06b051 ) ) game ( @@ -33607,18 +34132,6 @@ game ( rom ( name "Yu-Gi-Oh! Duel Monsters (Japan) (SGB Enhanced).gb" size 1048576 crc 8875ec54 sha1 07ae4a6437f00f6af462bf84fd0ac1cf345c8365 flags verified ) ) -game ( - name "Yuuto Ichika Makes Friends (World) (En,Ja) (Aftermarket) (Unl)" - description "Yuuto Ichika Makes Friends (World) (En,Ja) (Aftermarket) (Unl)" - rom ( name "Yuuto Ichika Makes Friends (World) (En,Ja) (Aftermarket) (Unl).gb" size 524288 crc 8a667058 sha1 e765d6915f543a5a65e8be440b3f29eb674a5448 ) -) - -game ( - name "Zagan Warrior (World) (Aftermarket) (Unl)" - description "Zagan Warrior (World) (Aftermarket) (Unl)" - rom ( name "Zagan Warrior (World) (Aftermarket) (Unl).gb" size 262144 crc 97fe7a94 sha1 88f76297a4ccf0e3a5ba16ca15237c88346c134a ) -) - game ( name "ZAS (Europe) (Proto)" description "ZAS (Europe) (Proto)" @@ -33637,6 +34150,12 @@ game ( rom ( name "Zelda no Densetsu - Yume o Miru Shima (Japan) (Rev 1).gb" size 524288 crc ea20b82a sha1 80f5d111c7e2d79d39f6c25a37b54c3196d2bd12 flags verified ) ) +game ( + name "Zelda no Densetsu - Yume o Miru Shima (Japan) (Rev 1) (Demo) (Special Version)" + description "Zelda no Densetsu - Yume o Miru Shima (Japan) (Rev 1) (Demo) (Special Version)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima (Japan) (Rev 1) (Demo) (Special Version).gb" size 524288 crc bcc0199a sha1 5fc7b8185096c4203536e0d8a302064e63511086 ) +) + game ( name "Zen - Intergalactic Ninja (Europe)" description "Zen - Intergalactic Ninja (Europe)" @@ -33698,9 +34217,9 @@ game ( ) game ( - name "Zoop (Japan)" - description "Zoop (Japan)" - rom ( name "Zoop (Japan).gb" size 65536 crc 10e1a10c sha1 89a74970761700d591c2affc47c9306f49d22ba8 ) + name "Zoop (Japan) (En)" + description "Zoop (Japan) (En)" + rom ( name "Zoop (Japan) (En).gb" size 65536 crc 10e1a10c sha1 89a74970761700d591c2affc47c9306f49d22ba8 ) ) game ( @@ -33716,16 +34235,1584 @@ game ( ) game ( - name "Zuigao Jimi - Top Secret (Taiwan) (Unl)" - description "Zuigao Jimi - Top Secret (Taiwan) (Unl)" - rom ( name "Zuigao Jimi - Top Secret (Taiwan) (Unl).gb" size 65536 crc f5f8d0b3 sha1 be706d1b46fa1de966f0b3b08e85399177eb148c ) + name "Zuigao Jimi (Top Secret) (Taiwan) (Multicart Rip) (Unl)" + description "Zuigao Jimi (Top Secret) (Taiwan) (Multicart Rip) (Unl)" + rom ( name "Zuigao Jimi (Top Secret) (Taiwan) (Multicart Rip) (Unl).gb" size 65536 crc f5f8d0b3 sha1 be706d1b46fa1de966f0b3b08e85399177eb148c ) +) + +game ( + name "Zuigao Jimi (Top Secret) (Taiwan) (Unl)" + description "Zuigao Jimi (Top Secret) (Taiwan) (Unl)" + rom ( name "Zuigao Jimi (Top Secret) (Taiwan) (Unl).gb" size 65536 crc 46402abe sha1 7afcc6dd82bb236f1ebe01c9b5ccad4d713ccbcf ) +) + +clrmamepro ( + name "Nintendo - Game Boy (Aftermarket)" + description "Nintendo - Game Boy (Aftermarket)" + version 20240809-004429 + author "aci68, akubi, Arctic Circle System, Aringon, baldjared, Bent, BigFred, BitLooter, buckwheat, C. V. Reynolds, chillerecke, darthcloud, DeadSkullzJr, Densetsu, DeriLoko3, ElBarto, foxe, fuzzball, Gefflon, Hiccup, hking0036, InternalLoss, Jack, jimmsu, Just001Kim, kazumi213, leekindo, Lesserkuma, Madeline, NESBrew12, NGEfreak, nnssxx, norkmetnoil577, NovaAurora, omonim2007, Powerpuff, PPLToast, Psychofox11, psykopat, rarenight, relax, RetroUprising, rpg2813, sCZther, SonGoku, Tauwasser, togemet2, UnlockerPT, xNo, xprism, xuom2" + homepage No-Intro + url "https://www.no-intro.org" + forcenodump required +) + +emulator ( + name "datafile" +) + +game ( + name "14 Juillet (World) (Fr) (Aftermarket) (Unl)" + description "14 Juillet (World) (Fr) (Aftermarket) (Unl)" + rom ( name "14 Juillet (World) (Fr) (Aftermarket) (Unl).gb" size 1048576 crc 7b66bee4 sha1 02f387457a779cbd2f493e52743cd32c169c098e ) +) + +game ( + name "Adulting! (World) (v2.0) (Aftermarket) (Unl)" + description "Adulting! (World) (v2.0) (Aftermarket) (Unl)" + rom ( name "Adulting! (World) (v2.0) (Aftermarket) (Unl).gb" size 524288 crc e56d1244 sha1 d107bd8bf32d0d94a988466885fe1a44aae32c9a flags verified ) +) + +game ( + name "Alley (World) (Aftermarket) (Unl)" + description "Alley (World) (Aftermarket) (Unl)" + rom ( name "Alley (World) (Aftermarket) (Unl).gb" size 32768 crc 2a26f8dd sha1 34bc4f54c0577f55bd40ce1155b6cc74a72ec4e2 ) +) + +game ( + name "Alphamax (World) (Aftermarket) (Unl)" + description "Alphamax (World) (Aftermarket) (Unl)" + rom ( name "Alphamax (World) (Aftermarket) (Unl).gb" size 131072 crc 8b493b41 sha1 798dda34d04a06dcee32f44f8a4a045caf734927 ) +) + +game ( + name "Anctrayl (World) (Aftermarket) (Unl)" + description "Anctrayl (World) (Aftermarket) (Unl)" + rom ( name "Anctrayl (World) (Aftermarket) (Unl).gb" size 65536 crc c6eca93a sha1 403a40761eec80cf7938bcae3a6deeaf17838311 ) +) + +game ( + name "Another Push Game (World) (v1.07) (Proto) (Aftermarket) (Unl)" + description "Another Push Game (World) (v1.07) (Proto) (Aftermarket) (Unl)" + rom ( name "Another Push Game (World) (v1.07) (Proto) (Aftermarket) (Unl).gb" size 262144 crc 8c40cbc9 sha1 6b84d7322d30e9c06a4fdac0050f2c22babaaa7d ) +) + +game ( + name "Aqua (World) (v1.1) (Aftermarket) (Unl)" + description "Aqua (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Aqua (World) (v1.1) (Aftermarket) (Unl).gb" size 32768 crc f9ad0e12 sha1 cb5871dc5bca8b6fd5888b9d3a591fbfe082c11d ) +) + +game ( + name "Aqua (World) (v1.0) (Aftermarket) (Unl)" + description "Aqua (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "Aqua (World) (v1.0) (Aftermarket) (Unl).gb" size 32768 crc 561aa835 sha1 311728bfcc1c4f51842f9da5022187e749e35045 ) +) + +game ( + name "Art School Pocket (World) (En) (Aftermarket) (Unl)" + description "Art School Pocket (World) (En) (Aftermarket) (Unl)" + rom ( name "Art School Pocket (World) (En) (Aftermarket) (Unl).gb" size 1048576 crc b4eab528 sha1 c482cfc6ec40b1f33c4ba48ecdc45fef4730b653 ) +) + +game ( + name "Art School Pocket (World) (Es) (Aftermarket) (Unl)" + description "Art School Pocket (World) (Es) (Aftermarket) (Unl)" + rom ( name "Art School Pocket (World) (Es) (Aftermarket) (Unl).gb" size 1048576 crc 240067df sha1 c8a75895c87b11f9493f629c19c54d0c607505bd ) +) + +game ( + name "Art School Pocket (World) (Fr) (Aftermarket) (Unl)" + description "Art School Pocket (World) (Fr) (Aftermarket) (Unl)" + rom ( name "Art School Pocket (World) (Fr) (Aftermarket) (Unl).gb" size 1048576 crc 49a5b74d sha1 73ecffaee185eb2caf1db385d04b863676c777fb ) +) + +game ( + name "Art School Pocket (World) (De) (Aftermarket) (Unl)" + description "Art School Pocket (World) (De) (Aftermarket) (Unl)" + rom ( name "Art School Pocket (World) (De) (Aftermarket) (Unl).gb" size 1048576 crc 82b73e5b sha1 7772e2b9d5e722e54d19fc6283ccb1fa5d19b641 ) +) + +game ( + name "Asteroids Chasers (World) (Aftermarket) (Unl)" + description "Asteroids Chasers (World) (Aftermarket) (Unl)" + rom ( name "Asteroids Chasers (World) (Aftermarket) (Unl).gb" size 131072 crc 58d8b1b8 sha1 f93a4e6788eaf0231a6ca269cca297f0d45ec830 flags verified ) +) + +game ( + name "Astro-Jump (World) (Aftermarket) (Unl)" + description "Astro-Jump (World) (Aftermarket) (Unl)" + rom ( name "Astro-Jump (World) (Aftermarket) (Unl).gb" size 262144 crc c35a3b39 sha1 1bcb4be684626ce061aad105701548fa3a77e254 ) +) + +game ( + name "Athletic World (World) (Demo) (SGB Enhanced) (Aftermarket) (Unl)" + description "Athletic World (World) (Demo) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Athletic World (World) (Demo) (SGB Enhanced) (Aftermarket) (Unl).gb" size 131072 crc afc128f2 sha1 956be9371990b18e351f2e10848b2ea8bb70c2b7 ) +) + +game ( + name "Auto Zone (World) (Aftermarket) (Unl)" + description "Auto Zone (World) (Aftermarket) (Unl)" + rom ( name "Auto Zone (World) (Aftermarket) (Unl).gb" size 524288 crc cee73c14 sha1 3070ec215014633dac5dbbb487aade2e2993c049 ) +) + +game ( + name "Binding of Isaac, The - Game Boy Edition (World) (Aftermarket) (Unl)" + description "Binding of Isaac, The - Game Boy Edition (World) (Aftermarket) (Unl)" + rom ( name "Binding of Isaac, The - Game Boy Edition (World) (Aftermarket) (Unl).gb" size 32768 crc bf922249 sha1 187782720d4f7c0986a0d916b0c7efa2c488612e ) +) + +game ( + name "Birdie Bartender (World) (Aftermarket) (Unl)" + description "Birdie Bartender (World) (Aftermarket) (Unl)" + rom ( name "Birdie Bartender (World) (Aftermarket) (Unl).gb" size 262144 crc 0bf2a1c8 sha1 aa1325fc7160b84745b076de9b976a1b368da50e ) +) + +game ( + name "Black Castle (World) (Aftermarket) (Unl)" + description "Black Castle (World) (Aftermarket) (Unl)" + rom ( name "Black Castle (World) (Aftermarket) (Unl).gb" size 65536 crc 10f577c7 sha1 45d979be572bb820835d2ecd4e990cd1eadbf5a6 ) +) + +game ( + name "Blitz Bomber (World) (Aftermarket) (Unl)" + description "Blitz Bomber (World) (Aftermarket) (Unl)" + rom ( name "Blitz Bomber (World) (Aftermarket) (Unl).gb" size 262144 crc 5e9956de sha1 b72cbc6bfa6ceef940f49c9c82024071c6f82b90 ) +) + +game ( + name "Blockade (World) (Aftermarket) (Unl)" + description "Blockade (World) (Aftermarket) (Unl)" + rom ( name "Blockade (World) (Aftermarket) (Unl).gb" size 262144 crc b8cfab16 sha1 9e753048a0eb036ac17c08f5a64d860abd1aaaf5 ) +) + +game ( + name "Bork Paw Kisses (World) (Aftermarket) (Unl)" + description "Bork Paw Kisses (World) (Aftermarket) (Unl)" + rom ( name "Bork Paw Kisses (World) (Aftermarket) (Unl).gb" size 262144 crc c29f0d35 sha1 8f1efe6982d2b4ebc1fbeb3ade68dd9b9aabb7a6 ) +) + +game ( + name "Borruga - Neo Pinball (World) (Aftermarket) (Unl)" + description "Borruga - Neo Pinball (World) (Aftermarket) (Unl)" + rom ( name "Borruga - Neo Pinball (World) (Aftermarket) (Unl).gb" size 32768 crc 2bb55ca5 sha1 269f12091d5ab87362a2cb2cf5484f14bfcbd537 flags verified ) +) + +game ( + name "Bounce (World) (v1.1) (Aftermarket) (Unl)" + description "Bounce (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Bounce (World) (v1.1) (Aftermarket) (Unl).gb" size 32768 crc 827f2bd5 sha1 e9abf64de3faeb48151003ac8bb77dea61e838b5 ) +) + +game ( + name "Bouncing Ball, The (World) (Aftermarket) (Unl)" + description "Bouncing Ball, The (World) (Aftermarket) (Unl)" + rom ( name "Bouncing Ball, The (World) (Aftermarket) (Unl).gb" size 65536 crc 42ddf53e sha1 5d331f2e66d7d3f4b4b0fcbaf6ab4b1a0147db3e ) +) + +game ( + name "Bourgogne Game Show 2022 (World) (Aftermarket) (Unl)" + description "Bourgogne Game Show 2022 (World) (Aftermarket) (Unl)" + rom ( name "Bourgogne Game Show 2022 (World) (Aftermarket) (Unl).gb" size 262144 crc 98222a4a sha1 0bdb8ad04469a329c8cee2fb0c55da35f7752042 ) +) + +game ( + name "Breakout Lava-Lamp (World) (Aftermarket) (Unl)" + description "Breakout Lava-Lamp (World) (Aftermarket) (Unl)" + rom ( name "Breakout Lava-Lamp (World) (Aftermarket) (Unl).gb" size 32768 crc 7fbe9fb7 sha1 9de08cdb4cdab58c79e0f2bdaef8b8bb736b9c50 ) +) + +game ( + name "Brimstone (World) (Demo) (Aftermarket) (Unl)" + description "Brimstone (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Brimstone (World) (Demo) (Aftermarket) (Unl).gb" size 262144 crc f18f44a6 sha1 f193af733f6dfdf8d4403be1d9caa67d7e6f3c37 ) +) + +game ( + name "Bug Bites! (World) (Aftermarket) (Unl)" + description "Bug Bites! (World) (Aftermarket) (Unl)" + rom ( name "Bug Bites! (World) (Aftermarket) (Unl).gb" size 262144 crc bb473d7a sha1 8d601612ac262e4548d8b8f6ac19a04cb92ecfb7 ) +) + +game ( + name "Busty Bunny the Bounty Babe (World) (v1.02) (Aftermarket) (Unl)" + description "Busty Bunny the Bounty Babe (World) (v1.02) (Aftermarket) (Unl)" + rom ( name "Busty Bunny the Bounty Babe (World) (v1.02) (Aftermarket) (Unl).gb" size 1048576 crc d0ed199c sha1 a1cbaacdf32cb8fb9a9c59fcb624c729e0ca17bf ) +) + +game ( + name "Castledark (World) (v2.0) (Demo) (Aftermarket) (Unl)" + description "Castledark (World) (v2.0) (Demo) (Aftermarket) (Unl)" + rom ( name "Castledark (World) (v2.0) (Demo) (Aftermarket) (Unl).gb" size 524288 crc 3c492b31 sha1 0861af0039dab4b4f5bce747c6fcd586eced401a ) +) + +game ( + name "Cat and His Boy, A (World) (En,Es) (Demo) (Aftermarket) (Unl)" + description "Cat and His Boy, A (World) (En,Es) (Demo) (Aftermarket) (Unl)" + rom ( name "Cat and His Boy, A (World) (En,Es) (Demo) (Aftermarket) (Unl).gb" size 1048576 crc 11043693 sha1 4db27714c7af6041d5af3cf550e78d7235394afa ) +) + +game ( + name "Cave Fighter (World) (Aftermarket) (Unl)" + description "Cave Fighter (World) (Aftermarket) (Unl)" + rom ( name "Cave Fighter (World) (Aftermarket) (Unl).gb" size 262144 crc e8f91f6a sha1 290048717d0a8cabb3cc591161339550eb53c161 ) +) + +game ( + name "Cel Story (World) (Aftermarket) (Unl)" + description "Cel Story (World) (Aftermarket) (Unl)" + rom ( name "Cel Story (World) (Aftermarket) (Unl).gb" size 524288 crc 8a456b61 sha1 730627b2298806e4f7e02dceffaa0f0edfc316f0 ) +) + +game ( + name "Cel Story (World) (Demo) (Aftermarket) (Unl)" + description "Cel Story (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Cel Story (World) (Demo) (Aftermarket) (Unl).gb" size 524288 crc 92a9b588 sha1 70ab2b72b26c1d1cacc13d377984b969ddf44965 ) +) + +game ( + name "Cheesy Town (World) (En,Ja) (Aftermarket) (Unl)" + description "Cheesy Town (World) (En,Ja) (Aftermarket) (Unl)" + rom ( name "Cheesy Town (World) (En,Ja) (Aftermarket) (Unl).gb" size 262144 crc 3e20c1a8 sha1 f76645a2830fcc733b7392a52112df628f0b7a4a ) +) + +game ( + name "Cherry Rescue! (World) (Aftermarket) (Unl)" + description "Cherry Rescue! (World) (Aftermarket) (Unl)" + rom ( name "Cherry Rescue! (World) (Aftermarket) (Unl).gb" size 524288 crc ba65812a sha1 740dba1827c730cc5d8bf67495bcede3a5352643 ) +) + +game ( + name "Christmas Carols (World) (Aftermarket) (Unl)" + description "Christmas Carols (World) (Aftermarket) (Unl)" + rom ( name "Christmas Carols (World) (Aftermarket) (Unl).gb" size 262144 crc a00bb310 sha1 e19b0a698d8194467d57c00664f00f9898ee5368 ) +) + +game ( + name "Ciao Nonna (World) (v1.1) (Aftermarket) (Unl)" + description "Ciao Nonna (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Ciao Nonna (World) (v1.1) (Aftermarket) (Unl).gb" size 1048576 crc 2165f2e4 sha1 f8e5020298183c3f47836da3890b6bb398e2ecab ) +) + +game ( + name "Ciao Nonna (World) (v2.0) (Aftermarket) (Unl)" + description "Ciao Nonna (World) (v2.0) (Aftermarket) (Unl)" + rom ( name "Ciao Nonna (World) (v2.0) (Aftermarket) (Unl).gb" size 1048576 crc 6afee818 sha1 602709c8655febb42899881a8ef598fb4b3da0c9 ) +) + +game ( + name "Ciao Nonna (World) (v2.1) (Aftermarket) (Unl)" + description "Ciao Nonna (World) (v2.1) (Aftermarket) (Unl)" + rom ( name "Ciao Nonna (World) (v2.1) (Aftermarket) (Unl).gb" size 1048576 crc 225ce296 sha1 45aebfe4e7f5382a4b31c3db270b75d2c458d1b2 ) +) + +game ( + name "Ciao Nonna (World) (Aftermarket) (Unl)" + description "Ciao Nonna (World) (Aftermarket) (Unl)" + rom ( name "Ciao Nonna (World) (Aftermarket) (Unl).gb" size 1048576 crc dd7576d6 sha1 0556eb6160fdca6e7959bba1a619b8e34d974375 ) +) + +game ( + name "Coat Man (World) (Aftermarket) (Unl)" + description "Coat Man (World) (Aftermarket) (Unl)" + rom ( name "Coat Man (World) (Aftermarket) (Unl).gb" size 262144 crc db882ef2 sha1 242f4b3e04fe00b514544c5ef14288d13b5faf2c ) +) + +game ( + name "Commando (World) (Aftermarket) (Unl)" + description "Commando (World) (Aftermarket) (Unl)" + rom ( name "Commando (World) (Aftermarket) (Unl).gb" size 262144 crc 48173941 sha1 c861858e9f2cf7470e739c26ae9f17d3834ce464 ) +) + +game ( + name "Cosmic Courier - Trapped in Limbo (World) (Aftermarket) (Unl)" + description "Cosmic Courier - Trapped in Limbo (World) (Aftermarket) (Unl)" + rom ( name "Cosmic Courier - Trapped in Limbo (World) (Aftermarket) (Unl).gb" size 262144 crc fd304687 sha1 7df11ec2946099d49dd62928118b6d76703dc57c ) +) + +game ( + name "Coucou (World) (Aftermarket) (Unl)" + description "Coucou (World) (Aftermarket) (Unl)" + rom ( name "Coucou (World) (Aftermarket) (Unl).gb" size 32768 crc e6aabd72 sha1 5283268e3640e2924d00aea3b12b2d3930bef43c ) +) + +game ( + name "Counting Sheep (World) (Aftermarket) (Unl)" + description "Counting Sheep (World) (Aftermarket) (Unl)" + rom ( name "Counting Sheep (World) (Aftermarket) (Unl).GB" size 65536 crc 6e97c837 sha1 e7e251ad86fa00803837cf871de62d3f100c83ce ) +) + +game ( + name "Cuthbert in the Cooler (World) (Aftermarket) (Unl)" + description "Cuthbert in the Cooler (World) (Aftermarket) (Unl)" + rom ( name "Cuthbert in the Cooler (World) (Aftermarket) (Unl).gb" size 262144 crc 10838580 sha1 c740bc995adf2bb638bb125a36edc416558fd4c6 ) +) + +game ( + name "Cyber Dreamscape Battle-Deckers 2199 (World) (Aftermarket) (Unl)" + description "Cyber Dreamscape Battle-Deckers 2199 (World) (Aftermarket) (Unl)" + rom ( name "Cyber Dreamscape Battle-Deckers 2199 (World) (Aftermarket) (Unl).gb" size 1048576 crc e3a78253 sha1 45c9c6a7a4ec985146a4a616a49dba45decc6d3e ) +) + +game ( + name "Cyberlice (World) (Proto) (Aftermarket) (Unl)" + description "Cyberlice (World) (Proto) (Aftermarket) (Unl)" + rom ( name "Cyberlice (World) (Proto) (Aftermarket) (Unl).gb" size 131072 crc 7e443267 sha1 220219db1870c3c0a562319aab9f1316b2863689 ) +) + +game ( + name "Dangan GB (World) (v1.1) (Aftermarket) (Unl)" + description "Dangan GB (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Dangan GB (World) (v1.1) (Aftermarket) (Unl).gb" size 262144 crc 5359d6db sha1 10029774046dabec2d8c0533caf94091f6e19071 ) +) + +game ( + name "Dangan GB (World) (Aftermarket) (Unl)" + description "Dangan GB (World) (Aftermarket) (Unl)" + rom ( name "Dangan GB (World) (Aftermarket) (Unl).gb" size 262144 crc daa59c9c sha1 8375d845fcfe4c236cd68f3d56a290f8c7b76c06 ) +) + +game ( + name "Dash (World) (Aftermarket) (Unl)" + description "Dash (World) (Aftermarket) (Unl)" + rom ( name "Dash (World) (Aftermarket) (Unl).gb" size 262144 crc 73868683 sha1 c1ffe7c25a34d65ed166293bc7d2b48b65ca922b ) +) + +game ( + name "Deadeus (World) (v1.3.8) (Aftermarket) (Unl)" + description "Deadeus (World) (v1.3.8) (Aftermarket) (Unl)" + rom ( name "Deadeus (World) (v1.3.8) (Aftermarket) (Unl).gb" size 1048576 crc 7da95971 sha1 23cff594ef4b0bb21883b422940526c7fe81f1fd flags verified ) +) + +game ( + name "Deadeus (World) (v1.2.5) (Aftermarket) (Unl)" + description "Deadeus (World) (v1.2.5) (Aftermarket) (Unl)" + rom ( name "Deadeus (World) (v1.2.5) (Aftermarket) (Unl).gb" size 1048576 crc 9e2bf649 sha1 3feeba5c438880f70cdfdc4ea7e29f77e645e9be flags verified ) +) + +game ( + name "Deadeus (World) (v1.1.0) (Aftermarket) (Unl)" + description "Deadeus (World) (v1.1.0) (Aftermarket) (Unl)" + rom ( name "Deadeus (World) (v1.1.0) (Aftermarket) (Unl).gb" size 1048576 crc 818a7db7 sha1 43a93dc6f7bef002271e583edaeaf2e7162b8af4 ) +) + +game ( + name "Deep Forest (World) (v1.1) (Aftermarket) (Unl)" + description "Deep Forest (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Deep Forest (World) (v1.1) (Aftermarket) (Unl).gb" size 1048576 crc 3ddf177d sha1 517302d20cb5140975e6cd1b3c495786b6390aaf ) +) + +game ( + name "DiaMaze (World) (Aftermarket) (Unl)" + description "DiaMaze (World) (Aftermarket) (Unl)" + rom ( name "DiaMaze (World) (Aftermarket) (Unl).gb" size 262144 crc 956fa901 sha1 f41b98ac4669920ffede1736ddbd9e1f62d4cb0d ) +) + +game ( + name "Dijon Gameboy (World) (En,Fr) (Demo) (Aftermarket) (Unl)" + description "Dijon Gameboy (World) (En,Fr) (Demo) (Aftermarket) (Unl)" + rom ( name "Dijon Gameboy (World) (En,Fr) (Demo) (Aftermarket) (Unl).gb" size 1048576 crc b230b782 sha1 f1796dcbfb6f0f5e01c60222c376cc1c46945806 ) +) + +game ( + name "Dino's Offline Adventure (World) (Aftermarket) (Unl)" + description "Dino's Offline Adventure (World) (Aftermarket) (Unl)" + rom ( name "Dino's Offline Adventure (World) (Aftermarket) (Unl).gb" size 32768 crc d6bd0e6a sha1 6d11c145606f8e7ab25b2b07c299e36c8b442d23 ) +) + +game ( + name "DMG Deals Damage (World) (Aftermarket) (Unl)" + description "DMG Deals Damage (World) (Aftermarket) (Unl)" + rom ( name "DMG Deals Damage (World) (Aftermarket) (Unl).gb" size 32768 crc 250e0cbd sha1 a15539199e4b6bd2a71d1ac0e7c61ae4f19a65e7 flags verified ) +) + +game ( + name "Do I Pass (World) (En) (Demo) (Aftermarket) (Unl)" + description "Do I Pass (World) (En) (Demo) (Aftermarket) (Unl)" + rom ( name "Do I Pass (World) (En) (Demo) (Aftermarket) (Unl).gb" size 1048576 crc f339fa82 sha1 bdbc082017bdf2e4caa84e7d00dad9707727e9d4 ) +) + +game ( + name "Do I Pass (World) (En) (v1.4) (Aftermarket) (Unl)" + description "Do I Pass (World) (En) (v1.4) (Aftermarket) (Unl)" + rom ( name "Do I Pass (World) (En) (v1.4) (Aftermarket) (Unl).gb" size 1048576 crc cfb44d68 sha1 6dde71bbec8b807af5132d1ef2e99c6bb6af3a1c ) +) + +game ( + name "Do I Pass (World) (En) (v1.4) (Web) (Aftermarket) (Unl)" + description "Do I Pass (World) (En) (v1.4) (Web) (Aftermarket) (Unl)" + rom ( name "Do I Pass (World) (En) (v1.4) (Web) (Aftermarket) (Unl).gb" size 1048576 crc 62e0c3a2 sha1 e1b516e472e0c681b4ad1c7f4aeda55c91e7f340 ) +) + +game ( + name "Do I Pass (World) (Fr) (v1.4.2) (Aftermarket) (Unl)" + description "Do I Pass (World) (Fr) (v1.4.2) (Aftermarket) (Unl)" + rom ( name "Do I Pass (World) (Fr) (v1.4.2) (Aftermarket) (Unl).gb" size 1048576 crc e393d4aa sha1 d45dfcab4a76b62ea1e10730d01f755e12137484 ) +) + +game ( + name "Do I Pass (World) (En) (v1.5) (Aftermarket) (Unl)" + description "Do I Pass (World) (En) (v1.5) (Aftermarket) (Unl)" + rom ( name "Do I Pass (World) (En) (v1.5) (Aftermarket) (Unl).gb" size 1048576 crc 3890e0a4 sha1 6998e1bbf2ccb9db3d661ddac2d7edf7571d0af7 ) +) + +game ( + name "Dog's Muck Island (World) (Aftermarket) (Unl)" + description "Dog's Muck Island (World) (Aftermarket) (Unl)" + rom ( name "Dog's Muck Island (World) (Aftermarket) (Unl).gb" size 262144 crc 79a7a06c sha1 eb4cea3b9db770bf3b586578af1ad7427d88ee8e ) +) + +game ( + name "Don't Call Me Mama But Yes I Am Your Mama (World) (v2.0) (Aftermarket) (Unl)" + description "Don't Call Me Mama But Yes I Am Your Mama (World) (v2.0) (Aftermarket) (Unl)" + rom ( name "Don't Call Me Mama But Yes I Am Your Mama (World) (v2.0) (Aftermarket) (Unl).gb" size 1048576 crc 83247308 sha1 4579eaa45e2bf8f17f4dc99bdfb0b98270b871f5 ) +) + +game ( + name "Dragon Battle (World) (Demo) (Aftermarket) (Unl)" + description "Dragon Battle (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Dragon Battle (World) (Demo) (Aftermarket) (Unl).gb" size 4194304 crc c1e1e52c sha1 c5ac56e266c421a1c5b82de46859a44f75d03359 ) +) + +game ( + name "Dragonborne (World) (Aftermarket) (Unl)" + description "Dragonborne (World) (Aftermarket) (Unl)" + rom ( name "Dragonborne (World) (Aftermarket) (Unl).gb" size 2097152 crc 0ae28712 sha1 e3cd09069ee59ed3f7915a79af0667de4ebd7d50 ) +) + +game ( + name "Dragonborne (World) (Demo) (Aftermarket) (Unl)" + description "Dragonborne (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Dragonborne (World) (Demo) (Aftermarket) (Unl).gb" size 2097152 crc eda66890 sha1 3a5bcd9daa830842da60d8ebf35fa7036a259d76 ) +) + +game ( + name "Duck (World) (Aftermarket) (Unl)" + description "Duck (World) (Aftermarket) (Unl)" + rom ( name "Duck (World) (Aftermarket) (Unl).gb" size 32768 crc 583691fd sha1 f7eccfb9ade282423db6122882adcef6fbf3e955 ) +) + +game ( + name "Elden Ring GB (World) (Aftermarket) (Unl)" + description "Elden Ring GB (World) (Aftermarket) (Unl)" + rom ( name "Elden Ring GB (World) (Aftermarket) (Unl).gb" size 524288 crc e7a420f3 sha1 2e0bec6acf1a94ae3f2f6cf2040323862933d95a ) +) + +game ( + name "ever - Lucid Space Program (World) (Aftermarket) (Unl)" + description "ever - Lucid Space Program (World) (Aftermarket) (Unl)" + rom ( name "ever - Lucid Space Program (World) (Aftermarket) (Unl).gb" size 262144 crc a5006140 sha1 051a1b8739c820424fad5103b64e578dd9a5b841 ) +) + +game ( + name "F-Zero - Project (World) (Aftermarket) (Unl)" + description "F-Zero - Project (World) (Aftermarket) (Unl)" + rom ( name "F-Zero - Project (World) (Aftermarket) (Unl).gb" size 1048576 crc 4c707059 sha1 5b823ee17691d286a45f0667cddd59ccaaab5d8b ) +) + +game ( + name "Fairy-chan (World) (v0.1.4) (Demo) (Aftermarket) (Unl)" + description "Fairy-chan (World) (v0.1.4) (Demo) (Aftermarket) (Unl)" + rom ( name "Fairy-chan (World) (v0.1.4) (Demo) (Aftermarket) (Unl).gb" size 262144 crc 4f04cdfc sha1 591980cb5e17104d826c2a915f53bfc8a21affca ) +) + +game ( + name "Farm, The (World) (Aftermarket) (Unl)" + description "Farm, The (World) (Aftermarket) (Unl)" + rom ( name "Farm, The (World) (Aftermarket) (Unl).gb" size 524288 crc fbc1b5e8 sha1 d0fe06920f7e771d76507f60881904370ffbc145 ) +) + +game ( + name "Final Fantasy XI Adventure (World) (Aftermarket) (Unl)" + description "Final Fantasy XI Adventure (World) (Aftermarket) (Unl)" + rom ( name "Final Fantasy XI Adventure (World) (Aftermarket) (Unl).gb" size 1048576 crc 6cfb4669 sha1 339fd673509a5ac8f25426af25b4ccc96e8d2880 ) +) + +game ( + name "Finders Keepers (World) (Aftermarket) (Unl)" + description "Finders Keepers (World) (Aftermarket) (Unl)" + rom ( name "Finders Keepers (World) (Aftermarket) (Unl).gb" size 524288 crc 6a98ac61 sha1 e40dd804388df8c08d3890d79eeafd8542cc8805 ) +) + +game ( + name "FlappyBird GB (World) (Aftermarket) (Unl)" + description "FlappyBird GB (World) (Aftermarket) (Unl)" + rom ( name "FlappyBird GB (World) (Aftermarket) (Unl).gb" size 131072 crc 51aa9cc2 sha1 8f2b803fdd737c9885b96d11622008f706061e00 ) +) + +game ( + name "Fly O'Clock (World) (Aftermarket) (Unl)" + description "Fly O'Clock (World) (Aftermarket) (Unl)" + rom ( name "Fly O'Clock (World) (Aftermarket) (Unl).gb" size 32768 crc 93df7f55 sha1 83dc8498bdbabc14a8f81a715c9da19970c1f0b9 ) +) + +game ( + name "Footballer of the Year (World) (v1.1) (Aftermarket) (Unl)" + description "Footballer of the Year (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Footballer of the Year (World) (v1.1) (Aftermarket) (Unl).gb" size 1048576 crc 6e6ce1bb sha1 44166b7e6e8411ae61f37c7a78e90acaae66bcc5 ) +) + +game ( + name "Footballer of the Year (World) (v1.0) (Aftermarket) (Unl)" + description "Footballer of the Year (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "Footballer of the Year (World) (v1.0) (Aftermarket) (Unl).gb" size 1048576 crc 91faa9b1 sha1 b7542729c8665a1a2af47f58fc59cc90f66fd77d ) +) + +game ( + name "Fydo's Magic Tiles (World) (2022-09-01) (Aftermarket) (Unl)" + description "Fydo's Magic Tiles (World) (2022-09-01) (Aftermarket) (Unl)" + rom ( name "Fydo's Magic Tiles (World) (2022-09-01) (Aftermarket) (Unl).gb" size 32768 crc 36e2ca02 sha1 fd985703b296dd0bf74225c72155ea9e51dd6853 ) +) + +game ( + name "G-Man (World) (Aftermarket) (Unl)" + description "G-Man (World) (Aftermarket) (Unl)" + rom ( name "G-Man (World) (Aftermarket) (Unl).gb" size 524288 crc 7296da69 sha1 fdc9933d46a063575c175453b1da8042fd28b135 ) +) + +game ( + name "G-ZERO (World) (v2.6) (Aftermarket) (Unl)" + description "G-ZERO (World) (v2.6) (Aftermarket) (Unl)" + rom ( name "G-ZERO (World) (v2.6) (Aftermarket) (Unl).gb" size 65536 crc 7dd0c878 sha1 929d25a612308614ac3ac2ee5a19a9cd4a9968d6 ) +) + +game ( + name "GameBoy WORDLE (World) (Aftermarket) (Unl)" + description "GameBoy WORDLE (World) (Aftermarket) (Unl)" + rom ( name "GameBoy WORDLE (World) (Aftermarket) (Unl).gb" size 32768 crc cc971c0f sha1 ba93939b93ab3f3aa5f7aa451d50d9b89220adbc ) +) + +game ( + name "Genesis (World) (Aftermarket) (Unl)" + description "Genesis (World) (Aftermarket) (Unl)" + rom ( name "Genesis (World) (Aftermarket) (Unl).gb" size 65536 crc 74b3ec78 sha1 ca43f82d73ba0b3e43ec17f6bc6761c09ca23626 ) +) + +game ( + name "Genesis II (World) (Demo) (Aftermarket) (Unl)" + description "Genesis II (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Genesis II (World) (Demo) (Aftermarket) (Unl).gb" size 262144 crc d7aec1cc sha1 9700ea1278850df004ded7553253cfdd354f4ada ) +) + +game ( + name "Ghost Town (World) (Aftermarket) (Unl)" + description "Ghost Town (World) (Aftermarket) (Unl)" + rom ( name "Ghost Town (World) (Aftermarket) (Unl).gb" size 262144 crc 2d27cdf2 sha1 af526273cdaa6423b92d0484fb27af56fe355a5d ) +) + +game ( + name "Glory Hunters - Chapter 1 (World) (v0.1) (Demo) (Aftermarket) (Unl)" + description "Glory Hunters - Chapter 1 (World) (v0.1) (Demo) (Aftermarket) (Unl)" + rom ( name "Glory Hunters - Chapter 1 (World) (v0.1) (Demo) (Aftermarket) (Unl).gb" size 2097152 crc 4b19366d sha1 77f3b561bf28a81f38dbedc351752e10ff4c23dc ) +) + +game ( + name "Glory Hunters - Chapter 1 (World) (v0.2) (Demo) (Aftermarket) (Unl)" + description "Glory Hunters - Chapter 1 (World) (v0.2) (Demo) (Aftermarket) (Unl)" + rom ( name "Glory Hunters - Chapter 1 (World) (v0.2) (Demo) (Aftermarket) (Unl).gb" size 2097152 crc 3f34ff66 sha1 a0bff49b6917186d27dc24773da0674a18a6212c ) +) + +game ( + name "Great Detention Getaway, The (World) (Aftermarket) (Unl)" + description "Great Detention Getaway, The (World) (Aftermarket) (Unl)" + rom ( name "Great Detention Getaway, The (World) (Aftermarket) (Unl).gb" size 131072 crc 13b72ee4 sha1 efc3208cb99f9fb213875acd7b9b6c2e633b696a ) +) + +game ( + name "Gun Law (World) (Aftermarket) (Unl)" + description "Gun Law (World) (Aftermarket) (Unl)" + rom ( name "Gun Law (World) (Aftermarket) (Unl).gb" size 262144 crc b0d53211 sha1 ef6e3d287e99bd61861a333165c92b306238a45f ) +) + +game ( + name "Gunman Clive (World) (Demo) (Aftermarket) (Unl)" + description "Gunman Clive (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Gunman Clive (World) (Demo) (Aftermarket) (Unl).gb" size 65536 crc 11f5fded sha1 ec03763db2c0d754e2eb7e98384ed92fc8aeeb1d ) +) + +game ( + name "Gunship (World) (Aftermarket) (Unl)" + description "Gunship (World) (Aftermarket) (Unl)" + rom ( name "Gunship (World) (Aftermarket) (Unl).gb" size 131072 crc bd31eef8 sha1 a801977c3746799cfb4d8bdfd679e45cccd3b719 ) +) + +game ( + name "Harbour Attack (World) (Aftermarket) (Unl)" + description "Harbour Attack (World) (Aftermarket) (Unl)" + rom ( name "Harbour Attack (World) (Aftermarket) (Unl).gb" size 262144 crc 4018ebf7 sha1 5bbbe727ebc6a489f1a498d067e4f05d0d69b60f ) +) + +game ( + name "Heart Knight (World) (Aftermarket) (Unl)" + description "Heart Knight (World) (Aftermarket) (Unl)" + rom ( name "Heart Knight (World) (Aftermarket) (Unl).gb" size 32768 crc c7ecac73 sha1 dedcab41f58c58834e3534e877c494669a0d8952 ) +) + +game ( + name "Hermano (World) (v1.1) (Aftermarket) (Unl)" + description "Hermano (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Hermano (World) (v1.1) (Aftermarket) (Unl).gb" size 262144 crc 74a0419b sha1 c42cfe91a1ec593a76291e031c47137bd794ffda ) +) + +game ( + name "Hugo (World) (Aftermarket) (Unl)" + description "Hugo (World) (Aftermarket) (Unl)" + rom ( name "Hugo (World) (Aftermarket) (Unl).gb" size 262144 crc 8cc87f60 sha1 53fac2774b29a32501788e1eac65db23bf5c7b8f ) +) + +game ( + name "If (World) (Aftermarket) (Unl)" + description "If (World) (Aftermarket) (Unl)" + rom ( name "If (World) (Aftermarket) (Unl).gb" size 1048576 crc be7e4454 sha1 c11d8dc9ce96133f679678b07822a82f985e16f9 ) +) + +game ( + name "Impossible Gameboy (World) (Aftermarket) (Unl)" + description "Impossible Gameboy (World) (Aftermarket) (Unl)" + rom ( name "Impossible Gameboy (World) (Aftermarket) (Unl).gb" size 131072 crc ab65b738 sha1 d31cedd6227b23cf3d8ef81c73f133ab0b57e4f4 ) +) + +game ( + name "Interblocked (World) (Aftermarket) (Unl)" + description "Interblocked (World) (Aftermarket) (Unl)" + rom ( name "Interblocked (World) (Aftermarket) (Unl).gb" size 262144 crc 5c208855 sha1 8e46486533a3de9ee87cc07bf8efaf818752a61a ) +) + +game ( + name "Into the Blue (World) (Aftermarket) (Unl)" + description "Into the Blue (World) (Aftermarket) (Unl)" + rom ( name "Into the Blue (World) (Aftermarket) (Unl).gb" size 131072 crc 7714e96e sha1 5ac7a349bb37c8767c9db264ed8ae7b7647fa8ea ) +) + +game ( + name "Island, The (World) (Demo) (Aftermarket) (Unl)" + description "Island, The (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Island, The (World) (Demo) (Aftermarket) (Unl).gb" size 131072 crc d6a43a64 sha1 38419c50713b4e403b80f1da151a3e9d0654d47c ) +) + +game ( + name "Jabberwocky (World) (Aftermarket) (Unl)" + description "Jabberwocky (World) (Aftermarket) (Unl)" + rom ( name "Jabberwocky (World) (Aftermarket) (Unl).gb" size 1048576 crc cfc51717 sha1 b4e447f2197688c740a45dce27879a62c742fb96 ) +) + +game ( + name "Jane in the Jungle (World) (Aftermarket) (Unl)" + description "Jane in the Jungle (World) (Aftermarket) (Unl)" + rom ( name "Jane in the Jungle (World) (Aftermarket) (Unl).gb" size 262144 crc c68e751a sha1 dfc65dcf700a26b273d705b7cfececbc44b80587 ) +) + +game ( + name "Jet Set Willy (World) (Aftermarket) (Unl)" + description "Jet Set Willy (World) (Aftermarket) (Unl)" + rom ( name "Jet Set Willy (World) (Aftermarket) (Unl).gb" size 262144 crc 1686d7ed sha1 0e594224506fd087e36c66bb66905d4c91b02461 ) +) + +game ( + name "Joe Blade 2 (World) (Aftermarket) (Unl)" + description "Joe Blade 2 (World) (Aftermarket) (Unl)" + rom ( name "Joe Blade 2 (World) (Aftermarket) (Unl).gb" size 524288 crc 09f75c70 sha1 f001dffcd16be670c36a98dd9136f6f9fbf5b85d ) +) + +game ( + name "Jumpy (World) (Aftermarket) (Unl)" + description "Jumpy (World) (Aftermarket) (Unl)" + rom ( name "Jumpy (World) (Aftermarket) (Unl).gb" size 262144 crc 70f9af24 sha1 29152d8874c2a048f71e0be86aa9ee2d77996fb6 ) +) + +game ( + name "Just Fishing (World) (Aftermarket) (Unl)" + description "Just Fishing (World) (Aftermarket) (Unl)" + rom ( name "Just Fishing (World) (Aftermarket) (Unl).gb" size 131072 crc c0f675fc sha1 3591b258afb94e0b4d9e095ecf702fc4de3061e3 ) +) + +game ( + name "Kenzie's Birthday Dash (World) (Aftermarket) (Unl)" + description "Kenzie's Birthday Dash (World) (Aftermarket) (Unl)" + rom ( name "Kenzie's Birthday Dash (World) (Aftermarket) (Unl).gb" size 1048576 crc 986bfd75 sha1 6d15b5bc33d7c7771ba62d56ae7f25fa081bc564 ) +) + +game ( + name "Kitten's Getaway (World) (Es) (Aftermarket) (Unl)" + description "Kitten's Getaway (World) (Es) (Aftermarket) (Unl)" + rom ( name "Kitten's Getaway (World) (Es) (Aftermarket) (Unl).gb" size 262144 crc e621c535 sha1 a9e71e4a27e633e1649a131150c5811483b441d6 ) +) + +game ( + name "Krezber (World) (Aftermarket) (Unl)" + description "Krezber (World) (Aftermarket) (Unl)" + rom ( name "Krezber (World) (Aftermarket) (Unl).gb" size 65536 crc 27bddf77 sha1 2f4cffafc411b6895bf365b0773c4fa5d2ef7be3 ) +) + +game ( + name "Kudzu (World) (v0.96) (Demo) (Aftermarket) (Unl)" + description "Kudzu (World) (v0.96) (Demo) (Aftermarket) (Unl)" + rom ( name "Kudzu (World) (v0.96) (Demo) (Aftermarket) (Unl).gb" size 2097152 crc 0610049a sha1 a6fbe1a524547bebabc5e6b3baff1dff8f13dbd0 ) +) + +game ( + name "Kudzu (World) (v1.1c) (Demo) (Aftermarket) (Unl)" + description "Kudzu (World) (v1.1c) (Demo) (Aftermarket) (Unl)" + rom ( name "Kudzu (World) (v1.1c) (Demo) (Aftermarket) (Unl).gb" size 2097152 crc 4462ff70 sha1 18a2a762d7b994865c845ac2aa0a0cf7655af74e flags verified ) +) + +game ( + name "Laser Squad Alter (World) (Aftermarket) (Unl)" + description "Laser Squad Alter (World) (Aftermarket) (Unl)" + rom ( name "Laser Squad Alter (World) (Aftermarket) (Unl).gb" size 1048576 crc a39b3a5a sha1 1620e585e77a2457cffde82453bec0c7a04e07cf ) +) + +game ( + name "Last Crown Warriors (World) (Demo) (SGB Enhanced) (Aftermarket) (Unl)" + description "Last Crown Warriors (World) (Demo) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Last Crown Warriors (World) (Demo) (SGB Enhanced) (Aftermarket) (Unl).gb" size 262144 crc 2c430576 sha1 0e290b387a45b6ea85c6d49bf18bce3ce94951b7 ) +) + +game ( + name "Last Crown Warriors (World) (v1.1.1) (Demo) (SGB Enhanced) (Aftermarket) (Unl)" + description "Last Crown Warriors (World) (v1.1.1) (Demo) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Last Crown Warriors (World) (v1.1.1) (Demo) (SGB Enhanced) (Aftermarket) (Unl).gb" size 262144 crc 5cf1a6f9 sha1 9fac1324e863f719674219eb41e45f1f745c67a9 ) +) + +game ( + name "Lawn Mower Land (World) (Aftermarket) (Unl)" + description "Lawn Mower Land (World) (Aftermarket) (Unl)" + rom ( name "Lawn Mower Land (World) (Aftermarket) (Unl).gb" size 32768 crc 11c62e39 sha1 1d6aa817ebf2a7e5d22285b906540272b67169da ) +) + +game ( + name "Leak, The (World) (Aftermarket) (Unl)" + description "Leak, The (World) (Aftermarket) (Unl)" + rom ( name "Leak, The (World) (Aftermarket) (Unl).GB" size 65536 crc ba3cfeae sha1 98de2d8be75e6d9cb4e87afe14b1380c033de797 ) +) + +game ( + name "Life's Too Short (World) (Aftermarket) (Unl)" + description "Life's Too Short (World) (Aftermarket) (Unl)" + rom ( name "Life's Too Short (World) (Aftermarket) (Unl).gb" size 262144 crc 458174cc sha1 7b704cd999cbeeb9991d675e2b1e67a906fa766d ) +) + +game ( + name "Linea, La (World) (Aftermarket) (Unl)" + description "Linea, La (World) (Aftermarket) (Unl)" + rom ( name "Linea, La (World) (Aftermarket) (Unl).gb" size 262144 crc c8750c01 sha1 00348fec54b5d3ebb762484bdcc015881bb9e95b ) +) + +game ( + name "Little Tales of Alexandria, The (World) (MBC3) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl)" + description "Little Tales of Alexandria, The (World) (MBC3) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl)" + rom ( name "Little Tales of Alexandria, The (World) (MBC3) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl).gb" size 524288 crc 9c4f03fd sha1 288cb53b4782df4409ee683e9aa11b4dd2a3a53e ) +) + +game ( + name "Little Tales of Alexandria, The (World) (MBC3) (SGB Enhanced) (Aftermarket) (Unl)" + description "Little Tales of Alexandria, The (World) (MBC3) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Little Tales of Alexandria, The (World) (MBC3) (SGB Enhanced) (Aftermarket) (Unl).gb" size 524288 crc e5988949 sha1 08d033c7ef20fd4d24d1f07b3ebb177fb9b78673 ) +) + +game ( + name "Little Tales of Alexandria, The (World) (MBC5) (SGB Enhanced) (Aftermarket) (Unl)" + description "Little Tales of Alexandria, The (World) (MBC5) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Little Tales of Alexandria, The (World) (MBC5) (SGB Enhanced) (Aftermarket) (Unl).gb" size 524288 crc 59568248 sha1 6571db155f6f25eeeec86d28b105bf8fef156322 ) +) + +game ( + name "Little Tales of Alexandria, The (World) (MBC5) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl)" + description "Little Tales of Alexandria, The (World) (MBC5) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl)" + rom ( name "Little Tales of Alexandria, The (World) (MBC5) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl).gb" size 524288 crc a26345b8 sha1 641110cb187657fd15ea254440e1c74ab4a88856 ) +) + +game ( + name "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC3) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl)" + description "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC3) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl)" + rom ( name "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC3) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl).gb" size 131072 crc d70f1d25 sha1 02e2fb6cbc5cff05ed775c9e1cd9acc07fa2e036 ) +) + +game ( + name "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC5) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl)" + description "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC5) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl)" + rom ( name "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC5) (SGB Enhanced) (Batteryless) (Aftermarket) (Unl).gb" size 131072 crc ae07c093 sha1 9f40b8719b3fdd2f7e6c59a4f616e9eb712d538d ) +) + +game ( + name "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC3) (SGB Enhanced) (Aftermarket) (Unl)" + description "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC3) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC3) (SGB Enhanced) (Aftermarket) (Unl).gb" size 131072 crc 34671dc6 sha1 377d22d54e6e1fa4fcd4b4576d5886774f9f6c97 ) +) + +game ( + name "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC5) (SGB Enhanced) (Aftermarket) (Unl)" + description "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC5) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Little Tales of Alexandria, The - Mr Meows Dance Party! (World) (MBC5) (SGB Enhanced) (Aftermarket) (Unl).gb" size 131072 crc a8fb0d7a sha1 26803ba3413c7c52a8a58393f63472bc87ec3c6b ) +) + +game ( + name "Lost Knight (World) (Proto) (Aftermarket) (Unl)" + description "Lost Knight (World) (Proto) (Aftermarket) (Unl)" + rom ( name "Lost Knight (World) (Proto) (Aftermarket) (Unl).gb" size 262144 crc 5ddcc941 sha1 ca9003ead7ee153faf087a83c4bdef1d409c597b ) +) + +game ( + name "Lucy and the Gem Dungeon (World) (Aftermarket) (Unl)" + description "Lucy and the Gem Dungeon (World) (Aftermarket) (Unl)" + rom ( name "Lucy and the Gem Dungeon (World) (Aftermarket) (Unl).gb" size 524288 crc 1a5106a2 sha1 f56c1b324b8c1e17da86e40c5e9a887ec19b0c80 ) +) + +game ( + name "Machine, The (World) (v1.0) (Aftermarket) (Unl)" + description "Machine, The (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "Machine, The (World) (v1.0) (Aftermarket) (Unl).gb" size 2097152 crc b06036a9 sha1 50c5d1eb7c8946ac2d7e2c566b1ea4a9b0d58e90 ) +) + +game ( + name "Mad Monster (World) (Aftermarket) (Unl)" + description "Mad Monster (World) (Aftermarket) (Unl)" + rom ( name "Mad Monster (World) (Aftermarket) (Unl).gb" size 524288 crc c3fd371c sha1 9f4bea7ca7d26080110f54392314c60761236638 ) +) + +game ( + name "Magipanels (World) (2022-02-09) (Demo) (Aftermarket) (Unl)" + description "Magipanels (World) (2022-02-09) (Demo) (Aftermarket) (Unl)" + rom ( name "Magipanels (World) (2022-02-09) (Demo) (Aftermarket) (Unl).gb" size 131072 crc 76fcbc30 sha1 7a759372bd013dcdb59c9131a2908085fc04d648 ) +) + +game ( + name "Magipanels (World) (Aftermarket) (Unl)" + description "Magipanels (World) (Aftermarket) (Unl)" + rom ( name "Magipanels (World) (Aftermarket) (Unl).gb" size 131072 crc 0b66561b sha1 c9513f6769098f2185f632f87386788f0f0b6ad8 ) +) + +game ( + name "Mai Nurse (World) (v1.01) (Aftermarket) (Unl)" + description "Mai Nurse (World) (v1.01) (Aftermarket) (Unl)" + rom ( name "Mai Nurse (World) (v1.01) (Aftermarket) (Unl).gb" size 131072 crc 20d562b2 sha1 2d3b1dac701b518f9e5109dbc5e7d2bc8420dec3 ) +) + +game ( + name "Make Way (World) (Aftermarket) (Unl)" + description "Make Way (World) (Aftermarket) (Unl)" + rom ( name "Make Way (World) (Aftermarket) (Unl).gb" size 1048576 crc edeee5a8 sha1 19fd02e9318ed81ec968a2fca31ea0c3d8d94a7b ) +) + +game ( + name "Marron Helps a Friend (World) (Aftermarket) (Unl)" + description "Marron Helps a Friend (World) (Aftermarket) (Unl)" + rom ( name "Marron Helps a Friend (World) (Aftermarket) (Unl).gb" size 1048576 crc 08a3a987 sha1 adcd56fa3eba93edd20be25ae5cb349070cd0323 flags verified ) +) + +game ( + name "Marzipan Beef Reverser (World) (v2.0) (Aftermarket) (Unl)" + description "Marzipan Beef Reverser (World) (v2.0) (Aftermarket) (Unl)" + rom ( name "Marzipan Beef Reverser (World) (v2.0) (Aftermarket) (Unl).gb" size 262144 crc dccaeb60 sha1 1e4fc83bfe9c9063975a3862770e4afee3f947a4 ) +) + +game ( + name "Marzipan Beef Reverser (World) (Aftermarket) (Unl)" + description "Marzipan Beef Reverser (World) (Aftermarket) (Unl)" + rom ( name "Marzipan Beef Reverser (World) (Aftermarket) (Unl).gb" size 131072 crc 4c3e0d15 sha1 6cbfb0390ee555718b5b0c3a5437b7d3d4ee0008 ) +) + +game ( + name "Meteorite (World) (Aftermarket) (Unl)" + description "Meteorite (World) (Aftermarket) (Unl)" + rom ( name "Meteorite (World) (Aftermarket) (Unl).gb" size 262144 crc 50cf593d sha1 0e88a47faf3273f87c1ead7f789faeb06d5333f3 ) +) + +game ( + name "Mission Mars (World) (Aftermarket) (Unl)" + description "Mission Mars (World) (Aftermarket) (Unl)" + rom ( name "Mission Mars (World) (Aftermarket) (Unl).gb" size 262144 crc cb3a9ab8 sha1 31625a90b61d28ac782909ed8b00b3a48df7742e ) +) + +game ( + name "Mona and the Witch's Hat (World) (Aftermarket) (Unl)" + description "Mona and the Witch's Hat (World) (Aftermarket) (Unl)" + rom ( name "Mona and the Witch's Hat (World) (Aftermarket) (Unl).gb" size 65536 crc 32ed7f4a sha1 625d3664d99dee075021b03ea6ff074ae2e49204 ) +) + +game ( + name "Monty on the Run (World) (Aftermarket) (Unl)" + description "Monty on the Run (World) (Aftermarket) (Unl)" + rom ( name "Monty on the Run (World) (Aftermarket) (Unl).gb" size 524288 crc e2ebb406 sha1 41ac5993fbff58be0712b554aae5e4367b68677b ) +) + +game ( + name "Muncher (World) (Aftermarket) (Unl)" + description "Muncher (World) (Aftermarket) (Unl)" + rom ( name "Muncher (World) (Aftermarket) (Unl).gb" size 262144 crc 444d3d5e sha1 c3e09aff66c7e395bf95a1864963fbe979d5cb9b ) +) + +game ( + name "My Husband is a WITCH (World) (v1.1) (Aftermarket) (Unl)" + description "My Husband is a WITCH (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "My Husband is a WITCH (World) (v1.1) (Aftermarket) (Unl).gb" size 262144 crc 68801328 sha1 3b45dc8b655b688832a6b217c5cbc93a7a9f70cd ) +) + +game ( + name "My World (World) (Aftermarket) (Unl)" + description "My World (World) (Aftermarket) (Unl)" + rom ( name "My World (World) (Aftermarket) (Unl).gb" size 131072 crc 530b2edd sha1 ae29a721e6d1894e2faf736384737da7676e4fbc ) +) + +game ( + name "Neko Can Dream (World) (En) (Aftermarket) (Unl)" + description "Neko Can Dream (World) (En) (Aftermarket) (Unl)" + rom ( name "Neko Can Dream (World) (En) (Aftermarket) (Unl).gb" size 2097152 crc 6e76ef25 sha1 55686fde78d17d00adfc831eca2c699274a82273 ) +) + +game ( + name "Neko Can Dream (World) (Ja) (Demo) (Aftermarket) (Unl)" + description "Neko Can Dream (World) (Ja) (Demo) (Aftermarket) (Unl)" + rom ( name "Neko Can Dream (World) (Ja) (Demo) (Aftermarket) (Unl).gb" size 2097152 crc a0ad7a18 sha1 5fb1a09e04cf1704b059468de8855dfa7e23043b ) +) + +game ( + name "Neko Can Dream (World) (En) (Demo) (Aftermarket) (Unl)" + description "Neko Can Dream (World) (En) (Demo) (Aftermarket) (Unl)" + rom ( name "Neko Can Dream (World) (En) (Demo) (Aftermarket) (Unl).gb" size 2097152 crc dc011d07 sha1 43312b149355d20944e8a366584c69e5cb3be868 ) +) + +game ( + name "Nocptern (World) (v1.0) (Demo) (Aftermarket) (Unl)" + description "Nocptern (World) (v1.0) (Demo) (Aftermarket) (Unl)" + rom ( name "Nocptern (World) (v1.0) (Demo) (Aftermarket) (Unl).gb" size 131072 crc 118da307 sha1 33174a7727f6a1cc7c94b598ed6e9a4c2d1d410c ) +) + +game ( + name "Nyghtmare - Betrayed (World) (Alpha A) (Aftermarket) (Unl)" + description "Nyghtmare - Betrayed (World) (Alpha A) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - Betrayed (World) (Alpha A) (Aftermarket) (Unl).gb" size 262144 crc d6166c62 sha1 fa2198c5308a15195adbda004f09646589860d11 ) +) + +game ( + name "Nyghtmare - Betrayed (World) (v0.1.1) (Beta) (Aftermarket) (Unl)" + description "Nyghtmare - Betrayed (World) (v0.1.1) (Beta) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - Betrayed (World) (v0.1.1) (Beta) (Aftermarket) (Unl).gb" size 1048576 crc 42b47080 sha1 08484b0f98e72d6577d9b7cde8c49908012d1fc5 ) +) + +game ( + name "Oblique Strategies (World) (Aftermarket) (Unl)" + description "Oblique Strategies (World) (Aftermarket) (Unl)" + rom ( name "Oblique Strategies (World) (Aftermarket) (Unl).gb" size 524288 crc 30eca8d3 sha1 6a09aabf30e2ebab2e31ae845cd2e8796c84797f ) +) + +game ( + name "Oiopolis (World) (Es) (Demo) (Aftermarket) (Unl)" + description "Oiopolis (World) (Es) (Demo) (Aftermarket) (Unl)" + rom ( name "Oiopolis (World) (Es) (Demo) (Aftermarket) (Unl).gb" size 524288 crc d3eba01d sha1 8cf234bbcb68ca2b676a4ccec89814b0cbce1c07 ) +) + +game ( + name "Oiopolis (World) (En) (Demo) (Aftermarket) (Unl)" + description "Oiopolis (World) (En) (Demo) (Aftermarket) (Unl)" + rom ( name "Oiopolis (World) (En) (Demo) (Aftermarket) (Unl).gb" size 524288 crc 71f34822 sha1 f24da97f44d280f27f8ebe3acdc33fea758d2255 ) +) + +game ( + name "Oiopolis (World) (Ca) (Demo) (Aftermarket) (Unl)" + description "Oiopolis (World) (Ca) (Demo) (Aftermarket) (Unl)" + rom ( name "Oiopolis (World) (Ca) (Demo) (Aftermarket) (Unl).gb" size 524288 crc 76baab68 sha1 cd76da35541535dd244ad60d10eb998f7692f07a ) +) + +game ( + name "Olympic Skier (World) (Aftermarket) (Unl)" + description "Olympic Skier (World) (Aftermarket) (Unl)" + rom ( name "Olympic Skier (World) (Aftermarket) (Unl).gb" size 524288 crc 93174431 sha1 7bcdf10533f8fe053e22534c4962ed4b1a5cf2e2 ) +) + +game ( + name "Opossum a la Mode (World) (Aftermarket) (Unl)" + description "Opossum a la Mode (World) (Aftermarket) (Unl)" + rom ( name "Opossum a la Mode (World) (Aftermarket) (Unl).gb" size 262144 crc 810477a9 sha1 3b6fb1311313687afebc4fb51f1b4befb5f47e1e ) +) + +game ( + name "Out on a Limb (World) (Aftermarket) (Unl)" + description "Out on a Limb (World) (Aftermarket) (Unl)" + rom ( name "Out on a Limb (World) (Aftermarket) (Unl).gb" size 262144 crc be197f87 sha1 2ddc2378539316cf7a10e2cf8b562f17e1cf7a6a ) +) + +game ( + name "Panty Hunty (World) (v1.4) (Aftermarket) (Unl)" + description "Panty Hunty (World) (v1.4) (Aftermarket) (Unl)" + rom ( name "Panty Hunty (World) (v1.4) (Aftermarket) (Unl).gb" size 524288 crc ce707b9a sha1 b5757b268a09d9085d469eda0676991f7361ad8c ) +) + +game ( + name "Parasol Islands (World) (Aftermarket) (Unl)" + description "Parasol Islands (World) (Aftermarket) (Unl)" + rom ( name "Parasol Islands (World) (Aftermarket) (Unl).gb" size 1048576 crc b1d79c80 sha1 381f76af67f77e575beae2f45aefd21f079709e6 ) +) + +game ( + name "Penguin Migrants (World) (v1.2) (Aftermarket) (Unl)" + description "Penguin Migrants (World) (v1.2) (Aftermarket) (Unl)" + rom ( name "Penguin Migrants (World) (v1.2) (Aftermarket) (Unl).gb" size 32768 crc 866ac302 sha1 fa94f4d06eae2c49bbf1a654a8f658783dc6c28c ) +) + +game ( + name "Penguin Migrants (World) (v1.1) (Aftermarket) (Unl)" + description "Penguin Migrants (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Penguin Migrants (World) (v1.1) (Aftermarket) (Unl).gb" size 32768 crc 1bc5f8aa sha1 bf5601202eeca5b892ae4f3db7a4019cdb3bc99a ) +) + +game ( + name "Penguin Migrants (World) (v1.0) (Aftermarket) (Unl)" + description "Penguin Migrants (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "Penguin Migrants (World) (v1.0) (Aftermarket) (Unl).gb" size 32768 crc f6f681fa sha1 57b9cc41fc6d1e7cecf8ba2a1613d1fd126d97ad ) +) + +game ( + name "Perfect Blend (World) (v0.9) (Aftermarket) (Unl)" + description "Perfect Blend (World) (v0.9) (Aftermarket) (Unl)" + rom ( name "Perfect Blend (World) (v0.9) (Aftermarket) (Unl).gb" size 262144 crc 9b4bacaa sha1 09b0691f6823c54f1515dd3b66f135ac45a7dbc3 ) +) + +game ( + name "Perfect Blend (World) (v0.9) (Bugfix) (Aftermarket) (Unl)" + description "Perfect Blend (World) (v0.9) (Bugfix) (Aftermarket) (Unl)" + rom ( name "Perfect Blend (World) (v0.9) (Bugfix) (Aftermarket) (Unl).gb" size 262144 crc 1e8b2a29 sha1 a25dfc43408080ac116479fa55c9e7320e5cc82a ) +) + +game ( + name "Phobos Dere .GB (World) (Aftermarket) (Unl)" + description "Phobos Dere .GB (World) (Aftermarket) (Unl)" + rom ( name "Phobos Dere .GB (World) (Aftermarket) (Unl).gb" size 1048576 crc ae97f4f8 sha1 e541505078ee5e7e5c897b4621cc693ce71e35ba flags verified ) +) + +game ( + name "Phobos Dere .GB (World) (2022-03-06) (Demo) (Aftermarket) (Unl)" + description "Phobos Dere .GB (World) (2022-03-06) (Demo) (Aftermarket) (Unl)" + rom ( name "Phobos Dere .GB (World) (2022-03-06) (Demo) (Aftermarket) (Unl).gb" size 262144 crc 58362b86 sha1 b4cc3c3735bc134e34b97e08ed24c57aef5c5ccf flags verified ) +) + +game ( + name "Pineapple Kid (World) (Aftermarket) (Unl)" + description "Pineapple Kid (World) (Aftermarket) (Unl)" + rom ( name "Pineapple Kid (World) (Aftermarket) (Unl).gb" size 131072 crc 9541488b sha1 fd574b5d407f3654db3227900a8ed7eff4fe48ae ) +) + +game ( + name "Pineapple Kid (World) (Demo) (Aftermarket) (Unl)" + description "Pineapple Kid (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Pineapple Kid (World) (Demo) (Aftermarket) (Unl).gb" size 131072 crc 9d9102d9 sha1 105e78f740d6bc517ef0079f867e9fdce8d012d2 ) +) + +game ( + name "Pixel Who - The Lost Legions (World) (Aftermarket) (Unl)" + description "Pixel Who - The Lost Legions (World) (Aftermarket) (Unl)" + rom ( name "Pixel Who - The Lost Legions (World) (Aftermarket) (Unl).gb" size 1048576 crc f41cf2a7 sha1 c07378c774602060f1f93f18fbfd3f0d552fe2d2 ) +) + +game ( + name "Plants Eat My Zombies (World) (v1.1) (Aftermarket) (Unl)" + description "Plants Eat My Zombies (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Plants Eat My Zombies (World) (v1.1) (Aftermarket) (Unl).gb" size 524288 crc 60c84f2e sha1 c39ec5e6a9a0be0970b56e788c3f60e9821dbbd3 ) +) + +game ( + name "Pluto's Corner (World) (Aftermarket) (Unl)" + description "Pluto's Corner (World) (Aftermarket) (Unl)" + rom ( name "Pluto's Corner (World) (Aftermarket) (Unl).gb" size 65536 crc 21fc06b3 sha1 94e4a442205079d85d5ca37042eaec555f7f49db ) +) + +game ( + name "Pogo Pete (World) (Aftermarket) (Unl)" + description "Pogo Pete (World) (Aftermarket) (Unl)" + rom ( name "Pogo Pete (World) (Aftermarket) (Unl).gb" size 262144 crc 185ce1d5 sha1 74021e84c1d095b2401302e26352e810dbc432d8 ) +) + +game ( + name "Popcorn Caravan (World) (Demo) (Aftermarket) (Unl)" + description "Popcorn Caravan (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Popcorn Caravan (World) (Demo) (Aftermarket) (Unl).gb" size 65536 crc ead528f9 sha1 909d3421747d211a2dc70918d2c952db953e49b2 ) +) + +game ( + name "Porklike (World) (v1.0.3) (Aftermarket) (Unl)" + description "Porklike (World) (v1.0.3) (Aftermarket) (Unl)" + rom ( name "Porklike (World) (v1.0.3) (Aftermarket) (Unl).gb" size 65536 crc 6c57e55e sha1 143f31656a5007f65b19d6e32967698bb8f72a66 ) +) + +game ( + name "Porklike (World) (v1.0.9) (SGB Enhanced) (Aftermarket) (Unl)" + description "Porklike (World) (v1.0.9) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Porklike (World) (v1.0.9) (SGB Enhanced) (Aftermarket) (Unl).gb" size 65536 crc 7aaa853a sha1 0868bffd52b2bdc5601ab6cf1e25f40924ca643d ) +) + +game ( + name "Porklike (World) (v1.05) (SGB Enhanced) (Aftermarket) (Unl)" + description "Porklike (World) (v1.05) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Porklike (World) (v1.05) (SGB Enhanced) (Aftermarket) (Unl).gb" size 65536 crc 801f097b sha1 5da110a88799765707e027bcedec0875a637509b ) +) + +game ( + name "Pull of the Void (World) (Aftermarket) (Unl)" + description "Pull of the Void (World) (Aftermarket) (Unl)" + rom ( name "Pull of the Void (World) (Aftermarket) (Unl).gb" size 262144 crc 69bfac8c sha1 df10665c8e79c587103d3de686b0261807819caf ) +) + +game ( + name "Purple Turtles (World) (Aftermarket) (Unl)" + description "Purple Turtles (World) (Aftermarket) (Unl)" + rom ( name "Purple Turtles (World) (Aftermarket) (Unl).gb" size 262144 crc f7041a97 sha1 d2d7eff063104c8f205c192a902a53092c0b5f4a ) +) + +game ( + name "Pushingo (World) (Aftermarket) (Unl)" + description "Pushingo (World) (Aftermarket) (Unl)" + rom ( name "Pushingo (World) (Aftermarket) (Unl).gb" size 262144 crc a8541ed0 sha1 1ac1e22b191a95fdfa00c34ccba7387c991c827b ) +) + +game ( + name "Pyro la Chronoflamme (World) (Fr) (Proto) (Aftermarket) (Unl)" + description "Pyro la Chronoflamme (World) (Fr) (Proto) (Aftermarket) (Unl)" + rom ( name "Pyro la Chronoflamme (World) (Fr) (Proto) (Aftermarket) (Unl).gb" size 262144 crc 2abc6b14 sha1 a13e1f09e9d3921e544c3fc17daebbadc93921b7 ) +) + +game ( + name "Quick Draw (World) (Aftermarket) (Unl)" + description "Quick Draw (World) (Aftermarket) (Unl)" + rom ( name "Quick Draw (World) (Aftermarket) (Unl).gb" size 262144 crc 7704671f sha1 75f96ce54ed8739d58153780e9b573a65f1c5880 ) +) + +game ( + name "radioRealm (World) (Ja) (Aftermarket) (Unl)" + description "radioRealm (World) (Ja) (Aftermarket) (Unl)" + rom ( name "radioRealm (World) (Ja) (Aftermarket) (Unl).gb" size 131072 crc 71375a39 sha1 489c8835c36a08f1d76a0653bf6ede3bbf53043f ) +) + +game ( + name "Raffles (World) (Aftermarket) (Unl)" + description "Raffles (World) (Aftermarket) (Unl)" + rom ( name "Raffles (World) (Aftermarket) (Unl).gb" size 262144 crc 0b400a91 sha1 aadfe3fd0720696547b73b272354b592b96f98f7 ) +) + +game ( + name "Remute - Living Electronics (World) (Album) (Aftermarket) (Unl)" + description "Remute - Living Electronics (World) (Album) (Aftermarket) (Unl)" + rom ( name "Remute - Living Electronics (World) (Album) (Aftermarket) (Unl).gb" size 2097152 crc 1ced0a62 sha1 bc4bf12344d3b9d028a7013c84b94aea515be196 flags verified ) +) + +game ( + name "Retroid (World) (Aftermarket) (Unl)" + description "Retroid (World) (Aftermarket) (Unl)" + rom ( name "Retroid (World) (Aftermarket) (Unl).gb" size 262144 crc 9f759f25 sha1 4c7323d6a10852fe416c7bd581d6ffdd2d473bb5 ) +) + +game ( + name "Rewind Time (World) (Aftermarket) (Unl)" + description "Rewind Time (World) (Aftermarket) (Unl)" + rom ( name "Rewind Time (World) (Aftermarket) (Unl).gb" size 262144 crc d8ad184a sha1 903ef8074e58a52bc98dcb9e3f2c88b52fc1335b ) +) + +game ( + name "Rhythm Land (World) (Aftermarket) (Unl)" + description "Rhythm Land (World) (Aftermarket) (Unl)" + rom ( name "Rhythm Land (World) (Aftermarket) (Unl).gb" size 131072 crc 4312c7ff sha1 c79f26ce187edea18cf92be8340ec0a0c8beec87 ) +) + +game ( + name "Rhythm Land (World) (v1.0.1) (Aftermarket) (Unl)" + description "Rhythm Land (World) (v1.0.1) (Aftermarket) (Unl)" + rom ( name "Rhythm Land (World) (v1.0.1) (Aftermarket) (Unl).gb" size 131072 crc fbf98400 sha1 1b831806d32e1ec35bc94a84384c6989433a274d ) +) + +game ( + name "Rig Attack (World) (Aftermarket) (Unl)" + description "Rig Attack (World) (Aftermarket) (Unl)" + rom ( name "Rig Attack (World) (Aftermarket) (Unl).gb" size 262144 crc dea8749d sha1 6f0fbac6b6c2e8f2d8df0a0a0e2f0c947e37b39a ) +) + +game ( + name "Robby's Day Out (World) (Aftermarket) (Unl)" + description "Robby's Day Out (World) (Aftermarket) (Unl)" + rom ( name "Robby's Day Out (World) (Aftermarket) (Unl).gb" size 262144 crc c3c89cd9 sha1 9d38b69ab9a4ff7bf387c88f2afed410d450f2e0 ) +) + +game ( + name "Roommate Simulator (World) (Aftermarket) (Unl)" + description "Roommate Simulator (World) (Aftermarket) (Unl)" + rom ( name "Roommate Simulator (World) (Aftermarket) (Unl).gb" size 131072 crc 3c95b1aa sha1 d5c99106c3bd4d46aeb75f513fd4314c19c734b2 ) +) + +game ( + name "Rosa Cupiditatis (World) (2023-05-17) (Demo) (Aftermarket) (Unl)" + description "Rosa Cupiditatis (World) (2023-05-17) (Demo) (Aftermarket) (Unl)" + rom ( name "Rosa Cupiditatis (World) (2023-05-17) (Demo) (Aftermarket) (Unl).gb" size 524288 crc 51d09337 sha1 9e935cca00cb4c3aad7b1dfce9fe59f5d913bdff ) +) + +game ( + name "Sacred Meat (World) (v1.3) (Aftermarket) (Unl)" + description "Sacred Meat (World) (v1.3) (Aftermarket) (Unl)" + rom ( name "Sacred Meat (World) (v1.3) (Aftermarket) (Unl).gb" size 2097152 crc 6669f0be sha1 25bcf936e8dadb10d288473989891e4f2ec6c605 ) +) + +game ( + name "Sacred Meat (World) (v1.1) (Aftermarket) (Unl)" + description "Sacred Meat (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Sacred Meat (World) (v1.1) (Aftermarket) (Unl).gb" size 2097152 crc 1c4b7eb0 sha1 5cd15f4629fdbcfd6f752d89be755d5ac02b9435 ) +) + +game ( + name "Safe File (World) (SGB Enhanced) (Aftermarket) (Unl)" + description "Safe File (World) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Safe File (World) (SGB Enhanced) (Aftermarket) (Unl).gb" size 262144 crc 03f2dd1a sha1 78fe9c7cd6d0d7f1157c8c7716642d17c4b80303 ) +) + +game ( + name "Sam Mallard - The Case of the Missing Swan (World) (SGB Enhanced) (Aftermarket) (Unl)" + description "Sam Mallard - The Case of the Missing Swan (World) (SGB Enhanced) (Aftermarket) (Unl)" + rom ( name "Sam Mallard - The Case of the Missing Swan (World) (SGB Enhanced) (Aftermarket) (Unl).gb" size 1048576 crc 994a2edd sha1 0132f0311d8478d4f45b3b8e2728698570091d69 ) +) + +game ( + name "Severen (World) (Demo) (Aftermarket) (Unl)" + description "Severen (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Severen (World) (Demo) (Aftermarket) (Unl).gb" size 1048576 crc 642f2244 sha1 d9692aa569820db3f38458819cba21846a2e06f4 ) +) + +game ( + name "Shapeshifter, The (World) (Aftermarket) (Unl)" + description "Shapeshifter, The (World) (Aftermarket) (Unl)" + rom ( name "Shapeshifter, The (World) (Aftermarket) (Unl).gb" size 1048576 crc ef735794 sha1 179e69199f19b403b4c1a9675a3ee431ee570797 ) +) + +game ( + name "Shark Attack (World) (Aftermarket) (Unl)" + description "Shark Attack (World) (Aftermarket) (Unl)" + rom ( name "Shark Attack (World) (Aftermarket) (Unl).gb" size 262144 crc 3032025a sha1 6cc65bb719af53128bb04c9ee7c6abbf4ff1c3cf ) +) + +game ( + name "Sheep It Up (World) (Digital) (Aftermarket) (Unl)" + description "Sheep It Up (World) (Digital) (Aftermarket) (Unl)" + rom ( name "Sheep It Up (World) (Digital) (Aftermarket) (Unl).gb" size 32768 crc fa6de2e4 sha1 9ad365ed7d4e07041c0147831a9bb1c496ea0bc8 ) +) + +game ( + name "Shock Lobster (World) (Aftermarket) (Unl)" + description "Shock Lobster (World) (Aftermarket) (Unl)" + rom ( name "Shock Lobster (World) (Aftermarket) (Unl).gb" size 32768 crc 7a0622e6 sha1 10c1816724cd6e332d2a5aeed4e546e7bd764ebf ) +) + +game ( + name "Shock Lobster (World) (v1.3) (Aftermarket) (Unl)" + description "Shock Lobster (World) (v1.3) (Aftermarket) (Unl)" + rom ( name "Shock Lobster (World) (v1.3) (Aftermarket) (Unl).gb" size 32768 crc 8f244e86 sha1 7b8c8a9ec4758c6880598b9d508bc5805293dd87 ) +) + +game ( + name "Shootris (World) (Aftermarket) (Unl)" + description "Shootris (World) (Aftermarket) (Unl)" + rom ( name "Shootris (World) (Aftermarket) (Unl).gb" size 262144 crc 50180f64 sha1 5d978e6fc4bd5d9717d022360122458e95fffc29 ) +) + +game ( + name "Sloth Story (World) (Aftermarket) (Unl)" + description "Sloth Story (World) (Aftermarket) (Unl)" + rom ( name "Sloth Story (World) (Aftermarket) (Unl).gb" size 262144 crc c873f232 sha1 369d2afec4ffb59d4f3a59ee684c5bfec0b34ff8 ) +) + +game ( + name "Slurpee Cycle (World) (Aftermarket) (Unl)" + description "Slurpee Cycle (World) (Aftermarket) (Unl)" + rom ( name "Slurpee Cycle (World) (Aftermarket) (Unl).gb" size 131072 crc 8985031a sha1 1addff376e2734513406eca69a9c6679965faba9 ) +) + +game ( + name "Smickeonn - The Game (World) (Aftermarket) (Unl)" + description "Smickeonn - The Game (World) (Aftermarket) (Unl)" + rom ( name "Smickeonn - The Game (World) (Aftermarket) (Unl).gb" size 524288 crc 93041fca sha1 e0981231d10aa8ea64eeaec1ff90210adf42ae05 ) +) + +game ( + name "Smickeonn 2 - The Game (World) (Aftermarket) (Unl)" + description "Smickeonn 2 - The Game (World) (Aftermarket) (Unl)" + rom ( name "Smickeonn 2 - The Game (World) (Aftermarket) (Unl).gb" size 1048576 crc cd99b998 sha1 ac6b35af80c98ca5822e540a725b64a8c6dd5069 ) +) + +game ( + name "Snail, The (World) (v1.3) (Aftermarket) (Unl)" + description "Snail, The (World) (v1.3) (Aftermarket) (Unl)" + rom ( name "Snail, The (World) (v1.3) (Aftermarket) (Unl).gb" size 262144 crc 422a7b44 sha1 776f7578d747f935ebccda93d6487ffa4dc4bce3 ) +) + +game ( + name "Snakebird (World) (Aftermarket) (Unl)" + description "Snakebird (World) (Aftermarket) (Unl)" + rom ( name "Snakebird (World) (Aftermarket) (Unl).gb" size 131072 crc 4627f98e sha1 99cc82279d65b86b4366bf61db9bf67a78e051dc ) +) + +game ( + name "Snaky Pocket (World) (Aftermarket) (Unl)" + description "Snaky Pocket (World) (Aftermarket) (Unl)" + rom ( name "Snaky Pocket (World) (Aftermarket) (Unl).gb" size 32768 crc 7209370d sha1 f5eab31a499f33b3ae1f7b5b006dcca1df3ac2b9 ) +) + +game ( + name "Song of Morus - Gala of Battle (World) (En,Ja) (Aftermarket) (Unl)" + description "Song of Morus - Gala of Battle (World) (En,Ja) (Aftermarket) (Unl)" + rom ( name "Song of Morus - Gala of Battle (World) (En,Ja) (Aftermarket) (Unl).gb" size 262144 crc 665ad70a sha1 c5b6eb610caa2213d8db7ab204bad44d60f7d63a ) +) + +game ( + name "Song of Morus - Ghostly Night (World) (2023-05-20) (Aftermarket) (Unl)" + description "Song of Morus - Ghostly Night (World) (2023-05-20) (Aftermarket) (Unl)" + rom ( name "Song of Morus - Ghostly Night (World) (2023-05-20) (Aftermarket) (Unl).gb" size 262144 crc feed93e0 sha1 721d78d4ef167acfcc00baf909db4c94d522d681 ) +) + +game ( + name "Song of Morus - Ghostly Night (World) (2023-06-08) (Aftermarket) (Unl)" + description "Song of Morus - Ghostly Night (World) (2023-06-08) (Aftermarket) (Unl)" + rom ( name "Song of Morus - Ghostly Night (World) (2023-06-08) (Aftermarket) (Unl).gb" size 262144 crc 6547e5c8 sha1 53a42f45b7ed368d7af9d41f2442fe463c26e545 ) +) + +game ( + name "Space Trouble (World) (Proto) (Aftermarket) (Unl)" + description "Space Trouble (World) (Proto) (Aftermarket) (Unl)" + rom ( name "Space Trouble (World) (Proto) (Aftermarket) (Unl).gb" size 524288 crc f015931c sha1 ec7bc27387d4d2ac01127bc24e1adf45b6ebc936 ) +) + +game ( + name "Spiky Harold (World) (Aftermarket) (Unl)" + description "Spiky Harold (World) (Aftermarket) (Unl)" + rom ( name "Spiky Harold (World) (Aftermarket) (Unl).gb" size 524288 crc 2ac1b945 sha1 b8f37a64524bde4c2b6e9a1938ed6e5c0a5aad7c ) +) + +game ( + name "Star Catcher (World) (Aftermarket) (Unl)" + description "Star Catcher (World) (Aftermarket) (Unl)" + rom ( name "Star Catcher (World) (Aftermarket) (Unl).gb" size 131072 crc a14dffef sha1 22a2693db5266238751ba3ae2b8ea634bfbe78aa ) +) + +game ( + name "Stardiver (World) (Aftermarket) (Unl)" + description "Stardiver (World) (Aftermarket) (Unl)" + rom ( name "Stardiver (World) (Aftermarket) (Unl).gb" size 1048576 crc 25ff97f7 sha1 d609b8de2c7a61b7281fec5c761e3504aa4d94e9 ) +) + +game ( + name "Stick Man Guy (World) (Aftermarket) (Unl)" + description "Stick Man Guy (World) (Aftermarket) (Unl)" + rom ( name "Stick Man Guy (World) (Aftermarket) (Unl).gb" size 262144 crc 3a61fefc sha1 2f7351579e09ef29e067a69dfa3556448626d68e ) +) + +game ( + name "Super Connard (World) (Fr) (Aftermarket) (Unl)" + description "Super Connard (World) (Fr) (Aftermarket) (Unl)" + rom ( name "Super Connard (World) (Fr) (Aftermarket) (Unl).gb" size 32768 crc 9aaf301a sha1 6f4bf6c8206cc95cf17bea6739aa942034c2a230 ) +) + +game ( + name "Super Connard (World) (Fr) (Digital) (Aftermarket) (Unl)" + description "Super Connard (World) (Fr) (Digital) (Aftermarket) (Unl)" + rom ( name "Super Connard (World) (Fr) (Digital) (Aftermarket) (Unl).gb" size 32768 crc 7ebd22cd sha1 24264376aeee13d7f9b9424553f7fa4ba4b3b116 ) +) + +game ( + name "Super Covid Go Get Biscuits Adventure (World) (Aftermarket) (Unl)" + description "Super Covid Go Get Biscuits Adventure (World) (Aftermarket) (Unl)" + rom ( name "Super Covid Go Get Biscuits Adventure (World) (Aftermarket) (Unl).gb" size 262144 crc 51946e8d sha1 cac4917d56da02cf88ba68e0c5189a18c2c234ac ) +) + +game ( + name "Super Hard Bouncer (World) (v1.1) (Aftermarket) (Unl)" + description "Super Hard Bouncer (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Super Hard Bouncer (World) (v1.1) (Aftermarket) (Unl).gb" size 32768 crc a653f726 sha1 09c242a4c0752f251388026df7ed4baab5a8c56f ) +) + +game ( + name "Super Hard Bouncer (World) (v1.0) (Aftermarket) (Unl)" + description "Super Hard Bouncer (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "Super Hard Bouncer (World) (v1.0) (Aftermarket) (Unl).gb" size 32768 crc 6308019a sha1 549c2624767633d6898ab9623eadb9579ec2779b ) +) + +game ( + name "Sushi Gun (World) (Aftermarket) (Unl)" + description "Sushi Gun (World) (Aftermarket) (Unl)" + rom ( name "Sushi Gun (World) (Aftermarket) (Unl).gb" size 262144 crc a9d405d6 sha1 c075856939d4fe3cd250083b527b3e09be70052d ) +) + +game ( + name "Swaplatformer (World) (Aftermarket) (Unl)" + description "Swaplatformer (World) (Aftermarket) (Unl)" + rom ( name "Swaplatformer (World) (Aftermarket) (Unl).gb" size 1048576 crc babe7935 sha1 3df0c37862b7c391a0d091a55db0d305341529c2 ) +) + +game ( + name "Take It Racing 2 (World) (Demo) (Aftermarket) (Unl)" + description "Take It Racing 2 (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Take It Racing 2 (World) (Demo) (Aftermarket) (Unl).gb" size 1048576 crc 5898c134 sha1 bd3468395deb0009b190d0b5d487962ae65adbee ) +) + +game ( + name "Tech and Blood (World) (Aftermarket) (Unl)" + description "Tech and Blood (World) (Aftermarket) (Unl)" + rom ( name "Tech and Blood (World) (Aftermarket) (Unl).gb" size 262144 crc 3da2a358 sha1 40a00fce49b16cb36793df30e5156e5bf3e47778 ) +) + +game ( + name "The Light, The Fire (World) (Aftermarket) (Unl)" + description "The Light, The Fire (World) (Aftermarket) (Unl)" + rom ( name "The Light, The Fire (World) (Aftermarket) (Unl).gb" size 524288 crc b6a19823 sha1 d98e03602699f8602689f006e1f55f0c549b3cb7 ) +) + +game ( + name "There's Nothing to Do in This Town (World) (Aftermarket) (Unl)" + description "There's Nothing to Do in This Town (World) (Aftermarket) (Unl)" + rom ( name "There's Nothing to Do in This Town (World) (Aftermarket) (Unl).gb" size 1048576 crc 173b549a sha1 e000fbecda9ea6bbbd0c0370cf8c3faaa54bf64e ) +) + +game ( + name "Thin Ice Rescue, The (World) (Aftermarket) (Unl)" + description "Thin Ice Rescue, The (World) (Aftermarket) (Unl)" + rom ( name "Thin Ice Rescue, The (World) (Aftermarket) (Unl).gb" size 32768 crc 3e0483d6 sha1 b789ced0fe26785e7bce765a9d6ee783f9d967d8 ) +) + +game ( + name "TimberMan (World) (Aftermarket) (Unl)" + description "TimberMan (World) (Aftermarket) (Unl)" + rom ( name "TimberMan (World) (Aftermarket) (Unl).gb" size 32768 crc e0b8459c sha1 e3f4b4c4816cc0dda2885519f1386385e6a5e817 ) +) + +game ( + name "Tobu Tobu Girl (World) (Aftermarket) (Unl)" + description "Tobu Tobu Girl (World) (Aftermarket) (Unl)" + rom ( name "Tobu Tobu Girl (World) (Aftermarket) (Unl).gb" size 262144 crc ed12be6c sha1 8a8f3c1f21f903ea5a7df8fc8b0a6aa5a602e150 ) +) + +game ( + name "Touch the Cat (World) (Aftermarket) (Unl)" + description "Touch the Cat (World) (Aftermarket) (Unl)" + rom ( name "Touch the Cat (World) (Aftermarket) (Unl).gb" size 131072 crc 351fd00a sha1 9dc7b51a44aec9055924596c161972f366caf067 ) +) + +game ( + name "Traumatarium (World) (Demo) (2021-12-09) (Aftermarket) (Unl)" + description "Traumatarium (World) (Demo) (2021-12-09) (Aftermarket) (Unl)" + rom ( name "Traumatarium (World) (Demo) (2021-12-09) (Aftermarket) (Unl).gb" size 2097152 crc 15afd765 sha1 c12e603492f8bcfffd28dd4733c7bc445c507642 ) +) + +game ( + name "Traumatarium (World) (Demo) (2022-06-18) (Aftermarket) (Unl)" + description "Traumatarium (World) (Demo) (2022-06-18) (Aftermarket) (Unl)" + rom ( name "Traumatarium (World) (Demo) (2022-06-18) (Aftermarket) (Unl).gb" size 2097152 crc e1bdf67f sha1 ba492778121622b5288d4188edc344aa41aa6803 ) +) + +game ( + name "Traumatarium (World) (Demo) (2022-03-13) (Aftermarket) (Unl)" + description "Traumatarium (World) (Demo) (2022-03-13) (Aftermarket) (Unl)" + rom ( name "Traumatarium (World) (Demo) (2022-03-13) (Aftermarket) (Unl).gb" size 1048576 crc 42bb7dab sha1 70fded7ce1edc54de85b020460f779feb9bdbc01 ) +) + +game ( + name "Traumatarium - Penitent (World) (2024-01-12) (Proto) (Aftermarket) (Unl)" + description "Traumatarium - Penitent (World) (2024-01-12) (Proto) (Aftermarket) (Unl)" + rom ( name "Traumatarium - Penitent (World) (2024-01-12) (Proto) (Aftermarket) (Unl).gb" size 4194304 crc 805f8257 sha1 a28d68f59b7ab3a6c95d5efc35c22ab9d7a74d31 ) +) + +game ( + name "Traumatarium - Penitent (World) (Demo) (Aftermarket) (Unl)" + description "Traumatarium - Penitent (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Traumatarium - Penitent (World) (Demo) (Aftermarket) (Unl).gb" size 4194304 crc 7d368277 sha1 efc91ca2873ff8f1733036e298950033d3456927 ) +) + +game ( + name "Treasure Island (World) (Aftermarket) (Unl)" + description "Treasure Island (World) (Aftermarket) (Unl)" + rom ( name "Treasure Island (World) (Aftermarket) (Unl).gb" size 262144 crc cbdec393 sha1 adeaba2723d286d143e0987f51ce9c8ad2f5e839 ) +) + +game ( + name "Vampire Night Shift (World) (Aftermarket) (Unl)" + description "Vampire Night Shift (World) (Aftermarket) (Unl)" + rom ( name "Vampire Night Shift (World) (Aftermarket) (Unl).gb" size 262144 crc 88acbc1a sha1 ef617803c2cdb14cfe3b3b2111aa239a3744e29e ) +) + +game ( + name "Waifu Clicker (World) (Aftermarket) (Unl)" + description "Waifu Clicker (World) (Aftermarket) (Unl)" + rom ( name "Waifu Clicker (World) (Aftermarket) (Unl).gb" size 65536 crc 155f85dc sha1 bb571ed69c3a33e45ba33fbb03a066ba98ae0b20 ) +) + +game ( + name "What Friends Are For (World) (Aftermarket) (Unl)" + description "What Friends Are For (World) (Aftermarket) (Unl)" + rom ( name "What Friends Are For (World) (Aftermarket) (Unl).gb" size 262144 crc cbed3dd6 sha1 58538084a964f779c2f756fbe732656f3f7bef66 ) +) + +game ( + name "Windows93 Adventure (World) (Aftermarket) (Unl)" + description "Windows93 Adventure (World) (Aftermarket) (Unl)" + rom ( name "Windows93 Adventure (World) (Aftermarket) (Unl).gb" size 1048576 crc e1ad0b6f sha1 3ad7327f6f94976c3d12054cf6deb2666ba9fa66 ) +) + +game ( + name "Witchscape (World) (Proto) (Aftermarket) (Unl)" + description "Witchscape (World) (Proto) (Aftermarket) (Unl)" + rom ( name "Witchscape (World) (Proto) (Aftermarket) (Unl).gb" size 262144 crc 2b2fcea0 sha1 8440a578567aa40c646d01c990317f9d12c444e5 ) +) + +game ( + name "Wizard of Wor (World) (Aftermarket) (Unl)" + description "Wizard of Wor (World) (Aftermarket) (Unl)" + rom ( name "Wizard of Wor (World) (Aftermarket) (Unl).gb" size 524288 crc bfb1563e sha1 108eefa154412e3422dce4e63bf34f5826ec1baa ) +) + +game ( + name "Woolball's Backyard (World) (Aftermarket) (Unl)" + description "Woolball's Backyard (World) (Aftermarket) (Unl)" + rom ( name "Woolball's Backyard (World) (Aftermarket) (Unl).gb" size 65536 crc 69e26eb6 sha1 28795c4b829440549b3ac2afe3282d85a439f7d7 ) +) + +game ( + name "Year After, The (World) (En) (Proto) (Aftermarket) (Unl)" + description "Year After, The (World) (En) (Proto) (Aftermarket) (Unl)" + rom ( name "Year After, The (World) (En) (Proto) (Aftermarket) (Unl).gb" size 1048576 crc 4e463a1a sha1 5d84f53f38aa24f54a6f897ca69ffc5d978805af ) +) + +game ( + name "Year After, The (World) (Fr) (Proto) (Aftermarket) (Unl)" + description "Year After, The (World) (Fr) (Proto) (Aftermarket) (Unl)" + rom ( name "Year After, The (World) (Fr) (Proto) (Aftermarket) (Unl).gb" size 1048576 crc fbc50ee8 sha1 52c27e64fb37412c97a53d5dde52c3803fd1e4f7 ) +) + +game ( + name "Yuuto Ichika Makes Friends (World) (En,Ja) (Aftermarket) (Unl)" + description "Yuuto Ichika Makes Friends (World) (En,Ja) (Aftermarket) (Unl)" + rom ( name "Yuuto Ichika Makes Friends (World) (En,Ja) (Aftermarket) (Unl).gb" size 524288 crc 8a667058 sha1 e765d6915f543a5a65e8be440b3f29eb674a5448 ) +) + +game ( + name "Yvonne Goes to Carbonic (World) (v4.2) (Aftermarket) (Unl)" + description "Yvonne Goes to Carbonic (World) (v4.2) (Aftermarket) (Unl)" + rom ( name "Yvonne Goes to Carbonic (World) (v4.2) (Aftermarket) (Unl).gb" size 262144 crc d46cd738 sha1 b5e8f7b572a47aa191462bb4f980813ad6634ae0 ) +) + +game ( + name "Zagan Warrior (World) (Aftermarket) (Unl)" + description "Zagan Warrior (World) (Aftermarket) (Unl)" + rom ( name "Zagan Warrior (World) (Aftermarket) (Unl).gb" size 262144 crc 97fe7a94 sha1 88f76297a4ccf0e3a5ba16ca15237c88346c134a ) +) + +game ( + name "Zelda - Majora's Mask (World) (v1.1) (Demo) (Aftermarket) (Unl)" + description "Zelda - Majora's Mask (World) (v1.1) (Demo) (Aftermarket) (Unl)" + rom ( name "Zelda - Majora's Mask (World) (v1.1) (Demo) (Aftermarket) (Unl).gb" size 524288 crc f86c2766 sha1 ee86a28cf271be43739e406135e4d8bd4edf7686 ) +) + +game ( + name "Zelda's Adventure (World) (v1.3.0) (Aftermarket) (Unl)" + description "Zelda's Adventure (World) (v1.3.0) (Aftermarket) (Unl)" + rom ( name "Zelda's Adventure (World) (v1.3.0) (Aftermarket) (Unl).gb" size 2097152 crc 0b10adaf sha1 12f9ba0a4673dd2f59ba38e636332333a199dea5 ) ) clrmamepro ( name "Nintendo - Game Boy Color" description "Nintendo - Game Boy Color" - version 20230422-225414 - author "akubi, Arctic Circle System, Aringon, baldjared, Bent, BigFred, BitLooter, C. V. Reynolds, chillerecke, coraz, darthcloud, DeadSkullzJr, Densetsu, DeriLoko3, Flashfire42, foxe, fuzzball, Gefflon, Hiccup, hking0036, InternalLoss, Just001Kim, kazumi213, Lesserkuma, Madeline, Money_114, NESBrew12, NGEfreak, nnssxx, norkmetnoil577, NovaAurora, omonim2007, PPLToast, rarenight, relax, Rifu, sCZther, SonGoku, Tauwasser, togemet2, UnlockerPT, Whovian9369, xuom2, zg" + version 20240810-021134 + author "akubi, Arctic Circle System, Aringon, baldjared, Bent, BigFred, bikerspade, BitLooter, C. V. Reynolds, chillerecke, coraz, darthcloud, DeadSkullzJr, Densetsu, DeriLoko3, Flashfire42, foxe, fuzzball, Gefflon, gordonj, Hiccup, hking0036, InternalLoss, Just001Kim, kazumi213, Lesserkuma, Madeline, Money_114, NESBrew12, NGEfreak, nnssxx, norkmetnoil577, NovaAurora, omonim2007, PPLToast, Psychofox11, psykopat, rarenight, relax, Rifu, sCZther, SonGoku, Tauwasser, togemet2, UnlockerPT, Whovian9369, xprism, xuom2, zg" homepage No-Intro url "https://www.no-intro.org" forcenodump required @@ -33825,6 +35912,12 @@ game ( rom ( name "1942 (USA, Europe).gbc" size 1048576 crc 87431672 sha1 d960e951b18d07e79d046313df49c18313664224 ) ) +game ( + name "2001 Fatal Fury (Taiwan) (En) (Unl)" + description "2001 Fatal Fury (Taiwan) (En) (Unl)" + rom ( name "2001 Fatal Fury (Taiwan) (En) (Unl).gbc" size 1048576 crc 7eda0e26 sha1 cd632530d71c560111bfc13a341f0f9a234db50a ) +) + game ( name "2002 Adventure Digimon 7 (Taiwan) (En) (Unl)" description "2002 Adventure Digimon 7 (Taiwan) (En) (Unl)" @@ -33849,6 +35942,12 @@ game ( rom ( name "2003 Digimom Sapphii (Taiwan) (En) (Unl).gbc" size 2097152 crc 7cff9f0b sha1 1e42c461e0c6705637a698dbda8b34bc37acc51d ) ) +game ( + name "2003 Digimom Sapphii (Taiwan) (De) (Unl)" + description "2003 Digimom Sapphii (Taiwan) (De) (Unl)" + rom ( name "2003 Digimom Sapphii (Taiwan) (De) (Unl).gbc" size 2097152 crc bd285d64 sha1 1cdffe470fde714898a2b0de92edd88e791a1bdf ) +) + game ( name "2003 Gu Huo Lang II (Taiwan) (Unl)" description "2003 Gu Huo Lang II (Taiwan) (Unl)" @@ -33939,12 +36038,6 @@ game ( rom ( name "3D Pool Allstars (USA) (En,Fr,Es) (Proto).gbc" size 1048576 crc 245de3e2 sha1 f7289c3eed275286d0fb3dc7097098276b746786 ) ) -game ( - name "3D Quasars (World) (Aftermarket) (Unl)" - description "3D Quasars (World) (Aftermarket) (Unl)" - rom ( name "3D Quasars (World) (Aftermarket) (Unl).gbc" size 262144 crc 1fd94e67 sha1 3f32226538d8c7f0c866c4b73e9f828265f2bb5b ) -) - game ( name "4 in 1 + 8 in 1 (World) (4B-001, 4B-009, 8B-001, Sachen) (Unl)" description "4 in 1 + 8 in 1 (World) (4B-001, 4B-009, 8B-001, Sachen) (Unl)" @@ -33981,12 +36074,6 @@ game ( rom ( name "720 Degrees (USA, Europe) (GB Compatible).gbc" size 1048576 crc e633841f sha1 78c0117c8ee32cfa605ac34eedf707cc535b3987 flags verified ) ) -game ( - name "Aardvark (World) (Aftermarket) (Unl)" - description "Aardvark (World) (Aftermarket) (Unl)" - rom ( name "Aardvark (World) (Aftermarket) (Unl).gbc" size 262144 crc 270d45b9 sha1 34a8d00af6be9083409e6fccd0825c6f185d135d flags verified ) -) - game ( name "Absolute X (Europe) (Proto)" description "Absolute X (Europe) (Proto)" @@ -33996,7 +36083,7 @@ game ( game ( name "Action Man - Search for Base X (USA, Europe)" description "Action Man - Search for Base X (USA, Europe)" - rom ( name "Action Man - Search for Base X (USA, Europe).gbc" size 1048576 crc 1226499e sha1 4b62b0344b8fed07ceb967f9a9c45bbeed3dc592 ) + rom ( name "Action Man - Search for Base X (USA, Europe).gbc" size 1048576 crc 1226499e sha1 4b62b0344b8fed07ceb967f9a9c45bbeed3dc592 flags verified ) ) game ( @@ -34017,18 +36104,6 @@ game ( rom ( name "Adventures of the Smurfs, The (Europe) (En,Fr,De,Es,It,Nl).gbc" size 1048576 crc d0d3dfed sha1 7919c5e6aa8d040b1f7953345b376d999cf22b18 ) ) -game ( - name "Agent B (World) (2021-12-29) (GB Compatible) (Aftermarket) (Unl)" - description "Agent B (World) (2021-12-29) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Agent B (World) (2021-12-29) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 31b6e3fa sha1 11b3ce59c4eb86cee05873eb473dbf262cf986bd ) -) - -game ( - name "Agent B (World) (2021-12-29) (Demo) (GB Compatible) (Aftermarket) (Unl)" - description "Agent B (World) (2021-12-29) (Demo) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Agent B (World) (2021-12-29) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc ae767ad7 sha1 1a332aac66b24381f16819d1145fd4a917f2e0f3 ) -) - game ( name "AirForce Delta (Japan)" description "AirForce Delta (Japan)" @@ -34078,9 +36153,9 @@ game ( ) game ( - name "All Star Tennis 2000 (Europe) (AZTP) (GB Compatible)" - description "All Star Tennis 2000 (Europe) (AZTP) (GB Compatible)" - rom ( name "All Star Tennis 2000 (Europe) (AZTP) (GB Compatible).gbc" size 1048576 crc 952b94e5 sha1 50f99b0fc5c2f5edc2e76ba973cc42fb0a1a02c8 ) + name "All Star Tennis '99 (USA) (Proto) (1999-09-13) (GB Compatible)" + description "All Star Tennis '99 (USA) (Proto) (1999-09-13) (GB Compatible)" + rom ( name "All Star Tennis '99 (USA) (Proto) (1999-09-13) (GB Compatible).gbc" size 1048576 crc e1b17e76 sha1 239e79281faacf7df2abfb527e6e2adfb58b0bc3 ) ) game ( @@ -34095,6 +36170,12 @@ game ( rom ( name "All Star Tennis 2000 (Europe) (AZTX) (Proto) (GB Compatible).gbc" size 1048576 crc deff8dfb sha1 c9db40e3e348668fe6fc41d031263acbe9041a67 ) ) +game ( + name "All Star Tennis 2000 (Europe) (AZTP) (GB Compatible)" + description "All Star Tennis 2000 (Europe) (AZTP) (GB Compatible)" + rom ( name "All Star Tennis 2000 (Europe) (AZTP) (GB Compatible).gbc" size 1048576 crc 952b94e5 sha1 50f99b0fc5c2f5edc2e76ba973cc42fb0a1a02c8 ) +) + game ( name "All-Star Baseball 2000 (USA, Europe)" description "All-Star Baseball 2000 (USA, Europe)" @@ -34107,12 +36188,6 @@ game ( rom ( name "All-Star Baseball 2001 (USA).gbc" size 1048576 crc bc562466 sha1 f702df64d368b763187a5b1263a60fb3e842962b ) ) -game ( - name "Alley Cat (World) (Aftermarket) (Unl)" - description "Alley Cat (World) (Aftermarket) (Unl)" - rom ( name "Alley Cat (World) (Aftermarket) (Unl).gbc" size 262144 crc edb3ac37 sha1 a9aa1ecad6b67a6e5096fb1c10e39899c00a96a0 ) -) - game ( name "Alone in the Dark - The New Nightmare (Europe) (En,Fr,De,Es,It,Nl) (Beta)" description "Alone in the Dark - The New Nightmare (Europe) (En,Fr,De,Es,It,Nl) (Beta)" @@ -34188,7 +36263,7 @@ game ( game ( name "Antz (USA) (En,Fr,Es) (GB Compatible)" description "Antz (USA) (En,Fr,Es) (GB Compatible)" - rom ( name "Antz (USA) (En,Fr,Es) (GB Compatible).gbc" size 1048576 crc dc0be439 sha1 85684d5891e4ec0f9fdf61b644bdf0ffbf1ba219 ) + rom ( name "Antz (USA) (En,Fr,Es) (GB Compatible).gbc" size 1048576 crc dc0be439 sha1 85684d5891e4ec0f9fdf61b644bdf0ffbf1ba219 flags verified ) ) game ( @@ -34248,7 +36323,7 @@ game ( game ( name "Army Men - Air Combat (USA, Europe) (En,Fr,De)" description "Army Men - Air Combat (USA, Europe) (En,Fr,De)" - rom ( name "Army Men - Air Combat (USA, Europe) (En,Fr,De).gbc" size 1048576 crc b0d1de8c sha1 4e1d964d31013e79ecae4a49dcd3777cc7e06af2 ) + rom ( name "Army Men - Air Combat (USA, Europe) (En,Fr,De).gbc" size 1048576 crc b0d1de8c sha1 4e1d964d31013e79ecae4a49dcd3777cc7e06af2 flags verified ) ) game ( @@ -34260,7 +36335,7 @@ game ( game ( name "Army Men 2 (USA, Europe) (En,Fr,De)" description "Army Men 2 (USA, Europe) (En,Fr,De)" - rom ( name "Army Men 2 (USA, Europe) (En,Fr,De).gbc" size 1048576 crc 2272baca sha1 6e52dcaca1a97ae557c4c87e4281667a9d9b14c5 ) + rom ( name "Army Men 2 (USA, Europe) (En,Fr,De).gbc" size 1048576 crc 2272baca sha1 6e52dcaca1a97ae557c4c87e4281667a9d9b14c5 flags verified ) ) game ( @@ -34272,7 +36347,7 @@ game ( game ( name "Asterix - Sur la Trace D'Idefix (Europe) (En,Fr,De,Es,It,Nl)" description "Asterix - Sur la Trace D'Idefix (Europe) (En,Fr,De,Es,It,Nl)" - rom ( name "Asterix - Sur la Trace D'Idefix (Europe) (En,Fr,De,Es,It,Nl).gbc" size 1048576 crc 408dc5c6 sha1 5c7207137ab422d3326d183d3433db161d8ecbc5 ) + rom ( name "Asterix - Sur la Trace D'Idefix (Europe) (En,Fr,De,Es,It,Nl).gbc" size 1048576 crc 408dc5c6 sha1 5c7207137ab422d3326d183d3433db161d8ecbc5 flags verified ) ) game ( @@ -34371,12 +36446,6 @@ game ( rom ( name "Austin Powers Episode IV (Europe) (En,Fr,De,Es,It) (Proto).gbc" size 2097152 crc f038cda7 sha1 937df6944709732d8d372ad5f629a665ffd12eac ) ) -game ( - name "Auto Zone (World) (Aftermarket) (Unl)" - description "Auto Zone (World) (Aftermarket) (Unl)" - rom ( name "Auto Zone (World) (Aftermarket) (Unl).gbc" size 524288 crc 2a86d386 sha1 83a37fb5c5d82e0ff06bb22b63761af996e4ad61 ) -) - game ( name "Aventures de Buzz l'Eclair, Les (France)" description "Aventures de Buzz l'Eclair, Les (France)" @@ -34437,12 +36506,6 @@ game ( rom ( name "Back to Earth 3D (Europe) (Demo).gbc" size 262144 crc d4255616 sha1 716722ed8756b656bba00cbff116f883e629cfd2 ) ) -game ( - name "Back to Nature (World) (Aftermarket) (Unl)" - description "Back to Nature (World) (Aftermarket) (Unl)" - rom ( name "Back to Nature (World) (Aftermarket) (Unl).gbc" size 262144 crc 861f9a63 sha1 3f4a6cd105d4c8af0312bef482c08784bbbfb0eb ) -) - game ( name "Backgammon (Europe) (En,Fr,De,Es) (GB Compatible)" description "Backgammon (Europe) (En,Fr,De,Es) (GB Compatible)" @@ -34509,12 +36572,6 @@ game ( rom ( name "Balloon Fight GB (Japan) (SGB Enhanced, GB Compatible) (NP).gbc" size 262144 crc d2af64ce sha1 dbaa1bf9061de0f052704d6a33892341a38f2152 ) ) -game ( - name "Bandits at Zero (World) (Aftermarket) (Unl)" - description "Bandits at Zero (World) (Aftermarket) (Unl)" - rom ( name "Bandits at Zero (World) (Aftermarket) (Unl).gbc" size 524288 crc c70f413e sha1 c885e109fbb53445db9618c6768c2259e6135921 ) -) - game ( name "Barbie - Aventura Submarina (Spain) (GB Compatible)" description "Barbie - Aventura Submarina (Spain) (GB Compatible)" @@ -34641,12 +36698,6 @@ game ( rom ( name "Battle Fishers (Japan).gbc" size 2097152 crc c99cf3c5 sha1 25d063b151c2d45a14d6952196490615b7e341c5 ) ) -game ( - name "Battle Star (World) (Aftermarket) (Unl)" - description "Battle Star (World) (Aftermarket) (Unl)" - rom ( name "Battle Star (World) (Aftermarket) (Unl).gbc" size 524288 crc b2fd062f sha1 ac4206129704e31386c9c0a1c961a148398f0ba3 ) -) - game ( name "Battleship (USA, Europe) (GB Compatible)" description "Battleship (USA, Europe) (GB Compatible)" @@ -34719,12 +36770,6 @@ game ( rom ( name "Benjamin Bluemchen - Ein verrueckter Tag im Zoo (Germany).gbc" size 2097152 crc 51972995 sha1 560fc8468ed559a72087f630eff015ffb8de22ca ) ) -game ( - name "Berks (World) (Aftermarket) (Unl)" - description "Berks (World) (Aftermarket) (Unl)" - rom ( name "Berks (World) (Aftermarket) (Unl).gbc" size 262144 crc 10ded9ab sha1 8b4c282cf973cdd9926a69ae1d8fcbaf79f8552b ) -) - game ( name "Beyblade - Fighting Tournament (Japan)" description "Beyblade - Fighting Tournament (Japan)" @@ -34761,6 +36806,12 @@ game ( rom ( name "Billy Bob's Huntin' 'n' Fishin' (USA, Europe).gbc" size 1048576 crc fa1e6853 sha1 9331fb3103a23340192968715adaa1e4ef140329 flags verified ) ) +game ( + name "Binary Monster 2 (Taiwan) (En) (Unl)" + description "Binary Monster 2 (Taiwan) (En) (Unl)" + rom ( name "Binary Monster 2 (Taiwan) (En) (Unl).gbc" size 131072 crc 16297b29 sha1 bccc7bd374166171f4961b8773bb881050b8a62d ) +) + game ( name "Bingyuan Lixian Ji (Taiwan) (Unl)" description "Bingyuan Lixian Ji (Taiwan) (Unl)" @@ -34815,12 +36866,6 @@ game ( rom ( name "Blaster Master - Enemy Below (USA, Europe) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 2f91e17c sha1 8b2e83d7f2b7d72d5cc1ac81c28c2173ad2fc9ba ) ) -game ( - name "Blinky's Revenge (World) (Aftermarket) (Unl)" - description "Blinky's Revenge (World) (Aftermarket) (Unl)" - rom ( name "Blinky's Revenge (World) (Aftermarket) (Unl).gbc" size 262144 crc 2d2f9c2b sha1 1c39cc02396c74e7b0b282ead510e94c77ff7f1e ) -) - game ( name "Blue's Clues - Blue's Alphabet Book (USA) (Rev 1) (Proto)" description "Blue's Clues - Blue's Alphabet Book (USA) (Rev 1) (Proto)" @@ -34959,12 +37004,6 @@ game ( rom ( name "Bomberman Selection (Korea) (Beta 1).gbc" size 1048576 crc 005ad4b7 sha1 206a19a48a35bcff18d5872b85ba4e8963827cb3 ) ) -game ( - name "Booty (World) (Aftermarket) (Unl)" - description "Booty (World) (Aftermarket) (Unl)" - rom ( name "Booty (World) (Aftermarket) (Unl).gbc" size 262144 crc ef6c39c8 sha1 3c487ddc03d935b583e186d1cc395966ef490412 ) -) - game ( name "Bouken! Dondoko Shima (Japan)" description "Bouken! Dondoko Shima (Japan)" @@ -34980,13 +37019,7 @@ game ( game ( name "Brave Saga - Shinshou Astaria (Japan)" description "Brave Saga - Shinshou Astaria (Japan)" - rom ( name "Brave Saga - Shinshou Astaria (Japan).gbc" size 2097152 crc 5d5d294a sha1 952b9e16a938b986a6216b8db6d62f71c4f853fa ) -) - -game ( - name "Bubble Trouble (World) (Aftermarket) (Unl)" - description "Bubble Trouble (World) (Aftermarket) (Unl)" - rom ( name "Bubble Trouble (World) (Aftermarket) (Unl).gbc" size 262144 crc 3374918b sha1 892388f81f7815ea3bca17632a6a9a33a6edafac ) + rom ( name "Brave Saga - Shinshou Astaria (Japan).gbc" size 2097152 crc 5d5d294a sha1 952b9e16a938b986a6216b8db6d62f71c4f853fa flags verified ) ) game ( @@ -35049,12 +37082,6 @@ game ( rom ( name "Bugs Bunny in - Crazy Castle 4 (USA).gbc" size 1048576 crc 98dbffe0 sha1 a22b9765e901b2a23a48c44b0b829ab73b9c1a82 ) ) -game ( - name "Bulb! (World) (v2.5) (Aftermarket) (Unl)" - description "Bulb! (World) (v2.5) (Aftermarket) (Unl)" - rom ( name "Bulb! (World) (v2.5) (Aftermarket) (Unl).gbc" size 524288 crc 650114a2 sha1 0c32d4b48a34614fb11fc69c17187d35ee22fabe flags verified ) -) - game ( name "Bundesliga Stars 2001 (Germany)" description "Bundesliga Stars 2001 (Germany)" @@ -35133,6 +37160,12 @@ game ( rom ( name "Cannon Fodder (USA) (En,Fr,De,Es,It).gbc" size 4194304 crc 26f8e1a0 sha1 cc601984a2b52b44cf135e42bcac1bec44b7a6a3 ) ) +game ( + name "Capcom Fight 2003 (Hong Kong) (En) (Unl)" + description "Capcom Fight 2003 (Hong Kong) (En) (Unl)" + rom ( name "Capcom Fight 2003 (Hong Kong) (En) (Unl).gbc" size 2097152 crc 2f8ac081 sha1 3b7a16d1a5d91118960cfadcc41eecaa36097bac ) +) + game ( name "Capcom vs SNK - Millennium Fight 2001 (Taiwan) (En) (Unl)" description "Capcom vs SNK - Millennium Fight 2001 (Taiwan) (En) (Unl)" @@ -35289,12 +37322,6 @@ game ( rom ( name "Catz (USA).gbc" size 1048576 crc 769a2c5a sha1 5c3c9a4d85a92779c7e8304f2c122296f62f9a9c ) ) -game ( - name "Cave Fighter (World) (Aftermarket) (Unl)" - description "Cave Fighter (World) (Aftermarket) (Unl)" - rom ( name "Cave Fighter (World) (Aftermarket) (Unl).gbc" size 262144 crc 6f4641f0 sha1 05b441e3542452b1724017d20e2db602d0997773 ) -) - game ( name "Centipede (Europe) (En,Fr,De,Es,It,Nl) (GB Compatible)" description "Centipede (Europe) (En,Fr,De,Es,It,Nl) (GB Compatible)" @@ -35308,9 +37335,9 @@ game ( ) game ( - name "CGB Test Cartridge (Japan) (En)" - description "CGB Test Cartridge (Japan) (En)" - rom ( name "CGB Test Cartridge (Japan) (En).gbc" size 65536 crc 4c050e29 sha1 5133d3dc7a4ced9d059dc72f0f351cb44e22f096 ) + name "CGB Test Cartridge (Japan) (En) [b]" + description "CGB Test Cartridge (Japan) (En) [b]" + rom ( name "CGB Test Cartridge (Japan) (En) [b].gbc" size 65536 crc 4c050e29 sha1 5133d3dc7a4ced9d059dc72f0f351cb44e22f096 flags baddump ) ) game ( @@ -35445,12 +37472,6 @@ game ( rom ( name "Classic Bubble Bobble (USA) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc c1b22246 sha1 6e3739c0538467c220750f2e8d474433692bac09 ) ) -game ( - name "Climb It (World) (Aftermarket) (Unl)" - description "Climb It (World) (Aftermarket) (Unl)" - rom ( name "Climb It (World) (Aftermarket) (Unl).gbc" size 262144 crc e7210290 sha1 19f3b825eada3eda3135350bd0ddca6a20a5281f ) -) - game ( name "Colin McRae Rally (Europe)" description "Colin McRae Rally (Europe)" @@ -35475,12 +37496,6 @@ game ( rom ( name "Commander Keen (USA, Europe).gbc" size 1048576 crc 4af4cc9c sha1 a00b7bdaaedeb67ad7e7555139301c8b4c92edea flags verified ) ) -game ( - name "Commando (World) (Aftermarket) (Unl)" - description "Commando (World) (Aftermarket) (Unl)" - rom ( name "Commando (World) (Aftermarket) (Unl).gbc" size 262144 crc 5381b103 sha1 414bb6bdc1ed5647707d7d49f194c387d4098f00 ) -) - game ( name "Conker's Pocket Tales (USA, Europe) (En,Fr,De) (SGB Enhanced) (GB Compatible)" description "Conker's Pocket Tales (USA, Europe) (En,Fr,De) (SGB Enhanced) (GB Compatible)" @@ -35517,12 +37532,6 @@ game ( rom ( name "Crazy Climber (USA) (Proto 1) (2000-09-22).gbc" size 131072 crc 748fa8b4 sha1 eb0eaed85cf5a72e0461eebbad38227bd018a999 ) ) -game ( - name "Crazy Golf (World) (Aftermarket) (Unl)" - description "Crazy Golf (World) (Aftermarket) (Unl)" - rom ( name "Crazy Golf (World) (Aftermarket) (Unl).gbc" size 262144 crc f7fe3d01 sha1 b06f47a713b66efa9133be43653c7c4cb5ebc93c ) -) - game ( name "Croc (USA, Europe)" description "Croc (USA, Europe)" @@ -35532,7 +37541,7 @@ game ( game ( name "Croc 2 (USA, Europe)" description "Croc 2 (USA, Europe)" - rom ( name "Croc 2 (USA, Europe).gbc" size 1048576 crc c1d60129 sha1 fa29d6c4239405b12b320bb6e8a65ca2083a4b1c ) + rom ( name "Croc 2 (USA, Europe).gbc" size 1048576 crc c1d60129 sha1 fa29d6c4239405b12b320bb6e8a65ca2083a4b1c flags verified ) ) game ( @@ -35577,12 +37586,6 @@ game ( rom ( name "Cubix - Robots for Everyone - Race 'n Robots (USA) (En,Fr,De,Es,It).gbc" size 1048576 crc 9f883b0f sha1 d62b85c664e0a42c84e56b939a201fe90d05a360 ) ) -game ( - name "Cuthbert in the Cooler (World) (Aftermarket) (Unl)" - description "Cuthbert in the Cooler (World) (Aftermarket) (Unl)" - rom ( name "Cuthbert in the Cooler (World) (Aftermarket) (Unl).gbc" size 262144 crc 30204c4e sha1 d6fb35f3bdd44429f88c10551692e1adf14356ab ) -) - game ( name "CyberTiger (USA, Europe)" description "CyberTiger (USA, Europe)" @@ -35622,7 +37625,7 @@ game ( game ( name "Daikaijuu Monogatari - Poyon no Dungeon Room (Japan) (SGB Enhanced) (GB Compatible)" description "Daikaijuu Monogatari - Poyon no Dungeon Room (Japan) (SGB Enhanced) (GB Compatible)" - rom ( name "Daikaijuu Monogatari - Poyon no Dungeon Room (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 2f368da6 sha1 0854b7ea4791a460c75ce9096583934b1af053e8 ) + rom ( name "Daikaijuu Monogatari - Poyon no Dungeon Room (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 2f368da6 sha1 0854b7ea4791a460c75ce9096583934b1af053e8 flags verified ) ) game ( @@ -35724,7 +37727,7 @@ game ( game ( name "David O'Leary's Total Soccer 2000 (Europe) (En,Fr,De,Es,It,Nl)" description "David O'Leary's Total Soccer 2000 (Europe) (En,Fr,De,Es,It,Nl)" - rom ( name "David O'Leary's Total Soccer 2000 (Europe) (En,Fr,De,Es,It,Nl).gbc" size 1048576 crc c25ee35a sha1 be0703ee2667ddc53cff9d6c7d22b30d272c0738 ) + rom ( name "David O'Leary's Total Soccer 2000 (Europe) (En,Fr,De,Es,It,Nl).gbc" size 1048576 crc c25ee35a sha1 be0703ee2667ddc53cff9d6c7d22b30d272c0738 flags verified ) ) game ( @@ -35739,24 +37742,12 @@ game ( rom ( name "Dear Daniel no Sweet Adventure - Kitty-chan o Sagashite (Japan) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 0fd34427 sha1 8598594285f0342b3d93c447b475fadd4722c6cb ) ) -game ( - name "Death Race 16 (World) (Aftermarket) (Unl)" - description "Death Race 16 (World) (Aftermarket) (Unl)" - rom ( name "Death Race 16 (World) (Aftermarket) (Unl).gbc" size 262144 crc 7b9488ec sha1 56b8a2d7117b12ff5e709e6a258f9a0b3b0ebe24 ) -) - game ( name "Deer Hunter (USA)" description "Deer Hunter (USA)" rom ( name "Deer Hunter (USA).gbc" size 1048576 crc 40a715fb sha1 87a012e82f2361760ae337b30e9d41ef2245419a ) ) -game ( - name "Deisanebe (World) (GB Compatible) (Aftermarket) (Unl)" - description "Deisanebe (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Deisanebe (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 7cff943e sha1 065b5325d44cb0e40f7b7803d707b8c1ea9ea5b2 ) -) - game ( name "Deja Vu I & II (Japan)" description "Deja Vu I & II (Japan)" @@ -35820,7 +37811,7 @@ game ( game ( name "Dexter's Laboratory - Robot Rampage (USA, Europe)" description "Dexter's Laboratory - Robot Rampage (USA, Europe)" - rom ( name "Dexter's Laboratory - Robot Rampage (USA, Europe).gbc" size 1048576 crc d24d6601 sha1 db107af55df07fb8c771c712b05d6aebb175e3c5 ) + rom ( name "Dexter's Laboratory - Robot Rampage (USA, Europe).gbc" size 1048576 crc d24d6601 sha1 db107af55df07fb8c771c712b05d6aebb175e3c5 flags verified ) ) game ( @@ -35835,6 +37826,12 @@ game ( rom ( name "Digimon 02 4 (Taiwan) (En) (Unl).gbc" size 1048576 crc a90061e9 sha1 0c8280e5349dda05fdd27bb1eb68a1be2f3d5c04 ) ) +game ( + name "Digimon 02 5 (USA) (Unl)" + description "Digimon 02 5 (USA) (Unl)" + rom ( name "Digimon 02 5 (USA) (Unl).gbc" size 1048576 crc 0bcbe728 sha1 f868fecce3bdec242937b93549f4861a0f481065 ) +) + game ( name "Digimon 2 (Taiwan) (En) (Unl)" description "Digimon 2 (Taiwan) (En) (Unl)" @@ -35853,6 +37850,12 @@ game ( rom ( name "Digimon Adventure 2001 (USA) (Unl).gbc" size 1048576 crc 01f1fcee sha1 cb4327829bc90c7bb448e7591e6ee3729a12a8cd ) ) +game ( + name "Digimon Amethyst (USA) (Unl)" + description "Digimon Amethyst (USA) (Unl)" + rom ( name "Digimon Amethyst (USA) (Unl).gbc" size 2097152 crc 726eed2a sha1 0b5f44cc2f583182a91ed8a815a3e7cec3bd1a58 ) +) + game ( name "Digimon Crystal II (USA) (Unl)" description "Digimon Crystal II (USA) (Unl)" @@ -35865,12 +37868,24 @@ game ( rom ( name "Digimon Pocket (Taiwan) (En) (Unl).gbc" size 524288 crc 6791b106 sha1 87750928d5f005e67e51e4d08a6d82351effc7b2 ) ) +game ( + name "Digimon Pocket (Taiwan) (Zh) (Unl)" + description "Digimon Pocket (Taiwan) (Zh) (Unl)" + rom ( name "Digimon Pocket (Taiwan) (Zh) (Unl).gbc" size 524288 crc 6d39574e sha1 9560dac8eb9d676aeb5f2d92fbb0228cb4ec27cc ) +) + game ( name "Digimon Saphire (USA) (Unl)" description "Digimon Saphire (USA) (Unl)" rom ( name "Digimon Saphire (USA) (Unl).gbc" size 1048576 crc be4c1d83 sha1 f5706a80bae20027d7643ab151607adbe13e6b1d ) ) +game ( + name "Digital Monster 2001 (Taiwan) (En) (Unl)" + description "Digital Monster 2001 (Taiwan) (En) (Unl)" + rom ( name "Digital Monster 2001 (Taiwan) (En) (Unl).gbc" size 524288 crc d9eb3f2a sha1 cc7d4a2e5bf1fbee8e0a0e0960f4038fca3e458f ) +) + game ( name "Dino Breeder 3 - Gaia Fukkatsu (Japan) (SGB Enhanced) (GB Compatible)" description "Dino Breeder 3 - Gaia Fukkatsu (Japan) (SGB Enhanced) (GB Compatible)" @@ -35931,12 +37946,6 @@ game ( rom ( name "Diva Starz - Mall Mania (USA).gbc" size 1048576 crc ebe0ecd6 sha1 1d0edb87404409f1e4c124503be4cc59165c01da ) ) -game ( - name "Doc Cosmos - The Saga Begins (World) (Aftermarket) (Unl)" - description "Doc Cosmos - The Saga Begins (World) (Aftermarket) (Unl)" - rom ( name "Doc Cosmos - The Saga Begins (World) (Aftermarket) (Unl).gbc" size 262144 crc 754dff51 sha1 a066d9973a2b90a08067dfcd22b04844557e89e2 ) -) - game ( name "Dogz (Europe)" description "Dogz (Europe)" @@ -36075,12 +38084,6 @@ game ( rom ( name "Doraemon no Study Boy - Kuku Game (Japan).gbc" size 1048576 crc a8a353d8 sha1 9b5c8b89b6e69d3803fbd43b2fe5130ad6d2f50b ) ) -game ( - name "Dork's Dilemma (World) (Aftermarket) (Unl)" - description "Dork's Dilemma (World) (Aftermarket) (Unl)" - rom ( name "Dork's Dilemma (World) (Aftermarket) (Unl).gbc" size 524288 crc 77b8b43b sha1 bd525f97cc316fed3f6271ed0929414df4c0389c ) -) - game ( name "Doug - La Grande Aventure (France)" description "Doug - La Grande Aventure (France)" @@ -36114,7 +38117,7 @@ game ( game ( name "Dracula - Crazy Vampire (Europe) (En,Fr,De,Es,It)" description "Dracula - Crazy Vampire (Europe) (En,Fr,De,Es,It)" - rom ( name "Dracula - Crazy Vampire (Europe) (En,Fr,De,Es,It).gbc" size 1048576 crc 2f7aef51 sha1 815f252f761e0fd3f29b7acf32b2360264aefab1 ) + rom ( name "Dracula - Crazy Vampire (Europe) (En,Fr,De,Es,It).gbc" size 1048576 crc 2f7aef51 sha1 815f252f761e0fd3f29b7acf32b2360264aefab1 flags verified ) ) game ( @@ -36126,13 +38129,7 @@ game ( game ( name "Dragon Ball - Final Bout (Taiwan) (Unl)" description "Dragon Ball - Final Bout (Taiwan) (Unl)" - rom ( name "Dragon Ball - Final Bout (Taiwan) (Unl).gbc" size 1048576 crc d9849157 sha1 51ebe1a27e8295340f996d2841c5cc6e2bc9f548 ) -) - -game ( - name "Dragon Ball Z - 2002 Fighting (Taiwan) (Zh) (Unl)" - description "Dragon Ball Z - 2002 Fighting (Taiwan) (Zh) (Unl)" - rom ( name "Dragon Ball Z - 2002 Fighting (Taiwan) (Zh) (Unl).gbc" size 2097152 crc 8fa35740 sha1 008a559635c9d351d9f68b3a1ac0c687521821cf ) + rom ( name "Dragon Ball - Final Bout (Taiwan) (Unl).gbc" size 1048576 crc 039079bd sha1 682b1be82eccb9044fc61af689c39d07fa325fec ) ) game ( @@ -36249,6 +38246,18 @@ game ( rom ( name "Dragon Ball Z 3 - 2002 Fighting (Taiwan) (En) (Unl).gbc" size 2097152 crc dbe0f44e sha1 baea9e5ee1411988039d563ece97d8d7f765396a ) ) +game ( + name "Dragon Ball Z Gedou 2005 (Taiwan) (Unl)" + description "Dragon Ball Z Gedou 2005 (Taiwan) (Unl)" + rom ( name "Dragon Ball Z Gedou 2005 (Taiwan) (Unl).gbc" size 2097152 crc d1c48145 sha1 8637ed614dc94e846c32adbc723e09a06b3da3ce ) +) + +game ( + name "Dragon Dance (USA) (SGB Enhanced) (GB Compatible)" + description "Dragon Dance (USA) (SGB Enhanced) (GB Compatible)" + rom ( name "Dragon Dance (USA) (SGB Enhanced) (GB Compatible).gbc" size 262144 crc 0602dbe1 sha1 a28bfabc4db62ad5aa6bfe29114b0878429586cc ) +) + game ( name "Dragon Dance (Europe) (Proto) (SGB Enhanced) (GB Compatible)" description "Dragon Dance (Europe) (Proto) (SGB Enhanced) (GB Compatible)" @@ -36267,12 +38276,6 @@ game ( rom ( name "Dragon Dance (USA) (Beta 2) (SGB Enhanced) (GB Compatible).gbc" size 262144 crc 9a90adbe sha1 5fc97752a98a18b7e2db238d1ab88c6b09e34602 ) ) -game ( - name "Dragon Dance (USA) (SGB Enhanced) (GB Compatible)" - description "Dragon Dance (USA) (SGB Enhanced) (GB Compatible)" - rom ( name "Dragon Dance (USA) (SGB Enhanced) (GB Compatible).gbc" size 262144 crc 0602dbe1 sha1 a28bfabc4db62ad5aa6bfe29114b0878429586cc ) -) - game ( name "Dragon Quest I & II (Japan) (SGB Enhanced) (GB Compatible)" description "Dragon Quest I & II (Japan) (SGB Enhanced) (GB Compatible)" @@ -36441,18 +38444,18 @@ game ( rom ( name "Dukes of Hazzard, The - Racing for Home (USA).gbc" size 2097152 crc fb08dceb sha1 6a39dfbce8b86db84615cdb5fb24012cbbac7b36 ) ) -game ( - name "Dungeon Savior (Japan) (SGB Enhanced) (GB Compatible)" - description "Dungeon Savior (Japan) (SGB Enhanced) (GB Compatible)" - rom ( name "Dungeon Savior (Japan) (SGB Enhanced) (GB Compatible).gbc" size 4194304 crc 2bcb5f78 sha1 766ab65d9420f361d8d9a4754ea8c6b692e34c36 ) -) - game ( name "Dungeon Savior (Japan) (Rev 1) (Proto) (SGB Enhanced) (GB Compatible)" description "Dungeon Savior (Japan) (Rev 1) (Proto) (SGB Enhanced) (GB Compatible)" rom ( name "Dungeon Savior (Japan) (Rev 1) (Proto) (SGB Enhanced) (GB Compatible).gbc" size 4194304 crc 0180364b sha1 c5e93f04cc41404320aaf70eb10b55465edb1083 ) ) +game ( + name "Dungeon Savior (Japan) (SGB Enhanced) (GB Compatible)" + description "Dungeon Savior (Japan) (SGB Enhanced) (GB Compatible)" + rom ( name "Dungeon Savior (Japan) (SGB Enhanced) (GB Compatible).gbc" size 4194304 crc 2bcb5f78 sha1 766ab65d9420f361d8d9a4754ea8c6b692e34c36 ) +) + game ( name "DX Jinsei Game (Japan)" description "DX Jinsei Game (Japan)" @@ -36507,6 +38510,12 @@ game ( rom ( name "E.T. - The Extra-Terrestrial and the Cosmic Garden (USA).gbc" size 1048576 crc 32c87958 sha1 da71b581f7415b6535ac4af2e8fccd2040c54215 ) ) +game ( + name "e'Fighter HOT (Taiwan) (En) (Unl)" + description "e'Fighter HOT (Taiwan) (En) (Unl)" + rom ( name "e'Fighter HOT (Taiwan) (En) (Unl).gbc" size 1048576 crc 8fa2539d sha1 93a3716f8f41b89bee795af6e8f6fdddfcd8acf1 ) +) + game ( name "Earthworm Jim - Menace 2 the Galaxy (USA, Europe) (GB Compatible)" description "Earthworm Jim - Menace 2 the Galaxy (USA, Europe) (GB Compatible)" @@ -36519,6 +38528,12 @@ game ( rom ( name "ECW Hardcore Revolution (USA, Europe).gbc" size 1048576 crc 484eba10 sha1 c337d0480e84f5e2b7e28b13c3667b8cf92d9649 ) ) +game ( + name "Elang 2003 - Mark of the Wolfs (Taiwan) (En) (Unl)" + description "Elang 2003 - Mark of the Wolfs (Taiwan) (En) (Unl)" + rom ( name "Elang 2003 - Mark of the Wolfs (Taiwan) (En) (Unl).gbc" size 1048576 crc 50a1e9a9 sha1 4a3ac88b7be532d5fd5c4d9e500532e96441a966 ) +) + game ( name "Elang Chuanshuo - Shiji Zhi Zhan (Taiwan) (Unl)" description "Elang Chuanshuo - Shiji Zhi Zhan (Taiwan) (Unl)" @@ -36556,9 +38571,15 @@ game ( ) game ( - name "Emo Cheng DX (Taiwan) (Beta) (Unl)" - description "Emo Cheng DX (Taiwan) (Beta) (Unl)" - rom ( name "Emo Cheng DX (Taiwan) (Beta) (Unl).gbc" size 1048576 crc ebf7bf6e sha1 29b1b595ca8f5ad76ebf4f997d0e4fb8069829f1 ) + name "Emo Cheng DX (Taiwan) (Demo) (Unl)" + description "Emo Cheng DX (Taiwan) (Demo) (Unl)" + rom ( name "Emo Cheng DX (Taiwan) (Demo) (Unl).gbc" size 1048576 crc ebf7bf6e sha1 29b1b595ca8f5ad76ebf4f997d0e4fb8069829f1 ) +) + +game ( + name "Emo Cheng DX (Taiwan) (Unl)" + description "Emo Cheng DX (Taiwan) (Unl)" + rom ( name "Emo Cheng DX (Taiwan) (Unl).gbc" size 4194304 crc 5c388c6d sha1 7919fe7b54a5bc53ebacc13dd338be9e841dadf7 ) ) game ( @@ -36630,19 +38651,7 @@ game ( game ( name "Evel Knievel (USA) (GB Compatible)" description "Evel Knievel (USA) (GB Compatible)" - rom ( name "Evel Knievel (USA) (GB Compatible).gbc" size 2097152 crc 51e951b5 sha1 24cac6ab0151b33d2b1fd06ee01931802fb98267 ) -) - -game ( - name "Expiration Date (World) (GB Compatible) (Aftermarket) (Unl)" - description "Expiration Date (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Expiration Date (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 050caa5e sha1 e4b61c220b046e2287272f9b1bef85ad2d835fe3 ) -) - -game ( - name "Exploits of Fingers Malone, The (World) (Aftermarket) (Unl)" - description "Exploits of Fingers Malone, The (World) (Aftermarket) (Unl)" - rom ( name "Exploits of Fingers Malone, The (World) (Aftermarket) (Unl).gbc" size 524288 crc 20fe84af sha1 18056b5b032955099c606651f26164de131e54a6 ) + rom ( name "Evel Knievel (USA) (GB Compatible).gbc" size 2097152 crc 51e951b5 sha1 24cac6ab0151b33d2b1fd06ee01931802fb98267 flags verified ) ) game ( @@ -36759,6 +38768,18 @@ game ( rom ( name "Fairy Kitty no Kaiun Jiten - Yousei no Kuni no Uranai Shugyou (Japan) (Rev 1) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc c4d3628f sha1 d07b600cc9af8cadc2581a6ac19aadea79313d69 flags verified ) ) +game ( + name "Fellowship of the Rings (Taiwan) (En) (Unl)" + description "Fellowship of the Rings (Taiwan) (En) (Unl)" + rom ( name "Fellowship of the Rings (Taiwan) (En) (Unl).gbc" size 524288 crc 4bcc59dc sha1 837232bd2eeb50b276049d0908f8ed4dc7efbcfe ) +) + +game ( + name "Fellowship of the Rings (China) (En) (Unl)" + description "Fellowship of the Rings (China) (En) (Unl)" + rom ( name "Fellowship of the Rings (China) (En) (Unl).gbc" size 524288 crc 759f07bd sha1 83fec0fb02fdeda160a0de610acdf7446e373022 ) +) + game ( name "Feng Kuang A Gei III - Chaoji Zhadan Ren (Taiwan) (Unl)" description "Feng Kuang A Gei III - Chaoji Zhadan Ren (Taiwan) (Unl)" @@ -36801,42 +38822,6 @@ game ( rom ( name "FIFA 2000 (USA, Europe) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc e6bc2e8c sha1 c40dd26a6d600818eca960bade3afa374a19bc12 ) ) -game ( - name "Fillo - Crystal Version (World) (Aftermarket) (Unl)" - description "Fillo - Crystal Version (World) (Aftermarket) (Unl)" - rom ( name "Fillo - Crystal Version (World) (Aftermarket) (Unl).gbc" size 524288 crc 88bb855c sha1 2ffc4199d94f8b29b3f84b7bdb2694154a0bd285 ) -) - -game ( - name "Find Out (World) (GB Compatible) (Aftermarket) (Unl)" - description "Find Out (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Find Out (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 5f8b660e sha1 3605a96f6713157a88e4d88989d2e2f11b9db42f ) -) - -game ( - name "Finders Keepers (World) (Aftermarket) (Unl)" - description "Finders Keepers (World) (Aftermarket) (Unl)" - rom ( name "Finders Keepers (World) (Aftermarket) (Unl).gbc" size 524288 crc 4cfa0cfd sha1 db002f4a2500a9dc98a9ac7c263293d6e4a72cf1 ) -) - -game ( - name "Fire Ant (World) (Aftermarket) (Unl)" - description "Fire Ant (World) (Aftermarket) (Unl)" - rom ( name "Fire Ant (World) (Aftermarket) (Unl).gbc" size 262144 crc 154cc020 sha1 b58ed66838db34fc7f8475ccb670267119d623a5 ) -) - -game ( - name "Fireman Fred (World) (Aftermarket) (Unl)" - description "Fireman Fred (World) (Aftermarket) (Unl)" - rom ( name "Fireman Fred (World) (Aftermarket) (Unl).gbc" size 524288 crc 563d9ca7 sha1 e62a9c6b6a39f0cb662fdb07b72669355b706f57 ) -) - -game ( - name "Firemen (World) (Aftermarket) (Unl)" - description "Firemen (World) (Aftermarket) (Unl)" - rom ( name "Firemen (World) (Aftermarket) (Unl).gbc" size 262144 crc 7299401f sha1 84c68614334578f866cfa929df736377f04f5d04 ) -) - game ( name "Fish Files, The (Europe) (En,Fr,De,Es,It)" description "Fish Files, The (Europe) (En,Fr,De,Es,It)" @@ -36849,12 +38834,6 @@ game ( rom ( name "Fix & Foxi - Episode 1 - Lupo (Europe) (En,Fr,De).gbc" size 1048576 crc 5dfc61e8 sha1 6d14bf255eb042e7185da32137f679f4e2c24ce5 ) ) -game ( - name "Fix It Felix Jr. (World) (GB Compatible) (Aftermarket) (Unl)" - description "Fix It Felix Jr. (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Fix It Felix Jr. (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc c8014615 sha1 7221f5e53f6027183301d06e258c6cb417007b8c ) -) - game ( name "Flintstones, The - Burgertime in Bedrock (Europe) (En,Fr,De,Es,It)" description "Flintstones, The - Burgertime in Bedrock (Europe) (En,Fr,De,Es,It)" @@ -37017,12 +38996,6 @@ game ( rom ( name "Fushigi no Dungeon - Fuurai no Shiren GB 2 - Sabaku no Majou (Japan) (BFWJ).gbc" size 4194304 crc f3c20fbe sha1 d9c490af97c08ac7053bbb9f7ae06d3501035127 flags verified ) ) -game ( - name "G-Man (World) (Aftermarket) (Unl)" - description "G-Man (World) (Aftermarket) (Unl)" - rom ( name "G-Man (World) (Aftermarket) (Unl).gbc" size 524288 crc ff3beab1 sha1 cb9486ca9a6ad3903662963aa966145257ef92a6 ) -) - game ( name "Gaiamaster Duel - Card Attackers (Japan)" description "Gaiamaster Duel - Card Attackers (Japan)" @@ -37125,18 +39098,6 @@ game ( rom ( name "Game Conveni 21 (Japan) (GB Compatible).gbc" size 1048576 crc 994314b3 sha1 6803617abc46db83dbec08d10e03b9f9297f260e ) ) -game ( - name "Gamer Boy Mission (World) (GB Compatible) (Aftermarket) (Unl)" - description "Gamer Boy Mission (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Gamer Boy Mission (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 96721e5d sha1 90fad94433a5b0dbcf73f4a2d4ebb75d7ab065c4 ) -) - -game ( - name "Gamer Boy Mission (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" - description "Gamer Boy Mission (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Gamer Boy Mission (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc a02d2ae2 sha1 7eb6865c5c265193763ec0bf751d26964e870120 ) -) - game ( name "Games Frenzy (Europe) (En,Fr,De)" description "Games Frenzy (Europe) (En,Fr,De)" @@ -37204,21 +39165,45 @@ game ( ) game ( - name "GB Memory Multi Menu (Japan) (SGB Enhanced, GB Compatible) (NP)" - description "GB Memory Multi Menu (Japan) (SGB Enhanced, GB Compatible) (NP)" - rom ( name "GB Memory Multi Menu (Japan) (SGB Enhanced, GB Compatible) (NP).gbc" size 131072 crc ec823cc1 sha1 0781eaecb7fd25c068e396b5eb02c6231baf6ea3 ) + name "GB-Memory Multi Menu (Japan) (SGB Enhanced, GB Compatible) (NP)" + description "GB-Memory Multi Menu (Japan) (SGB Enhanced, GB Compatible) (NP)" + rom ( name "GB-Memory Multi Menu (Japan) (SGB Enhanced, GB Compatible) (NP).gbc" size 131072 crc ec823cc1 sha1 0781eaecb7fd25c068e396b5eb02c6231baf6ea3 ) ) game ( - name "Gedou Jian Shen - Soul Falchion (Taiwan) (Unl) (Alt)" - description "Gedou Jian Shen - Soul Falchion (Taiwan) (Unl) (Alt)" - rom ( name "Gedou Jian Shen - Soul Falchion (Taiwan) (Unl) (Alt).gbc" size 1048576 crc c0ac1b50 sha1 4dcef6fcfe009e17da0bb13e50e7410a3f586e23 ) + name "Gedou Jian Shen - Soul Falchion (Taiwan) (En) (Unl) (Alt 2)" + description "Gedou Jian Shen - Soul Falchion (Taiwan) (En) (Unl) (Alt 2)" + rom ( name "Gedou Jian Shen - Soul Falchion (Taiwan) (En) (Unl) (Alt 2).gbc" size 1048576 crc 7afae089 sha1 b33c9f5012cc1a1a8c7ac9d95a183fd28d9bf9f3 ) ) game ( - name "Gedou Jian Shen - Soul Falchion (Taiwan) (Unl)" - description "Gedou Jian Shen - Soul Falchion (Taiwan) (Unl)" - rom ( name "Gedou Jian Shen - Soul Falchion (Taiwan) (Unl).gbc" size 1048576 crc 1b1c6f68 sha1 fd06c62b42878e8094e610b180c1848c785f67e9 ) + name "Gedou Jian Shen - Soul Falchion (Taiwan) (En) (Unl) (Alt)" + description "Gedou Jian Shen - Soul Falchion (Taiwan) (En) (Unl) (Alt)" + rom ( name "Gedou Jian Shen - Soul Falchion (Taiwan) (En) (Unl) (Alt).gbc" size 1048576 crc c0ac1b50 sha1 4dcef6fcfe009e17da0bb13e50e7410a3f586e23 ) +) + +game ( + name "Gedou Jian Shen - Soul Falchion (Taiwan) (En) (Unl)" + description "Gedou Jian Shen - Soul Falchion (Taiwan) (En) (Unl)" + rom ( name "Gedou Jian Shen - Soul Falchion (Taiwan) (En) (Unl).gbc" size 1048576 crc 1b1c6f68 sha1 fd06c62b42878e8094e610b180c1848c785f67e9 ) +) + +game ( + name "Gedou Jian Shen KF (Taiwan) (En) (Unl)" + description "Gedou Jian Shen KF (Taiwan) (En) (Unl)" + rom ( name "Gedou Jian Shen KF (Taiwan) (En) (Unl).gbc" size 1048576 crc 190702b3 sha1 be03f86ef0c6df8c6741fe1298496670fcc682cf ) +) + +game ( + name "Gedou Qi Long Qiu 2002 (Taiwan) (Zh) (Unl)" + description "Gedou Qi Long Qiu 2002 (Taiwan) (Zh) (Unl)" + rom ( name "Gedou Qi Long Qiu 2002 (Taiwan) (Zh) (Unl).gbc" size 2097152 crc 8fa35740 sha1 008a559635c9d351d9f68b3a1ac0c687521821cf ) +) + +game ( + name "Gedou Zhizun 2003 (Taiwan) (Unl)" + description "Gedou Zhizun 2003 (Taiwan) (Unl)" + rom ( name "Gedou Zhizun 2003 (Taiwan) (Unl).gbc" size 1048576 crc f7630d88 sha1 f43c4055f69a1ff6b325494b5b34c8043914cd9d ) ) game ( @@ -37275,12 +39260,6 @@ game ( rom ( name "Gex 3 - Deep Pocket Gecko (USA).gbc" size 2097152 crc 85a98c7d sha1 0da71536a3e92dd537c7067ec1014a262dbc3837 ) ) -game ( - name "Ghost Town (World) (Aftermarket) (Unl)" - description "Ghost Town (World) (Aftermarket) (Unl)" - rom ( name "Ghost Town (World) (Aftermarket) (Unl).gbc" size 262144 crc 52efcc35 sha1 1a4a7846d6c87f0bd8b267aa6a8aa98e797fedf8 ) -) - game ( name "Ghosts'n Goblins (USA, Europe) (GB Compatible)" description "Ghosts'n Goblins (USA, Europe) (GB Compatible)" @@ -37533,12 +39512,6 @@ game ( rom ( name "Guiwu Zhe 2 (Taiwan) (Unl).gbc" size 2097152 crc 955bc6ad sha1 5fe41ac064f4b4d4476ef4177a2f4d69fae1a933 ) ) -game ( - name "Gun Law (World) (Aftermarket) (Unl)" - description "Gun Law (World) (Aftermarket) (Unl)" - rom ( name "Gun Law (World) (Aftermarket) (Unl).gbc" size 262144 crc 3a0b6823 sha1 c49f7e0a5055f836528a7bc0cb6f45f221c76475 ) -) - game ( name "Guruguru Garakutas (Japan) (SGB Enhanced) (GB Compatible)" description "Guruguru Garakutas (Japan) (SGB Enhanced) (GB Compatible)" @@ -37659,6 +39632,18 @@ game ( rom ( name "Hamtaro - Ham-Hams Unite! (USA).gbc" size 2097152 crc 1271117f sha1 9770bf59e932b41882839ce9eec033f576094fee flags verified ) ) +game ( + name "Hamtaro - Ham-Hams Unite! (USA) (2002-08-07) (Beta)" + description "Hamtaro - Ham-Hams Unite! (USA) (2002-08-07) (Beta)" + rom ( name "Hamtaro - Ham-Hams Unite! (USA) (2002-08-07) (Beta).gbc" size 2097152 crc d0cf0d86 sha1 c85ba2da0a652544f938439c8826c5c6754f5e75 ) +) + +game ( + name "Hamtaro - Ham-Hams Unite! (Europe) (En,Fr,De,Es,It) (2002-11-11) (Beta)" + description "Hamtaro - Ham-Hams Unite! (Europe) (En,Fr,De,Es,It) (2002-11-11) (Beta)" + rom ( name "Hamtaro - Ham-Hams Unite! (Europe) (En,Fr,De,Es,It) (2002-11-11) (Beta).gbc" size 4194304 crc 816b0325 sha1 17c3ff0da5b9733a768ee53eccd13059fda16116 ) +) + game ( name "Hamunaptra - Ushinawareta Sabaku no Miyako (Japan)" description "Hamunaptra - Ushinawareta Sabaku no Miyako (Japan)" @@ -37689,12 +39674,6 @@ game ( rom ( name "Hang Time Basketball (Europe) (Unl).gbc" size 262144 crc 3207b7d9 sha1 340201c045c020be6de3504fdecbce1ff07a2139 ) ) -game ( - name "Harbour Attack (World) (Aftermarket) (Unl)" - description "Harbour Attack (World) (Aftermarket) (Unl)" - rom ( name "Harbour Attack (World) (Aftermarket) (Unl).gbc" size 262144 crc 7455782e sha1 1d0b3779007ba8f34e11b189552955dbf5c75a28 ) -) - game ( name "Harley-Davidson Motor Cycles - Race Across America (USA)" description "Harley-Davidson Motor Cycles - Race Across America (USA)" @@ -37887,18 +39866,6 @@ game ( rom ( name "Hexcite - The Shapes of Victory (USA, Europe) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 84084e5f sha1 bb00ff88af717b45e08ef421ac77e0546870b1f4 flags verified ) ) -game ( - name "High Noon (World) (Aftermarket) (Unl)" - description "High Noon (World) (Aftermarket) (Unl)" - rom ( name "High Noon (World) (Aftermarket) (Unl).gbc" size 262144 crc 1d00e48d sha1 21d5e871ed009a674659344d3d768fb2389c0d04 ) -) - -game ( - name "Hime's Quest (World) (Aftermarket) (Unl)" - description "Hime's Quest (World) (Aftermarket) (Unl)" - rom ( name "Hime's Quest (World) (Aftermarket) (Unl).gbc" size 2097152 crc de5c21c2 sha1 7b6672c46c23aaa282bd4fded0713c6dfae2eb66 ) -) - game ( name "Hiryuu no Ken - Retsuden GB (Japan)" description "Hiryuu no Ken - Retsuden GB (Japan)" @@ -37977,12 +39944,6 @@ game ( rom ( name "Hoyle Casino (USA).gbc" size 1048576 crc 413473b0 sha1 827efa6d7b56e919b95ae52c451be2a40d870822 ) ) -game ( - name "Hugo (World) (Aftermarket) (Unl)" - description "Hugo (World) (Aftermarket) (Unl)" - rom ( name "Hugo (World) (Aftermarket) (Unl).gbc" size 524288 crc 6581c78a sha1 390d2665f34ceaa5e34cc9f8f7c26d9e7583a92b ) -) - game ( name "Hugo - Black Diamond Fever (Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi)" description "Hugo - Black Diamond Fever (Europe) (En,Fr,De,Es,It,Nl,Pt,Sv,No,Da,Fi)" @@ -38037,6 +39998,12 @@ game ( rom ( name "Hyper Olympic Series - Track & Field GB (Japan) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 77f76ebc sha1 6dabafe260b53e61a810cbae2f14287adafffd8e ) ) +game ( + name "Ice Age II (Taiwan) (En) (Unl)" + description "Ice Age II (Taiwan) (En) (Unl)" + rom ( name "Ice Age II (Taiwan) (En) (Unl).gbc" size 2097152 crc 50bc8e9d sha1 c57912e67c135c48233f351f68cdc34020de8d01 ) +) + game ( name "Ide Yousuke no Mahjong Kyoushitsu GB (Japan)" description "Ide Yousuke no Mahjong Kyoushitsu GB (Japan)" @@ -38055,6 +40022,12 @@ game ( rom ( name "Infinity (USA) (Proto) (2001-03-22).gbc" size 2097152 crc 4ade94aa sha1 fdfd6d4cbebbf64fc7d1264f0450be270be89823 ) ) +game ( + name "Inspector Gadget - Operation Madkactus (Europe) (Fr) (Beta)" + description "Inspector Gadget - Operation Madkactus (Europe) (Fr) (Beta)" + rom ( name "Inspector Gadget - Operation Madkactus (Europe) (Fr) (Beta).gbc" size 1048576 crc 93ec798b sha1 8444ff17aa3f865eec33cc49398b450e345376c3 ) +) + game ( name "Inspector Gadget - Operation Madkactus (Europe) (En,Fr,De,Es,It,Nl)" description "Inspector Gadget - Operation Madkactus (Europe) (En,Fr,De,Es,It,Nl)" @@ -38458,9 +40431,9 @@ game ( ) game ( - name "Katakis 3D (USA, Europe) (Proto)" - description "Katakis 3D (USA, Europe) (Proto)" - rom ( name "Katakis 3D (USA, Europe) (Proto).gbc" size 2097152 crc 7c4b3795 sha1 8cd4be6772c592bbc2908fa826c090ec122e384c ) + name "Katakis 3D (Europe) (Proto)" + description "Katakis 3D (Europe) (Proto)" + rom ( name "Katakis 3D (Europe) (Proto).gbc" size 2097152 crc 7c4b3795 sha1 8cd4be6772c592bbc2908fa826c090ec122e384c ) ) game ( @@ -38553,18 +40526,18 @@ game ( rom ( name "Kikansha Thomas - Sodor-tou no Nakama-tachi (Japan).gbc" size 1048576 crc 223bb19c sha1 8abd4406ec19bfecd6d675285fa73ef2d5ea622e ) ) -game ( - name "Kikstart (World) (Aftermarket) (Unl)" - description "Kikstart (World) (Aftermarket) (Unl)" - rom ( name "Kikstart (World) (Aftermarket) (Unl).gbc" size 524288 crc 9a9f483b sha1 bc472506f73f0c1a3f0a610c0136b324b7635c7f ) -) - game ( name "Kindaichi Shounen no Jikenbo - 10 Nenme no Shoutaijou (Japan) (SGB Enhanced) (GB Compatible)" description "Kindaichi Shounen no Jikenbo - 10 Nenme no Shoutaijou (Japan) (SGB Enhanced) (GB Compatible)" rom ( name "Kindaichi Shounen no Jikenbo - 10 Nenme no Shoutaijou (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc de52ffdc sha1 468ea148eb15eac3b771a2520e0b5248ea5085a1 ) ) +game ( + name "King of Fighters R2 (Taiwan) (Unl)" + description "King of Fighters R2 (Taiwan) (Unl)" + rom ( name "King of Fighters R2 (Taiwan) (Unl).gbc" size 1048576 crc 9913e18b sha1 43c2b6f0c3559ed90032cba6569811047f9e20d0 ) +) + game ( name "Kinniku Banzuke GB - Chousensha wa Kimida! (Japan) (SGB Enhanced) (GB Compatible)" description "Kinniku Banzuke GB - Chousensha wa Kimida! (Japan) (SGB Enhanced) (GB Compatible)" @@ -38649,12 +40622,6 @@ game ( rom ( name "Klustar (Japan) (Proto 1) (1998-10-01) (GB Compatible).gbc" size 131072 crc f9c6e0a5 sha1 4990b427f1b85ceca9646b3edfa921ed160a55a9 ) ) -game ( - name "Knit-Wit (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" - description "Knit-Wit (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Knit-Wit (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc f19d5e86 sha1 0f0e01a143182a9784c80a882ac206d02d8679d7 ) -) - game ( name "Knockout Kings (USA, Europe)" description "Knockout Kings (USA, Europe)" @@ -38739,6 +40706,12 @@ game ( rom ( name "Koto Battle - Tengai no Moribito (Japan).gbc" size 2097152 crc 430eb1e1 sha1 ac30025352026b34a0d9ccede82862f6e04aaf00 ) ) +game ( + name "Koudai Guaishou - Da Jihe (Taiwan) (Ja) (Pirate)" + description "Koudai Guaishou - Da Jihe (Taiwan) (Ja) (Pirate)" + rom ( name "Koudai Guaishou - Da Jihe (Taiwan) (Ja) (Pirate).gbc" size 2097152 crc a96e26c4 sha1 69d345f0da430d0b1c5f4edd086f244ddcf49c78 ) +) + game ( name "Koudai Guaishou - Dongzuo Pian (Taiwan) (En) (Unl)" description "Koudai Guaishou - Dongzuo Pian (Taiwan) (En) (Unl)" @@ -38751,12 +40724,30 @@ game ( rom ( name "Koudai Guaishou - Dongzuo Pian (Taiwan) (En) (Unl) (Alt).gbc" size 1048576 crc ec2fbdfd sha1 c7a1020797b57d292e16c5297199d977e025256b ) ) +game ( + name "Koudai Guaishou - Feicui Ban (Taiwan) (Unl)" + description "Koudai Guaishou - Feicui Ban (Taiwan) (Unl)" + rom ( name "Koudai Guaishou - Feicui Ban (Taiwan) (Unl).gbc" size 2097152 crc 8494465f sha1 a3b2818c778fe6b5811841a9f28a1a06334216ea ) +) + +game ( + name "Koudai Guaishou - Sheng Bianshi (China) (Unl)" + description "Koudai Guaishou - Sheng Bianshi (China) (Unl)" + rom ( name "Koudai Guaishou - Sheng Bianshi (China) (Unl).gbc" size 2097152 crc 0791c3a7 sha1 8a61c2dc4d1acf96d8ae871b0f371c7f8a17e9f1 ) +) + game ( name "Koudai Yaoguai - Baijin Ban (Taiwan) (Unl)" description "Koudai Yaoguai - Baijin Ban (Taiwan) (Unl)" rom ( name "Koudai Yaoguai - Baijin Ban (Taiwan) (Unl).gbc" size 2097152 crc 998ad382 sha1 f9013985d7c40eccfa863e2ba808e64deaa4b384 ) ) +game ( + name "Koudai Yaoguai Lu Baoshi (Taiwan) (Unl)" + description "Koudai Yaoguai Lu Baoshi (Taiwan) (Unl)" + rom ( name "Koudai Yaoguai Lu Baoshi (Taiwan) (Unl).gbc" size 2097152 crc ee74e4a2 sha1 59e4550bd3958464188fd9b8c11b2dc1c9ad7d06 ) +) + game ( name "Koushien Pocket (Japan) (SGB Enhanced) (GB Compatible)" description "Koushien Pocket (Japan) (SGB Enhanced) (GB Compatible)" @@ -38793,12 +40784,6 @@ game ( rom ( name "Las Vegas Cool Hand (USA) (GB Compatible).gbc" size 524288 crc bef1cde4 sha1 c7423c03e5976f85de361fe1b83dfee11e75a60f flags verified ) ) -game ( - name "Laser Squad (World) (Aftermarket) (Unl)" - description "Laser Squad (World) (Aftermarket) (Unl)" - rom ( name "Laser Squad (World) (Aftermarket) (Unl).gbc" size 1048576 crc 32f24248 sha1 26f4efe636214e72ec724f8887ca79fbc8abad80 ) -) - game ( name "Laura (Europe) (En,Fr,De,Es,It,Nl,Sv,Da) (Beta)" description "Laura (Europe) (En,Fr,De,Es,It,Nl,Sv,Da) (Beta)" @@ -38862,7 +40847,7 @@ game ( game ( name "Legend of Zelda, The - Link's Awakening DX (France) (SGB Enhanced) (GB Compatible)" description "Legend of Zelda, The - Link's Awakening DX (France) (SGB Enhanced) (GB Compatible)" - rom ( name "Legend of Zelda, The - Link's Awakening DX (France) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc f48824fe sha1 9a679e30b03e119a21ae7daac65e73e0ef4e0894 ) + rom ( name "Legend of Zelda, The - Link's Awakening DX (France) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc f48824fe sha1 9a679e30b03e119a21ae7daac65e73e0ef4e0894 flags verified ) ) game ( @@ -38901,6 +40886,24 @@ game ( rom ( name "Legend of Zelda, The - Link's Awakening DX (USA, Europe) (Rev 2) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 06887a34 sha1 1c091225688d966928cc74336dbef2e07d12a47c flags verified ) ) +game ( + name "Legend of Zelda, The - Link's Awakening DX (France) (Beta) (1998-12-11) (SGB Enhanced) (GB Compatible)" + description "Legend of Zelda, The - Link's Awakening DX (France) (Beta) (1998-12-11) (SGB Enhanced) (GB Compatible)" + rom ( name "Legend of Zelda, The - Link's Awakening DX (France) (Beta) (1998-12-11) (SGB Enhanced) (GB Compatible).gbc" size 1015808 crc c17259db sha1 a5a6f0251e8eafd0a02b1eeceaa5b51705c12f0d ) +) + +game ( + name "Legend of Zelda, The - Link's Awakening DX (France) (Rev 1) (Beta) (1999-09-22) (SGB Enhanced) (GB Compatible)" + description "Legend of Zelda, The - Link's Awakening DX (France) (Rev 1) (Beta) (1999-09-22) (SGB Enhanced) (GB Compatible)" + rom ( name "Legend of Zelda, The - Link's Awakening DX (France) (Rev 1) (Beta) (1999-09-22) (SGB Enhanced) (GB Compatible).gbc" size 1015808 crc 8afd751e sha1 797925a26eb39656aea60e10c8e9dd986b515b53 ) +) + +game ( + name "Legend of Zelda, The - Link's Awakening DX (USA, Europe) (Rev 2) (Beta) (1999-09-23) (SGB Enhanced) (GB Compatible)" + description "Legend of Zelda, The - Link's Awakening DX (USA, Europe) (Rev 2) (Beta) (1999-09-23) (SGB Enhanced) (GB Compatible)" + rom ( name "Legend of Zelda, The - Link's Awakening DX (USA, Europe) (Rev 2) (Beta) (1999-09-23) (SGB Enhanced) (GB Compatible).gbc" size 1015808 crc 0559bc89 sha1 dbe7a909c71d407f01af2cdb0aaf7d164ac7a9bd ) +) + game ( name "Legend of Zelda, The - Link's Awakening DX (Germany) (Beta) (1998-12-11) (SGB Enhanced) (GB Compatible)" description "Legend of Zelda, The - Link's Awakening DX (Germany) (Beta) (1998-12-11) (SGB Enhanced) (GB Compatible)" @@ -39051,12 +41054,6 @@ game ( rom ( name "Lemmings VS (Japan).gbc" size 4194304 crc 947d45ae sha1 2ebb428a53acbcbc215f37bb263e44d94f547473 ) ) -game ( - name "Liberator (World) (Aftermarket) (Unl)" - description "Liberator (World) (Aftermarket) (Unl)" - rom ( name "Liberator (World) (Aftermarket) (Unl).gbc" size 262144 crc ebe70d3d sha1 e3afce5a2357732ed15d7f3c0900f7b48113efdc ) -) - game ( name "Lil' Monster (USA) (SGB Enhanced) (GB Compatible)" description "Lil' Monster (USA) (SGB Enhanced) (GB Compatible)" @@ -39105,12 +41102,6 @@ game ( rom ( name "LNF Stars 2001 (France).gbc" size 1048576 crc f8bf3ee7 sha1 07a0e1c0ddde6371dbaf25fd016bdc77c0eca090 ) ) -game ( - name "Loco-coco (World) (Aftermarket) (Unl)" - description "Loco-coco (World) (Aftermarket) (Unl)" - rom ( name "Loco-coco (World) (Aftermarket) (Unl).gbc" size 262144 crc f6b9fe4e sha1 8a8972ff3e208280a746a2015a20f67248180a1c ) -) - game ( name "Lode Runner - Domudomu Dan no Yabou (Japan) (GB Compatible)" description "Lode Runner - Domudomu Dan no Yabou (Japan) (GB Compatible)" @@ -39250,9 +41241,9 @@ game ( ) game ( - name "Loppi Puzzle Magazine - Kangaeru Puzzle Dai-2-gou (Japan) (Rev 1) (SGB Enhanced, GB Compatible) (NP) [b]" - description "Loppi Puzzle Magazine - Kangaeru Puzzle Dai-2-gou (Japan) (Rev 1) (SGB Enhanced, GB Compatible) (NP) [b]" - rom ( name "Loppi Puzzle Magazine - Kangaeru Puzzle Dai-2-gou (Japan) (Rev 1) (SGB Enhanced, GB Compatible) (NP) [b].gbc" size 262144 crc a30ad68d sha1 bbb3c1b9d0dcfabc177f443ea11efa6b6e3112e1 flags baddump ) + name "Loppi Puzzle Magazine - Kangaeru Puzzle Dai-2-gou (Japan) (Rev 1) (SGB Enhanced, GB Compatible) (NP)" + description "Loppi Puzzle Magazine - Kangaeru Puzzle Dai-2-gou (Japan) (Rev 1) (SGB Enhanced, GB Compatible) (NP)" + rom ( name "Loppi Puzzle Magazine - Kangaeru Puzzle Dai-2-gou (Japan) (Rev 1) (SGB Enhanced, GB Compatible) (NP).gbc" size 262144 crc 27ab2187 sha1 49a63339bc253d1bd55f6db75f7324980572925a ) ) game ( @@ -39312,7 +41303,7 @@ game ( game ( name "Lucky Luke (Europe) (En,Fr,De,Es)" description "Lucky Luke (Europe) (En,Fr,De,Es)" - rom ( name "Lucky Luke (Europe) (En,Fr,De,Es).gbc" size 1048576 crc 412fb57c sha1 36b59251751a55285dbedc3bd4b33b2c73b811c9 ) + rom ( name "Lucky Luke (Europe) (En,Fr,De,Es).gbc" size 1048576 crc 412fb57c sha1 36b59251751a55285dbedc3bd4b33b2c73b811c9 flags verified ) ) game ( @@ -39352,15 +41343,15 @@ game ( ) game ( - name "Luke Yingxiong Z (Taiwan) (Unl)" - description "Luke Yingxiong Z (Taiwan) (Unl)" - rom ( name "Luke Yingxiong Z (Taiwan) (Unl).gbc" size 1048576 crc 8ced0c21 sha1 271097c99be5f60fbdb561875d006a622093fe70 ) + name "Luke Yingxiong Chuan 3 (Taiwan) (Unl)" + description "Luke Yingxiong Chuan 3 (Taiwan) (Unl)" + rom ( name "Luke Yingxiong Chuan 3 (Taiwan) (Unl).gbc" size 4194304 crc bd0e7c73 sha1 a095388a2ba13f0f846bbf4ee86ef25e49327c67 ) ) game ( - name "Lunar Docking (World) (Aftermarket) (Unl)" - description "Lunar Docking (World) (Aftermarket) (Unl)" - rom ( name "Lunar Docking (World) (Aftermarket) (Unl).gbc" size 262144 crc 9edd066c sha1 4d43a38e8b5df41309f5b6ec13e4829db739d980 ) + name "Luke Yingxiong Z (Taiwan) (Unl)" + description "Luke Yingxiong Z (Taiwan) (Unl)" + rom ( name "Luke Yingxiong Z (Taiwan) (Unl).gbc" size 1048576 crc 8ced0c21 sha1 271097c99be5f60fbdb561875d006a622093fe70 ) ) game ( @@ -39393,24 +41384,6 @@ game ( rom ( name "M&M's Minis Madness (USA) (Sample).gbc" size 1048576 crc 83293b1b sha1 2a0d0b7aa3b96b05bc020da496f2ce08e8fac190 ) ) -game ( - name "Machine, The (USA) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" - description "Machine, The (USA) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Machine, The (USA) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc f55a9d95 sha1 2b22fbd76e11e6e45053b1e6989de303e3033c9e ) -) - -game ( - name "Machine, The (USA) (Demo) (GB Compatible) (Aftermarket) (Unl)" - description "Machine, The (USA) (Demo) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Machine, The (USA) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 5662865e sha1 a5ac99a4087bd5ea45417e5b4a7c9af10433911a ) -) - -game ( - name "Machine, The (World) (GB Compatible) (Aftermarket) (Unl)" - description "Machine, The (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Machine, The (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc da01eb3e sha1 cd9a27077ba7ed49d2f2878577cb6ff005d6f785 ) -) - game ( name "Macross 7 - Ginga no Heart o Furuwasero!! (Japan)" description "Macross 7 - Ginga no Heart o Furuwasero!! (Japan)" @@ -39462,7 +41435,7 @@ game ( game ( name "Magical Drop (Europe) (En,Fr,De)" description "Magical Drop (Europe) (En,Fr,De)" - rom ( name "Magical Drop (Europe) (En,Fr,De).gbc" size 1048576 crc ea9ee203 sha1 8ef276f9c6a64d7cec527bcba8d1b7223de0e01c ) + rom ( name "Magical Drop (Europe) (En,Fr,De).gbc" size 1048576 crc ea9ee203 sha1 8ef276f9c6a64d7cec527bcba8d1b7223de0e01c flags verified ) ) game ( @@ -39495,12 +41468,6 @@ game ( rom ( name "Magical Tetris Challenge (USA).gbc" size 1048576 crc f53cf66c sha1 7cdb0bf463ad87ec8a68a564c3f03dbc890edd7e ) ) -game ( - name "Magician's Curse, The (World) (Aftermarket) (Unl)" - description "Magician's Curse, The (World) (Aftermarket) (Unl)" - rom ( name "Magician's Curse, The (World) (Aftermarket) (Unl).gbc" size 524288 crc f2b1967e sha1 3b5f97f9a0b4d63a3795695b0bda6e969de8e051 ) -) - game ( name "Mahjong Joou (Japan) (SGB Enhanced) (GB Compatible)" description "Mahjong Joou (Japan) (SGB Enhanced) (GB Compatible)" @@ -39681,12 +41648,6 @@ game ( rom ( name "Maya the Bee & Her Friends (Europe) (En,Fr,De) (GB Compatible).gbc" size 1048576 crc 983b1d26 sha1 522d7f33fd39bd00f48208743fb2246ef0bd3ff1 ) ) -game ( - name "Mayhem (World) (Aftermarket) (Unl)" - description "Mayhem (World) (Aftermarket) (Unl)" - rom ( name "Mayhem (World) (Aftermarket) (Unl).gbc" size 262144 crc 4d739ad7 sha1 9f141728a74432820f47cc24d230dc56d6ac099b ) -) - game ( name "McDonald's Monogatari - Honobono Tenchou Ikusei Game (Japan)" description "McDonald's Monogatari - Honobono Tenchou Ikusei Game (Japan)" @@ -39702,7 +41663,7 @@ game ( game ( name "Medarot 2 - Kuwagata Version (Japan) (SGB Enhanced) (GB Compatible)" description "Medarot 2 - Kuwagata Version (Japan) (SGB Enhanced) (GB Compatible)" - rom ( name "Medarot 2 - Kuwagata Version (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 5b8ffd37 sha1 48fc8c6e84c63ee47f5a2c5e99dc1666d6e9f496 ) + rom ( name "Medarot 2 - Kuwagata Version (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 5b8ffd37 sha1 48fc8c6e84c63ee47f5a2c5e99dc1666d6e9f496 flags verified ) ) game ( @@ -39819,16 +41780,10 @@ game ( rom ( name "Meitantei Conan - Norowareta Kouro (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc cabdd802 sha1 0858a619d716b0191713734d506d9f113f0d1c62 ) ) -game ( - name "Memory Mania Challenge (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" - description "Memory Mania Challenge (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Memory Mania Challenge (World) (v1.3) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 50618f4b sha1 c8d74af4746313800df3a23c1ad01f931e0e2eca flags verified ) -) - game ( name "Men in Black - The Series (USA, Europe) (SGB Enhanced) (GB Compatible)" description "Men in Black - The Series (USA, Europe) (SGB Enhanced) (GB Compatible)" - rom ( name "Men in Black - The Series (USA, Europe) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 65b8b343 sha1 7ceb1c82bdd185546c3dd5d2653788d74d811f7a ) + rom ( name "Men in Black - The Series (USA, Europe) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 65b8b343 sha1 7ceb1c82bdd185546c3dd5d2653788d74d811f7a flags verified ) ) game ( @@ -39891,12 +41846,6 @@ game ( rom ( name "Metamode (Japan).gbc" size 2097152 crc a76eed5b sha1 1c1d74c810b90cf4d2ee32859eaea569a5b45c3f ) ) -game ( - name "Meteorite (World) (Aftermarket) (Unl)" - description "Meteorite (World) (Aftermarket) (Unl)" - rom ( name "Meteorite (World) (Aftermarket) (Unl).gbc" size 131072 crc fafbcebf sha1 25a81d916f1ed80a2bca2fe7a555433f06d025e3 ) -) - game ( name "Mia Hamm Soccer Shootout (USA)" description "Mia Hamm Soccer Shootout (USA)" @@ -40023,12 +41972,6 @@ game ( rom ( name "Minnie & Friends - Yume no Kuni o Sagashite (Japan).gbc" size 2097152 crc d47ae577 sha1 146f336d16d165590d09f41f44ba52a81816a033 flags verified ) ) -game ( - name "Mirror Between Us, The (World) (GB Compatible) (Aftermarket) (Unl)" - description "Mirror Between Us, The (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Mirror Between Us, The (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 854f4297 sha1 a1a44ce8052f06349df3cbdf9a6d976609213d68 ) -) - game ( name "Missile Command (Europe)" description "Missile Command (Europe)" @@ -40038,7 +41981,7 @@ game ( game ( name "Missile Command (USA) (Rumble Version)" description "Missile Command (USA) (Rumble Version)" - rom ( name "Missile Command (USA) (Rumble Version).gbc" size 1048576 crc 47543c51 sha1 7bd68586df8754cbc81b2dcbb6e2b5de43f812e8 ) + rom ( name "Missile Command (USA) (Rumble Version).gbc" size 1048576 crc 47543c51 sha1 7bd68586df8754cbc81b2dcbb6e2b5de43f812e8 flags verified ) ) game ( @@ -40065,24 +42008,12 @@ game ( rom ( name "Mission Bravo (USA) (Proto).gbc" size 1048576 crc b8fc72b6 sha1 2833855bb2b9fde988f8efcac3e357ef9f0f4f50 ) ) -game ( - name "Mission to Mars (World) (Aftermarket) (Unl)" - description "Mission to Mars (World) (Aftermarket) (Unl)" - rom ( name "Mission to Mars (World) (Aftermarket) (Unl).gbc" size 262144 crc f651fcf4 sha1 479c70dd9c63cdcad99ca44720a9e0e2582df119 ) -) - game ( name "Mizuki Shigeru no Shin Youkaiden (Japan)" description "Mizuki Shigeru no Shin Youkaiden (Japan)" rom ( name "Mizuki Shigeru no Shin Youkaiden (Japan).gbc" size 4194304 crc fc1f100f sha1 ab12770558fb95434bba0da0d3b8a91e2d9179fb ) ) -game ( - name "Mo Jie 3-bu Wanme de Shijie (Taiwan) (Unl)" - description "Mo Jie 3-bu Wanme de Shijie (Taiwan) (Unl)" - rom ( name "Mo Jie 3-bu Wanme de Shijie (Taiwan) (Unl).gbc" size 524288 crc d91e3f98 sha1 556913f2687a49034e1229ef1e375f6036ec5719 ) -) - game ( name "Mobile Golf (Japan)" description "Mobile Golf (Japan)" @@ -40095,28 +42026,28 @@ game ( rom ( name "Mobile Trainer (Japan).gbc" size 2097152 crc 7226ead0 sha1 ecc0579edeaf9eccd722d605cc288cd023c8576a flags verified ) ) +game ( + name "Mojie 3-bu Wanme de Shijie (Taiwan) (Zh) (Unl)" + description "Mojie 3-bu Wanme de Shijie (Taiwan) (Zh) (Unl)" + rom ( name "Mojie 3-bu Wanme de Shijie (Taiwan) (Zh) (Unl).gbc" size 524288 crc d91e3f98 sha1 556913f2687a49034e1229ef1e375f6036ec5719 ) +) + game ( name "Mojie Chuanshuo (Taiwan) (Unl)" description "Mojie Chuanshuo (Taiwan) (Unl)" rom ( name "Mojie Chuanshuo (Taiwan) (Unl).gbc" size 524288 crc 7aa7eea5 sha1 109e4ba61b04afe15cc5a5ee994f56405938cee3 ) ) +game ( + name "Mojie Zhanshi Chuanshuo (Taiwan) (Unl)" + description "Mojie Zhanshi Chuanshuo (Taiwan) (Unl)" + rom ( name "Mojie Zhanshi Chuanshuo (Taiwan) (Unl).gbc" size 2097152 crc 620c56b8 sha1 25fd8c132601cd9f74784a010141572505a2ef66 ) +) + game ( name "Momotarou Densetsu 1-2 (Japan)" description "Momotarou Densetsu 1-2 (Japan)" - rom ( name "Momotarou Densetsu 1-2 (Japan).gbc" size 2097152 crc da7fb08f sha1 acffa3417c85be574aa28432e29e1d40f28a565b ) -) - -game ( - name "Mona and the Witch's Hat Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" - description "Mona and the Witch's Hat Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Mona and the Witch's Hat Deluxe (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 39480c79 sha1 4348a7903e538e5367f2a60718f43cbeeccf96df ) -) - -game ( - name "Monkey Magic (World) (Aftermarket) (Unl)" - description "Monkey Magic (World) (Aftermarket) (Unl)" - rom ( name "Monkey Magic (World) (Aftermarket) (Unl).gbc" size 262144 crc c9c68715 sha1 bf5dc5593334fe1114461065a2b7284d28b31462 ) + rom ( name "Momotarou Densetsu 1-2 (Japan).gbc" size 2097152 crc da7fb08f sha1 acffa3417c85be574aa28432e29e1d40f28a565b flags verified ) ) game ( @@ -40221,12 +42152,6 @@ game ( rom ( name "Montezuma's Return! (USA) (En,Es) (GB Compatible).gbc" size 524288 crc de04772f sha1 616bb04e0254ef2ba9e1ea629493efdcc37d807c ) ) -game ( - name "Monty on the Run (World) (Aftermarket) (Unl)" - description "Monty on the Run (World) (Aftermarket) (Unl)" - rom ( name "Monty on the Run (World) (Aftermarket) (Unl).gbc" size 524288 crc fd1066ac sha1 8390175e6be4731d9afa91715d7f8dd11693bb69 ) -) - game ( name "Moomin no Daibouken (Japan) (Beta)" description "Moomin no Daibouken (Japan) (Beta)" @@ -40281,12 +42206,6 @@ game ( rom ( name "Motocross Maniacs 2 (USA).gbc" size 1048576 crc 17d27fa9 sha1 5a0e7a9a71a88ee79529531274eb3696cf0fa42c ) ) -game ( - name "Mr. Angry (World) (Aftermarket) (Unl)" - description "Mr. Angry (World) (Aftermarket) (Unl)" - rom ( name "Mr. Angry (World) (Aftermarket) (Unl).gbc" size 524288 crc b85e63a5 sha1 127ad5315e2bce37614a1e9f8605798e68718926 ) -) - game ( name "Mr. Driller (Europe)" description "Mr. Driller (Europe)" @@ -40326,7 +42245,7 @@ game ( game ( name "Ms. Pac-Man - Special Color Edition (USA) (SGB Enhanced) (GB Compatible)" description "Ms. Pac-Man - Special Color Edition (USA) (SGB Enhanced) (GB Compatible)" - rom ( name "Ms. Pac-Man - Special Color Edition (USA) (SGB Enhanced) (GB Compatible).gbc" size 524288 crc 103e212d sha1 a468f7ad011c1b42ea3144e65607694493e7e4a7 ) + rom ( name "Ms. Pac-Man - Special Color Edition (USA) (SGB Enhanced) (GB Compatible).gbc" size 524288 crc 103e212d sha1 a468f7ad011c1b42ea3144e65607694493e7e4a7 flags verified ) ) game ( @@ -40482,7 +42401,7 @@ game ( game ( name "NASCAR 2000 (USA, Europe)" description "NASCAR 2000 (USA, Europe)" - rom ( name "NASCAR 2000 (USA, Europe).gbc" size 1048576 crc 54d90a4c sha1 37d3ffb5ae9bcf4c1cab7cece0a19d6b0b45c3a2 ) + rom ( name "NASCAR 2000 (USA, Europe).gbc" size 1048576 crc 54d90a4c sha1 37d3ffb5ae9bcf4c1cab7cece0a19d6b0b45c3a2 flags verified ) ) game ( @@ -40551,6 +42470,24 @@ game ( rom ( name "NBA Jam 2001 (USA, Europe).gbc" size 1048576 crc 3aa75f1c sha1 b1f7230dcccaecb7ae9b2a0e786effac2fc24497 flags verified ) ) +game ( + name "NBA Jam 2001 (USA, Europe) (Beta) (2000-02-07)" + description "NBA Jam 2001 (USA, Europe) (Beta) (2000-02-07)" + rom ( name "NBA Jam 2001 (USA, Europe) (Beta) (2000-02-07).gbc" size 131072 crc 594ee678 sha1 5d8ae5937a374fe4e36fe5303e3ad3757ee9675c ) +) + +game ( + name "NBA Jam 2001 (USA, Europe) (Beta) (2000-05-05)" + description "NBA Jam 2001 (USA, Europe) (Beta) (2000-05-05)" + rom ( name "NBA Jam 2001 (USA, Europe) (Beta) (2000-05-05).gbc" size 1048576 crc 926b47d1 sha1 ddbb720be9dd573728f897abe77569d42dae7baf ) +) + +game ( + name "NBA Jam 2001 (USA, Europe) (Beta) (2000-09-26)" + description "NBA Jam 2001 (USA, Europe) (Beta) (2000-09-26)" + rom ( name "NBA Jam 2001 (USA, Europe) (Beta) (2000-09-26).gbc" size 1048576 crc 0d5506ae sha1 2859d6ad2af7ff3333ad0d3750a1fd4b3088d47d ) +) + game ( name "NBA Jam 99 (USA, Europe) (GB Compatible)" description "NBA Jam 99 (USA, Europe) (GB Compatible)" @@ -40575,18 +42512,6 @@ game ( rom ( name "NBA Show Time - NBA on NBC (USA) (Rev 1) (Proto).gbc" size 1048576 crc 8bc9be45 sha1 fd4bb16f306e309834e276ed768e8e2ed402e138 ) ) -game ( - name "Neclaus' Quest (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" - description "Neclaus' Quest (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Neclaus' Quest (World) (v1.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc eedefa0c sha1 e63c16fe987fe655408be66198366a0147ac607c ) -) - -game ( - name "Neclaus' Quest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" - description "Neclaus' Quest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Neclaus' Quest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 53cf930c sha1 bd3272ca7ead64da3f68f774661a560add433b94 ) -) - game ( name "Net de Get - Minigame @ 100 (Japan)" description "Net de Get - Minigame @ 100 (Japan)" @@ -40638,7 +42563,7 @@ game ( game ( name "NFL Blitz (USA, Europe) (Rev 1) (GB Compatible)" description "NFL Blitz (USA, Europe) (Rev 1) (GB Compatible)" - rom ( name "NFL Blitz (USA, Europe) (Rev 1) (GB Compatible).gbc" size 524288 crc 107d734b sha1 66b69cba0705f0670759f01cfd586a50c47c7c89 ) + rom ( name "NFL Blitz (USA, Europe) (Rev 1) (GB Compatible).gbc" size 524288 crc 107d734b sha1 66b69cba0705f0670759f01cfd586a50c47c7c89 flags verified ) ) game ( @@ -40704,7 +42629,7 @@ game ( game ( name "Nobunaga no Yabou - Game Boy Ban 2 (Japan) (SGB Enhanced) (GB Compatible)" description "Nobunaga no Yabou - Game Boy Ban 2 (Japan) (SGB Enhanced) (GB Compatible)" - rom ( name "Nobunaga no Yabou - Game Boy Ban 2 (Japan) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 233862d0 sha1 a61e35306405e41c03b98b162ee14442e77c0da1 ) + rom ( name "Nobunaga no Yabou - Game Boy Ban 2 (Japan) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 233862d0 sha1 a61e35306405e41c03b98b162ee14442e77c0da1 flags verified ) ) game ( @@ -40731,48 +42656,6 @@ game ( rom ( name "Nv Wang Gedou 2000 (Taiwan) (Unl).gbc" size 2097152 crc e1668b49 sha1 37516139aa317a16440379c1dc00bdfc4c1e607a flags verified ) ) -game ( - name "Nyghtmare - The Ninth King (World) (v0.2.6) (Beta) (Aftermarket) (Unl)" - description "Nyghtmare - The Ninth King (World) (v0.2.6) (Beta) (Aftermarket) (Unl)" - rom ( name "Nyghtmare - The Ninth King (World) (v0.2.6) (Beta) (Aftermarket) (Unl).gbc" size 1048576 crc e983e8d1 sha1 fc2a58d49327c88c895ae6681bde57e1a2687974 flags verified ) -) - -game ( - name "Nyghtmare - The Ninth King (World) (v0.1.2) (Beta, Demo) (GB Compatible) (Aftermarket) (Unl)" - description "Nyghtmare - The Ninth King (World) (v0.1.2) (Beta, Demo) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Nyghtmare - The Ninth King (World) (v0.1.2) (Beta, Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc ef42955e sha1 485b4d672d9edda40f9191f5f5cc223046000e67 flags verified ) -) - -game ( - name "Nyghtmare - The Ninth King (World) (v0.2.1) (Beta) (Aftermarket) (Unl)" - description "Nyghtmare - The Ninth King (World) (v0.2.1) (Beta) (Aftermarket) (Unl)" - rom ( name "Nyghtmare - The Ninth King (World) (v0.2.1) (Beta) (Aftermarket) (Unl).gbc" size 1048576 crc 581efe4d sha1 125bb0564ee17f8e55046a1c25e53ee9a4254303 ) -) - -game ( - name "Nyghtmare - The Ninth King (World) (v0.2.3) (Beta) (Aftermarket) (Unl)" - description "Nyghtmare - The Ninth King (World) (v0.2.3) (Beta) (Aftermarket) (Unl)" - rom ( name "Nyghtmare - The Ninth King (World) (v0.2.3) (Beta) (Aftermarket) (Unl).gbc" size 1048576 crc e26ddbbb sha1 853115369b8ca583d038d00c1dde59b6a74b73a2 ) -) - -game ( - name "Nyghtmare - The Ninth King (World) (v0.2.5) (Beta) (Aftermarket) (Unl)" - description "Nyghtmare - The Ninth King (World) (v0.2.5) (Beta) (Aftermarket) (Unl)" - rom ( name "Nyghtmare - The Ninth King (World) (v0.2.5) (Beta) (Aftermarket) (Unl).gbc" size 1048576 crc 1e8ac5b9 sha1 99c11bef7feb17a9e7212cf9b6593478f671bc32 ) -) - -game ( - name "Nyghtmare - The Ninth King (World) (Free Version) (GB Compatible) (Aftermarket) (Unl)" - description "Nyghtmare - The Ninth King (World) (Free Version) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Nyghtmare - The Ninth King (World) (Free Version) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc f5df28c2 sha1 7b511444e1eb86fffcf93599a78e0e2c44aecc8a ) -) - -game ( - name "Nyghtmare - The Ninth King (World) (Rev 1) (Free Version) (Aftermarket) (Unl)" - description "Nyghtmare - The Ninth King (World) (Rev 1) (Free Version) (Aftermarket) (Unl)" - rom ( name "Nyghtmare - The Ninth King (World) (Rev 1) (Free Version) (Aftermarket) (Unl).gbc" size 2097152 crc 63bddc68 sha1 fab777e607bd8aba70eb65829143039dbe6ac08e ) -) - game ( name "NYR - New York Race (Europe) (En,Fr,De,Es,It,Pt)" description "NYR - New York Race (Europe) (En,Fr,De,Es,It,Pt)" @@ -40827,18 +42710,6 @@ game ( rom ( name "Ojarumaru - Tsukiyo ga Ike no Takaramono (Japan) (GB Compatible).gbc" size 2097152 crc ed7461d2 sha1 66d87a06d4d951e7695df73f53793a462509e4d0 ) ) -game ( - name "Olympic Skier (World) (Aftermarket) (Unl)" - description "Olympic Skier (World) (Aftermarket) (Unl)" - rom ( name "Olympic Skier (World) (Aftermarket) (Unl).gbc" size 524288 crc 5e81cef7 sha1 a7a552a9eb984098a67e063c2eca907eec000fc1 ) -) - -game ( - name "Opossum Country (World) (GB Compatible) (Aftermarket) (Unl)" - description "Opossum Country (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Opossum Country (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 7348bb32 sha1 e63e06d602473206b21138f5322acf86b5b6b9b8 ) -) - game ( name "Original Moorhuhn Jagd, Die (Germany)" description "Original Moorhuhn Jagd, Die (Germany)" @@ -40875,12 +42746,6 @@ game ( rom ( name "Ou Dorobou Jing - Devil Version (Japan) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 2a39a874 sha1 71797aa125b88614182ce3d0f8252d6ed8cfa08e ) ) -game ( - name "Out on a Limb (World) (Aftermarket) (Unl)" - description "Out on a Limb (World) (Aftermarket) (Unl)" - rom ( name "Out on a Limb (World) (Aftermarket) (Unl).gbc" size 262144 crc a6671528 sha1 f21cb71adcea1029151930eb98c4e9b446e4cfee ) -) - game ( name "Owarai Yoiko no Geemumichi - Oyaji Sagashite 3 Choume (Japan) (SGB Enhanced) (GB Compatible)" description "Owarai Yoiko no Geemumichi - Oyaji Sagashite 3 Choume (Japan) (SGB Enhanced) (GB Compatible)" @@ -40923,12 +42788,6 @@ game ( rom ( name "Painter (Europe) (Unl).gbc" size 262144 crc f4801f21 sha1 78db482d1d12b4556b6a5b995ce37a2435236a06 ) ) -game ( - name "Panik!16 (World) (Aftermarket) (Unl)" - description "Panik!16 (World) (Aftermarket) (Unl)" - rom ( name "Panik!16 (World) (Aftermarket) (Unl).gbc" size 262144 crc 7b31122d sha1 98d74fd64e4f7e835f1101b05816b8938a34a416 ) -) - game ( name "Paperboy (USA, Europe)" description "Paperboy (USA, Europe)" @@ -40990,21 +42849,9 @@ game ( ) game ( - name "Pie Crust (World) (v1.0) (Unl)" - description "Pie Crust (World) (v1.0) (Unl)" - rom ( name "Pie Crust (World) (v1.0) (Unl).gbc" size 32768 crc f39c8119 sha1 b01cad9652bf1c65151dd8d2bd21251a9cf44d43 ) -) - -game ( - name "Pine Creek (World) (En-US,Es-MX,Pt-BR) (GB Compatible) (Aftermarket) (Unl)" - description "Pine Creek (World) (En-US,Es-MX,Pt-BR) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Pine Creek (World) (En-US,Es-MX,Pt-BR) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 189aa999 sha1 2cf46a36502eaf22ac9572fe1136d369fcbe9e46 ) -) - -game ( - name "Pinecone Pizza Party (World) (Prototype) (GB Compatible) (Aftermarket) (Unl)" - description "Pinecone Pizza Party (World) (Prototype) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Pinecone Pizza Party (World) (Prototype) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 1601d6fa sha1 87b4edf0398f0154d7556e3cd96f97b19e699a40 ) + name "Piecrust (World) (Unl)" + description "Piecrust (World) (Unl)" + rom ( name "Piecrust (World) (Unl).gbc" size 32768 crc f39c8119 sha1 b01cad9652bf1c65151dd8d2bd21251a9cf44d43 ) ) game ( @@ -41206,9 +43053,9 @@ game ( ) game ( - name "Pocket Music (USA) (En,Fr,De,Es,It) (Proto)" - description "Pocket Music (USA) (En,Fr,De,Es,It) (Proto)" - rom ( name "Pocket Music (USA) (En,Fr,De,Es,It) (Proto).gbc" size 1048576 crc c4387812 sha1 ad547a79af864eb56a18e1c2ad4346eb35df41ed ) + name "Pocket Music (USA) (En,Es) (Proto)" + description "Pocket Music (USA) (En,Es) (Proto)" + rom ( name "Pocket Music (USA) (En,Es) (Proto).gbc" size 1048576 crc c4387812 sha1 ad547a79af864eb56a18e1c2ad4346eb35df41ed ) ) game ( @@ -41277,12 +43124,6 @@ game ( rom ( name "Pocket Soccer (Europe) (En,Fr,De,Es,It,Pt).gbc" size 2097152 crc e8f5824f sha1 4d06ea937a02a8f458186a9382994b09a97481a4 ) ) -game ( - name "Pogo Pete (World) (Aftermarket) (Unl)" - description "Pogo Pete (World) (Aftermarket) (Unl)" - rom ( name "Pogo Pete (World) (Aftermarket) (Unl).gbc" size 262144 crc 3001ed1b sha1 f9dab150843c2b8f300d36b1dd53dd1a22b481a3 ) -) - game ( name "Pokemon - Crystal Version (Australia)" description "Pokemon - Crystal Version (Australia)" @@ -41337,6 +43178,18 @@ game ( rom ( name "Pokemon - Kristall-Edition (Germany).gbc" size 2097152 crc 616d85de sha1 accb584293ba056152f1fd908439b019017ff2fe ) ) +game ( + name "Pokemon - La Version Esmeralda - Special Pikachu Edition (Spain) (Pirate)" + description "Pokemon - La Version Esmeralda - Special Pikachu Edition (Spain) (Pirate)" + rom ( name "Pokemon - La Version Esmeralda - Special Pikachu Edition (Spain) (Pirate).gbc" size 524288 crc 0d009399 sha1 9e953c1acccd3527a555cf4ba25da38adf99755c ) +) + +game ( + name "Pokemon - Mewtwo Strikes Back (Taiwan) (Zh) (Unl)" + description "Pokemon - Mewtwo Strikes Back (Taiwan) (Zh) (Unl)" + rom ( name "Pokemon - Mewtwo Strikes Back (Taiwan) (Zh) (Unl).gbc" size 524288 crc 2930fa45 sha1 382a257199720d970f58e94cd4102acb809dec07 ) +) + game ( name "Pokemon - Mewtwo Strikes Back (Taiwan) (En) (Unl)" description "Pokemon - Mewtwo Strikes Back (Taiwan) (En) (Unl)" @@ -41370,19 +43223,19 @@ game ( game ( name "Pokemon - Version Argent (France) (SGB Enhanced) (GB Compatible)" description "Pokemon - Version Argent (France) (SGB Enhanced) (GB Compatible)" - rom ( name "Pokemon - Version Argent (France) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc e0c216ea sha1 a4a7e8079b7a53e4d9ef43382bbb1090b9d45d1a ) + rom ( name "Pokemon - Version Argent (France) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc e0c216ea sha1 a4a7e8079b7a53e4d9ef43382bbb1090b9d45d1a flags verified ) ) game ( name "Pokemon - Version Cristal (France)" description "Pokemon - Version Cristal (France)" - rom ( name "Pokemon - Version Cristal (France).gbc" size 2097152 crc 878b2aa7 sha1 c055992b16b7399c687647725cdd1f4f13a2f75c ) + rom ( name "Pokemon - Version Cristal (France).gbc" size 2097152 crc 878b2aa7 sha1 c055992b16b7399c687647725cdd1f4f13a2f75c flags verified ) ) game ( name "Pokemon - Version Or (France) (SGB Enhanced) (GB Compatible)" description "Pokemon - Version Or (France) (SGB Enhanced) (GB Compatible)" - rom ( name "Pokemon - Version Or (France) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 37a70702 sha1 c147c0d8c2b71b7628a7233436f5c052b5b17081 ) + rom ( name "Pokemon - Version Or (France) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 37a70702 sha1 c147c0d8c2b71b7628a7233436f5c052b5b17081 flags verified ) ) game ( @@ -41433,6 +43286,18 @@ game ( rom ( name "Pokemon Diamond (Taiwan) (En) (Unl).gbc" size 524288 crc 1b5bef4b sha1 433e7991b706baedf59af8b91bc142ba2f72112f ) ) +game ( + name "Pokemon Diamond (Taiwan) (Zh) (Unl)" + description "Pokemon Diamond (Taiwan) (Zh) (Unl)" + rom ( name "Pokemon Diamond (Taiwan) (Zh) (Unl).gbc" size 524288 crc 7309551a sha1 3fb38a7f49e13f5bfce0cd1983d9006b30f68930 ) +) + +game ( + name "Pokemon Gold (Taiwan) (En) (Unl)" + description "Pokemon Gold (Taiwan) (En) (Unl)" + rom ( name "Pokemon Gold (Taiwan) (En) (Unl).gbc" size 1048576 crc 479f3c4e sha1 26503e3262022be29b845a0b2ba555013d8ad12f ) +) + game ( name "Pokemon Gold Version 2 (Taiwan) (Unl)" description "Pokemon Gold Version 2 (Taiwan) (Unl)" @@ -41445,6 +43310,12 @@ game ( rom ( name "Pokemon Jade (Taiwan) (En) (Pirate).gbc" size 2097152 crc aa07f269 sha1 994a205d7c0b55f45715a65b23ec31258e43652f ) ) +game ( + name "Pokemon Jade (Taiwan) (Zh) (Unl)" + description "Pokemon Jade (Taiwan) (Zh) (Unl)" + rom ( name "Pokemon Jade (Taiwan) (Zh) (Unl).gbc" size 524288 crc b9ffd78c sha1 c46c3a9e221da8d41a9eb1a84765368d975dfaa1 ) +) + game ( name "Pokemon Jade Version - Special Pikachu Edition (USA) (Pirate)" description "Pokemon Jade Version - Special Pikachu Edition (USA) (Pirate)" @@ -41493,6 +43364,36 @@ game ( rom ( name "Pokemon Puzzle Challenge (USA, Australia).gbc" size 2097152 crc d06bba96 sha1 bbf952412250ae511b3b862566e424ce6a672f99 flags verified ) ) +game ( + name "Pokemon Ruby (Taiwan) (Unl)" + description "Pokemon Ruby (Taiwan) (Unl)" + rom ( name "Pokemon Ruby (Taiwan) (Unl).gbc" size 524288 crc 7a2fc378 sha1 1f9e62faa85e9058bec16be8b6c14223bb3ac15b ) +) + +game ( + name "Pokemon Sapphire (Taiwan) (En) (Unl)" + description "Pokemon Sapphire (Taiwan) (En) (Unl)" + rom ( name "Pokemon Sapphire (Taiwan) (En) (Unl).gbc" size 524288 crc 8077dd95 sha1 2e3a28e02d5bfe259d9367d1205daa52912a1f8f ) +) + +game ( + name "Pokemon Sapphire (Taiwan) (Zh) (Unl)" + description "Pokemon Sapphire (Taiwan) (Zh) (Unl)" + rom ( name "Pokemon Sapphire (Taiwan) (Zh) (Unl).gbc" size 524288 crc f3c1c00c sha1 75639d4dbe72d044002f768d5dbbd08caf003fdc ) +) + +game ( + name "Pokemon Trading Card Game (Europe) (En,Fr,De) (Rev 1) (SGB Enhanced) (GB Compatible)" + description "Pokemon Trading Card Game (Europe) (En,Fr,De) (Rev 1) (SGB Enhanced) (GB Compatible)" + rom ( name "Pokemon Trading Card Game (Europe) (En,Fr,De) (Rev 1) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 942d0b7f sha1 dffc15f3063a4c2df84c6361406b41aec1696d3e flags verified ) +) + +game ( + name "Pokemon Trading Card Game (Europe) (En,Es,It) (Rev 1) (SGB Enhanced) (GB Compatible)" + description "Pokemon Trading Card Game (Europe) (En,Es,It) (Rev 1) (SGB Enhanced) (GB Compatible)" + rom ( name "Pokemon Trading Card Game (Europe) (En,Es,It) (Rev 1) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 3f1d7e58 sha1 c54b81e638b0c45d3569f9f5f0345df9e95ce975 ) +) + game ( name "Pokemon Trading Card Game (Europe) (En,Es,It) (SGB Enhanced) (GB Compatible)" description "Pokemon Trading Card Game (Europe) (En,Es,It) (SGB Enhanced) (GB Compatible)" @@ -41511,18 +43412,6 @@ game ( rom ( name "Pokemon Trading Card Game (USA, Australia) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 81069d53 sha1 0f8670a583255cff3e5b7ca71b5d7454d928fc48 flags verified ) ) -game ( - name "Pokemon Trading Card Game (Europe) (En,Fr,De) (Rev 1) (SGB Enhanced) (GB Compatible)" - description "Pokemon Trading Card Game (Europe) (En,Fr,De) (Rev 1) (SGB Enhanced) (GB Compatible)" - rom ( name "Pokemon Trading Card Game (Europe) (En,Fr,De) (Rev 1) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 942d0b7f sha1 dffc15f3063a4c2df84c6361406b41aec1696d3e flags verified ) -) - -game ( - name "Pokemon Trading Card Game (Europe) (En,Es,It) (Rev 1) (SGB Enhanced) (GB Compatible)" - description "Pokemon Trading Card Game (Europe) (En,Es,It) (Rev 1) (SGB Enhanced) (GB Compatible)" - rom ( name "Pokemon Trading Card Game (Europe) (En,Es,It) (Rev 1) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 3f1d7e58 sha1 c54b81e638b0c45d3569f9f5f0345df9e95ce975 ) -) - game ( name "Pokemon Vision Jade (Taiwan) (De) (Unl)" description "Pokemon Vision Jade (Taiwan) (De) (Unl)" @@ -41595,24 +43484,6 @@ game ( rom ( name "Portal Runner (USA).gbc" size 1048576 crc 913ac306 sha1 a8347366f15c0e454fa253bad5b4053d2a9613aa ) ) -game ( - name "Powa! (World) (En) (GB Compatible) (Aftermarket) (Unl)" - description "Powa! (World) (En) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Powa! (World) (En) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc f0191467 sha1 3876f1aa896759f427ad2dc88a48788817e60c06 flags verified ) -) - -game ( - name "Powa! (World) (Ja) (GB Compatible) (Aftermarket) (Unl)" - description "Powa! (World) (Ja) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Powa! (World) (Ja) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc e8f68acc sha1 156d315b7a2a035d5cd429fb8c7e051e67e83c93 flags verified ) -) - -game ( - name "Powa! (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" - description "Powa! (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Powa! (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 592b6097 sha1 874d5e4ffc7d36259bef6ec6a86a1de8289b8d54 ) -) - game ( name "Power Pro Kun Pocket (Japan) (SGB Enhanced) (GB Compatible)" description "Power Pro Kun Pocket (Japan) (SGB Enhanced) (GB Compatible)" @@ -41829,12 +43700,6 @@ game ( rom ( name "Project S-11 (USA).gbc" size 524288 crc 20cee2e8 sha1 cbedd34a0c6a2f4e58d05f0bb6d54f7cbcda815c ) ) -game ( - name "Proof of Destruction (World) (Aftermarket) (Unl)" - description "Proof of Destruction (World) (Aftermarket) (Unl)" - rom ( name "Proof of Destruction (World) (Aftermarket) (Unl).gbc" size 262144 crc fa528f88 sha1 5062f16346c31cae1b13e469cb610ce84d4eecb2 ) -) - game ( name "Puchi Carat (USA) (Proto 2) (SGB Enhanced) (GB Compatible)" description "Puchi Carat (USA) (Proto 2) (SGB Enhanced) (GB Compatible)" @@ -41871,12 +43736,6 @@ game ( rom ( name "Pumuckls Abenteuer im Geisterschloss (Germany).gbc" size 1048576 crc 87fcec24 sha1 0fe14ef81b11c854f080e804c5d3cb14601b2794 ) ) -game ( - name "Purple Turtles (World) (Aftermarket) (Unl)" - description "Purple Turtles (World) (Aftermarket) (Unl)" - rom ( name "Purple Turtles (World) (Aftermarket) (Unl).gbc" size 262144 crc 471277df sha1 a73cb69d1fb42f45f3649c4d1b4775e98fe35b78 ) -) - game ( name "Puyo Puyo Gaiden - Puyo Wars (Japan) (SGB Enhanced) (GB Compatible)" description "Puyo Puyo Gaiden - Puyo Wars (Japan) (SGB Enhanced) (GB Compatible)" @@ -42081,12 +43940,6 @@ game ( rom ( name "Rats! (USA) (En,Es) (GB Compatible).gbc" size 524288 crc 17635ad1 sha1 5e423dfab8221b69a641d2e535ebfe1e3759a2e4 ) ) -game ( - name "Ravenia (World) (GB Compatible) (Aftermarket) (Unl)" - description "Ravenia (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Ravenia (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 09196a32 sha1 8218ad22b29fb32c66430a17a97775dd30b2f34b flags verified ) -) - game ( name "Rayman (Europe) (En,Fr,De,Es,It,Nl)" description "Rayman (Europe) (En,Fr,De,Es,It,Nl)" @@ -42166,15 +44019,9 @@ game ( ) game ( - name "Repugnant Bounty (World) (Demo) (Aftermarket) (Unl)" - description "Repugnant Bounty (World) (Demo) (Aftermarket) (Unl)" - rom ( name "Repugnant Bounty (World) (Demo) (Aftermarket) (Unl).gbc" size 2097152 crc f8c7f180 sha1 07674d42f5d4efaec14750ae56d8f28c4b54c020 ) -) - -game ( - name "Repugnant Bounty (World) (Rev B) (Beta) (Aftermarket) (Unl)" - description "Repugnant Bounty (World) (Rev B) (Beta) (Aftermarket) (Unl)" - rom ( name "Repugnant Bounty (World) (Rev B) (Beta) (Aftermarket) (Unl).gbc" size 4194304 crc 9cce02d9 sha1 b83f9aca2a382729a490856c4100dc4a17594921 ) + name "Remen Gaoxiao - Shuma Guaishou III (Taiwan) (Unl)" + description "Remen Gaoxiao - Shuma Guaishou III (Taiwan) (Unl)" + rom ( name "Remen Gaoxiao - Shuma Guaishou III (Taiwan) (Unl).gbc" size 524288 crc 9f64fb1c sha1 b8d6910c8b5c1cab044c61679bbbc4f213648f56 ) ) game ( @@ -42231,6 +44078,12 @@ game ( rom ( name "Return of the Ninja (USA).gbc" size 1048576 crc a07da702 sha1 e33352f0ac19d28983ebed0758d022861473ec0e ) ) +game ( + name "Return of the Ninja (World) (Limited Run Games)" + description "Return of the Ninja (World) (Limited Run Games)" + rom ( name "Return of the Ninja (World) (Limited Run Games).gbc" size 1048576 crc df445c4a sha1 d73049119fbc163183fdb95e9b299ca4d1d4e8e3 ) +) + game ( name "Revelations - The Demon Slayer (USA) (SGB Enhanced) (GB Compatible)" description "Revelations - The Demon Slayer (USA) (SGB Enhanced) (GB Compatible)" @@ -42243,12 +44096,6 @@ game ( rom ( name "Rhino Rumble (USA, Europe).gbc" size 1048576 crc 73160e05 sha1 2caf47c20d8632e47c4426dd3564e76415139973 flags verified ) ) -game ( - name "Rig Attack (World) (Aftermarket) (Unl)" - description "Rig Attack (World) (Aftermarket) (Unl)" - rom ( name "Rig Attack (World) (Aftermarket) (Unl).gbc" size 262144 crc d013d775 sha1 90bfd921c986abff4555b761cedc90ec36c43fff ) -) - game ( name "Rip-Tide Racer (Europe) (En,Fr,De,Es,It) (GB Compatible)" description "Rip-Tide Racer (Europe) (En,Fr,De,Es,It) (GB Compatible)" @@ -42276,7 +44123,7 @@ game ( game ( name "Roadsters (USA) (En,Fr,De,Es,It,Nl) (GB Compatible)" description "Roadsters (USA) (En,Fr,De,Es,It,Nl) (GB Compatible)" - rom ( name "Roadsters (USA) (En,Fr,De,Es,It,Nl) (GB Compatible).gbc" size 1048576 crc 38b022be sha1 ede737e99108be29daf94fee8e10f5dd770731bb ) + rom ( name "Roadsters (USA) (En,Fr,De,Es,It,Nl) (GB Compatible).gbc" size 1048576 crc 38b022be sha1 ede737e99108be29daf94fee8e10f5dd770731bb flags verified ) ) game ( @@ -42291,12 +44138,6 @@ game ( rom ( name "Robin Hood (Europe) (En,Fr,De,Es,It,Nl).gbc" size 1048576 crc d4f84329 sha1 fe0c42e949bc41f070b22dd24e643aa42b007667 ) ) -game ( - name "Robin to the Rescue (World) (Aftermarket) (Unl)" - description "Robin to the Rescue (World) (Aftermarket) (Unl)" - rom ( name "Robin to the Rescue (World) (Aftermarket) (Unl).gbc" size 262144 crc 9cd52c18 sha1 ef3bea9ed0de41e311b5f15fccbb0f451848d56c ) -) - game ( name "RoboCop (Europe) (En,Fr,De,Es,It,Nl)" description "RoboCop (Europe) (En,Fr,De,Es,It,Nl)" @@ -42363,12 +44204,6 @@ game ( rom ( name "Rocket Power - La Glisse de l'Extreme (France).gbc" size 1048576 crc c9a7aa7b sha1 b6b9b7b2fb2ff11d41c6531fe21bfd5aa89f7ab4 ) ) -game ( - name "Rockman (World) (Aftermarket) (Unl)" - description "Rockman (World) (Aftermarket) (Unl)" - rom ( name "Rockman (World) (Aftermarket) (Unl).gbc" size 262144 crc 490b5676 sha1 6f78200acb6698e268e26c1912d64a002cbd3d89 ) -) - game ( name "Rockman 3 (Taiwan) (Unl)" description "Rockman 3 (Taiwan) (Unl)" @@ -42382,9 +44217,9 @@ game ( ) game ( - name "Rockman DX8 (Taiwan) (En) (Unl)" - description "Rockman DX8 (Taiwan) (En) (Unl)" - rom ( name "Rockman DX8 (Taiwan) (En) (Unl).gbc" size 1048576 crc 4c6c9eaf sha1 1274bb7d5570f4f1101dff1d13d9b5665deaa3da ) + name "Rockman DX8 (China) (En) (Unl)" + description "Rockman DX8 (China) (En) (Unl)" + rom ( name "Rockman DX8 (China) (En) (Unl).gbc" size 1048576 crc 4c6c9eaf sha1 1274bb7d5570f4f1101dff1d13d9b5665deaa3da ) ) game ( @@ -42489,30 +44324,6 @@ game ( rom ( name "RPG Tsukuru GB (Japan) (Rev 1) (Possible Proto) (NP).gbc" size 2097152 crc 57f82031 sha1 f4c36b3cbb13d3cbaaa81e97b0636c4515ce501e ) ) -game ( - name "Ruby & Rusty Save the Crows (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" - description "Ruby & Rusty Save the Crows (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Ruby & Rusty Save the Crows (World) (v1.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc a46baa15 sha1 87dd5a6ccb5db59dae09f1953062420977ad2d92 ) -) - -game ( - name "Ruby & Rusty Save the Crows (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" - description "Ruby & Rusty Save the Crows (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Ruby & Rusty Save the Crows (World) (v2.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 5602ca84 sha1 49d692796a6d0f3dcfc988648b446c0934f0e794 ) -) - -game ( - name "Ruby & Rusty Save the Crows (World) (Beta 3) (GB Compatible) (Aftermarket) (Unl)" - description "Ruby & Rusty Save the Crows (World) (Beta 3) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Ruby & Rusty Save the Crows (World) (Beta 3) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc b2547aa6 sha1 981a464d6e1c9e5ac59549845b41dae4817ed3b8 ) -) - -game ( - name "Ruby & Rusty Save the Crows (World) (v2.6) (GB Compatible) (Aftermarket) (Unl)" - description "Ruby & Rusty Save the Crows (World) (v2.6) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Ruby & Rusty Save the Crows (World) (v2.6) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc c18f82cb sha1 bd8cd5822dcc61f7eb0cf2584c9a5b5a94bde14a ) -) - game ( name "Rugrats - Time Travelers (USA, Europe) (GB Compatible)" description "Rugrats - Time Travelers (USA, Europe) (GB Compatible)" @@ -42522,7 +44333,7 @@ game ( game ( name "Rugrats - Totally Angelica (USA, Europe)" description "Rugrats - Totally Angelica (USA, Europe)" - rom ( name "Rugrats - Totally Angelica (USA, Europe).gbc" size 1048576 crc fc6195ef sha1 d4396a974aee16f74a5a80f4845c24dde5a083d6 ) + rom ( name "Rugrats - Totally Angelica (USA, Europe).gbc" size 1048576 crc fc6195ef sha1 d4396a974aee16f74a5a80f4845c24dde5a083d6 flags verified ) ) game ( @@ -42570,7 +44381,7 @@ game ( game ( name "Saban's Power Rangers - Lightspeed Rescue (USA, Europe)" description "Saban's Power Rangers - Lightspeed Rescue (USA, Europe)" - rom ( name "Saban's Power Rangers - Lightspeed Rescue (USA, Europe).gbc" size 1048576 crc 99869172 sha1 e7d0f2f21cdcda49516f682092d0b2017e82d379 ) + rom ( name "Saban's Power Rangers - Lightspeed Rescue (USA, Europe).gbc" size 1048576 crc 99869172 sha1 e7d0f2f21cdcda49516f682092d0b2017e82d379 flags verified ) ) game ( @@ -42615,12 +44426,6 @@ game ( rom ( name "Sakura Taisen GB 2 - Thunderbolt Sakusen (Japan).gbc" size 4194304 crc 47636a2c sha1 13092603ea1d54264bc48f02c2796947badb462c ) ) -game ( - name "Sam the Optimistic Hedgehog (World) (GB Compatible) (Aftermarket) (Unl)" - description "Sam the Optimistic Hedgehog (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Sam the Optimistic Hedgehog (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 4e4af60b sha1 ab8d49a99d02eb5c97d75f62dfb3720eec2b5abd ) -) - game ( name "Samurai Kid (Japan)" description "Samurai Kid (Japan)" @@ -42651,10 +44456,16 @@ game ( rom ( name "Sangokushi - Game Boy Ban 2 (Japan) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc e787b44c sha1 ec6089ff2cfcb17faf6a8ea9a4171869b3c7289b ) ) +game ( + name "Sanguozhi - Aoshi Tianxia (Taiwan) (Unl) (Alt)" + description "Sanguozhi - Aoshi Tianxia (Taiwan) (Unl) (Alt)" + rom ( name "Sanguozhi - Aoshi Tianxia (Taiwan) (Unl) (Alt).gbc" size 1048576 crc 728255e5 sha1 d9a978c6b4745d964128eb0eced022337849467c ) +) + game ( name "Sanguozhi - Aoshi Tianxia (Taiwan) (Unl)" description "Sanguozhi - Aoshi Tianxia (Taiwan) (Unl)" - rom ( name "Sanguozhi - Aoshi Tianxia (Taiwan) (Unl).gbc" size 1048576 crc 728255e5 sha1 d9a978c6b4745d964128eb0eced022337849467c ) + rom ( name "Sanguozhi - Aoshi Tianxia (Taiwan) (Unl).gbc" size 1048576 crc 48d2607f sha1 8ee81543442932b87349eef3a9287a923cec827c ) ) game ( @@ -42693,12 +44504,6 @@ game ( rom ( name "Santa Claus Junior (Europe).gbc" size 1048576 crc a744df64 sha1 ab74474cd63a2c74bf9617907270d26b5d183b89 ) ) -game ( - name "Sapphire Hotel - The Little Tales of (World) (v1.2) (Demo) (MBC5) (Aftermarket) (Unl)" - description "Sapphire Hotel - The Little Tales of (World) (v1.2) (Demo) (MBC5) (Aftermarket) (Unl)" - rom ( name "Sapphire Hotel - The Little Tales of (World) (v1.2) (Demo) (MBC5) (Aftermarket) (Unl).gbc" size 262144 crc db928e22 sha1 e175d35e6112c347ecd1e0a379e98f430823ba94 ) -) - game ( name "Saru Puncher (Japan) (SGB Enhanced) (GB Compatible)" description "Saru Puncher (Japan) (SGB Enhanced) (GB Compatible)" @@ -42825,6 +44630,12 @@ game ( rom ( name "Sewing Machine Operation Software (Europe) (En,Fr,Es,Pt) (Proto) (GB Compatible).gbc" size 1048576 crc e34b5ce8 sha1 500439c5e14400ef2bc45cacf5ff834b70c2acd4 ) ) +game ( + name "SGB Test Program (World) (1994.4) (Demo) (SGB Enhanced)" + description "SGB Test Program (World) (1994.4) (Demo) (SGB Enhanced)" + rom ( name "SGB Test Program (World) (1994.4) (Demo) (SGB Enhanced).gbc" size 49152 crc 8960ac1d sha1 a310a9629ce6ad0a607ac9e985056fe257f305b5 ) +) + game ( name "Sgt. Rock - On the Frontline (USA)" description "Sgt. Rock - On the Frontline (USA)" @@ -42903,6 +44714,12 @@ game ( rom ( name "Shantae (USA) (Beta).gbc" size 4194304 crc 3b4d6c50 sha1 141dc57955e84d51f0099c0709a0626d43ab8fa7 ) ) +game ( + name "Shantae (World) (Limited Run Games)" + description "Shantae (World) (Limited Run Games)" + rom ( name "Shantae (World) (Limited Run Games).gbc" size 4194304 crc 96d2774e sha1 71bc428f2746df2a2c6238e14f594d3e5c8da131 ) +) + game ( name "Shantae (World) (Switch)" description "Shantae (World) (Switch)" @@ -42927,12 +44744,6 @@ game ( rom ( name "Shaoling Legend - Hero, the Saver (Taiwan) (En) (Unl).gbc" size 2097152 crc a321ff7d sha1 b1194edd0962c50cf909262004a102f01f556723 ) ) -game ( - name "Shark Attack (World) (Aftermarket) (Unl)" - description "Shark Attack (World) (Aftermarket) (Unl)" - rom ( name "Shark Attack (World) (Aftermarket) (Unl).gbc" size 262144 crc cf80a2ba sha1 291f453a185f836fcafbd7e41945a409638980c0 ) -) - game ( name "Shaun Palmer's Pro Snowboarder (USA, Australia)" description "Shaun Palmer's Pro Snowboarder (USA, Australia)" @@ -42951,6 +44762,18 @@ game ( rom ( name "Sheng Shou Wuyu - Shenlong Chuanshuo (Taiwan) (Unl).gbc" size 1048576 crc 99a6e58a sha1 13bd97249b68eb824858a9d7a6061edf94140ac3 ) ) +game ( + name "Shenghuo Jiangmo Lu Waizhuan (Taiwan) (Unl)" + description "Shenghuo Jiangmo Lu Waizhuan (Taiwan) (Unl)" + rom ( name "Shenghuo Jiangmo Lu Waizhuan (Taiwan) (Unl).gbc" size 2097152 crc 1066ec96 sha1 394709afedc0632c09fee33785b0c4f00a45d3e6 ) +) + +game ( + name "Shenghuo Jiangmo Lu Waizhuan - Guang Yu An De Lunhui (Taiwan) (Unl)" + description "Shenghuo Jiangmo Lu Waizhuan - Guang Yu An De Lunhui (Taiwan) (Unl)" + rom ( name "Shenghuo Jiangmo Lu Waizhuan - Guang Yu An De Lunhui (Taiwan) (Unl).gbc" size 2097152 crc 808f19d7 sha1 62620a2cb01fe93388adc42da0b7cbaf53c11ba8 ) +) + game ( name "Shengui Diguo Zhi Emo Cheng (Taiwan) (Unl)" description "Shengui Diguo Zhi Emo Cheng (Taiwan) (Unl)" @@ -42958,9 +44781,21 @@ game ( ) game ( - name "Shi Mian Maifu - Fengyun Pian (Taiwan) (Unl)" - description "Shi Mian Maifu - Fengyun Pian (Taiwan) (Unl)" - rom ( name "Shi Mian Maifu - Fengyun Pian (Taiwan) (Unl).gbc" size 1048576 crc a5f686c3 sha1 68798ac090df9f5fb1ea9c409adf3dc639bc9842 ) + name "Shi Mian Maifu - Fengyun Pian (China) (Unl)" + description "Shi Mian Maifu - Fengyun Pian (China) (Unl)" + rom ( name "Shi Mian Maifu - Fengyun Pian (China) (Unl).gbc" size 1048576 crc a5f686c3 sha1 68798ac090df9f5fb1ea9c409adf3dc639bc9842 ) +) + +game ( + name "Shi Mian Maifu - Tianlong Pian (China) (Unl)" + description "Shi Mian Maifu - Tianlong Pian (China) (Unl)" + rom ( name "Shi Mian Maifu - Tianlong Pian (China) (Unl).gbc" size 1048576 crc 605cd86e sha1 b457bafb6b55a82920743d52284918ac74f35852 ) +) + +game ( + name "Shi Mian Maifu - Yingxiong Pian (China) (Unl)" + description "Shi Mian Maifu - Yingxiong Pian (China) (Unl)" + rom ( name "Shi Mian Maifu - Yingxiong Pian (China) (Unl).gbc" size 1048576 crc 2382b3d7 sha1 72077d32c2ab84b6bb1e4ad59bc8c88dbcf1da77 ) ) game ( @@ -42972,7 +44807,7 @@ game ( game ( name "Shin Megami Tensei Devil Children - Aka no Sho (Japan) (SGB Enhanced) (GB Compatible)" description "Shin Megami Tensei Devil Children - Aka no Sho (Japan) (SGB Enhanced) (GB Compatible)" - rom ( name "Shin Megami Tensei Devil Children - Aka no Sho (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc f90c4977 sha1 b15cbd01a21048d0fd022f0e023ab5d91faaf442 ) + rom ( name "Shin Megami Tensei Devil Children - Aka no Sho (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc f90c4977 sha1 b15cbd01a21048d0fd022f0e023ab5d91faaf442 flags verified ) ) game ( @@ -43026,7 +44861,7 @@ game ( game ( name "Shougi 2 (Japan) (GB Compatible)" description "Shougi 2 (Japan) (GB Compatible)" - rom ( name "Shougi 2 (Japan) (GB Compatible).gbc" size 262144 crc a7748d2b sha1 7c89cebc4dfcf8713c94b0553e4f4d4f8945052f ) + rom ( name "Shougi 2 (Japan) (GB Compatible).gbc" size 262144 crc a7748d2b sha1 7c89cebc4dfcf8713c94b0553e4f4d4f8945052f flags verified ) ) game ( @@ -43126,9 +44961,33 @@ game ( ) game ( - name "Shuma Baolong 02 4 (Taiwan) (Zh) (Unl)" - description "Shuma Baolong 02 4 (Taiwan) (Zh) (Unl)" - rom ( name "Shuma Baolong 02 4 (Taiwan) (Zh) (Unl).gbc" size 1048576 crc 2ee18ab2 sha1 839f0880749735ba2113e437f8efede171b7474d ) + name "Shuma Baolong 02 4 (Taiwan) (Unl)" + description "Shuma Baolong 02 4 (Taiwan) (Unl)" + rom ( name "Shuma Baolong 02 4 (Taiwan) (Unl).gbc" size 1048576 crc 2ee18ab2 sha1 839f0880749735ba2113e437f8efede171b7474d ) +) + +game ( + name "Shuma Baolong 02 4 (China) (Unl)" + description "Shuma Baolong 02 4 (China) (Unl)" + rom ( name "Shuma Baolong 02 4 (China) (Unl).gbc" size 1048576 crc 6f67dfc6 sha1 5c5d1675188a5f618f9babf2b3848942ce08c659 ) +) + +game ( + name "Shuma Baolong 02 5 (Taiwan) (Unl)" + description "Shuma Baolong 02 5 (Taiwan) (Unl)" + rom ( name "Shuma Baolong 02 5 (Taiwan) (Unl).gbc" size 1048576 crc 5ba9f8b5 sha1 c441fcbdb343e0c3c76803aa55ceb728158a8948 ) +) + +game ( + name "Shuma Baolong 2 (China) (Unl)" + description "Shuma Baolong 2 (China) (Unl)" + rom ( name "Shuma Baolong 2 (China) (Unl).gbc" size 1048576 crc acbfc58f sha1 76b1eccf666ea01320134d88d6f7558c24016ca8 ) +) + +game ( + name "Shuma Baolong 3 (China) (Unl)" + description "Shuma Baolong 3 (China) (Unl)" + rom ( name "Shuma Baolong 3 (China) (Unl).gbc" size 1048576 crc dab66d8c sha1 3902ecd4b233d0dff168a285788843de0b6df05e ) ) game ( @@ -43155,18 +45014,6 @@ game ( rom ( name "Simpsons, The - Night of the Living Treehouse of Horror (USA, Europe).gbc" size 1048576 crc ebaf4888 sha1 a5be079336e48552e53706f0380f35829d91b3c0 ) ) -game ( - name "Skelby (World) (Aftermarket) (Unl)" - description "Skelby (World) (Aftermarket) (Unl)" - rom ( name "Skelby (World) (Aftermarket) (Unl).gbc" size 524288 crc 6ec6c18c sha1 887555aa7e2e61b68a21020237b7d508bb71aded ) -) - -game ( - name "Skycon (World) (Aftermarket) (Unl)" - description "Skycon (World) (Aftermarket) (Unl)" - rom ( name "Skycon (World) (Aftermarket) (Unl).gbc" size 524288 crc 195dbc30 sha1 df29ece6c5f5b14840663495230135dd79c5163a ) -) - game ( name "Smurfs Nightmare, The (Europe) (En,Fr,De,Es)" description "Smurfs Nightmare, The (Europe) (En,Fr,De,Es)" @@ -43386,7 +45233,7 @@ game ( game ( name "Spider-Man 2 - The Sinister Six (USA, Europe)" description "Spider-Man 2 - The Sinister Six (USA, Europe)" - rom ( name "Spider-Man 2 - The Sinister Six (USA, Europe).gbc" size 1048576 crc a7faaccf sha1 22c63fa198df68edb9cbe22e35cbd307174c9eb9 ) + rom ( name "Spider-Man 2 - The Sinister Six (USA, Europe).gbc" size 1048576 crc a7faaccf sha1 22c63fa198df68edb9cbe22e35cbd307174c9eb9 flags verified ) ) game ( @@ -43395,12 +45242,6 @@ game ( rom ( name "Spider-Man 3 - Movie Version (USA) (Unl).gbc" size 2097152 crc 2c0d43a9 sha1 8a6b6a1300db59b86ddf87599cfc8edd2e52e2b0 ) ) -game ( - name "Spiky Harold (World) (Aftermarket) (Unl)" - description "Spiky Harold (World) (Aftermarket) (Unl)" - rom ( name "Spiky Harold (World) (Aftermarket) (Unl).gbc" size 262144 crc 7e9eda35 sha1 486d294b8cf226876581d543e3a08018321bc402 ) -) - game ( name "Spirou - The Robot Invasion (Europe) (En,Fr,De,Es,It,Nl,Da)" description "Spirou - The Robot Invasion (Europe) (En,Fr,De,Es,It,Nl,Da)" @@ -43503,12 +45344,6 @@ game ( rom ( name "Startled 911 (Taiwan) (En) (Unl).gbc" size 2097152 crc 7273a4f4 sha1 14154ba420826a406890079d7cc0b420a042e34f ) ) -game ( - name "Stellar Wars (World) (Aftermarket) (Unl)" - description "Stellar Wars (World) (Aftermarket) (Unl)" - rom ( name "Stellar Wars (World) (Aftermarket) (Unl).gbc" size 262144 crc e0b96256 sha1 ba2d10a2a5f3f073aea11e26ae5c53c9cf7866f8 ) -) - game ( name "Stranded Kids (Europe) (En,Fr,De) (SGB Enhanced) (GB Compatible)" description "Stranded Kids (Europe) (En,Fr,De) (SGB Enhanced) (GB Compatible)" @@ -43557,18 +45392,18 @@ game ( rom ( name "Stuart Little - The Journey Home (USA, Europe).gbc" size 1048576 crc eb273887 sha1 d3c31e41709c54af328787036db1b98997f508ea ) ) -game ( - name "Suicide Run (World) (GB Compatible) (Aftermarket) (Unl)" - description "Suicide Run (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Suicide Run (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 2dc3fdae sha1 a551d904c4af661bd4b6e88063cb5541900117b0 ) -) - game ( name "Super 16 in 1 (Taiwan) (En) (Sachen) (Unl)" description "Super 16 in 1 (Taiwan) (En) (Sachen) (Unl)" rom ( name "Super 16 in 1 (Taiwan) (En) (Sachen) (Unl).gbc" size 2097152 crc 6a99a079 sha1 bcb683600278094e4d40a7da0226b83ec1f92c81 ) ) +game ( + name "Super 21 in 1 - New GB Rumble (Taiwan) (Unl)" + description "Super 21 in 1 - New GB Rumble (Taiwan) (Unl)" + rom ( name "Super 21 in 1 - New GB Rumble (Taiwan) (Unl).gbc" size 2097152 crc 21746216 sha1 829cc0fcd4b96cf5cac909a7c0697583f4c62241 ) +) + game ( name "Super 6 in 1 (Taiwan) (En,Zh) (6B-001, Sachen) (Unl)" description "Super 6 in 1 (Taiwan) (En,Zh) (6B-001, Sachen) (Unl)" @@ -43611,6 +45446,12 @@ game ( rom ( name "Super Chinese Fighter EX (Japan).gbc" size 1048576 crc dcdaa333 sha1 0296d0a60933c798b21399195789d10eb319872f ) ) +game ( + name "Super Color 26-in-1 (Taiwan) (Unl)" + description "Super Color 26-in-1 (Taiwan) (Unl)" + rom ( name "Super Color 26-in-1 (Taiwan) (Unl).gbc" size 4194304 crc 71e9a5d9 sha1 0f8657e4583389a23d61d8d0bd7fe322bcaabf6b ) +) + game ( name "Super Doll Licca-chan - Kisekae Daisakusen (Japan)" description "Super Doll Licca-chan - Kisekae Daisakusen (Japan)" @@ -43620,7 +45461,7 @@ game ( game ( name "Super Donkey Kong 5 (Taiwan) (En) (Rumble Version) (Unl)" description "Super Donkey Kong 5 (Taiwan) (En) (Rumble Version) (Unl)" - rom ( name "Super Donkey Kong 5 (Taiwan) (En) (Rumble Version) (Unl).gbc" size 524288 crc d44c9806 sha1 c761dca73b520711b3205e11091e2bf8d4fd7549 ) + rom ( name "Super Donkey Kong 5 (Taiwan) (En) (Rumble Version) (Unl).gbc" size 524288 crc d44c9806 sha1 c761dca73b520711b3205e11091e2bf8d4fd7549 flags verified ) ) game ( @@ -43635,6 +45476,12 @@ game ( rom ( name "Super Fighters 99 (Taiwan) (SGB Enhanced) (Unl).gbc" size 2097152 crc ce41b1bb sha1 e5af8afdce844f02c4128748067933840a759773 ) ) +game ( + name "Super Fighters S (Taiwan) (GB Compatible) (Unl)" + description "Super Fighters S (Taiwan) (GB Compatible) (Unl)" + rom ( name "Super Fighters S (Taiwan) (GB Compatible) (Unl).gbc" size 2097152 crc 64db799a sha1 ef0bf0feaf9e2bdfb10acd469e915266655adb43 ) +) + game ( name "Super Gals! Kotobuki Ran (Japan)" description "Super Gals! Kotobuki Ran (Japan)" @@ -43647,24 +45494,6 @@ game ( rom ( name "Super Gals! Kotobuki Ran 2 - Miracle Getting (Japan).gbc" size 4194304 crc e77fa0f2 sha1 a724c6dd33b84ae9120d041fc49d66692c798dd0 ) ) -game ( - name "Super Gran (World) (Aftermarket) (Unl)" - description "Super Gran (World) (Aftermarket) (Unl)" - rom ( name "Super Gran (World) (Aftermarket) (Unl).gbc" size 262144 crc 98ee2e8a sha1 5afe9c7ab1b9d86048a570e7a37a0c244cb84e43 ) -) - -game ( - name "Super Jacked Up Tomato Face Johnson (World) (Aftermarket) (Unl)" - description "Super Jacked Up Tomato Face Johnson (World) (Aftermarket) (Unl)" - rom ( name "Super Jacked Up Tomato Face Johnson (World) (Aftermarket) (Unl).gbc" size 524288 crc 87956ddf sha1 b23320d5d3fde2a55b301f7bea324833c31c32d5 ) -) - -game ( - name "Super JetPak DX (World) (GB Compatible) (Aftermarket)" - description "Super JetPak DX (World) (GB Compatible) (Aftermarket)" - rom ( name "Super JetPak DX (World) (GB Compatible) (Aftermarket).gbc" size 131072 crc 22def6f9 sha1 e7438db01fbbdeea2404dbf3d093370421ec4e1c ) -) - game ( name "Super Mario Bros. Deluxe (Japan) (NP)" description "Super Mario Bros. Deluxe (Japan) (NP)" @@ -43917,6 +45746,12 @@ game ( rom ( name "Taikong Zhanshi DX3 - Zuizhong Huanxiang (Taiwan) (Unl).gbc" size 2097152 crc ddf36a27 sha1 0a62b484c5730a3a1f8b32cc2ed97af128d2130c ) ) +game ( + name "Taikong Zhanshi X - Fantasy War (Taiwan) (Unl)" + description "Taikong Zhanshi X - Fantasy War (Taiwan) (Unl)" + rom ( name "Taikong Zhanshi X - Fantasy War (Taiwan) (Unl).gbc" size 1048576 crc 09fedecc sha1 c4fd2de9cf8d75de069abadf165252dac5712691 ) +) + game ( name "Taisen Tsume Shougi (Japan) (NP) (GB Compatible)" description "Taisen Tsume Shougi (Japan) (NP) (GB Compatible)" @@ -43938,7 +45773,7 @@ game ( game ( name "Tales of Phantasia - Narikiri Dungeon (Japan) (SGB Enhanced) (GB Compatible)" description "Tales of Phantasia - Narikiri Dungeon (Japan) (SGB Enhanced) (GB Compatible)" - rom ( name "Tales of Phantasia - Narikiri Dungeon (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 725cf31c sha1 ef322f4160ceebd8da67758ebd73225190af6d23 ) + rom ( name "Tales of Phantasia - Narikiri Dungeon (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc 725cf31c sha1 ef322f4160ceebd8da67758ebd73225190af6d23 flags verified ) ) game ( @@ -43947,12 +45782,6 @@ game ( rom ( name "Tanimura Hitoshi Ryuu Pachinko Kouryaku Daisakusen - Don Quijote ga Iku (Japan) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc ce8ae58c sha1 f752e96602274a29006425a06086d8ab45e1075c ) ) -game ( - name "Tank Attack (World) (Aftermarket) (Unl)" - description "Tank Attack (World) (Aftermarket) (Unl)" - rom ( name "Tank Attack (World) (Aftermarket) (Unl).gbc" size 262144 crc c77dc518 sha1 4751a6999f4dbe7e66b997372588f6bd15e4d9d0 ) -) - game ( name "Tarzan (France)" description "Tarzan (France)" @@ -44007,18 +45836,6 @@ game ( rom ( name "Taxi 3 (France).gbc" size 1048576 crc 2838996f sha1 e43817c673d47b7587f542dcc9f74190c63629ff ) ) -game ( - name "Tazz (World) (2022-10-14) (Aftermarket) (Unl)" - description "Tazz (World) (2022-10-14) (Aftermarket) (Unl)" - rom ( name "Tazz (World) (2022-10-14) (Aftermarket) (Unl).gbc" size 262144 crc 1d97b754 sha1 39226ed715ae8d94f9187c3e5e8a849eac92ca26 ) -) - -game ( - name "Tazz (World) (2022-10-18) (Aftermarket) (Unl)" - description "Tazz (World) (2022-10-18) (Aftermarket) (Unl)" - rom ( name "Tazz (World) (2022-10-18) (Aftermarket) (Unl).gbc" size 262144 crc 6fb0ba23 sha1 543118e54b166ea2b8b5979f8468cc2f5662161f ) -) - game ( name "Tech Deck Skateboarding (USA, Europe)" description "Tech Deck Skateboarding (USA, Europe)" @@ -44110,9 +45927,9 @@ game ( ) game ( - name "Tezhong Budui (Taiwan) (Unl) (Alt)" - description "Tezhong Budui (Taiwan) (Unl) (Alt)" - rom ( name "Tezhong Budui (Taiwan) (Unl) (Alt).gbc" size 1048576 crc bf0028d9 sha1 99f536400bb99892b736f66305e1b11d8229c668 ) + name "Tezhong Budui (Taiwan) (Unl) (Alt) [b]" + description "Tezhong Budui (Taiwan) (Unl) (Alt) [b]" + rom ( name "Tezhong Budui (Taiwan) (Unl) (Alt) [b].gbc" size 1048576 crc bf0028d9 sha1 99f536400bb99892b736f66305e1b11d8229c668 flags baddump ) ) game ( @@ -44199,12 +46016,6 @@ game ( rom ( name "Tiny Toon Adventures - Dizzy's Candy Quest (USA) (Proto).gbc" size 1048576 crc 23bb87a5 sha1 4eb0359a278173ae6c12e9452a7a2a9573a58c77 ) ) -game ( - name "Tir Na Nog (World) (Aftermarket) (Unl)" - description "Tir Na Nog (World) (Aftermarket) (Unl)" - rom ( name "Tir Na Nog (World) (Aftermarket) (Unl).gbc" size 1048576 crc 44524c90 sha1 ac712228460e9d4268f90ec4cf9ac2137fa667c4 ) -) - game ( name "Titi - Le Tour du Monde en 80 Chats (France)" description "Titi - Le Tour du Monde en 80 Chats (France)" @@ -44229,12 +46040,6 @@ game ( rom ( name "TNN Outdoors Fishing Champ (USA) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 00a14d18 sha1 acfe7c9edd20f7d6b155deebc9428703edf28978 ) ) -game ( - name "Tobu Tobu Girl Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" - description "Tobu Tobu Girl Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Tobu Tobu Girl Deluxe (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 16650a8b sha1 fe6eef70d48dda741f7ad3b6cc5e753e8cd13239 ) -) - game ( name "TOCA Touring Car Championship (USA, Europe)" description "TOCA Touring Car Championship (USA, Europe)" @@ -44310,7 +46115,7 @@ game ( game ( name "Tom Clancy's Rainbow Six (USA, Europe) (En,Fr,De)" description "Tom Clancy's Rainbow Six (USA, Europe) (En,Fr,De)" - rom ( name "Tom Clancy's Rainbow Six (USA, Europe) (En,Fr,De).gbc" size 1048576 crc e72f2683 sha1 7e9e21db84d1bfdab3c604c9e3328f624f86a9b1 ) + rom ( name "Tom Clancy's Rainbow Six (USA, Europe) (En,Fr,De).gbc" size 1048576 crc e72f2683 sha1 7e9e21db84d1bfdab3c604c9e3328f624f86a9b1 flags verified ) ) game ( @@ -44376,7 +46181,7 @@ game ( game ( name "Tonka Raceway (USA) (Rumble Version)" description "Tonka Raceway (USA) (Rumble Version)" - rom ( name "Tonka Raceway (USA) (Rumble Version).gbc" size 1048576 crc a5af4b28 sha1 6a86b7172c53a8e67f3d72f953116991640f6e71 ) + rom ( name "Tonka Raceway (USA) (Rumble Version).gbc" size 1048576 crc a5af4b28 sha1 6a86b7172c53a8e67f3d72f953116991640f6e71 flags verified ) ) game ( @@ -44511,12 +46316,6 @@ game ( rom ( name "Tottoko Hamutarou 2 - Hamu-chan Zu Daishuugou Dechu (Japan).gbc" size 2097152 crc f1fbcf84 sha1 adb1d5242a62d41c6e435b31082685ea4eec651a flags verified ) ) -game ( - name "Tower of Evil (World) (Aftermarket) (Unl)" - description "Tower of Evil (World) (Aftermarket) (Unl)" - rom ( name "Tower of Evil (World) (Aftermarket) (Unl).gbc" size 524288 crc aeb6e36f sha1 e9a6a007e935afb522c67d355e0354b0fb9af3c6 ) -) - game ( name "Towers - Lord Baniff's Deceit (USA, Europe)" description "Towers - Lord Baniff's Deceit (USA, Europe)" @@ -44571,12 +46370,6 @@ game ( rom ( name "Trade & Battle Card Hero (Japan) (Rev 1) (3DS Virtual Console) (SGB Enhanced) (GB Compatible).gbc" size 2097152 crc d98a877d sha1 c6c1e0365166b53d25a1f84bc380948a9661df30 ) ) -game ( - name "Treasure Island Color (World) (Aftermarket) (Unl)" - description "Treasure Island Color (World) (Aftermarket) (Unl)" - rom ( name "Treasure Island Color (World) (Aftermarket) (Unl).gbc" size 262144 crc 4ab0eb5a sha1 3ebddd4e1f5b3a87726ef34a5b7d36de8c722f36 ) -) - game ( name "Trick Boarder (Europe)" description "Trick Boarder (Europe)" @@ -44595,6 +46388,12 @@ game ( rom ( name "Trickboarder GP (Japan).gbc" size 1048576 crc 31740097 sha1 263d8612ecdf651115df6f896737b8c498c970c0 ) ) +game ( + name "Trip World DX (World) (Limited Run Games)" + description "Trip World DX (World) (Limited Run Games)" + rom ( name "Trip World DX (World) (Limited Run Games).gbc" size 524288 crc af17b3eb sha1 6871dd15e2081432ab4c7727f88491f7bbd95099 flags verified ) +) + game ( name "Triple Play 2001 (USA, Europe)" description "Triple Play 2001 (USA, Europe)" @@ -44661,12 +46460,6 @@ game ( rom ( name "Turok 3 - Shadow of Oblivion (USA, Europe) (En,Fr,De,Es).gbc" size 1048576 crc 6d48765e sha1 4b240f6b8e3648f2cbafa2fd6ee4e5b508950122 flags verified ) ) -game ( - name "Tutti Frutti (World) (Aftermarket) (Unl)" - description "Tutti Frutti (World) (Aftermarket) (Unl)" - rom ( name "Tutti Frutti (World) (Aftermarket) (Unl).gbc" size 262144 crc ca377ca6 sha1 53d97b93b9d190de40ed2d81e18b4cbe44f99a23 ) -) - game ( name "Tutty (Europe) (Demo)" description "Tutty (Europe) (Demo)" @@ -44709,24 +46502,12 @@ game ( rom ( name "Tweety's High-Flying Adventure (USA).gbc" size 1048576 crc 4e226396 sha1 9702aeea4a92625d2c19aa7f606b589cb7531613 ) ) -game ( - name "Tycoon Tex (World) (Aftermarket) (Unl)" - description "Tycoon Tex (World) (Aftermarket) (Unl)" - rom ( name "Tycoon Tex (World) (Aftermarket) (Unl).gbc" size 262144 crc fa8436ba sha1 d37bcd93d647ac7efb761c539785a4ef570cdcc8 ) -) - game ( name "Tyrannosaurus Tex (USA) (Proto)" description "Tyrannosaurus Tex (USA) (Proto)" rom ( name "Tyrannosaurus Tex (USA) (Proto).gbc" size 2097152 crc 1bd4e588 sha1 e2fcc7fcc643f9d7fc61acce6c5ed1f8abc13fa0 ) ) -game ( - name "Tyrannosaurus Tex (World) (Aftermarket) (Unl)" - description "Tyrannosaurus Tex (World) (Aftermarket) (Unl)" - rom ( name "Tyrannosaurus Tex (World) (Aftermarket) (Unl).gbc" size 2097152 crc e90504c1 sha1 7e41e92f92ff06101e48dee758420f1bd3959013 ) -) - game ( name "Tyrian 2000 (USA) (Proto) (GB Compatible)" description "Tyrian 2000 (USA) (Proto) (GB Compatible)" @@ -44793,12 +46574,6 @@ game ( rom ( name "Uno (USA) (GB Compatible).gbc" size 1048576 crc f026d509 sha1 20868148461618d1195570775b183a065781ce35 ) ) -game ( - name "UXB (World) (Aftermarket) (Unl)" - description "UXB (World) (Aftermarket) (Unl)" - rom ( name "UXB (World) (Aftermarket) (Unl).gbc" size 262144 crc dd42be4c sha1 6ef7abb689b1c75f613ed253644fbb0f377b7a95 ) -) - game ( name "V-Rally - Championship Edition (Europe) (En,Fr,De,Es)" description "V-Rally - Championship Edition (Europe) (En,Fr,De,Es)" @@ -44817,12 +46592,6 @@ game ( rom ( name "V-Rally - Edition 99 (USA) (En,Fr,Es).gbc" size 1048576 crc da300c6c sha1 638266c9d2d16486c2ed00510176112071b05e2c ) ) -game ( - name "Varmit (World) (Aftermarket) (Unl)" - description "Varmit (World) (Aftermarket) (Unl)" - rom ( name "Varmit (World) (Aftermarket) (Unl).gbc" size 2097152 crc e4827006 sha1 b61876c714c47f62a77304b79f6e34b8d0e7f8a2 ) -) - game ( name "Vegas Games (Europe) (En,Fr,De)" description "Vegas Games (Europe) (En,Fr,De)" @@ -44865,24 +46634,12 @@ game ( rom ( name "Visiteurs, Les (France) (GB Compatible).gbc" size 1048576 crc d843f898 sha1 307b5d80fd7def049d446bf3406ec8d57dfee93d ) ) -game ( - name "VOX (World) (Aftermarket) (Unl)" - description "VOX (World) (Aftermarket) (Unl)" - rom ( name "VOX (World) (Aftermarket) (Unl).gbc" size 262144 crc 346561fb sha1 54a03c77653a19eb1b0d8a6ac82f498f83f35ef2 ) -) - game ( name "VR Sports - Powerboat Racing (USA) (Proto)" description "VR Sports - Powerboat Racing (USA) (Proto)" rom ( name "VR Sports - Powerboat Racing (USA) (Proto).gbc" size 1048576 crc cff671f1 sha1 1c77f032cdd373bfa108ea82c463f8f9f6874c71 ) ) -game ( - name "Wacky Painter (World) (Aftermarket) (Unl)" - description "Wacky Painter (World) (Aftermarket) (Unl)" - rom ( name "Wacky Painter (World) (Aftermarket) (Unl).gbc" size 262144 crc 09daa18d sha1 5425dc675101d63bea03b1c8f46f86fe200ad392 ) -) - game ( name "Wacky Races (Europe) (En,Fr,De,Es,It,Nl)" description "Wacky Races (Europe) (En,Fr,De,Es,It,Nl)" @@ -44991,24 +46748,6 @@ game ( rom ( name "Watashi no Restaurant (Japan) (Beta 3).gbc" size 1048576 crc a0ed2859 sha1 343bf8ebb6fa3ce89501f7c4c219fb7e864c38a3 ) ) -game ( - name "Waternet (World) (GB Compatible) (Aftermarket) (Unl)" - description "Waternet (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Waternet (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc ef202121 sha1 a11f931b18ba42f48a91e817b7117fa0e3e79518 ) -) - -game ( - name "Waternet (World) (Batteryless Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl)" - description "Waternet (World) (Batteryless Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Waternet (World) (Batteryless Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 75591760 sha1 e04b01ada17e6924503029cd09a107b7f5d06f17 ) -) - -game ( - name "Waternet (World) (Batteryless Generic Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl)" - description "Waternet (World) (Batteryless Generic Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Waternet (World) (Batteryless Generic Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc f8402dc5 sha1 6feb4178589e87c6267683078201f0630cca23d6 ) -) - game ( name "WCW Mayhem (USA, Europe)" description "WCW Mayhem (USA, Europe)" @@ -45057,12 +46796,6 @@ game ( rom ( name "Wetrix GB (Japan) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc 6215c5b3 sha1 92944052b6e4448abf0103f085998662e0140825 ) ) -game ( - name "Where's My Cake (World) (GB Compatible) (Aftermarket) (Unl)" - description "Where's My Cake (World) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Where's My Cake (World) (GB Compatible) (Aftermarket) (Unl).GBC" size 65536 crc 28114b89 sha1 05b90f0a7e92d42b3008c749d5edeab2a2eae973 ) -) - game ( name "Who Wants to Be a Millionaire - 2nd Edition (USA)" description "Who Wants to Be a Millionaire - 2nd Edition (USA)" @@ -45075,12 +46808,6 @@ game ( rom ( name "Wild Thornberrys, The - Rambler (USA).gbc" size 1048576 crc 0e1465cb sha1 0e806f0e6c1a41e764683850a3c15a80ac7fc9a5 ) ) -game ( - name "Wing Warriors (World) (En,Fr,Es) (GB Compatible) (Aftermarket) (Unl)" - description "Wing Warriors (World) (En,Fr,Es) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Wing Warriors (World) (En,Fr,Es) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 7328cfb6 sha1 039874148f27ffe533de4ef086f29e724a3217a9 ) -) - game ( name "Wings of Fury (Europe) (En,Fr,De) (GB Compatible)" description "Wings of Fury (Europe) (En,Fr,De) (GB Compatible)" @@ -45102,13 +46829,7 @@ game ( game ( name "Winnie the Pooh - Adventures in the 100 Acre Wood (USA)" description "Winnie the Pooh - Adventures in the 100 Acre Wood (USA)" - rom ( name "Winnie the Pooh - Adventures in the 100 Acre Wood (USA).gbc" size 2097152 crc 066a2196 sha1 5ff68bc5ec735d090b24aab79a787f77f26afb08 ) -) - -game ( - name "Wizard of Wor (World) (Aftermarket) (Unl)" - description "Wizard of Wor (World) (Aftermarket) (Unl)" - rom ( name "Wizard of Wor (World) (Aftermarket) (Unl).gbc" size 524288 crc 492a9529 sha1 a391646d259a39e7026574145e0a2bacf5f6937b ) + rom ( name "Winnie the Pooh - Adventures in the 100 Acre Wood (USA).gbc" size 2097152 crc 066a2196 sha1 5ff68bc5ec735d090b24aab79a787f77f26afb08 flags verified ) ) game ( @@ -45177,12 +46898,6 @@ game ( rom ( name "Woody Woodpecker Racing (USA).gbc" size 1048576 crc 0424cf43 sha1 be98d0a54aedcf59cddc111c72db66105aea1375 ) ) -game ( - name "World Cup (World) (Aftermarket) (Unl)" - description "World Cup (World) (Aftermarket) (Unl)" - rom ( name "World Cup (World) (Aftermarket) (Unl).gbc" size 262144 crc 56b3ab5f sha1 075890510b3ef205ca50ebbbcf7c0a0c56032cb9 ) -) - game ( name "World Soccer GB 2 (Japan) (SGB Enhanced) (GB Compatible)" description "World Soccer GB 2 (Japan) (SGB Enhanced) (GB Compatible)" @@ -45213,10 +46928,16 @@ game ( rom ( name "Worms Armageddon (Europe) (Beta).gbc" size 1048576 crc 66fda365 sha1 b0b14b13ec7cffb04efbf0dcdd93a2eea679ea0c ) ) +game ( + name "Worms Armageddon (World) (Limited Run Games)" + description "Worms Armageddon (World) (Limited Run Games)" + rom ( name "Worms Armageddon (World) (Limited Run Games).gbc" size 1048576 crc 626dfadb sha1 5fce1d1b6a7cfa994808d473602f569537dc0231 ) +) + game ( name "WWF Attitude (USA, Europe)" description "WWF Attitude (USA, Europe)" - rom ( name "WWF Attitude (USA, Europe).gbc" size 1048576 crc d5fdf68a sha1 d5c37eabe3311666123b22f44a973c06d96bfce0 ) + rom ( name "WWF Attitude (USA, Europe).gbc" size 1048576 crc d5fdf68a sha1 d5c37eabe3311666123b22f44a973c06d96bfce0 flags verified ) ) game ( @@ -45285,6 +47006,12 @@ game ( rom ( name "Xiao Taiji - Shenhua Lixian (Taiwan) (Unl).gbc" size 2097152 crc 322c3816 sha1 c89f8d19a52ab5f183a03d65680bf80d1af4a0ee ) ) +game ( + name "Xin Fengkuang A Gei Pao Pao Tang (Taiwan) (Unl)" + description "Xin Fengkuang A Gei Pao Pao Tang (Taiwan) (Unl)" + rom ( name "Xin Fengkuang A Gei Pao Pao Tang (Taiwan) (Unl).gbc" size 2097152 crc e40f757f sha1 6d1332456e10e9da78726415640117262fe53e99 ) +) + game ( name "Xin Fengshenbang (Taiwan) (Unl)" description "Xin Fengshenbang (Taiwan) (Unl)" @@ -45303,6 +47030,12 @@ game ( rom ( name "Xin Shediao Yingxiong Chuan (Taiwan) (Unl).gbc" size 1048576 crc 20e40d8f sha1 a11aa648810f3e69d3678d2c53137575bfbd34d6 ) ) +game ( + name "Xin Shiqi Shidai (Taiwan) (Unl)" + description "Xin Shiqi Shidai (Taiwan) (Unl)" + rom ( name "Xin Shiqi Shidai (Taiwan) (Unl).gbc" size 2097152 crc f55342ca sha1 d51300e59c67f88dd2281ca53ae7c035489a723c ) +) + game ( name "Xingqiu Dazhan II - Kelong Ren Zhanyi (Taiwan) (Unl)" description "Xingqiu Dazhan II - Kelong Ren Zhanyi (Taiwan) (Unl)" @@ -45339,6 +47072,18 @@ game ( rom ( name "Xtreme Sports (USA).gbc" size 4194304 crc 19828751 sha1 ffca13207e6284a3cc16f7f130b68fca87663d08 ) ) +game ( + name "Xtreme Sports (World) (Switch)" + description "Xtreme Sports (World) (Switch)" + rom ( name "Xtreme Sports (World) (Switch).gbc" size 4194304 crc c0437e08 sha1 5da3ad1c5354f29a74c571c2b598da96213afbe1 flags verified ) +) + +game ( + name "Xtreme Sports (World) (Limited Run Games)" + description "Xtreme Sports (World) (Limited Run Games)" + rom ( name "Xtreme Sports (World) (Limited Run Games).gbc" size 4194304 crc b8a3ecdd sha1 7ec1e0e88f4827c421dc91cff03ad7932bd652f5 ) +) + game ( name "Xtreme Wheels (Europe)" description "Xtreme Wheels (Europe)" @@ -45369,18 +47114,18 @@ game ( rom ( name "Yars' Revenge (USA, Europe) (GB Compatible).gbc" size 1048576 crc d6a26444 sha1 45fb176d539ae4a65af1f6340a9bd398dd7956d2 ) ) -game ( - name "Year After, The (World) (En,Fr,Pt) (GB Compatible) (Aftermarket) (Unl)" - description "Year After, The (World) (En,Fr,Pt) (GB Compatible) (Aftermarket) (Unl)" - rom ( name "Year After, The (World) (En,Fr,Pt) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc b304833d sha1 c2be46b8230bfcf509d031902c9bf144de97ef58 ) -) - game ( name "Yin Ban Zhongwen RPG Zhanlve + Dongzuo + Yizhi 12 in 1 (Taiwan) (Unl)" description "Yin Ban Zhongwen RPG Zhanlve + Dongzuo + Yizhi 12 in 1 (Taiwan) (Unl)" rom ( name "Yin Ban Zhongwen RPG Zhanlve + Dongzuo + Yizhi 12 in 1 (Taiwan) (Unl).gbc" size 8388608 crc dc3171ad sha1 bfb93e7b4b523ef21c2b98ba9dcb15eb7d4f07e4 ) ) +game ( + name "Yinghan Zidian (Taiwan) (Unl)" + description "Yinghan Zidian (Taiwan) (Unl)" + rom ( name "Yinghan Zidian (Taiwan) (Unl).gbc" size 1048576 crc 87158db6 sha1 5d42f3b769176df569a99c167c67e685c70501e1 ) +) + game ( name "Yingxiong Jian 2 (Taiwan) (Unl)" description "Yingxiong Jian 2 (Taiwan) (Unl)" @@ -45393,6 +47138,12 @@ game ( rom ( name "Yingxiong Tianxia (Taiwan) (Zh) (Unl).gbc" size 2097152 crc 5f2d6317 sha1 41f5f0c11e4e99b7d2d1433b09922a0fd2c48d7f ) ) +game ( + name "Yinyang (Taiwan) (De) (Unl)" + description "Yinyang (Taiwan) (De) (Unl)" + rom ( name "Yinyang (Taiwan) (De) (Unl).gbc" size 2097152 crc 1dd042ab sha1 2da9f06d57dcd397d0333b5d85a26a593acea8b3 ) +) + game ( name "Yixing VS Tiexue Zhanshi (Taiwan) (Unl)" description "Yixing VS Tiexue Zhanshi (Taiwan) (Unl)" @@ -45513,22 +47264,10 @@ game ( rom ( name "Yuenan Zhanyi X - Shenru Dihou (Taiwan) (Unl).gbc" size 2097152 crc 602951a6 sha1 6703e9f68b989c976e93bd2eb63f884ceaff63f1 ) ) -game ( - name "Zagan Warrior (World) (Aftermarket) (Unl)" - description "Zagan Warrior (World) (Aftermarket) (Unl)" - rom ( name "Zagan Warrior (World) (Aftermarket) (Unl).gbc" size 262144 crc e770f71a sha1 99d9267946e7bf26942a8276863ba50ef0b8f90e ) -) - -game ( - name "Zap'em (World) (Aftermarket) (Unl)" - description "Zap'em (World) (Aftermarket) (Unl)" - rom ( name "Zap'em (World) (Aftermarket) (Unl).gbc" size 262144 crc 66f17c5e sha1 63d44c8c2492dc32bcf632feb2d994e9af25fc97 ) -) - game ( name "Zebco Fishing! (USA) (Rumble Version)" description "Zebco Fishing! (USA) (Rumble Version)" - rom ( name "Zebco Fishing! (USA) (Rumble Version).gbc" size 1048576 crc 3cc6b1f9 sha1 9b6c536b403c62af102e3800658c9dec258be249 ) + rom ( name "Zebco Fishing! (USA) (Rumble Version).gbc" size 1048576 crc 3cc6b1f9 sha1 9b6c536b403c62af102e3800658c9dec258be249 flags verified ) ) game ( @@ -45540,7 +47279,7 @@ game ( game ( name "Zelda no Densetsu - Fushigi no Kinomi - Jikuu no Shou (Japan)" description "Zelda no Densetsu - Fushigi no Kinomi - Jikuu no Shou (Japan)" - rom ( name "Zelda no Densetsu - Fushigi no Kinomi - Jikuu no Shou (Japan).gbc" size 1048576 crc 3272e6f9 sha1 596aa066ccee9fae71643576f7526baa22d26d6d ) + rom ( name "Zelda no Densetsu - Fushigi no Kinomi - Jikuu no Shou (Japan).gbc" size 1048576 crc 3272e6f9 sha1 596aa066ccee9fae71643576f7526baa22d26d6d flags verified ) ) game ( @@ -45552,7 +47291,7 @@ game ( game ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (SGB Enhanced) (GB Compatible)" description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (SGB Enhanced) (GB Compatible)" - rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc bd8a1041 sha1 d3de302d44bdb240bcf55a5dc70f491f5456d721 ) + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (SGB Enhanced) (GB Compatible).gbc" size 1048576 crc bd8a1041 sha1 d3de302d44bdb240bcf55a5dc70f491f5456d721 flags verified ) ) game ( @@ -45568,15 +47307,15 @@ game ( ) game ( - name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05 18.00.56) (GB Compatible)" - description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05 18.00.56) (GB Compatible)" - rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05 18.00.56) (GB Compatible).gbc" size 1048576 crc 11290c31 sha1 8d7ab85686ced1642b9519bcb6a3e157c6bd8938 ) + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05T180056) (GB Compatible)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05T180056) (GB Compatible)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05T180056) (GB Compatible).gbc" size 1048576 crc 11290c31 sha1 8d7ab85686ced1642b9519bcb6a3e157c6bd8938 ) ) game ( - name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05 21.55.32) (GB Compatible)" - description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05 21.55.32) (GB Compatible)" - rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05 21.55.32) (GB Compatible).gbc" size 1048576 crc 3c63e083 sha1 a068abd403a1dad70bd9b53d215995f8159aea47 ) + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05T215532) (GB Compatible)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05T215532) (GB Compatible)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-05T215532) (GB Compatible).gbc" size 1048576 crc 3c63e083 sha1 a068abd403a1dad70bd9b53d215995f8159aea47 ) ) game ( @@ -45586,9 +47325,93 @@ game ( ) game ( - name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-14) (GB Compatible)" - description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-14) (GB Compatible)" - rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-14) (GB Compatible).gbc" size 1048576 crc 13c76902 sha1 08dea3565740a4b5bd5c13e82adb61e3d5669a31 ) + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-14T022124) (GB Compatible)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-14T022124) (GB Compatible)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-14T022124) (GB Compatible).gbc" size 1048576 crc 13c76902 sha1 08dea3565740a4b5bd5c13e82adb61e3d5669a31 ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-02) (SGB Enhanced)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-02) (SGB Enhanced)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-02) (SGB Enhanced).gbc" size 1048576 crc 34ff47ba sha1 5ccc4c05123b4c38d0d93916ae8a0c93fb63f23f ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-03) (SGB Enhanced)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-03) (SGB Enhanced)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-03) (SGB Enhanced).gbc" size 1048576 crc ac0ef411 sha1 5aeb68b00a3a4f391afb324d9513311cb796a51f ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-04) (SGB Enhanced)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-04) (SGB Enhanced)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-04) (SGB Enhanced).gbc" size 1048576 crc 260bd98a sha1 ce1e48c82a09de0f93d5a60016318a9116331ccb ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-09-04) (SGB Enhanced)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-09-04) (SGB Enhanced)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-09-04) (SGB Enhanced).gbc" size 1048576 crc 883ef4ef sha1 87ca50396ba25914131866c74633afbe0007b2fb ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-07) (SGB Enhanced)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-07) (SGB Enhanced)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-07) (SGB Enhanced).gbc" size 1048576 crc 89a4a355 sha1 48931a00f5fec39492c264e9979646e88242c53e ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-07) (SGB Enhanced) (Alt)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-07) (SGB Enhanced) (Alt)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-07) (SGB Enhanced) (Alt).gbc" size 1048576 crc e5312966 sha1 fedd0fa70bbf5039dfec37b8e27674be839c47ca ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-07) (SGB Enhanced) (Alt 2)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-07) (SGB Enhanced) (Alt 2)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-08-07) (SGB Enhanced) (Alt 2).gbc" size 1048576 crc 1c374afd sha1 800db3d07a7abcca2138a0c7808cf25386e87712 ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-06-15) (GB Compatible)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-06-15) (GB Compatible)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-06-15) (GB Compatible).gbc" size 1048576 crc 3fd6c8fc sha1 017b81b26fc37db662063482e3947dfc2d814390 ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-06-15) (GB Compatible) (Alt)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-06-15) (GB Compatible) (Alt)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-06-15) (GB Compatible) (Alt).gbc" size 1048576 crc 9367653b sha1 544b803db49d8f312e193e4c105f0762d9e3fbf4 ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-14T181500) (GB Compatible)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-14T181500) (GB Compatible)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-07-14T181500) (GB Compatible).gbc" size 1048576 crc 2f884286 sha1 a7cb241de2139ddac5d1172a6ef1184b5fbb827e ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-11-09) (GB Compatible)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-11-09) (GB Compatible)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Beta) (1998-11-09) (GB Compatible).gbc" size 1048576 crc 3e5216c3 sha1 0fe1c48e36cb8e6e975c5421bf881c550746d29c ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (Demo) (Special Version 1) (GB Compatible)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (Demo) (Special Version 1) (GB Compatible)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (Demo) (Special Version 1) (GB Compatible).gbc" size 1048576 crc e05757f6 sha1 ee2df3c8449187fcd82f2fc830386bfe8144b387 ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (Demo) (Special Version 2) (GB Compatible)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (Demo) (Special Version 2) (GB Compatible)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 1) (Demo) (Special Version 2) (GB Compatible).gbc" size 1048576 crc e6101132 sha1 515f8d2fcaebe9495fb21f46ec32cce877c35e56 ) +) + +game ( + name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-09-22) (SGB Enhanced) (GB Compatible)" + description "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-09-22) (SGB Enhanced) (GB Compatible)" + rom ( name "Zelda no Densetsu - Yume o Miru Shima DX (Japan) (Rev 2) (Beta) (1999-09-22) (SGB Enhanced) (GB Compatible).gbc" size 1015808 crc c07979bf sha1 4a9ce5ced2234fa668dace888bd5d6130e375985 ) ) game ( @@ -45609,12 +47432,24 @@ game ( rom ( name "Zhihuan Wang - Shoubu Qu (Taiwan) (Zh) (Unl).gbc" size 2097152 crc 8160b3f5 sha1 97d7e0d05205b02c6cb69e68978a3f0fd2e3fde0 ) ) +game ( + name "Zhihuan Wang 2 (China) (Zh) (Unl)" + description "Zhihuan Wang 2 (China) (Zh) (Unl)" + rom ( name "Zhihuan Wang 2 (China) (Zh) (Unl).gbc" size 524288 crc e6748d1f sha1 108c318a859b39e88d15b2e3dc4d26002286305f ) +) + game ( name "Zhizhu Xia III - Dianying Ban (Taiwan) (Unl)" description "Zhizhu Xia III - Dianying Ban (Taiwan) (Unl)" rom ( name "Zhizhu Xia III - Dianying Ban (Taiwan) (Unl).gbc" size 2097152 crc d311efcc sha1 9eb0c468d5f898ef7b4d6ff74d7ff497b8c7818d ) ) +game ( + name "Zhong Zhuang Ji Bing (China) (Pirate)" + description "Zhong Zhuang Ji Bing (China) (Pirate)" + rom ( name "Zhong Zhuang Ji Bing (China) (Pirate).gbc" size 2097152 crc ad626c50 sha1 c3b3d8d43495ded5e4aff1b9416fe4d43b8e7453 ) +) + game ( name "Zidane - Football Generation (Europe) (En,Fr,De,Es,It)" description "Zidane - Football Generation (Europe) (En,Fr,De,Es,It)" @@ -45633,12 +47468,6 @@ game ( rom ( name "Zoboomafoo - Playtime in Zobooland (USA).gbc" size 1048576 crc 38d91885 sha1 a85a113bc266325f807f110daaf30feeea4b2738 ) ) -game ( - name "Zodiac (World) (Aftermarket) (Unl)" - description "Zodiac (World) (Aftermarket) (Unl)" - rom ( name "Zodiac (World) (Aftermarket) (Unl).gbc" size 262144 crc c4d86c05 sha1 73bd9e6e3bede8de489680ba84129e8fd17abbc0 ) -) - game ( name "Zoids - Jashin Fukkatsu! Genobreaker Hen (Japan) (SGB Enhanced) (GB Compatible)" description "Zoids - Jashin Fukkatsu! Genobreaker Hen (Japan) (SGB Enhanced) (GB Compatible)" @@ -45669,3 +47498,3203 @@ game ( rom ( name "Zook Z (USA) (Unl).gbc" size 1048576 crc a7b09e70 sha1 243cc40cfc6bcbd3b6106870773a72edff079904 ) ) +clrmamepro ( + name "Nintendo - Game Boy Color (Aftermarket)" + description "Nintendo - Game Boy Color (Aftermarket)" + version 20240810-021134 + author "akubi, Arctic Circle System, Aringon, baldjared, Bent, BigFred, bikerspade, BitLooter, C. V. Reynolds, chillerecke, coraz, darthcloud, DeadSkullzJr, Densetsu, DeriLoko3, Flashfire42, foxe, fuzzball, Gefflon, gordonj, Hiccup, hking0036, InternalLoss, Just001Kim, kazumi213, Lesserkuma, Madeline, Money_114, NESBrew12, NGEfreak, nnssxx, norkmetnoil577, NovaAurora, omonim2007, PPLToast, Psychofox11, psykopat, rarenight, relax, Rifu, sCZther, SonGoku, Tauwasser, togemet2, UnlockerPT, Whovian9369, xprism, xuom2, zg" + homepage No-Intro + url "https://www.no-intro.org" + forcenodump required +) + +emulator ( + name "datafile" +) + +game ( + name "20 Second Platformer, A (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "20 Second Platformer, A (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "20 Second Platformer, A (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 2edc4684 sha1 a00b40a3f31bd875f4a0376d22099c3822c9ef98 ) +) + +game ( + name "20 Second Platformer, A (World) (GB Compatible) (Aftermarket) (Unl)" + description "20 Second Platformer, A (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "20 Second Platformer, A (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc ff0a848b sha1 837cbb4cf3a92266833099fa06b95edfcdb1865f ) +) + +game ( + name "2123 (World) (Aftermarket) (Unl)" + description "2123 (World) (Aftermarket) (Unl)" + rom ( name "2123 (World) (Aftermarket) (Unl).gbc" size 262144 crc 22836942 sha1 eb9a2aff6485962f1a7773b7138f3c4208fa36e4 ) +) + +game ( + name "3D Quasars (World) (Aftermarket) (Unl)" + description "3D Quasars (World) (Aftermarket) (Unl)" + rom ( name "3D Quasars (World) (Aftermarket) (Unl).gbc" size 262144 crc 1fd94e67 sha1 3f32226538d8c7f0c866c4b73e9f828265f2bb5b ) +) + +game ( + name "5 Minutes until Goodbye (World) (GB Compatible) (Aftermarket) (Unl)" + description "5 Minutes until Goodbye (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "5 Minutes until Goodbye (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 48f0b5f2 sha1 fcb0161c637cd3d0f1ae66d032917f94aea11047 ) +) + +game ( + name "60 Minutes til Rot (World) (v1.6b) (GB Compatible) (Aftermarket) (Unl)" + description "60 Minutes til Rot (World) (v1.6b) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "60 Minutes til Rot (World) (v1.6b) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 9a10228a sha1 43ee50322e45c533fe67972db9a9d56f91a6a99b ) +) + +game ( + name "Aardvark (World) (Aftermarket) (Unl)" + description "Aardvark (World) (Aftermarket) (Unl)" + rom ( name "Aardvark (World) (Aftermarket) (Unl).gbc" size 262144 crc 270d45b9 sha1 34a8d00af6be9083409e6fccd0825c6f185d135d flags verified ) +) + +game ( + name "Ack Ack Attack (World) (Aftermarket) (Unl)" + description "Ack Ack Attack (World) (Aftermarket) (Unl)" + rom ( name "Ack Ack Attack (World) (Aftermarket) (Unl).gbc" size 262144 crc c5bedd2e sha1 2a5c7cfb58ccb233a4e688f007ff1436c6c9a208 ) +) + +game ( + name "Adulting! Soundtrack (World) (GB Compatible) (Aftermarket) (Unl)" + description "Adulting! Soundtrack (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Adulting! Soundtrack (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 1b5b9e64 sha1 c5dad32be800c36814a0f9b940e99b5eada34150 ) +) + +game ( + name "Adventure (World) (Aftermarket) (Unl)" + description "Adventure (World) (Aftermarket) (Unl)" + rom ( name "Adventure (World) (Aftermarket) (Unl).gbc" size 262144 crc c23d33c9 sha1 d579a1753d7875413f9e0022285b5741665e4abc ) +) + +game ( + name "Adventures in Carnal Hell, The (World) (En) (v1.02) (GB Compatible) (Aftermarket) (Unl)" + description "Adventures in Carnal Hell, The (World) (En) (v1.02) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Adventures in Carnal Hell, The (World) (En) (v1.02) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 9f81e7a0 sha1 895148bc0a3b6f9ec59bebae43413d1f4eafd21a ) +) + +game ( + name "Adventures in Carnal Hell, The (World) (Ja) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + description "Adventures in Carnal Hell, The (World) (Ja) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Adventures in Carnal Hell, The (World) (Ja) (v1.01) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc a5d0d1ec sha1 bc6367f77c235640cea5a1230cee253c99f846e5 ) +) + +game ( + name "Adventures in Carnal Hell, The (World) (Ja) (v1.02) (GB Compatible) (Aftermarket) (Unl)" + description "Adventures in Carnal Hell, The (World) (Ja) (v1.02) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Adventures in Carnal Hell, The (World) (Ja) (v1.02) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 3c9b424f sha1 7bd924752dca6fd772f6df9360117bd4b006ad88 ) +) + +game ( + name "Adventures in Carnal Hell, The (World) (Es) (v1.02) (GB Compatible) (Aftermarket) (Unl)" + description "Adventures in Carnal Hell, The (World) (Es) (v1.02) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Adventures in Carnal Hell, The (World) (Es) (v1.02) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 2f758976 sha1 2aa834c26a06771d53ce35bb0b5b1b9c87e9e2ce ) +) + +game ( + name "AF+ER (World) (GB Compatible) (Aftermarket) (Unl)" + description "AF+ER (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "AF+ER (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc f689b91e sha1 e55e427819916bb02189efe3883fb1dab3d80d35 ) +) + +game ( + name "Agency (World) (Aftermarket) (Unl)" + description "Agency (World) (Aftermarket) (Unl)" + rom ( name "Agency (World) (Aftermarket) (Unl).gbc" size 1048576 crc 0d1bb2f7 sha1 5266589244fab2e9ff047af9f72641cda91e1d90 ) +) + +game ( + name "Agent B (World) (GB Compatible) (Aftermarket) (Unl)" + description "Agent B (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Agent B (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 31b6e3fa sha1 11b3ce59c4eb86cee05873eb473dbf262cf986bd ) +) + +game ( + name "Agent B (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Agent B (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Agent B (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc ae767ad7 sha1 1a332aac66b24381f16819d1145fd4a917f2e0f3 ) +) + +game ( + name "Airwolf 16 (World) (Aftermarket) (Unl)" + description "Airwolf 16 (World) (Aftermarket) (Unl)" + rom ( name "Airwolf 16 (World) (Aftermarket) (Unl).gbc" size 262144 crc 6ecfd234 sha1 968355e655492a9aa5c36faacac9d34b289132bd ) +) + +game ( + name "All Humans Must Die! (World) (GB Compatible) (Aftermarket) (Unl)" + description "All Humans Must Die! (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "All Humans Must Die! (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc b4d50eed sha1 f4513fc525cbcfa4a2804b55ce20c809e01d1c87 ) +) + +game ( + name "Alley Cat (World) (Aftermarket) (Unl)" + description "Alley Cat (World) (Aftermarket) (Unl)" + rom ( name "Alley Cat (World) (Aftermarket) (Unl).gbc" size 262144 crc edb3ac37 sha1 a9aa1ecad6b67a6e5096fb1c10e39899c00a96a0 ) +) + +game ( + name "Android Nim (World) (Aftermarket) (Unl)" + description "Android Nim (World) (Aftermarket) (Unl)" + rom ( name "Android Nim (World) (Aftermarket) (Unl).gbc" size 262144 crc bd1e0cd7 sha1 efe551c498f6fdb3089a5b453b043fb61246e777 ) +) + +game ( + name "Another Adventure (World) (En,Es) (GB Compatible) (Aftermarket) (Unl)" + description "Another Adventure (World) (En,Es) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Another Adventure (World) (En,Es) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc dfcd02ef sha1 041473b2381dd9e11b3cbda5858f9841324327af ) +) + +game ( + name "Apollo Mission (World) (Aftermarket) (Unl)" + description "Apollo Mission (World) (Aftermarket) (Unl)" + rom ( name "Apollo Mission (World) (Aftermarket) (Unl).gbc" size 262144 crc bec9d9a2 sha1 b2bcc61bcf269c0f5c0ce2a6e0bb1c7015dc9ff9 ) +) + +game ( + name "Arena 3000 (World) (Aftermarket) (Unl)" + description "Arena 3000 (World) (Aftermarket) (Unl)" + rom ( name "Arena 3000 (World) (Aftermarket) (Unl).gbc" size 262144 crc 9c17c15c sha1 007d23f73f68de01c250ec3d07403679137851ff ) +) + +game ( + name "Astral Possession (World) (GB Compatible) (Aftermarket) (Unl)" + description "Astral Possession (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Astral Possession (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 788043b5 sha1 0d5e4098b62e93c68108cfd5b767d45241ec6963 ) +) + +game ( + name "Astro Plumber (World) (Aftermarket) (Unl)" + description "Astro Plumber (World) (Aftermarket) (Unl)" + rom ( name "Astro Plumber (World) (Aftermarket) (Unl).gbc" size 262144 crc d746db41 sha1 bf46ab2a3a1ffc3b712b9ae5cfa05441781ac9e4 ) +) + +game ( + name "Astro-Jump - The Sequel (World) (GB Compatible) (Aftermarket) (Unl)" + description "Astro-Jump - The Sequel (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Astro-Jump - The Sequel (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc e6a96130 sha1 2cd0ef086c4b89497d9497a17d871a6568a9e2d3 ) +) + +game ( + name "Atop the Witch's Tower (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Atop the Witch's Tower (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Atop the Witch's Tower (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 0d60b100 sha1 9cc1a5140b96ad072d36151f5d99ff6eb699e605 ) +) + +game ( + name "Auto Zone (World) (Aftermarket) (Unl)" + description "Auto Zone (World) (Aftermarket) (Unl)" + rom ( name "Auto Zone (World) (Aftermarket) (Unl).gbc" size 524288 crc 2a86d386 sha1 83a37fb5c5d82e0ff06bb22b63761af996e4ad61 ) +) + +game ( + name "Autobahn (World) (Aftermarket) (Unl)" + description "Autobahn (World) (Aftermarket) (Unl)" + rom ( name "Autobahn (World) (Aftermarket) (Unl).gbc" size 262144 crc d2fee5f1 sha1 6de35bd07f46720372ede9b5175399f2055e593d ) +) + +game ( + name "Autumn With You, An (World) (GB Compatible) (Aftermarket) (Unl)" + description "Autumn With You, An (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Autumn With You, An (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc eac459fa sha1 68a5520be76c52a4936ad1756ea274667f2ac0e3 ) +) + +game ( + name "Back to Nature (World) (Aftermarket) (Unl)" + description "Back to Nature (World) (Aftermarket) (Unl)" + rom ( name "Back to Nature (World) (Aftermarket) (Unl).gbc" size 262144 crc 861f9a63 sha1 3f4a6cd105d4c8af0312bef482c08784bbbfb0eb ) +) + +game ( + name "Bandits at Zero (World) (Aftermarket) (Unl)" + description "Bandits at Zero (World) (Aftermarket) (Unl)" + rom ( name "Bandits at Zero (World) (Aftermarket) (Unl).gbc" size 524288 crc c70f413e sha1 c885e109fbb53445db9618c6768c2259e6135921 ) +) + +game ( + name "Basketbrawl (World) (Aftermarket) (Unl)" + description "Basketbrawl (World) (Aftermarket) (Unl)" + rom ( name "Basketbrawl (World) (Aftermarket) (Unl).gbc" size 1048576 crc 51efcd7b sha1 3c626d9fec2eb252a50c5022be46525103560fde ) +) + +game ( + name "Basketbrawl - Deluxe Edition (World) (Aftermarket) (Unl)" + description "Basketbrawl - Deluxe Edition (World) (Aftermarket) (Unl)" + rom ( name "Basketbrawl - Deluxe Edition (World) (Aftermarket) (Unl).gbc" size 1048576 crc 3da834f2 sha1 a627c03f958bc13b11e1832b6ab53fe298167ebc ) +) + +game ( + name "Battle Star (World) (Aftermarket) (Unl)" + description "Battle Star (World) (Aftermarket) (Unl)" + rom ( name "Battle Star (World) (Aftermarket) (Unl).gbc" size 524288 crc b2fd062f sha1 ac4206129704e31386c9c0a1c961a148398f0ba3 ) +) + +game ( + name "Berks (World) (Aftermarket) (Unl)" + description "Berks (World) (Aftermarket) (Unl)" + rom ( name "Berks (World) (Aftermarket) (Unl).gbc" size 262144 crc 10ded9ab sha1 8b4c282cf973cdd9926a69ae1d8fcbaf79f8552b ) +) + +game ( + name "BIG2SMALL (World) (Digital) (GB Compatible) (Aftermarket) (Unl)" + description "BIG2SMALL (World) (Digital) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "BIG2SMALL (World) (Digital) (GB Compatible) (Aftermarket) (Unl).gbc" size 65536 crc b0401d96 sha1 ee5f2db597bb2fa06efe4a279a887b97bf23cac6 ) +) + +game ( + name "Bitterroot (World) (En) (GB Compatible) (Aftermarket) (Unl)" + description "Bitterroot (World) (En) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Bitterroot (World) (En) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 0d464785 sha1 790b9d231f6e66027e76264ef646c7a7cb9c878c ) +) + +game ( + name "Bitterroot (World) (Es) (GB Compatible) (Aftermarket) (Unl)" + description "Bitterroot (World) (Es) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Bitterroot (World) (Es) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 936443e2 sha1 b874c45d4866d5ef0c0d9837502ae42dd0ea3787 ) +) + +game ( + name "Black Tape (World) (GB Compatible) (Aftermarket) (Unl)" + description "Black Tape (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Black Tape (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 45c5f990 sha1 ec8c467e955d69b2084805f11a954e0d90855461 ) +) + +game ( + name "Blaze (World) (Aftermarket) (Unl)" + description "Blaze (World) (Aftermarket) (Unl)" + rom ( name "Blaze (World) (Aftermarket) (Unl).gbc" size 262144 crc 7d2519c7 sha1 f9b1422a91cc1f3a55526ef8ba81b7a8297fc55e ) +) + +game ( + name "Blinky's Revenge (World) (Aftermarket) (Unl)" + description "Blinky's Revenge (World) (Aftermarket) (Unl)" + rom ( name "Blinky's Revenge (World) (Aftermarket) (Unl).gbc" size 262144 crc 2d2f9c2b sha1 1c39cc02396c74e7b0b282ead510e94c77ff7f1e ) +) + +game ( + name "Block Droppin' (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Block Droppin' (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Block Droppin' (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 7e8ec278 sha1 6e8577c68402888a3244f153909a959f701eca0e ) +) + +game ( + name "Block Droppin' (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + description "Block Droppin' (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Block Droppin' (World) (v1.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 5a0f9578 sha1 37743ac843330cfc8350e67238fdd395174ca1d4 ) +) + +game ( + name "Board (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Board (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Board (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 440a2260 sha1 8472981264122ea588d991628c51020545779926 ) +) + +game ( + name "Boing! (World) (Aftermarket) (Unl)" + description "Boing! (World) (Aftermarket) (Unl)" + rom ( name "Boing! (World) (Aftermarket) (Unl).gbc" size 2097152 crc 91961796 sha1 09fde4065941784bab4cf8f624a0398049ed4add ) +) + +game ( + name "Bomb Runner 1-2 (World) (Aftermarket) (Unl)" + description "Bomb Runner 1-2 (World) (Aftermarket) (Unl)" + rom ( name "Bomb Runner 1-2 (World) (Aftermarket) (Unl).gbc" size 262144 crc d4c95ac0 sha1 3d020eb6e118b431899d79ce4a7bda9bc571c3a0 ) +) + +game ( + name "Booga-Boo (World) (Aftermarket) (Unl)" + description "Booga-Boo (World) (Aftermarket) (Unl)" + rom ( name "Booga-Boo (World) (Aftermarket) (Unl).gbc" size 262144 crc 7fa7fe54 sha1 00323df5a855f1499810dfe959a58d105daf6871 ) +) + +game ( + name "Booty (World) (Aftermarket) (Unl)" + description "Booty (World) (Aftermarket) (Unl)" + rom ( name "Booty (World) (Aftermarket) (Unl).gbc" size 262144 crc ef6c39c8 sha1 3c487ddc03d935b583e186d1cc395966ef490412 ) +) + +game ( + name "Borbo's Quest (World) (GB Compatible) (Aftermarket) (Unl)" + description "Borbo's Quest (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Borbo's Quest (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc e92ce3d4 sha1 1ddf864188dfd741ccda0b0715e75e162d212605 ) +) + +game ( + name "Boxed In (World) (GB Compatible) (Aftermarket) (Unl)" + description "Boxed In (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Boxed In (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc ee1c2e1d sha1 b95dfdf10820671ab5f734ed7180cbf1967ca277 ) +) + +game ( + name "Boxing Master (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Boxing Master (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Boxing Master (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc d1fc5295 sha1 cd336de23457b30cf7a5bf6ae62e8c606507a5a5 ) +) + +game ( + name "Bub-O Escape - Tournament Edition (World) (Aftermarket) (Unl)" + description "Bub-O Escape - Tournament Edition (World) (Aftermarket) (Unl)" + rom ( name "Bub-O Escape - Tournament Edition (World) (Aftermarket) (Unl).gbc" size 524288 crc 437a2973 sha1 9c219e2c489f5140314e89fbdc0bb387e1f1eed0 ) +) + +game ( + name "Bubble Frog (World) (GB Compatible) (Aftermarket) (Unl)" + description "Bubble Frog (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Bubble Frog (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 0fd51f93 sha1 e4894fd9392a9e1c42d432bc73681ca5bccfe9a8 ) +) + +game ( + name "Bubble Trouble (World) (Aftermarket) (Unl)" + description "Bubble Trouble (World) (Aftermarket) (Unl)" + rom ( name "Bubble Trouble (World) (Aftermarket) (Unl).gbc" size 262144 crc 3374918b sha1 892388f81f7815ea3bca17632a6a9a33a6edafac ) +) + +game ( + name "Bubblegum Attack (World) (GB Compatible) (Aftermarket) (Unl)" + description "Bubblegum Attack (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Bubblegum Attack (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc e3f64fec sha1 51e302fd27d579c9a4e8109e6ea4af3275d475dd ) +) + +game ( + name "Bug Byte (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Bug Byte (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Bug Byte (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc ee41d61b sha1 68f5712ca543c9f02b731e6dc8ec042fc790f839 ) +) + +game ( + name "Buried Behind the Cabin (World) (GB Compatible) (Aftermarket) (Unl)" + description "Buried Behind the Cabin (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Buried Behind the Cabin (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc a5d6cd6a sha1 7464af8e6d9d0a4b11f510d22789a6830cd4c272 ) +) + +game ( + name "Bygone Choices (World) (GB Compatible) (Aftermarket) (Unl)" + description "Bygone Choices (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Bygone Choices (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 4194304 crc dbaec8ec sha1 699b752e8a4a21b7f814f59e35260e0b82fc6795 ) +) + +game ( + name "Cancer Culture VS The Illuminati (World) (2023-05-03) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Cancer Culture VS The Illuminati (World) (2023-05-03) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Cancer Culture VS The Illuminati (World) (2023-05-03) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 52da152b sha1 1bb4a376c03af67ca1e8426375fe1a644499d9ae ) +) + +game ( + name "Candy Quest (World) (v2) (Demo) (Aftermarket) (Unl)" + description "Candy Quest (World) (v2) (Demo) (Aftermarket) (Unl)" + rom ( name "Candy Quest (World) (v2) (Demo) (Aftermarket) (Unl).gbc" size 1048576 crc 1f2823cb sha1 8906832db7816be01ed37728f6e5a23e981e7e38 ) +) + +game ( + name "Canoe Slalom (World) (Aftermarket) (Unl)" + description "Canoe Slalom (World) (Aftermarket) (Unl)" + rom ( name "Canoe Slalom (World) (Aftermarket) (Unl).gbc" size 262144 crc 38ce9e68 sha1 9fc025682ea0f19f975aa492dd51c5710d8b04a7 ) +) + +game ( + name "Cappimon (World) (v1.1) (Demo) (Aftermarket) (Unl)" + description "Cappimon (World) (v1.1) (Demo) (Aftermarket) (Unl)" + rom ( name "Cappimon (World) (v1.1) (Demo) (Aftermarket) (Unl).gbc" size 262144 crc ee6da010 sha1 a9d24cc03a6892035eaa448fea9c54ba16569b2d ) +) + +game ( + name "Cappimon (World) (v1.0) (Demo) (Aftermarket) (Unl)" + description "Cappimon (World) (v1.0) (Demo) (Aftermarket) (Unl)" + rom ( name "Cappimon (World) (v1.0) (Demo) (Aftermarket) (Unl).gbc" size 262144 crc 46201a19 sha1 c641e81c551158a2cf3a43403ddb384a7d76bab4 ) +) + +game ( + name "Capybara Quest (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + description "Capybara Quest (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Capybara Quest (World) (v1.2) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc b4719bab sha1 5e952ffe5136fd818d8663047f195f20dad9c3f6 ) +) + +game ( + name "Capybara Quest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Capybara Quest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Capybara Quest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 10854c85 sha1 7c4cdccc471ccf925a9ccf258c3e862681c3d1e9 ) +) + +game ( + name "Capybara Quest (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + description "Capybara Quest (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Capybara Quest (World) (v1.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 0795de60 sha1 7bed040a4bd916d04a9b251d14c89c9c1361cf09 ) +) + +game ( + name "Capybara Village (World) (v1.1) (Proto) (Aftermarket) (Unl)" + description "Capybara Village (World) (v1.1) (Proto) (Aftermarket) (Unl)" + rom ( name "Capybara Village (World) (v1.1) (Proto) (Aftermarket) (Unl).gbc" size 524288 crc b761bac5 sha1 9c299efb05516075a67516875ecfe47a32d04ef0 ) +) + +game ( + name "Capybara Village (World) (v1.0) (Proto) (Cozy Spring Jam) (Aftermarket) (Unl)" + description "Capybara Village (World) (v1.0) (Proto) (Cozy Spring Jam) (Aftermarket) (Unl)" + rom ( name "Capybara Village (World) (v1.0) (Proto) (Cozy Spring Jam) (Aftermarket) (Unl).gbc" size 524288 crc 44deeab3 sha1 057ade8edd41efbfb168ad709e95222c7c0118fa ) +) + +game ( + name "Cargo (World) (GB Compatible) (Aftermarket) (Unl)" + description "Cargo (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Cargo (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc a65d66f4 sha1 83c35ad553bde5ce3a6af418d7f8ad1fbe73b0f6 ) +) + +game ( + name "Castlevania - Demon Castle (World) (Aftermarket) (Unl)" + description "Castlevania - Demon Castle (World) (Aftermarket) (Unl)" + rom ( name "Castlevania - Demon Castle (World) (Aftermarket) (Unl).gbc" size 4194304 crc af20c186 sha1 8b593ebcb4c30f7709ca97ec977e8680df9b5fb7 ) +) + +game ( + name "Cat Boy's Stellar Journey (World) (GB Compatible) (Aftermarket) (Unl)" + description "Cat Boy's Stellar Journey (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Cat Boy's Stellar Journey (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 280937cc sha1 9ec53942f0136076b6468671562764e1ab9dee3b ) +) + +game ( + name "Cat Jumper (World) (GB Compatible) (Aftermarket) (Unl)" + description "Cat Jumper (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Cat Jumper (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc cde77e9d sha1 1acc8a49751cd45a84e53a435ddeed0357b87894 ) +) + +game ( + name "Cave Fighter (World) (Aftermarket) (Unl)" + description "Cave Fighter (World) (Aftermarket) (Unl)" + rom ( name "Cave Fighter (World) (Aftermarket) (Unl).gbc" size 262144 crc 6f4641f0 sha1 05b441e3542452b1724017d20e2db602d0997773 ) +) + +game ( + name "Cave Hunter (World) (GB Compatible) (Aftermarket) (Unl)" + description "Cave Hunter (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Cave Hunter (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc defb3151 sha1 94770d13bd9b1b52224fe753f94ec580e1b4017c ) +) + +game ( + name "Cavelon (World) (Aftermarket) (Unl)" + description "Cavelon (World) (Aftermarket) (Unl)" + rom ( name "Cavelon (World) (Aftermarket) (Unl).gbc" size 262144 crc 9fdd01f6 sha1 ff40729d06a6ce91446347b4bd69deaa6ba7d8b4 ) +) + +game ( + name "Chase the Chuck Wagon (World) (Aftermarket) (Unl)" + description "Chase the Chuck Wagon (World) (Aftermarket) (Unl)" + rom ( name "Chase the Chuck Wagon (World) (Aftermarket) (Unl).gbc" size 262144 crc 3c3d653c sha1 27b462be532a37c15798eba0fd48154eff596753 ) +) + +game ( + name "Chester's Big Ol' Day (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Chester's Big Ol' Day (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Chester's Big Ol' Day (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 490a874a sha1 92567a6a58739a38e0d7b35d1327ccb999527fa0 ) +) + +game ( + name "Chopper War (World) (Aftermarket) (Unl)" + description "Chopper War (World) (Aftermarket) (Unl)" + rom ( name "Chopper War (World) (Aftermarket) (Unl).gbc" size 524288 crc eb0f4f3e sha1 26970bb0753e792aaeb328e0f88d650acd413a9d ) +) + +game ( + name "Choro-Q (World) (Aftermarket) (Unl)" + description "Choro-Q (World) (Aftermarket) (Unl)" + rom ( name "Choro-Q (World) (Aftermarket) (Unl).gbc" size 262144 crc e40e99bd sha1 8534c4fe58aef32b8cfd4812fa1f2c1094e6b129 ) +) + +game ( + name "Chromanoids (World) (v1.1) (Aftermarket) (Unl)" + description "Chromanoids (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Chromanoids (World) (v1.1) (Aftermarket) (Unl).gbc" size 262144 crc 05d5d28f sha1 2885e9bfeca429a261f0871e31fdd3c5e682bd33 ) +) + +game ( + name "Chromanoids (World) (v1.0) (Aftermarket) (Unl)" + description "Chromanoids (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "Chromanoids (World) (v1.0) (Aftermarket) (Unl).gbc" size 262144 crc 50c4585f sha1 2d1dc090806463a6ff8c2fc17c32061a9e731d6f ) +) + +game ( + name "Chrome and Blood (World) (v1.02) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Chrome and Blood (World) (v1.02) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Chrome and Blood (World) (v1.02) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 5c3f27d7 sha1 cda9b333b019dbe460f2a5cebe71c0cae258d7cd ) +) + +game ( + name "Chrome and Blood (World) (v1.00) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Chrome and Blood (World) (v1.00) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Chrome and Blood (World) (v1.00) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 15cb5c58 sha1 a0d441f71caed08a52a41813d74031f13fd49d49 ) +) + +game ( + name "Chumbles Bumbles (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + description "Chumbles Bumbles (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Chumbles Bumbles (World) (v1.2) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 0ff2779c sha1 976790e64ce929a48a756cd1df46f325a7819f31 ) +) + +game ( + name "Church of Pastor Chuck (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Church of Pastor Chuck (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Church of Pastor Chuck (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc b9ca1669 sha1 d86af4b9288df8dc175a4c5647bc010328aab257 ) +) + +game ( + name "Climb It (World) (Aftermarket) (Unl)" + description "Climb It (World) (Aftermarket) (Unl)" + rom ( name "Climb It (World) (Aftermarket) (Unl).gbc" size 262144 crc e7210290 sha1 19f3b825eada3eda3135350bd0ddca6a20a5281f ) +) + +game ( + name "Clockmaker's Tale, A (World) (GB Compatible) (Aftermarket) (Unl)" + description "Clockmaker's Tale, A (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Clockmaker's Tale, A (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc c4b00adb sha1 07e4254c7f74b9d4caa6a1231558b2430dff163a flags verified ) +) + +game ( + name "Closet Monsters (World) (GB Compatible) (Aftermarket) (Unl)" + description "Closet Monsters (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Closet Monsters (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 57b5d189 sha1 42e8694bb746df0b61662238d81369b15e26e6de ) +) + +game ( + name "Cold Nights (World) (Aftermarket) (Unl)" + description "Cold Nights (World) (Aftermarket) (Unl)" + rom ( name "Cold Nights (World) (Aftermarket) (Unl).gbc" size 524288 crc cdca8a46 sha1 5a2222da34e7cf9166502f9a6bea13a713744e89 ) +) + +game ( + name "Commando (World) (Aftermarket) (Unl)" + description "Commando (World) (Aftermarket) (Unl)" + rom ( name "Commando (World) (Aftermarket) (Unl).gbc" size 262144 crc 5381b103 sha1 414bb6bdc1ed5647707d7d49f194c387d4098f00 ) +) + +game ( + name "Cookie Monster Munch (World) (Aftermarket) (Unl)" + description "Cookie Monster Munch (World) (Aftermarket) (Unl)" + rom ( name "Cookie Monster Munch (World) (Aftermarket) (Unl).gbc" size 262144 crc 420db35c sha1 0584d434503040f3922595250c9b311f62483e70 ) +) + +game ( + name "Cookie's Bakery (World) (v1.0.3) (GB Compatible) (Aftermarket) (Unl)" + description "Cookie's Bakery (World) (v1.0.3) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Cookie's Bakery (World) (v1.0.3) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc c53ace00 sha1 02fdc52bc934b80aa41520d92cf0340753d8f668 ) +) + +game ( + name "Cops and Robbers (World) (Aftermarket) (Unl)" + description "Cops and Robbers (World) (Aftermarket) (Unl)" + rom ( name "Cops and Robbers (World) (Aftermarket) (Unl).gbc" size 262144 crc 3c185eca sha1 8f8bbd15c0ab85345f3a3ae7e737e596311c19a1 ) +) + +game ( + name "Coria and the Sunken City (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Coria and the Sunken City (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Coria and the Sunken City (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc fe1bdae6 sha1 00d86bbdbc228ff3ea0684984a261cadbed5fb0a ) +) + +game ( + name "Cosmo Knight ZiON (World) (En) (v0.24) (Demo) (Aftermarket) (Unl)" + description "Cosmo Knight ZiON (World) (En) (v0.24) (Demo) (Aftermarket) (Unl)" + rom ( name "Cosmo Knight ZiON (World) (En) (v0.24) (Demo) (Aftermarket) (Unl).gbc" size 2097152 crc 1780b904 sha1 fcbe2c2389e6c51a38eb17eb80ffb2e51955c7f2 ) +) + +game ( + name "Cosmo Knight ZiON (World) (En,Es) (v0.47) (Demo) (Aftermarket) (Unl)" + description "Cosmo Knight ZiON (World) (En,Es) (v0.47) (Demo) (Aftermarket) (Unl)" + rom ( name "Cosmo Knight ZiON (World) (En,Es) (v0.47) (Demo) (Aftermarket) (Unl).gbc" size 2097152 crc e983a31f sha1 1d811dd440572243f9e95527d970f3ffa91ddbdf ) +) + +game ( + name "Cosmo Knight ZiON (World) (En,Es) (v2.38) (Demo) (Aftermarket) (Unl)" + description "Cosmo Knight ZiON (World) (En,Es) (v2.38) (Demo) (Aftermarket) (Unl)" + rom ( name "Cosmo Knight ZiON (World) (En,Es) (v2.38) (Demo) (Aftermarket) (Unl).gbc" size 1048576 crc 936752aa sha1 68e31afa8bc49f8b5e7ba9d978896539669cf3d1 ) +) + +game ( + name "Crazy Golf (World) (Aftermarket) (Unl)" + description "Crazy Golf (World) (Aftermarket) (Unl)" + rom ( name "Crazy Golf (World) (Aftermarket) (Unl).gbc" size 262144 crc f7fe3d01 sha1 b06f47a713b66efa9133be43653c7c4cb5ebc93c ) +) + +game ( + name "Crest RPG (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Crest RPG (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Crest RPG (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc c28f1ec5 sha1 2dd0b6a18e265653d382414de009ec8f154880da ) +) + +game ( + name "Cult of Blood, The (World) (Demo 4) (GB Compatible) (Aftermarket) (Unl)" + description "Cult of Blood, The (World) (Demo 4) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Cult of Blood, The (World) (Demo 4) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 5064aa20 sha1 2700521c7ff492fb015cc8dd453672a5989b80a7 ) +) + +game ( + name "Cult of Blood, The (World) (Demo 1) (GB Compatible) (Aftermarket) (Unl)" + description "Cult of Blood, The (World) (Demo 1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Cult of Blood, The (World) (Demo 1) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 9015c454 sha1 60b41b89cc9bce22ea06595ee332c3c1549db935 ) +) + +game ( + name "Cuthbert Enters the Tombs of Doom (World) (Aftermarket) (Unl)" + description "Cuthbert Enters the Tombs of Doom (World) (Aftermarket) (Unl)" + rom ( name "Cuthbert Enters the Tombs of Doom (World) (Aftermarket) (Unl).gbc" size 524288 crc 149a2951 sha1 2e7d760cd0836599bbc4222c66dddb4643183f07 ) +) + +game ( + name "Cuthbert in Space (World) (Aftermarket) (Unl)" + description "Cuthbert in Space (World) (Aftermarket) (Unl)" + rom ( name "Cuthbert in Space (World) (Aftermarket) (Unl).gbc" size 262144 crc c64000f3 sha1 6818167c491863cb19c2308c177203e38e0338d9 ) +) + +game ( + name "Cuthbert in the Cooler (World) (Aftermarket) (Unl)" + description "Cuthbert in the Cooler (World) (Aftermarket) (Unl)" + rom ( name "Cuthbert in the Cooler (World) (Aftermarket) (Unl).gbc" size 262144 crc 30204c4e sha1 d6fb35f3bdd44429f88c10551692e1adf14356ab ) +) + +game ( + name "Daisu-ki (World) (v1.2.1) (Aftermarket) (Unl)" + description "Daisu-ki (World) (v1.2.1) (Aftermarket) (Unl)" + rom ( name "Daisu-ki (World) (v1.2.1) (Aftermarket) (Unl).gbc" size 262144 crc 502385c4 sha1 3a310be21d5cc077da6eb8e3afa99ccff2eda84e ) +) + +game ( + name "Daisu-ki (World) (v1.1) (Aftermarket) (Unl)" + description "Daisu-ki (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Daisu-ki (World) (v1.1) (Aftermarket) (Unl).gbc" size 262144 crc a504b906 sha1 4634631f2c0b4a618aeefc114e5b8e4ba9c7ee04 ) +) + +game ( + name "Daisu-ki (World) (v1.1.1) (Aftermarket) (Unl)" + description "Daisu-ki (World) (v1.1.1) (Aftermarket) (Unl)" + rom ( name "Daisu-ki (World) (v1.1.1) (Aftermarket) (Unl).gbc" size 262144 crc a9714871 sha1 7d5b22d1c528603007e340f9d3562c1e53f10796 ) +) + +game ( + name "Daisu-ki (World) (v1.2) (Aftermarket) (Unl)" + description "Daisu-ki (World) (v1.2) (Aftermarket) (Unl)" + rom ( name "Daisu-ki (World) (v1.2) (Aftermarket) (Unl).gbc" size 262144 crc 26d3fe7a sha1 36c9649d4e99fdcaa4cf590963d0c49a3cf8084e ) +) + +game ( + name "Daisu-ki - Jam Edition (World) (GB Compatible) (Aftermarket) (Unl)" + description "Daisu-ki - Jam Edition (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Daisu-ki - Jam Edition (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc d34b719a sha1 446ca937d3e54ce33a49d1fff4692b3b906b539e ) +) + +game ( + name "Dark Winter Wander, A (World) (GB Compatible) (Aftermarket) (Unl)" + description "Dark Winter Wander, A (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dark Winter Wander, A (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc df19aa9f sha1 412f18ba08f2f2a2afbf3bfb5281e360d7aba31d ) +) + +game ( + name "Darklite (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Darklite (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Darklite (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 98a264a8 sha1 4cbd2cc8779698deb61f39ca255c6f45db7bd3b9 ) +) + +game ( + name "Dawn Will Come (World) (GB Compatible) (Aftermarket) (Unl)" + description "Dawn Will Come (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dawn Will Come (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc bb64f51c sha1 1611ddfdb9af72f20ddeca4133d8eebd0f14e424 ) +) + +game ( + name "Days Without (World) (Multiple Endings) (Aftermarket) (Unl)" + description "Days Without (World) (Multiple Endings) (Aftermarket) (Unl)" + rom ( name "Days Without (World) (Multiple Endings) (Aftermarket) (Unl).gbc" size 262144 crc 57ca8f69 sha1 8992f14f02bd37e11cb05511c17fff3d253ccf25 ) +) + +game ( + name "Days Without (World) (Aftermarket) (Unl)" + description "Days Without (World) (Aftermarket) (Unl)" + rom ( name "Days Without (World) (Aftermarket) (Unl).gbc" size 262144 crc 437b4921 sha1 cb21c1bca18d750ecde91dc3adb6b599c2ad75fa ) +) + +game ( + name "Death Race 16 (World) (Aftermarket) (Unl)" + description "Death Race 16 (World) (Aftermarket) (Unl)" + rom ( name "Death Race 16 (World) (Aftermarket) (Unl).gbc" size 262144 crc 7b9488ec sha1 56b8a2d7117b12ff5e709e6a258f9a0b3b0ebe24 ) +) + +game ( + name "Deisanebe (World) (GB Compatible) (Aftermarket) (Unl)" + description "Deisanebe (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Deisanebe (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 7cff943e sha1 065b5325d44cb0e40f7b7803d707b8c1ea9ea5b2 ) +) + +game ( + name "Descent (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Descent (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Descent (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 7d3ce321 sha1 1a42289186a7722a8ccdbd35bcd704f832dc3c04 ) +) + +game ( + name "Dia de Sol Noite de Lua (World) (GB Compatible) (Aftermarket) (Unl)" + description "Dia de Sol Noite de Lua (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dia de Sol Noite de Lua (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc c6b965b9 sha1 ac43f43bdcfc0347f24a0a70de213a4b701d8155 ) +) + +game ( + name "Dicee! (World) (v1.4) (GB Compatible) (Aftermarket) (Unl)" + description "Dicee! (World) (v1.4) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dicee! (World) (v1.4) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc b7f0a85f sha1 6911854fe18000b0fe6015863240d0664d914547 ) +) + +game ( + name "Dicee! (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Dicee! (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dicee! (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 08b37ad8 sha1 27e7a34d44640162a4aec02e28b93d295d78180b ) +) + +game ( + name "Disco Elysium - Game Boy Edition (World) (Music) (GB Compatible) (Aftermarket) (Unl)" + description "Disco Elysium - Game Boy Edition (World) (Music) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Disco Elysium - Game Boy Edition (World) (Music) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc ef349515 sha1 06fe25086432c82f1e4b4c44473dd5b487a8af05 ) +) + +game ( + name "Disco Elysium - Game Boy Edition (World) (No Music) (GB Compatible) (Aftermarket) (Unl)" + description "Disco Elysium - Game Boy Edition (World) (No Music) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Disco Elysium - Game Boy Edition (World) (No Music) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 7c0f52cc sha1 8bc16b70838f9245b7e37c6dbe57159b294fbf81 ) +) + +game ( + name "Diver 94 (World) (GB Compatible) (Aftermarket) (Unl)" + description "Diver 94 (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Diver 94 (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc f4ff5eb0 sha1 6b421505acc626a34bb9306a3d88e1964a4502f3 ) +) + +game ( + name "Don't Forget About Me (World) (GB Compatible) (Aftermarket) (Unl)" + description "Don't Forget About Me (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Don't Forget About Me (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 52cf7153 sha1 74e6246405dd52d4c5c2eabc417946550c637164 ) +) + +game ( + name "Don't Forget About Me (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Don't Forget About Me (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Don't Forget About Me (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 8ca9dbe0 sha1 cf6eaac37c4ae1b3cfc4ed8d2ce73a143635b525 ) +) + +game ( + name "Don't Forget About Me (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + description "Don't Forget About Me (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Don't Forget About Me (World) (v1.2) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 3d87efd8 sha1 83201c43e9fc89f4393678ade8c6107b4cfdb628 ) +) + +game ( + name "Dork's Dilemma (World) (Aftermarket) (Unl)" + description "Dork's Dilemma (World) (Aftermarket) (Unl)" + rom ( name "Dork's Dilemma (World) (Aftermarket) (Unl).gbc" size 524288 crc 77b8b43b sha1 bd525f97cc316fed3f6271ed0929414df4c0389c ) +) + +game ( + name "Downer (World) (GB Compatible) (Aftermarket) (Unl)" + description "Downer (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Downer (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 7a1c9a9f sha1 70044dca1282f4445fe05305586ecc69f4e52304 ) +) + +game ( + name "Dracula - Dark Reign (World) (Demo) (Aftermarket) (Unl)" + description "Dracula - Dark Reign (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Dracula - Dark Reign (World) (Demo) (Aftermarket) (Unl).gbc" size 524288 crc 4cfb1db2 sha1 6052c794b2c30a0538f57af0ab5253c626c860c5 ) +) + +game ( + name "Dragonborne DX (World) (v1.0.2) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Dragonborne DX (World) (v1.0.2) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dragonborne DX (World) (v1.0.2) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 4194304 crc 9f30b891 sha1 9974d28975a2d8e1e41ce8f32351c6eef144919d ) +) + +game ( + name "Dragonmaster (World) (Aftermarket) (Unl)" + description "Dragonmaster (World) (Aftermarket) (Unl)" + rom ( name "Dragonmaster (World) (Aftermarket) (Unl).gbc" size 262144 crc 4aaf9f58 sha1 6400de1108f1c3e5fca15de47f62299bfc66a938 ) +) + +game ( + name "Dragonyhm (World) (v1.0.0) (Demo) (SGB Enhanced) (GB Compatible) (Aftermarket) (Unl)" + description "Dragonyhm (World) (v1.0.0) (Demo) (SGB Enhanced) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dragonyhm (World) (v1.0.0) (Demo) (SGB Enhanced) (GB Compatible) (Aftermarket) (Unl).gbc" size 4194304 crc 96f9b7c0 sha1 2b74d076cabff92e5935d922e8f37202a723aaf0 flags verified ) +) + +game ( + name "Dragonyhm (World) (v1.1.0) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Dragonyhm (World) (v1.1.0) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dragonyhm (World) (v1.1.0) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 4194304 crc cad7369d sha1 0058096f8fcbb2774f908811aaa0b1ee54111493 ) +) + +game ( + name "Dungeon Crystal (World) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Dungeon Crystal (World) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dungeon Crystal (World) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 028a6e47 sha1 3fb673067aee3c50b65f0f8316bfff46a76c19bb ) +) + +game ( + name "Dungeon Crystal (World) (v1.0) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Dungeon Crystal (World) (v1.0) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dungeon Crystal (World) (v1.0) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 0eaeeca3 sha1 0b452000a244cd9757c4bb158d997785a13b0d1e ) +) + +game ( + name "Dusky Dungeon (World) (v0.1.0) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Dusky Dungeon (World) (v0.1.0) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dusky Dungeon (World) (v0.1.0) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 7c41cef6 sha1 e2df238887da0b6cf79513c7799ad707740eae30 ) +) + +game ( + name "Dusky Dungeon (World) (v0.2.0) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Dusky Dungeon (World) (v0.2.0) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Dusky Dungeon (World) (v0.2.0) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc abb154db sha1 f3b456d6318bee05150403efa5a933996e1d744a ) +) + +game ( + name "Egbert (World) (Aftermarket) (Unl)" + description "Egbert (World) (Aftermarket) (Unl)" + rom ( name "Egbert (World) (Aftermarket) (Unl).gbc" size 262144 crc a0e904fc sha1 ead756b54b2c1462708b4509ac35503f04e482cf ) +) + +game ( + name "Elementaria - Orientational Waltz (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Elementaria - Orientational Waltz (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Elementaria - Orientational Waltz (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc bffec2e1 sha1 a25cc6ee07e524f9a7121786bd0e513a1c6c2a8d ) +) + +game ( + name "Empire of Dreams, The (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Empire of Dreams, The (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Empire of Dreams, The (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 9ca3cf6c sha1 d3f4d21bf543431672268b476802693b2da9b6b9 ) +) + +game ( + name "Escape from Vostok (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Escape from Vostok (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Escape from Vostok (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 5d19bbcb sha1 6bb0ddd2b05d0ae6c7d2538f68f4b587901c29fd ) +) + +game ( + name "Everlasting Summer (World) (Proto) (Aftermarket) (Unl)" + description "Everlasting Summer (World) (Proto) (Aftermarket) (Unl)" + rom ( name "Everlasting Summer (World) (Proto) (Aftermarket) (Unl).gbc" size 262144 crc e45f6923 sha1 a4d7b12c71faf37a6703ded4d8a39844cf4f0395 ) +) + +game ( + name "Expiration Date (World) (v1.5) (GB Compatible) (Aftermarket) (Unl)" + description "Expiration Date (World) (v1.5) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Expiration Date (World) (v1.5) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc f222b03b sha1 c14f008cfc182f35fe670e14b57052ae4f8d1c60 ) +) + +game ( + name "Expiration Date (World) (GB Compatible) (Aftermarket) (Unl)" + description "Expiration Date (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Expiration Date (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 050caa5e sha1 e4b61c220b046e2287272f9b1bef85ad2d835fe3 ) +) + +game ( + name "Exploits of Fingers Malone, The (World) (Aftermarket) (Unl)" + description "Exploits of Fingers Malone, The (World) (Aftermarket) (Unl)" + rom ( name "Exploits of Fingers Malone, The (World) (Aftermarket) (Unl).gbc" size 524288 crc 20fe84af sha1 18056b5b032955099c606651f26164de131e54a6 ) +) + +game ( + name "Far After (World) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Far After (World) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Far After (World) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc bdaf8f3f sha1 d1ed0fb4d926f4c337399ca342644f89cf00790a ) +) + +game ( + name "Far After (World) (v1.01) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Far After (World) (v1.01) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Far After (World) (v1.01) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc e61c1dc2 sha1 d7a88a68ec65d9cf3f9521fc9ad9d3f4b51bac5d flags verified ) +) + +game ( + name "Featherless Cake Delivery (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" + description "Featherless Cake Delivery (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Featherless Cake Delivery (World) (v2.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 63c6c960 sha1 b62ec7a341ea9a0bfe8f0b014da971b73606a86e ) +) + +game ( + name "Featherless Cake Delivery (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + description "Featherless Cake Delivery (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Featherless Cake Delivery (World) (v1.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc de373eba sha1 dbf2228017515b407ed9f4a9b3bf01bc2a5f7b0f ) +) + +game ( + name "Feed IT Souls (World) (v1.3) (Aftermarket) (Unl)" + description "Feed IT Souls (World) (v1.3) (Aftermarket) (Unl)" + rom ( name "Feed IT Souls (World) (v1.3) (Aftermarket) (Unl).gbc" size 1048576 crc 701847f5 sha1 aba3fecd55c0cee7fbe49506b367b7e94b56b81c ) +) + +game ( + name "Feed IT Souls (World) (v1.4) (Aftermarket) (Unl)" + description "Feed IT Souls (World) (v1.4) (Aftermarket) (Unl)" + rom ( name "Feed IT Souls (World) (v1.4) (Aftermarket) (Unl).gbc" size 1048576 crc f87760b3 sha1 ea0dd170812d1bcc38de1cabe12a372cd2178c95 ) +) + +game ( + name "Feed The Monster (World) (GB Compatible) (Aftermarket) (Pirate)" + description "Feed The Monster (World) (GB Compatible) (Aftermarket) (Pirate)" + rom ( name "Feed The Monster (World) (GB Compatible) (Aftermarket) (Pirate).gbc" size 524288 crc 7bec6553 sha1 bdcadc0f98d8c9061cbe83c53a047719280b6e09 ) +) + +game ( + name "Fighter on the Path of Glory (World) (En,Ja) (v1.00) (GB Compatible) (Aftermarket) (Unl)" + description "Fighter on the Path of Glory (World) (En,Ja) (v1.00) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Fighter on the Path of Glory (World) (En,Ja) (v1.00) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 38f208f3 sha1 a4034a72dfacfe33fc924ab689f9a9303656c43d ) +) + +game ( + name "Fillo - Crystal Version (World) (Aftermarket) (Unl)" + description "Fillo - Crystal Version (World) (Aftermarket) (Unl)" + rom ( name "Fillo - Crystal Version (World) (Aftermarket) (Unl).gbc" size 524288 crc 88bb855c sha1 2ffc4199d94f8b29b3f84b7bdb2694154a0bd285 ) +) + +game ( + name "Find Out (World) (GB Compatible) (Aftermarket) (Unl)" + description "Find Out (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Find Out (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 5f8b660e sha1 3605a96f6713157a88e4d88989d2e2f11b9db42f ) +) + +game ( + name "Finders Keepers (World) (Aftermarket) (Unl)" + description "Finders Keepers (World) (Aftermarket) (Unl)" + rom ( name "Finders Keepers (World) (Aftermarket) (Unl).gbc" size 524288 crc 4cfa0cfd sha1 db002f4a2500a9dc98a9ac7c263293d6e4a72cf1 ) +) + +game ( + name "Fire Ant (World) (Aftermarket) (Unl)" + description "Fire Ant (World) (Aftermarket) (Unl)" + rom ( name "Fire Ant (World) (Aftermarket) (Unl).gbc" size 262144 crc 154cc020 sha1 b58ed66838db34fc7f8475ccb670267119d623a5 ) +) + +game ( + name "Fireman Fred (World) (Aftermarket) (Unl)" + description "Fireman Fred (World) (Aftermarket) (Unl)" + rom ( name "Fireman Fred (World) (Aftermarket) (Unl).gbc" size 524288 crc 563d9ca7 sha1 e62a9c6b6a39f0cb662fdb07b72669355b706f57 ) +) + +game ( + name "Firemen (World) (Aftermarket) (Unl)" + description "Firemen (World) (Aftermarket) (Unl)" + rom ( name "Firemen (World) (Aftermarket) (Unl).gbc" size 262144 crc 7299401f sha1 84c68614334578f866cfa929df736377f04f5d04 ) +) + +game ( + name "Fishing for Asteroids (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Fishing for Asteroids (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Fishing for Asteroids (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc aae310ed sha1 b874c82fe582ee34b93cd4f6dcfc16e6fe991efe ) +) + +game ( + name "Fishing for Asteroids (World) (v1.0) (Mini Jam 153) (GB Compatible) (Aftermarket) (Unl)" + description "Fishing for Asteroids (World) (v1.0) (Mini Jam 153) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Fishing for Asteroids (World) (v1.0) (Mini Jam 153) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc efbefb4b sha1 966f3f17b7acf5a60212d300c62fd5a4e50047ae ) +) + +game ( + name "Fishnet Burn (World) (Demo) (Aftermarket) (Unl)" + description "Fishnet Burn (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Fishnet Burn (World) (Demo) (Aftermarket) (Unl).gbc" size 262144 crc a317673d sha1 3b28ba3bbcb2c387976e98a47650426131823c56 ) +) + +game ( + name "Fix It Felix Jr. (World) (GB Compatible) (Aftermarket) (Unl)" + description "Fix It Felix Jr. (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Fix It Felix Jr. (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc c8014615 sha1 7221f5e53f6027183301d06e258c6cb417007b8c ) +) + +game ( + name "Fix My Heart (World) (GB Compo 2021) (GB Compatible) (Aftermarket) (Unl)" + description "Fix My Heart (World) (GB Compo 2021) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Fix My Heart (World) (GB Compo 2021) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 507f9ea2 sha1 28ad64e379dc60d6e1c2617e073f6361c0feb475 flags verified ) +) + +game ( + name "Flashin' (World) (v3.0) (GB Compatible) (Aftermarket) (Unl)" + description "Flashin' (World) (v3.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Flashin' (World) (v3.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc fcc05ec4 sha1 64d31f34e189b3af08bf0c659a93f71dbf83ef71 ) +) + +game ( + name "Flooder (World) (Aftermarket) (Unl)" + description "Flooder (World) (Aftermarket) (Unl)" + rom ( name "Flooder (World) (Aftermarket) (Unl).gbc" size 32768 crc 253dcbe0 sha1 8fdcd8b02604ac5259fb6aa80e5ba67a03c861fb ) +) + +game ( + name "Flooder (World) (Anniversary Edition) (Aftermarket) (Unl)" + description "Flooder (World) (Anniversary Edition) (Aftermarket) (Unl)" + rom ( name "Flooder (World) (Anniversary Edition) (Aftermarket) (Unl).gbc" size 32768 crc cdda76f8 sha1 e5eec8efc032aa5bce1826f7b6b8790c61c96e06 ) +) + +game ( + name "Foal's Creek (World) (v1.06) (GB Compatible) (Aftermarket) (Unl)" + description "Foal's Creek (World) (v1.06) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Foal's Creek (World) (v1.06) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 40027de8 sha1 6d4152d0db5c7fdc2d3271ffc9195494e637c85a ) +) + +game ( + name "Foal's Creek (World) (v1.05) (GB Compatible) (Aftermarket) (Unl)" + description "Foal's Creek (World) (v1.05) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Foal's Creek (World) (v1.05) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc c0db789e sha1 025e83abce412435c41e77dc7ecc606af96f874b ) +) + +game ( + name "Forest of Fallen Knights (World) (GB Compatible) (Aftermarket) (Unl)" + description "Forest of Fallen Knights (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Forest of Fallen Knights (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc fa2d92a1 sha1 24f02d116aafb7b55d6cfd6d263b7595986af843 ) +) + +game ( + name "Forest of Fallen Knights (World) (Beta) (GB Compatible) (Aftermarket) (Unl)" + description "Forest of Fallen Knights (World) (Beta) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Forest of Fallen Knights (World) (Beta) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 4c21e563 sha1 f6f84f1a44d41fa7d26a9195ddf791fae53dfcdf ) +) + +game ( + name "Friday the 13th - The GB Game (World) (GB Compatible) (Aftermarket) (Unl)" + description "Friday the 13th - The GB Game (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Friday the 13th - The GB Game (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 7543586a sha1 397821751ac6464582f61566f3a7c731a46b24ba ) +) + +game ( + name "Friendly Fire (World) (Aftermarket) (Unl)" + description "Friendly Fire (World) (Aftermarket) (Unl)" + rom ( name "Friendly Fire (World) (Aftermarket) (Unl).gbc" size 262144 crc 5c6dca2b sha1 8f8085010e28aa8bdb312d086b0002b706742282 ) +) + +game ( + name "Friendly Fire (World) (GB Showdown) (GB Compatible) (Aftermarket) (Unl)" + description "Friendly Fire (World) (GB Showdown) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Friendly Fire (World) (GB Showdown) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc d8be10d6 sha1 d09f4d2f799ac2e2731be0171625846d28d0f57e ) +) + +game ( + name "From Below Pocket (World) (Aftermarket) (Unl)" + description "From Below Pocket (World) (Aftermarket) (Unl)" + rom ( name "From Below Pocket (World) (Aftermarket) (Unl).gbc" size 131072 crc 35ad9b5a sha1 c0e072bfb88c84dc68b2eded1f9c088d75ffa5ed ) +) + +game ( + name "Fugazim (World) (Pt) (GB Compatible) (Aftermarket) (Unl)" + description "Fugazim (World) (Pt) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Fugazim (World) (Pt) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 85edfba4 sha1 8a95571a32c5a23bd6be4edf6429f630d7a1a15a ) +) + +game ( + name "Fury (World) (Aftermarket) (Unl)" + description "Fury (World) (Aftermarket) (Unl)" + rom ( name "Fury (World) (Aftermarket) (Unl).gbc" size 262144 crc 7217c41d sha1 ef532b587eb438f1a39a77086ac0b8bbae23a16d ) +) + +game ( + name "G-Man (World) (Aftermarket) (Unl)" + description "G-Man (World) (Aftermarket) (Unl)" + rom ( name "G-Man (World) (Aftermarket) (Unl).gbc" size 524288 crc ff3beab1 sha1 cb9486ca9a6ad3903662963aa966145257ef92a6 ) +) + +game ( + name "G.B Corp. (World) (Beta) (GB Compatible) (Aftermarket) (Unl)" + description "G.B Corp. (World) (Beta) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "G.B Corp. (World) (Beta) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc fd2e40f4 sha1 e442316132506ff223a9e5f33d874b71ec09d71a flags verified ) +) + +game ( + name "Game Boy Camera Gallery - Mystery Show (World) (v1.4) (Digital) (GB Compatible) (Aftermarket) (Unl)" + description "Game Boy Camera Gallery - Mystery Show (World) (v1.4) (Digital) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Game Boy Camera Gallery - Mystery Show (World) (v1.4) (Digital) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc aba1f99a sha1 8278abbe74202537bdc42f2e00875a12e77c9115 ) +) + +game ( + name "Game Boy Camera Gallery - Mystery Show (World) (v1.2) (Digital) (GB Compatible) (Aftermarket) (Unl)" + description "Game Boy Camera Gallery - Mystery Show (World) (v1.2) (Digital) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Game Boy Camera Gallery - Mystery Show (World) (v1.2) (Digital) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc b3629b4a sha1 649678adc47eeb1386a90084ddb2fbf99b08ca4c ) +) + +game ( + name "Game Boy Camera Gallery 2022, The (World) (GB Compatible) (Aftermarket) (Unl)" + description "Game Boy Camera Gallery 2022, The (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Game Boy Camera Gallery 2022, The (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc f1948966 sha1 14849ab5831c71949ec3a1fe7657050057d2cf29 ) +) + +game ( + name "Game with The Cerulean Blob, The (World) (Demo) (Aftermarket) (Unl)" + description "Game with The Cerulean Blob, The (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Game with The Cerulean Blob, The (World) (Demo) (Aftermarket) (Unl).gbc" size 524288 crc be05262e sha1 9fff6703a876d19027f8d8c590d1223d0e931420 ) +) + +game ( + name "Gamer Boy Mission (World) (GB Compatible) (Aftermarket) (Unl)" + description "Gamer Boy Mission (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Gamer Boy Mission (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 96721e5d sha1 90fad94433a5b0dbcf73f4a2d4ebb75d7ab065c4 ) +) + +game ( + name "Gamer Boy Mission (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Gamer Boy Mission (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Gamer Boy Mission (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc a02d2ae2 sha1 7eb6865c5c265193763ec0bf751d26964e870120 ) +) + +game ( + name "GB-Wordyl (World) (Pt-BR) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (Pt-BR) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (Pt-BR) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc f20c0097 sha1 691af25434a09931a302ced52c757d28b9b06619 ) +) + +game ( + name "GB-Wordyl (World) (Ca) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (Ca) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (Ca) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc 164999eb sha1 197d3d194d4cb6cae9a358f7fb53d6de649e7c5f ) +) + +game ( + name "GB-Wordyl (World) (De) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (De) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (De) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc 60b075d1 sha1 0a66254b2327b48657de64d6102ac05f1e8700e7 ) +) + +game ( + name "GB-Wordyl (World) (Es) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (Es) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (Es) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc 1a169897 sha1 0636b968e8e24fe7c1910f61db6e94fa84824494 ) +) + +game ( + name "GB-Wordyl (World) (Fr) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (Fr) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (Fr) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc 593965ff sha1 75d566045a680aaed4d40b83b6418cbfab5b4422 ) +) + +game ( + name "GB-Wordyl (World) (It) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (It) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (It) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc d81ab567 sha1 1dfd3c4508ffb6598662bcf1b16ec109a9282dd5 ) +) + +game ( + name "GB-Wordyl (World) (Kw) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (Kw) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (Kw) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc f795689c sha1 9a332127182e8155d1a3dc53e1382a6c9dde6aeb ) +) + +game ( + name "GB-Wordyl (World) (Es-XL) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (Es-XL) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (Es-XL) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc 660ed37b sha1 0792fbef010cac21c12cbcb8b3c85b3af30faec4 ) +) + +game ( + name "GB-Wordyl (World) (Nl) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (Nl) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (Nl) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc 6dc4faaa sha1 7617083f9b13b2f95bdf1b0b327ffb4f8ccbe3c9 ) +) + +game ( + name "GB-Wordyl (World) (En) (GB Compatible) (Aftermarket) (Unl)" + description "GB-Wordyl (World) (En) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "GB-Wordyl (World) (En) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc 8780e125 sha1 7163bfbaa2cae2f9d41c472128f69a4fa5879180 ) +) + +game ( + name "Ghost of the Arcade (World) (v1.7) (Aftermarket) (Unl)" + description "Ghost of the Arcade (World) (v1.7) (Aftermarket) (Unl)" + rom ( name "Ghost of the Arcade (World) (v1.7) (Aftermarket) (Unl).gbc" size 1048576 crc 4aa9a9c2 sha1 ac697bc27a126c1389e6bef94a2c83404e8819f2 ) +) + +game ( + name "Ghost of the Arcade (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + description "Ghost of the Arcade (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ghost of the Arcade (World) (v1.3) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 32e2ea48 sha1 ee11d5397316b69eee5ae3023de08c3b919c93df ) +) + +game ( + name "Ghost of the Arcade (World) (GB Compo 2023) (GB Compatible) (Aftermarket) (Unl)" + description "Ghost of the Arcade (World) (GB Compo 2023) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ghost of the Arcade (World) (GB Compo 2023) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc ea87ad5d sha1 433e25df1421e77cdc807296e1ed662d9e43d685 ) +) + +game ( + name "Ghost Town (World) (Aftermarket) (Unl)" + description "Ghost Town (World) (Aftermarket) (Unl)" + rom ( name "Ghost Town (World) (Aftermarket) (Unl).gbc" size 262144 crc 52efcc35 sha1 1a4a7846d6c87f0bd8b267aa6a8aa98e797fedf8 ) +) + +game ( + name "Gods of the Universe (World) (Aftermarket) (Unl)" + description "Gods of the Universe (World) (Aftermarket) (Unl)" + rom ( name "Gods of the Universe (World) (Aftermarket) (Unl).gbc" size 262144 crc 27b87354 sha1 74eb8cd698097290b93fb08d9b19486d05411877 ) +) + +game ( + name "Gopher (World) (Aftermarket) (Unl)" + description "Gopher (World) (Aftermarket) (Unl)" + rom ( name "Gopher (World) (Aftermarket) (Unl).gbc" size 262144 crc 22802c30 sha1 e629199b6bd492bd5efa77c0d4d467e053d44877 ) +) + +game ( + name "Gorf the Ghost Saves Halloween (World) (GB Compatible) (Aftermarket) (Unl)" + description "Gorf the Ghost Saves Halloween (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Gorf the Ghost Saves Halloween (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc ab10cec6 sha1 9dcaa6824fab806683737bdf1c76609c68c451a5 ) +) + +game ( + name "GPC Rally (World) (v1.1) (Aftermarket) (Unl)" + description "GPC Rally (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "GPC Rally (World) (v1.1) (Aftermarket) (Unl).gbc" size 262144 crc 2ed2487c sha1 a711bbb2d7dc2b0c377ecd7b20f4862330961b51 ) +) + +game ( + name "GPC Rally (World) (v1.0) (Aftermarket) (Unl)" + description "GPC Rally (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "GPC Rally (World) (v1.0) (Aftermarket) (Unl).gbc" size 262144 crc 3b15bdb8 sha1 b6500b0250d8358644e41e26ed8fb92c5b24535d ) +) + +game ( + name "Grave Encounter, A (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + description "Grave Encounter, A (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Grave Encounter, A (World) (v1.3) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc a5ad3c0b sha1 1cf0cf6d1da5c5337856ecc0a60d2e9fb3c98f58 ) +) + +game ( + name "Grave Encounter, A (World) (v1.21) (GB Compatible) (Aftermarket) (Unl)" + description "Grave Encounter, A (World) (v1.21) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Grave Encounter, A (World) (v1.21) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc b29fc03f sha1 2f979202a4bf4f98f3026a7548a8b6c7008806bf ) +) + +game ( + name "Gravitorque (World) (GB Compatible) (Aftermarket) (Unl)" + description "Gravitorque (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Gravitorque (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc a0e998e1 sha1 ab656383e9aaaa2991aa344bdc8f21370f0eda36 ) +) + +game ( + name "Gridtrap (World) (Aftermarket) (Unl)" + description "Gridtrap (World) (Aftermarket) (Unl)" + rom ( name "Gridtrap (World) (Aftermarket) (Unl).gbc" size 262144 crc 5a5453f6 sha1 b43d05eddcd1ab2d5934dd2a722f145a3084c4ad ) +) + +game ( + name "Grimace's Birthday (World) (Aftermarket) (Unl)" + description "Grimace's Birthday (World) (Aftermarket) (Unl)" + rom ( name "Grimace's Birthday (World) (Aftermarket) (Unl).gbc" size 1048576 crc 7f4386e9 sha1 d6358d100ea65d34d95588f800635b64927baf82 ) +) + +game ( + name "Grimace's Birthday (World) (v1.1) (Aftermarket) (Unl)" + description "Grimace's Birthday (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Grimace's Birthday (World) (v1.1) (Aftermarket) (Unl).gbc" size 1048576 crc 7744f551 sha1 035b7417e03c4e264a90212f2a3811012f03c2a2 flags verified ) +) + +game ( + name "Grimace's Birthday (World) (v1.2) (Aftermarket) (Unl)" + description "Grimace's Birthday (World) (v1.2) (Aftermarket) (Unl)" + rom ( name "Grimace's Birthday (World) (v1.2) (Aftermarket) (Unl).gbc" size 1048576 crc 9dee42fe sha1 071fa179df96950c3c92b0abbe32092b1816ec40 flags verified ) +) + +game ( + name "Grimace's Birthday (World) (v1.4) (Aftermarket) (Unl)" + description "Grimace's Birthday (World) (v1.4) (Aftermarket) (Unl)" + rom ( name "Grimace's Birthday (World) (v1.4) (Aftermarket) (Unl).gbc" size 1048576 crc 9baa5f46 sha1 d247c03119ac14f97fdeeaa6bf0defa98e35fa17 flags verified ) +) + +game ( + name "Grimace's Birthday (World) (v1.3) (Aftermarket) (Unl)" + description "Grimace's Birthday (World) (v1.3) (Aftermarket) (Unl)" + rom ( name "Grimace's Birthday (World) (v1.3) (Aftermarket) (Unl).gbc" size 1048576 crc ab41a9ef sha1 d8e727745e285f5e467f5eccbfd30ee175bafc2e flags verified ) +) + +game ( + name "Grimace's Birthday (World) (v1.5) (Aftermarket) (Unl)" + description "Grimace's Birthday (World) (v1.5) (Aftermarket) (Unl)" + rom ( name "Grimace's Birthday (World) (v1.5) (Aftermarket) (Unl).gbc" size 1048576 crc f8e8e1f3 sha1 a3fdfe3981e800fa7c73ff989bc06426f668c331 flags verified ) +) + +game ( + name "Grimace's Birthday (World) (v1.6) (Aftermarket) (Unl)" + description "Grimace's Birthday (World) (v1.6) (Aftermarket) (Unl)" + rom ( name "Grimace's Birthday (World) (v1.6) (Aftermarket) (Unl).gbc" size 1048576 crc a7b59d7b sha1 295fdc3218d1699dea6d5832d068b721fccf9bd4 flags verified ) +) + +game ( + name "Grimace's Birthday (World) (v1.7) (Aftermarket) (Unl)" + description "Grimace's Birthday (World) (v1.7) (Aftermarket) (Unl)" + rom ( name "Grimace's Birthday (World) (v1.7) (Aftermarket) (Unl).gbc" size 1048576 crc f3879ef0 sha1 27d7ee2f31bf575185711217c3cc9e08cbc5928a flags verified ) +) + +game ( + name "Gun Law (World) (Aftermarket) (Unl)" + description "Gun Law (World) (Aftermarket) (Unl)" + rom ( name "Gun Law (World) (Aftermarket) (Unl).gbc" size 262144 crc 3a0b6823 sha1 c49f7e0a5055f836528a7bc0cb6f45f221c76475 ) +) + +game ( + name "Gunslinger (World) (Aftermarket) (Unl)" + description "Gunslinger (World) (Aftermarket) (Unl)" + rom ( name "Gunslinger (World) (Aftermarket) (Unl).gbc" size 262144 crc 0dfd765f sha1 8410ef1558649f9badc71629827ba1500510d221 ) +) + +game ( + name "Gunther the Monster and His Friends (World) (Aftermarket) (Unl)" + description "Gunther the Monster and His Friends (World) (Aftermarket) (Unl)" + rom ( name "Gunther the Monster and His Friends (World) (Aftermarket) (Unl).gbc" size 524288 crc 2d9b59bf sha1 d89fe1cd97d1ef2c457aa90b1c00e7b473c57270 ) +) + +game ( + name "Guzzler (World) (Aftermarket) (Unl)" + description "Guzzler (World) (Aftermarket) (Unl)" + rom ( name "Guzzler (World) (Aftermarket) (Unl).gbc" size 524288 crc 3684abd0 sha1 e36cd02fe2b697901843c4cbf6d83da8a9b7b923 ) +) + +game ( + name "Halo - Combat Devolved (World) (GB Compatible) (Aftermarket) (Unl)" + description "Halo - Combat Devolved (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Halo - Combat Devolved (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc c7297c31 sha1 c38cc0e80a2e04693e3a86574c03f23f3e472c88 flags verified ) +) + +game ( + name "Harbour Attack (World) (Aftermarket) (Unl)" + description "Harbour Attack (World) (Aftermarket) (Unl)" + rom ( name "Harbour Attack (World) (Aftermarket) (Unl).gbc" size 262144 crc 7455782e sha1 1d0b3779007ba8f34e11b189552955dbf5c75a28 ) +) + +game ( + name "Hat Boy (World) (GB Compatible) (Aftermarket) (Unl)" + description "Hat Boy (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Hat Boy (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 81d24d61 sha1 7265cad6c8e253d3cf6d1f0dcb218316f10ca091 ) +) + +game ( + name "Haunted (World) (GB Compatible) (Aftermarket) (Unl)" + description "Haunted (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Haunted (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 4b3670bd sha1 f245b8e21716a400769488b852f15d276f3549a6 ) +) + +game ( + name "Hauntsfield (World) (GB Compatible) (Aftermarket) (Unl)" + description "Hauntsfield (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Hauntsfield (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 287afc75 sha1 42ccc76883c041bc5c6c25a2e61ccc939c14811f ) +) + +game ( + name "Hauntsfield (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" + description "Hauntsfield (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Hauntsfield (World) (v2.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 6e484d6a sha1 7282ef5cc2354345c8832b4dde66a559de74f73f ) +) + +game ( + name "Heebie Jeebies (World) (Aftermarket) (Unl)" + description "Heebie Jeebies (World) (Aftermarket) (Unl)" + rom ( name "Heebie Jeebies (World) (Aftermarket) (Unl).gbc" size 262144 crc 73762d53 sha1 d427f18cb854e1387d93c19b88cb7193975e6472 ) +) + +game ( + name "Hidden Gems (World) (GB Compo 2023) (GB Compatible) (Aftermarket) (Unl)" + description "Hidden Gems (World) (GB Compo 2023) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Hidden Gems (World) (GB Compo 2023) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 6f430dda sha1 e0cfe038063b1cd601a5f1b5af047efc705a7aaa ) +) + +game ( + name "Hidden Gems (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Hidden Gems (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Hidden Gems (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 7296d7e0 sha1 ae0fd7bcda2a3d7c1c342157ecb801ba8e380b5f ) +) + +game ( + name "High Noon (World) (Aftermarket) (Unl)" + description "High Noon (World) (Aftermarket) (Unl)" + rom ( name "High Noon (World) (Aftermarket) (Unl).gbc" size 262144 crc 1d00e48d sha1 21d5e871ed009a674659344d3d768fb2389c0d04 ) +) + +game ( + name "Hightail (World) (Demo 4F) (Aftermarket) (Unl)" + description "Hightail (World) (Demo 4F) (Aftermarket) (Unl)" + rom ( name "Hightail (World) (Demo 4F) (Aftermarket) (Unl).gbc" size 524288 crc f199c768 sha1 c794f30bedc69aa4d3567ab8f06f4ad651d5be24 ) +) + +game ( + name "Hightail (World) (Demo 4A) (Aftermarket) (Unl)" + description "Hightail (World) (Demo 4A) (Aftermarket) (Unl)" + rom ( name "Hightail (World) (Demo 4A) (Aftermarket) (Unl).gbc" size 262144 crc 8f01efcb sha1 bbf1f2af7594862f94b72f2f5a7be54040aa8569 ) +) + +game ( + name "Hime's Quest (World) (Aftermarket) (Unl)" + description "Hime's Quest (World) (Aftermarket) (Unl)" + rom ( name "Hime's Quest (World) (Aftermarket) (Unl).gbc" size 2097152 crc 546f578a sha1 ff90ca3ec7fb5d02865ae3cfd807ad3541dd21fc ) +) + +game ( + name "Hime's Quest (World) (Digital) (Aftermarket) (Unl)" + description "Hime's Quest (World) (Digital) (Aftermarket) (Unl)" + rom ( name "Hime's Quest (World) (Digital) (Aftermarket) (Unl).gbc" size 2097152 crc de5c21c2 sha1 7b6672c46c23aaa282bd4fded0713c6dfae2eb66 ) +) + +game ( + name "Hopp It (World) (Aftermarket) (Unl)" + description "Hopp It (World) (Aftermarket) (Unl)" + rom ( name "Hopp It (World) (Aftermarket) (Unl).gbc" size 262144 crc 675fbae3 sha1 cc10828f99675068eb79310b629f1365540b2979 ) +) + +game ( + name "Host, The (World) (Aftermarket) (Unl)" + description "Host, The (World) (Aftermarket) (Unl)" + rom ( name "Host, The (World) (Aftermarket) (Unl).gbc" size 524288 crc 5f783000 sha1 05cc1f1e52167c6985ebb0a3e67af1fc2fbff93c ) +) + +game ( + name "Hugo (World) (Aftermarket) (Unl)" + description "Hugo (World) (Aftermarket) (Unl)" + rom ( name "Hugo (World) (Aftermarket) (Unl).gbc" size 524288 crc 6581c78a sha1 390d2665f34ceaa5e34cc9f8f7c26d9e7583a92b ) +) + +game ( + name "Hunt the Gwumbus (World) (v2.1) (Aftermarket) (Unl)" + description "Hunt the Gwumbus (World) (v2.1) (Aftermarket) (Unl)" + rom ( name "Hunt the Gwumbus (World) (v2.1) (Aftermarket) (Unl).gbc" size 524288 crc 956f1e5d sha1 66769e2feb53ad70503849f271146c6f830bc2fe ) +) + +game ( + name "Hunter in the Lost Forest (World) (En) (GB Compatible) (Aftermarket) (Unl)" + description "Hunter in the Lost Forest (World) (En) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Hunter in the Lost Forest (World) (En) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc feac2611 sha1 1b10f2ec15d25584da2f2c123ecc97df7f7a0af0 ) +) + +game ( + name "Hunter in the Lost Forest (World) (Ja) (GB Compatible) (Aftermarket) (Unl)" + description "Hunter in the Lost Forest (World) (Ja) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Hunter in the Lost Forest (World) (Ja) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc ee633b7b sha1 6fc0ab0c6dffc8925ceb538ffc78cc70cd4ac0e4 ) +) + +game ( + name "Infall (World) (Aftermarket) (Unl)" + description "Infall (World) (Aftermarket) (Unl)" + rom ( name "Infall (World) (Aftermarket) (Unl).gbc" size 131072 crc d9d90319 sha1 aafaf33fa43c7f0fd65cc8af03a42df25361fc74 ) +) + +game ( + name "Inscryption (World) (v0.5) (Aftermarket) (Unl)" + description "Inscryption (World) (v0.5) (Aftermarket) (Unl)" + rom ( name "Inscryption (World) (v0.5) (Aftermarket) (Unl).gbc" size 524288 crc ae0a1c16 sha1 480ce539500d814fd3822fed7525c21027ac361b ) +) + +game ( + name "Inspector Waffles Early Days (World) (v1.0.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Inspector Waffles Early Days (World) (v1.0.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Inspector Waffles Early Days (World) (v1.0.1) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc fea1cdb9 sha1 ac10ca63f15ca78af9f7d0eabb85eef8733aef50 ) +) + +game ( + name "Iron Cor - Stainless (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" + description "Iron Cor - Stainless (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Iron Cor - Stainless (World) (v2.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc d6c1c1ac sha1 d722e95155455cf146a97222ccbc2237bea86509 ) +) + +game ( + name "Jayro's Game Boy Test Cartridge (World) (v1.18) (GB Compatible) (Aftermarket) (Unl)" + description "Jayro's Game Boy Test Cartridge (World) (v1.18) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Jayro's Game Boy Test Cartridge (World) (v1.18) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 9e97ac30 sha1 c07237d0f9c13b36ac2fcc5324b6e81122b0e189 ) +) + +game ( + name "Jet Set Willy (World) (Aftermarket) (Unl)" + description "Jet Set Willy (World) (Aftermarket) (Unl)" + rom ( name "Jet Set Willy (World) (Aftermarket) (Unl).gbc" size 262144 crc 659295ee sha1 bcb5a0e4566572aeb6cddea0897903ba207dc54f ) +) + +game ( + name "Jet Set Willy II - The Final Frontier (World) (Aftermarket) (Unl)" + description "Jet Set Willy II - The Final Frontier (World) (Aftermarket) (Unl)" + rom ( name "Jet Set Willy II - The Final Frontier (World) (Aftermarket) (Unl).gbc" size 524288 crc 8a4c58fa sha1 2e5b5a943b9f449bccb968b52ebc3dc8a4b3cb83 ) +) + +game ( + name "Judy's Adventure (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Judy's Adventure (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Judy's Adventure (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 8884d532 sha1 a41195443613fb4414d8536b1f3494677f6f253d ) +) + +game ( + name "Judy's Adventure (World) (v11.3) (GB Compatible) (Aftermarket) (Unl)" + description "Judy's Adventure (World) (v11.3) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Judy's Adventure (World) (v11.3) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 570a8043 sha1 1ccbf555412a417135acea0b7b185a7f795a89da ) +) + +game ( + name "Junior Maths 2 (World) (Aftermarket) (Unl)" + description "Junior Maths 2 (World) (Aftermarket) (Unl)" + rom ( name "Junior Maths 2 (World) (Aftermarket) (Unl).gbc" size 262144 crc 72c67d63 sha1 648273123a1bb64cd7fda7f611bb9cf53a5b0214 ) +) + +game ( + name "Kero Kero Cowboy (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Kero Kero Cowboy (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Kero Kero Cowboy (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 6a5abba1 sha1 0b3deef7a27201e81b4d39bc0bd10ff7ec73e380 ) +) + +game ( + name "Kikstart (World) (Aftermarket) (Unl)" + description "Kikstart (World) (Aftermarket) (Unl)" + rom ( name "Kikstart (World) (Aftermarket) (Unl).gbc" size 524288 crc 9a9f483b sha1 bc472506f73f0c1a3f0a610c0136b324b7635c7f ) +) + +game ( + name "Knit-Wit (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Knit-Wit (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Knit-Wit (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc f19d5e86 sha1 0f0e01a143182a9784c80a882ac206d02d8679d7 ) +) + +game ( + name "KnockOut (World) (Aftermarket) (Unl)" + description "KnockOut (World) (Aftermarket) (Unl)" + rom ( name "KnockOut (World) (Aftermarket) (Unl).gbc" size 131072 crc a060e59f sha1 164e078fce73674e3a5ad1cfd9e881813ce7a210 ) +) + +game ( + name "Larion's Tinker Toys (World) (Proto 2) (Aftermarket) (Unl)" + description "Larion's Tinker Toys (World) (Proto 2) (Aftermarket) (Unl)" + rom ( name "Larion's Tinker Toys (World) (Proto 2) (Aftermarket) (Unl).gbc" size 262144 crc fe421365 sha1 545551a382899d3689e2a501ccaccf500b9291df ) +) + +game ( + name "Larion's Tinker Toys (World) (Proto 1) (Aftermarket) (Unl)" + description "Larion's Tinker Toys (World) (Proto 1) (Aftermarket) (Unl)" + rom ( name "Larion's Tinker Toys (World) (Proto 1) (Aftermarket) (Unl).gbc" size 262144 crc 317d6e20 sha1 1867920232b32cf95eedfd47d9935e2d482c567d ) +) + +game ( + name "Laser Squad Alter (World) (Aftermarket) (Unl)" + description "Laser Squad Alter (World) (Aftermarket) (Unl)" + rom ( name "Laser Squad Alter (World) (Aftermarket) (Unl).gbc" size 1048576 crc 32f24248 sha1 26f4efe636214e72ec724f8887ca79fbc8abad80 ) +) + +game ( + name "Last Crown Warriors (World) (v1.0.1) (Demo) (Kickstarter) (GB Compatible) (Aftermarket) (Unl)" + description "Last Crown Warriors (World) (v1.0.1) (Demo) (Kickstarter) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Last Crown Warriors (World) (v1.0.1) (Demo) (Kickstarter) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 4a58315b sha1 5a234e33f7429b48f4374b5989e6df4d20352b4c ) +) + +game ( + name "Last Crown Warriors (World) (v2.1.0) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Last Crown Warriors (World) (v2.1.0) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Last Crown Warriors (World) (v2.1.0) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 5c405584 sha1 3ee043ba17f46a6afbbba8ac05f35d093b817fbc ) +) + +game ( + name "Last Crown Warriors (World) (v2.1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Last Crown Warriors (World) (v2.1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Last Crown Warriors (World) (v2.1.1) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 9a134100 sha1 75b5188a5b8a720ff08894379147c7870ac8825d ) +) + +game ( + name "Leaper (World) (Aftermarket) (Unl)" + description "Leaper (World) (Aftermarket) (Unl)" + rom ( name "Leaper (World) (Aftermarket) (Unl).gbc" size 524288 crc ed8cd385 sha1 425db2916263121f4aee91a8cab6286e39364f87 ) +) + +game ( + name "Lee Carvallo's Putting Challenge II (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + description "Lee Carvallo's Putting Challenge II (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Lee Carvallo's Putting Challenge II (World) (v1.2) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc e8f402e2 sha1 16633011144af9519037672f67f42c9a9459bb65 ) +) + +game ( + name "Lee Carvallo's Putting Challenge II (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Lee Carvallo's Putting Challenge II (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Lee Carvallo's Putting Challenge II (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 67f5a155 sha1 9f25aaf58f440cc62992b3268d239399fb5b377b ) +) + +game ( + name "Lee Carvallo's Putting Challenge II (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + description "Lee Carvallo's Putting Challenge II (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Lee Carvallo's Putting Challenge II (World) (v1.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 915b7710 sha1 10d60a8d381b547e622e84859ee6ae7f19995818 ) +) + +game ( + name "Legacy of Verintia (World) (2023-05-15) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Legacy of Verintia (World) (2023-05-15) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Legacy of Verintia (World) (2023-05-15) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 953e25d1 sha1 018c7cada41e693a02b9c596d307b0aa9207eef4 ) +) + +game ( + name "Legacy of Verintia (World) (2023-05-31) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Legacy of Verintia (World) (2023-05-31) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Legacy of Verintia (World) (2023-05-31) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 1096252a sha1 c22cc79b25a05afad66e769dc0365b7c25f1bb85 ) +) + +game ( + name "Legend of Carrot (World) (Aftermarket) (Unl)" + description "Legend of Carrot (World) (Aftermarket) (Unl)" + rom ( name "Legend of Carrot (World) (Aftermarket) (Unl).gbc" size 131072 crc 965a02af sha1 fa404e1b2b4544b4969c14ec41f81e87304234c8 ) +) + +game ( + name "Let's Bee Friends (World) (GB Compatible) (Aftermarket) (Unl)" + description "Let's Bee Friends (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Let's Bee Friends (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc a91a698f sha1 26f38b3908c086b3e349324da32bc37213975030 ) +) + +game ( + name "Liberator (World) (Aftermarket) (Unl)" + description "Liberator (World) (Aftermarket) (Unl)" + rom ( name "Liberator (World) (Aftermarket) (Unl).gbc" size 262144 crc ebe70d3d sha1 e3afce5a2357732ed15d7f3c0900f7b48113efdc ) +) + +game ( + name "Lightseeker (World) (GB Compatible) (Aftermarket) (Unl)" + description "Lightseeker (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Lightseeker (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc b8dd8409 sha1 281abb583ec0039e2c981c2e95f7a92002da081b ) +) + +game ( + name "Loco-coco (World) (Aftermarket) (Unl)" + description "Loco-coco (World) (Aftermarket) (Unl)" + rom ( name "Loco-coco (World) (Aftermarket) (Unl).gbc" size 262144 crc f6b9fe4e sha1 8a8972ff3e208280a746a2015a20f67248180a1c ) +) + +game ( + name "Love is Dead (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Love is Dead (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Love is Dead (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc dd537a3b sha1 f3e44fea9faed10c0aebaf11dd2f7821076a7315 ) +) + +game ( + name "Lunar Docking (World) (2021-12-30) (Aftermarket) (Unl)" + description "Lunar Docking (World) (2021-12-30) (Aftermarket) (Unl)" + rom ( name "Lunar Docking (World) (2021-12-30) (Aftermarket) (Unl).gbc" size 262144 crc 9edd066c sha1 4d43a38e8b5df41309f5b6ec13e4829db739d980 ) +) + +game ( + name "Lunar Docking (World) (2022-08-07) (Aftermarket) (Unl)" + description "Lunar Docking (World) (2022-08-07) (Aftermarket) (Unl)" + rom ( name "Lunar Docking (World) (2022-08-07) (Aftermarket) (Unl).gbc" size 262144 crc de5d5c0b sha1 5f038ef3657d3fbfb3be6917b24c3f933363ad4c ) +) + +game ( + name "Lunatic Tower (World) (Aftermarket) (Unl)" + description "Lunatic Tower (World) (Aftermarket) (Unl)" + rom ( name "Lunatic Tower (World) (Aftermarket) (Unl).gbc" size 524288 crc 6edacbb3 sha1 ee706a5f6272bda950a5d80ffc071453a9880fb6 ) +) + +game ( + name "Machine, The (World) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Machine, The (World) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Machine, The (World) (v1.1) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc f55a9d95 sha1 2b22fbd76e11e6e45053b1e6989de303e3033c9e ) +) + +game ( + name "Machine, The (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Machine, The (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Machine, The (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 5662865e sha1 a5ac99a4087bd5ea45417e5b4a7c9af10433911a ) +) + +game ( + name "Mage and the Grimoire of Beast (World) (En) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + description "Mage and the Grimoire of Beast (World) (En) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Mage and the Grimoire of Beast (World) (En) (v1.01) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 4197bfd5 sha1 83f15e10963a2991636a382168aa035c7f340b3c ) +) + +game ( + name "Mage and the Grimoire of Beast (World) (Ja) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + description "Mage and the Grimoire of Beast (World) (Ja) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Mage and the Grimoire of Beast (World) (Ja) (v1.01) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 6d8126b4 sha1 89d7df077818f000fef3c59429a6deb1a423aa03 ) +) + +game ( + name "Magic & Legend - Time Knights (World) (Demo) (The Retro Room) (GB Compatible) (Aftermarket) (Unl)" + description "Magic & Legend - Time Knights (World) (Demo) (The Retro Room) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Magic & Legend - Time Knights (World) (Demo) (The Retro Room) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc c276843d sha1 852697a2952d2e7375b73aba877ebc17aa4f4179 ) +) + +game ( + name "Magician's Curse, The (World) (Aftermarket) (Unl)" + description "Magician's Curse, The (World) (Aftermarket) (Unl)" + rom ( name "Magician's Curse, The (World) (Aftermarket) (Unl).gbc" size 524288 crc f2b1967e sha1 3b5f97f9a0b4d63a3795695b0bda6e969de8e051 ) +) + +game ( + name "Mayhem (World) (Aftermarket) (Unl)" + description "Mayhem (World) (Aftermarket) (Unl)" + rom ( name "Mayhem (World) (Aftermarket) (Unl).gbc" size 262144 crc 4d739ad7 sha1 9f141728a74432820f47cc24d230dc56d6ac099b ) +) + +game ( + name "Meiji Jingu (World) (Aftermarket) (Unl)" + description "Meiji Jingu (World) (Aftermarket) (Unl)" + rom ( name "Meiji Jingu (World) (Aftermarket) (Unl).gbc" size 262144 crc 56905954 sha1 9656d278857f6cfa08b8820409b665306c3d18aa ) +) + +game ( + name "Melanie and the Magic Forest (World) (GB Compatible) (Aftermarket) (Unl)" + description "Melanie and the Magic Forest (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Melanie and the Magic Forest (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc f614bdff sha1 7e46c193f6566f620acf20ead3a1fca1d677c221 ) +) + +game ( + name "Melanie and the Magic Forest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Melanie and the Magic Forest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Melanie and the Magic Forest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 949c6ab9 sha1 34269af4db6c37b92fdc7f7f914c282174603ba8 ) +) + +game ( + name "Memory Mania Challenge (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + description "Memory Mania Challenge (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Memory Mania Challenge (World) (v1.3) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 50618f4b sha1 c8d74af4746313800df3a23c1ad01f931e0e2eca flags verified ) +) + +game ( + name "Meteorite (World) (Aftermarket) (Unl)" + description "Meteorite (World) (Aftermarket) (Unl)" + rom ( name "Meteorite (World) (Aftermarket) (Unl).gbc" size 131072 crc fafbcebf sha1 25a81d916f1ed80a2bca2fe7a555433f06d025e3 ) +) + +game ( + name "Midterm Moments (World) (2022-05-28) (GB Compatible) (Aftermarket) (Unl)" + description "Midterm Moments (World) (2022-05-28) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Midterm Moments (World) (2022-05-28) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc f9a5ed4e sha1 8b3e18287d5adf3b5a711e28a896f843927f22a2 ) +) + +game ( + name "Midterm Moments (World) (2022-06-15) (GB Compatible) (Aftermarket) (Unl)" + description "Midterm Moments (World) (2022-06-15) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Midterm Moments (World) (2022-06-15) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 177f0b6e sha1 e5fdb741d870de25affdc841c07eaa3000da25f5 ) +) + +game ( + name "Mirror Between Us, The (World) (GB Compatible) (Aftermarket) (Unl)" + description "Mirror Between Us, The (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Mirror Between Us, The (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 854f4297 sha1 a1a44ce8052f06349df3cbdf9a6d976609213d68 ) +) + +game ( + name "Mission Mars (World) (Aftermarket) (Unl)" + description "Mission Mars (World) (Aftermarket) (Unl)" + rom ( name "Mission Mars (World) (Aftermarket) (Unl).gbc" size 262144 crc f651fcf4 sha1 479c70dd9c63cdcad99ca44720a9e0e2582df119 ) +) + +game ( + name "Mob Creche Parallel Game (World) (En,Ja) (Aftermarket) (Unl)" + description "Mob Creche Parallel Game (World) (En,Ja) (Aftermarket) (Unl)" + rom ( name "Mob Creche Parallel Game (World) (En,Ja) (Aftermarket) (Unl).gbc" size 262144 crc e138c5a5 sha1 9446639471efe21304c0c09c9540010941ae3f9f ) +) + +game ( + name "Mommy (World) (GB Compatible) (Aftermarket) (Unl)" + description "Mommy (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Mommy (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 5d644d24 sha1 3bc152e2899d54d6c400e2e0a114e0aa67a56a69 ) +) + +game ( + name "Mona and the Witch's Hat Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" + description "Mona and the Witch's Hat Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Mona and the Witch's Hat Deluxe (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 39480c79 sha1 4348a7903e538e5367f2a60718f43cbeeccf96df ) +) + +game ( + name "Monkey Magic (World) (Aftermarket) (Unl)" + description "Monkey Magic (World) (Aftermarket) (Unl)" + rom ( name "Monkey Magic (World) (Aftermarket) (Unl).gbc" size 262144 crc c9c68715 sha1 bf5dc5593334fe1114461065a2b7284d28b31462 ) +) + +game ( + name "Monty on the Run (World) (Aftermarket) (Unl)" + description "Monty on the Run (World) (Aftermarket) (Unl)" + rom ( name "Monty on the Run (World) (Aftermarket) (Unl).gbc" size 524288 crc fd1066ac sha1 8390175e6be4731d9afa91715d7f8dd11693bb69 ) +) + +game ( + name "Mount Vesuvius (World) (Aftermarket) (Unl)" + description "Mount Vesuvius (World) (Aftermarket) (Unl)" + rom ( name "Mount Vesuvius (World) (Aftermarket) (Unl).gbc" size 262144 crc 1292ecfb sha1 dd71a1a7282a8a68c70d705d8eab8b2bd73132e3 ) +) + +game ( + name "Mountain Climber (World) (En,Es) (GB Compatible) (Aftermarket) (Unl)" + description "Mountain Climber (World) (En,Es) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Mountain Climber (World) (En,Es) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 362a84ba sha1 b4b3afa2379a07acab6965ae8fcf6d2ba82d6d7e ) +) + +game ( + name "Mr. Angry (World) (Aftermarket) (Unl)" + description "Mr. Angry (World) (Aftermarket) (Unl)" + rom ( name "Mr. Angry (World) (Aftermarket) (Unl).gbc" size 524288 crc b85e63a5 sha1 127ad5315e2bce37614a1e9f8605798e68718926 ) +) + +game ( + name "Mud Warriors (World) (GB Compatible) (Aftermarket) (Unl)" + description "Mud Warriors (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Mud Warriors (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 846afc79 sha1 dae84fbc60839da29878714cd845c3704b915323 ) +) + +game ( + name "Munch It (World) (Aftermarket) (Unl)" + description "Munch It (World) (Aftermarket) (Unl)" + rom ( name "Munch It (World) (Aftermarket) (Unl).gbc" size 262144 crc 3d7ce6c7 sha1 55b390866d0922685bd1f42e8ee7310f021fa0dc ) +) + +game ( + name "Musical Notes (World) (2023-05-27) (Aftermarket) (Unl)" + description "Musical Notes (World) (2023-05-27) (Aftermarket) (Unl)" + rom ( name "Musical Notes (World) (2023-05-27) (Aftermarket) (Unl).gbc" size 524288 crc ec4f9d49 sha1 357db81755f1f0eb732367dd4090c446eb226ddf ) +) + +game ( + name "Musical Notes (World) (2023-05-19) (Aftermarket) (Unl)" + description "Musical Notes (World) (2023-05-19) (Aftermarket) (Unl)" + rom ( name "Musical Notes (World) (2023-05-19) (Aftermarket) (Unl).gbc" size 524288 crc 1ba7d27f sha1 d4c4be65ba469369cd90aaa733d0a8e8af6bcdc1 ) +) + +game ( + name "My Friendly Little Island (World) (GB Showdown) (GB Compatible) (Aftermarket) (Unl)" + description "My Friendly Little Island (World) (GB Showdown) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "My Friendly Little Island (World) (GB Showdown) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 9bff7b15 sha1 1f3aac8a3725cd1d0968529afc1c2031372d8ed1 ) +) + +game ( + name "My Friendly Little Island (World) (Aftermarket) (Unl)" + description "My Friendly Little Island (World) (Aftermarket) (Unl)" + rom ( name "My Friendly Little Island (World) (Aftermarket) (Unl).gbc" size 1048576 crc f6bf0584 sha1 81d724ad696084283712145adfef15769648b045 ) +) + +game ( + name "Neclaus' Quest (World) (GB Compatible) (Aftermarket) (Unl)" + description "Neclaus' Quest (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Neclaus' Quest (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc eedefa0c sha1 e63c16fe987fe655408be66198366a0147ac607c ) +) + +game ( + name "Neclaus' Quest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Neclaus' Quest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Neclaus' Quest (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 53cf930c sha1 bd3272ca7ead64da3f68f774661a560add433b94 ) +) + +game ( + name "Neighbor (World) (GB Compatible) (Aftermarket) (Unl)" + description "Neighbor (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Neighbor (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 705b150f sha1 6258cf6ad167c9ae86609a8e620face1674a7ea7 ) +) + +game ( + name "Neonsomnia (World) (v0.1) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Neonsomnia (World) (v0.1) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Neonsomnia (World) (v0.1) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 394ce9cb sha1 3d24808bf0bb1a06212a48309d8affe5d26eeeba ) +) + +game ( + name "Nightmare Hamlet (World) (Aftermarket) (Unl)" + description "Nightmare Hamlet (World) (Aftermarket) (Unl)" + rom ( name "Nightmare Hamlet (World) (Aftermarket) (Unl).gbc" size 131072 crc 574bf5b6 sha1 05d043816bb4eb9cc57b369ab5f966b610ba5c2f ) +) + +game ( + name "Ninja Master (World) (Aftermarket) (Unl)" + description "Ninja Master (World) (Aftermarket) (Unl)" + rom ( name "Ninja Master (World) (Aftermarket) (Unl).gbc" size 262144 crc bc550b84 sha1 0def135723ac40e4981c88f8888afbd40a15bb40 ) +) + +game ( + name "Number Builder (World) (Aftermarket) (Unl)" + description "Number Builder (World) (Aftermarket) (Unl)" + rom ( name "Number Builder (World) (Aftermarket) (Unl).gbc" size 262144 crc b8609d43 sha1 92952b752f50af889db891acc9eed8436ac6b87e ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (v0.2.6) (Beta) (Aftermarket) (Unl)" + description "Nyghtmare - The Ninth King (World) (v0.2.6) (Beta) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - The Ninth King (World) (v0.2.6) (Beta) (Aftermarket) (Unl).gbc" size 1048576 crc e983e8d1 sha1 fc2a58d49327c88c895ae6681bde57e1a2687974 flags verified ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (v0.1.2) (Beta) (GB Compatible) (Aftermarket) (Unl)" + description "Nyghtmare - The Ninth King (World) (v0.1.2) (Beta) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - The Ninth King (World) (v0.1.2) (Beta) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc ef42955e sha1 485b4d672d9edda40f9191f5f5cc223046000e67 flags verified ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (v0.2.1) (Beta) (Aftermarket) (Unl)" + description "Nyghtmare - The Ninth King (World) (v0.2.1) (Beta) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - The Ninth King (World) (v0.2.1) (Beta) (Aftermarket) (Unl).gbc" size 1048576 crc 581efe4d sha1 125bb0564ee17f8e55046a1c25e53ee9a4254303 ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (v0.2.3) (Beta) (Aftermarket) (Unl)" + description "Nyghtmare - The Ninth King (World) (v0.2.3) (Beta) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - The Ninth King (World) (v0.2.3) (Beta) (Aftermarket) (Unl).gbc" size 1048576 crc e26ddbbb sha1 853115369b8ca583d038d00c1dde59b6a74b73a2 ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (v0.2.5) (Beta) (Aftermarket) (Unl)" + description "Nyghtmare - The Ninth King (World) (v0.2.5) (Beta) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - The Ninth King (World) (v0.2.5) (Beta) (Aftermarket) (Unl).gbc" size 1048576 crc 1e8ac5b9 sha1 99c11bef7feb17a9e7212cf9b6593478f671bc32 ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (Free Version) (GB Compatible) (Aftermarket) (Unl)" + description "Nyghtmare - The Ninth King (World) (Free Version) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - The Ninth King (World) (Free Version) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc f5df28c2 sha1 7b511444e1eb86fffcf93599a78e0e2c44aecc8a ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (Rev 1) (Free Version) (Aftermarket) (Unl)" + description "Nyghtmare - The Ninth King (World) (Rev 1) (Free Version) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - The Ninth King (World) (Rev 1) (Free Version) (Aftermarket) (Unl).gbc" size 2097152 crc 63bddc68 sha1 fab777e607bd8aba70eb65829143039dbe6ac08e ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (v0.1.0) (Beta) (GB Compatible) (Aftermarket) (Unl)" + description "Nyghtmare - The Ninth King (World) (v0.1.0) (Beta) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - The Ninth King (World) (v0.1.0) (Beta) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 1f1af42a sha1 ddcdbfa716d716e1b7bb258caaaa7b76d041b5a9 ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (v0.1.2) (Beta) (GB Compatible) (Aftermarket) (Unl) (Alt)" + description "Nyghtmare - The Ninth King (World) (v0.1.2) (Beta) (GB Compatible) (Aftermarket) (Unl) (Alt)" + rom ( name "Nyghtmare - The Ninth King (World) (v0.1.2) (Beta) (GB Compatible) (Aftermarket) (Unl) (Alt).gbc" size 524288 crc 834a8021 sha1 d5af2bf38eda4c181993e992764788003509ebfd ) +) + +game ( + name "Nyghtmare - The Ninth King (World) (v0.1.9) (Beta) (GB Compatible) (Aftermarket) (Unl)" + description "Nyghtmare - The Ninth King (World) (v0.1.9) (Beta) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Nyghtmare - The Ninth King (World) (v0.1.9) (Beta) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 42d9c38c sha1 ae719190cf2f433c359bc425775710f4aa67e860 ) +) + +game ( + name "Octopus Stressus (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Octopus Stressus (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Octopus Stressus (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 2c055ef9 sha1 d4fa4e02753a9fe539f70d0927ba5bf9caa02d3c ) +) + +game ( + name "Octopus Stressus (World) (GB Compatible) (Aftermarket) (Unl)" + description "Octopus Stressus (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Octopus Stressus (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 7ed58128 sha1 e543c39f8e55b1788476b94028a54fc2fc9c7ea0 ) +) + +game ( + name "Office Combat (World) (GB Compatible) (Aftermarket) (Unl)" + description "Office Combat (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Office Combat (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 9742276d sha1 cd8f18d6e5fabaa130a42e5618e29c5ff26f6a93 ) +) + +game ( + name "Olympic Skier (World) (Aftermarket) (Unl)" + description "Olympic Skier (World) (Aftermarket) (Unl)" + rom ( name "Olympic Skier (World) (Aftermarket) (Unl).gbc" size 524288 crc 5e81cef7 sha1 a7a552a9eb984098a67e063c2eca907eec000fc1 ) +) + +game ( + name "One Day (World) (GB Compatible) (Aftermarket) (Unl)" + description "One Day (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "One Day (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc fd52acc7 sha1 bdb5590b61791b89e9afa871d32648d7a66ce1f4 ) +) + +game ( + name "Opossum Country (World) (GB Compatible) (Aftermarket) (Unl)" + description "Opossum Country (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Opossum Country (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 7348bb32 sha1 e63e06d602473206b21138f5322acf86b5b6b9b8 ) +) + +game ( + name "Out on a Limb (World) (Aftermarket) (Unl)" + description "Out on a Limb (World) (Aftermarket) (Unl)" + rom ( name "Out on a Limb (World) (Aftermarket) (Unl).gbc" size 262144 crc a6671528 sha1 f21cb71adcea1029151930eb98c4e9b446e4cfee ) +) + +game ( + name "Outta Time (World) (Aftermarket) (Unl)" + description "Outta Time (World) (Aftermarket) (Unl)" + rom ( name "Outta Time (World) (Aftermarket) (Unl).gbc" size 262144 crc 18522ba7 sha1 e9ef4c1d24e42ba7920bf8e7d72f804f058b93c6 ) +) + +game ( + name "Outward (World) (Aftermarket) (Unl)" + description "Outward (World) (Aftermarket) (Unl)" + rom ( name "Outward (World) (Aftermarket) (Unl).gbc" size 131072 crc c554bf64 sha1 6cfb29fed8ce82384d9051424a4b55673c182c8f ) +) + +game ( + name "Pacifist, The (World) (GB Compatible) (Aftermarket) (Unl)" + description "Pacifist, The (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Pacifist, The (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc c6e83f41 sha1 44b117d94a80617a77abbdcc76d9d69b66efe56b ) +) + +game ( + name "Pacifist, The (World) (GB Showdown) (GB Compatible) (Aftermarket) (Unl)" + description "Pacifist, The (World) (GB Showdown) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Pacifist, The (World) (GB Showdown) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 69483f81 sha1 4d162c9637a20cfc7c92e6ea7a61fad0ed22137a ) +) + +game ( + name "Pact, The (World) (GB Showdown) (Aftermarket) (Unl)" + description "Pact, The (World) (GB Showdown) (Aftermarket) (Unl)" + rom ( name "Pact, The (World) (GB Showdown) (Aftermarket) (Unl).gbc" size 262144 crc 0db301c2 sha1 58ec8f209ed6e33adfb253014ea69ae1ee53c145 ) +) + +game ( + name "Pact, The (World) (Aftermarket) (Unl)" + description "Pact, The (World) (Aftermarket) (Unl)" + rom ( name "Pact, The (World) (Aftermarket) (Unl).gbc" size 262144 crc 304df19a sha1 97af064f9063cd353e55ac0e1f6d1ca8b4a6d2b9 ) +) + +game ( + name "Paku Paku GB (World) (GB Compatible) (Aftermarket) (Unl)" + description "Paku Paku GB (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Paku Paku GB (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc 62b5a15f sha1 2b85528aef01cb5caab4cff898c2bc66e211b3bf ) +) + +game ( + name "Pancho (World) (Aftermarket) (Unl)" + description "Pancho (World) (Aftermarket) (Unl)" + rom ( name "Pancho (World) (Aftermarket) (Unl).gbc" size 524288 crc d32d46c5 sha1 2f46974e6d92f5deb277818d95426a4507b3701d ) +) + +game ( + name "Panik!16 (World) (Aftermarket) (Unl)" + description "Panik!16 (World) (Aftermarket) (Unl)" + rom ( name "Panik!16 (World) (Aftermarket) (Unl).gbc" size 262144 crc 7b31122d sha1 98d74fd64e4f7e835f1101b05816b8938a34a416 ) +) + +game ( + name "Phantom Fright (World) (GB Compatible) (Aftermarket) (Unl)" + description "Phantom Fright (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Phantom Fright (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 154cb547 sha1 3b217c595e6a5b115dc7130123a321049cf01d22 ) +) + +game ( + name "Pilgrim's Peril (World) (Demo 1) (GB Compatible) (Aftermarket) (Unl)" + description "Pilgrim's Peril (World) (Demo 1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Pilgrim's Peril (World) (Demo 1) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 3c2bafdc sha1 d38f3f5e491dbaed84e88099987712449db9b33d ) +) + +game ( + name "Pilgrim's Peril (World) (Demo 2) (GB Compatible) (Aftermarket) (Unl)" + description "Pilgrim's Peril (World) (Demo 2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Pilgrim's Peril (World) (Demo 2) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc cdded15b sha1 2b85eb77ab2dcea4f645abcc1a66dbce54a6ebaa ) +) + +game ( + name "Pine Creek (World) (En-US,Es-MX,Pt-BR) (Beta) (GB Compatible) (Aftermarket) (Unl)" + description "Pine Creek (World) (En-US,Es-MX,Pt-BR) (Beta) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Pine Creek (World) (En-US,Es-MX,Pt-BR) (Beta) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 189aa999 sha1 2cf46a36502eaf22ac9572fe1136d369fcbe9e46 ) +) + +game ( + name "Pinecone Pizza Party (World) (Prototype) (GB Compatible) (Aftermarket) (Unl)" + description "Pinecone Pizza Party (World) (Prototype) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Pinecone Pizza Party (World) (Prototype) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 1601d6fa sha1 87b4edf0398f0154d7556e3cd96f97b19e699a40 ) +) + +game ( + name "PlayTime (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "PlayTime (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "PlayTime (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 29415ff7 sha1 89b3fd633e8cef3b8523b1ef2a0072db2d7416d7 ) +) + +game ( + name "Pogo Pete (World) (Aftermarket) (Unl)" + description "Pogo Pete (World) (Aftermarket) (Unl)" + rom ( name "Pogo Pete (World) (Aftermarket) (Unl).gbc" size 262144 crc 3001ed1b sha1 f9dab150843c2b8f300d36b1dd53dd1a22b481a3 ) +) + +game ( + name "Pokettohiro! (World) (v2.0) (Demo) (Aftermarket) (Unl)" + description "Pokettohiro! (World) (v2.0) (Demo) (Aftermarket) (Unl)" + rom ( name "Pokettohiro! (World) (v2.0) (Demo) (Aftermarket) (Unl).gbc" size 1048576 crc 42298fd8 sha1 90c535bf70e2ca7b91af67b8f08865f423c3034f ) +) + +game ( + name "Pokettohiro! (World) (v1.0) (Demo) (Aftermarket) (Unl)" + description "Pokettohiro! (World) (v1.0) (Demo) (Aftermarket) (Unl)" + rom ( name "Pokettohiro! (World) (v1.0) (Demo) (Aftermarket) (Unl).gbc" size 1048576 crc b9e724ef sha1 28a01fd6ea95a146008435c5bc27b51b607bb86b ) +) + +game ( + name "Pokettohiro! (World) (v3.0) (Demo) (Aftermarket) (Unl)" + description "Pokettohiro! (World) (v3.0) (Demo) (Aftermarket) (Unl)" + rom ( name "Pokettohiro! (World) (v3.0) (Demo) (Aftermarket) (Unl).gbc" size 2097152 crc b9b4e3c0 sha1 a8ba9c09ef0889640e41d79838bcd98b7bc4e5d4 ) +) + +game ( + name "Pomape Castle (World) (GB Compatible) (Aftermarket) (Unl)" + description "Pomape Castle (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Pomape Castle (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 9350c71d sha1 a0f449e270b72de56bfea151b5ac271c0c7e3c93 ) +) + +game ( + name "Postie (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Postie (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Postie (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 50393a65 sha1 2c2c6ed8be7a13bf279e435c5984f175c8affcad ) +) + +game ( + name "Postie (World) (GB Compatible) (Aftermarket) (Unl)" + description "Postie (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Postie (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc ff6bbc83 sha1 3ff236972d1e344eb50e696db3cc090f2b5d28b1 ) +) + +game ( + name "Postman Pat's Trail Game (World) (Aftermarket) (Unl)" + description "Postman Pat's Trail Game (World) (Aftermarket) (Unl)" + rom ( name "Postman Pat's Trail Game (World) (Aftermarket) (Unl).gbc" size 262144 crc ad31b512 sha1 135977fe71677e3c49450e2c6ff63105d10dfaac ) +) + +game ( + name "Potbound (World) (2022-09-27) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Potbound (World) (2022-09-27) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Potbound (World) (2022-09-27) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 6da19041 sha1 eb581935ad9223d723fdbc8339c03436df051947 ) +) + +game ( + name "Potbound (World) (2022-09-26) (Proto) (GBJam 10) (GB Compatible) (Aftermarket) (Unl)" + description "Potbound (World) (2022-09-26) (Proto) (GBJam 10) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Potbound (World) (2022-09-26) (Proto) (GBJam 10) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc d0d8386d sha1 fbddf81a1663388ff0efeeb9051e68e0c323c839 ) +) + +game ( + name "POWA! (World) (En) (GB Compatible) (Aftermarket) (Unl)" + description "POWA! (World) (En) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "POWA! (World) (En) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc f0191467 sha1 3876f1aa896759f427ad2dc88a48788817e60c06 flags verified ) +) + +game ( + name "POWA! (World) (Ja) (GB Compatible) (Aftermarket) (Unl)" + description "POWA! (World) (Ja) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "POWA! (World) (Ja) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc e8f68acc sha1 156d315b7a2a035d5cd429fb8c7e051e67e83c93 flags verified ) +) + +game ( + name "POWA! (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "POWA! (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "POWA! (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 592b6097 sha1 874d5e4ffc7d36259bef6ec6a86a1de8289b8d54 ) +) + +game ( + name "Power Ball - Monster's Quest (World) (v1.04) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Power Ball - Monster's Quest (World) (v1.04) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Power Ball - Monster's Quest (World) (v1.04) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc b01c4ff1 sha1 898dbf10550af7e39b8f7a0818a78083ae40f4fe ) +) + +game ( + name "Princess Poffin and the Spider Invasion! (World) (2023-06-04) (GB Compatible) (Aftermarket) (Unl)" + description "Princess Poffin and the Spider Invasion! (World) (2023-06-04) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Princess Poffin and the Spider Invasion! (World) (2023-06-04) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc a86cada1 sha1 b02096c489c0f36582061d6eb62beb17e8294b61 ) +) + +game ( + name "Princess Poffin and the Spider Invasion! (World) (2023-06-06) (GB Compatible) (Aftermarket) (Unl)" + description "Princess Poffin and the Spider Invasion! (World) (2023-06-06) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Princess Poffin and the Spider Invasion! (World) (2023-06-06) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc e171f327 sha1 b03df48f48529ac1be79699d6f34f324adcfb436 ) +) + +game ( + name "Proof of Destruction (World) (Aftermarket) (Unl)" + description "Proof of Destruction (World) (Aftermarket) (Unl)" + rom ( name "Proof of Destruction (World) (Aftermarket) (Unl).gbc" size 262144 crc fa528f88 sha1 5062f16346c31cae1b13e469cb610ce84d4eecb2 ) +) + +game ( + name "Purple Turtles (World) (Aftermarket) (Unl)" + description "Purple Turtles (World) (Aftermarket) (Unl)" + rom ( name "Purple Turtles (World) (Aftermarket) (Unl).gbc" size 262144 crc 471277df sha1 a73cb69d1fb42f45f3649c4d1b4775e98fe35b78 ) +) + +game ( + name "Quartet (World) (GB Compatible) (Aftermarket) (Unl)" + description "Quartet (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Quartet (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc 46743216 sha1 bf866b438a602af386f8fad02727b4084edf6047 ) +) + +game ( + name "Quest Arrest (World) (v1.1) (Digital) (GB Compatible) (Aftermarket) (Unl)" + description "Quest Arrest (World) (v1.1) (Digital) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Quest Arrest (World) (v1.1) (Digital) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 9ac546d5 sha1 25b3a21135bfc7587c096b10f4a20d8b3095d721 ) +) + +game ( + name "Quest of the MX-129 Wizard (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Quest of the MX-129 Wizard (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Quest of the MX-129 Wizard (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 776ab9fd sha1 65d98bae58e5e4f723b1ec838ad4e1f2036c4468 ) +) + +game ( + name "Raffles (World) (Aftermarket) (Unl)" + description "Raffles (World) (Aftermarket) (Unl)" + rom ( name "Raffles (World) (Aftermarket) (Unl).gbc" size 262144 crc e41d6472 sha1 4b5eb518ff52c235c674e0695fdde2b8b01f58fa ) +) + +game ( + name "Ravenia (World) (GB Compatible) (Aftermarket) (Unl)" + description "Ravenia (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ravenia (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 09196a32 sha1 8218ad22b29fb32c66430a17a97775dd30b2f34b flags verified ) +) + +game ( + name "Remi's Pizzaria (World) (GB Compatible) (Aftermarket) (Unl)" + description "Remi's Pizzaria (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Remi's Pizzaria (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc f7a4fcfb sha1 fdc8c8a1bab2dfcfe3e43175e830382fe63d5c7d ) +) + +game ( + name "Repugnant Bounty (World) (Demo) (GB Compo 2021) (GB Compatible) (Aftermarket) (Unl)" + description "Repugnant Bounty (World) (Demo) (GB Compo 2021) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Repugnant Bounty (World) (Demo) (GB Compo 2021) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc e92034d8 sha1 14b9614cea9be7d5c6e12aece692582ba2ca2b75 flags verified ) +) + +game ( + name "Repugnant Bounty (World) (v0.1.023) (Beta) (GB Compatible) (Aftermarket) (Unl)" + description "Repugnant Bounty (World) (v0.1.023) (Beta) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Repugnant Bounty (World) (v0.1.023) (Beta) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 3a1b1d83 sha1 4dda0cce6907de94eeae3f11a40238c3f5155ca7 ) +) + +game ( + name "Repugnant Bounty (World) (Demo) (Aftermarket) (Unl)" + description "Repugnant Bounty (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Repugnant Bounty (World) (Demo) (Aftermarket) (Unl).gbc" size 2097152 crc f8c7f180 sha1 07674d42f5d4efaec14750ae56d8f28c4b54c020 flags verified ) +) + +game ( + name "Retro Quiz Tower (World) (GB Compatible) (Aftermarket) (Unl)" + description "Retro Quiz Tower (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Retro Quiz Tower (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 8bd98942 sha1 3a5dbafa829e57089de8cfc93c806f7ee023ff1b ) +) + +game ( + name "Retro Quiz Tower (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + description "Retro Quiz Tower (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Retro Quiz Tower (World) (v1.2) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc c761189c sha1 f7f18d83218b66b9d1cd7267d6d4acfd4eded6c7 ) +) + +game ( + name "Rig Attack (World) (Aftermarket) (Unl)" + description "Rig Attack (World) (Aftermarket) (Unl)" + rom ( name "Rig Attack (World) (Aftermarket) (Unl).gbc" size 262144 crc d013d775 sha1 90bfd921c986abff4555b761cedc90ec36c43fff ) +) + +game ( + name "Ripjack (World) (GB Compatible) (Aftermarket) (Unl)" + description "Ripjack (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ripjack (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 218b54ec sha1 624cb4afcabd03f4f2f4bea95f9998a6a04ae42b ) +) + +game ( + name "River Styx Round-Up (World) (GB Compatible) (Aftermarket) (Unl)" + description "River Styx Round-Up (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "River Styx Round-Up (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc ae3f980b sha1 67f63517eacfea22922d07be0efc5fc8f8b8a1d2 ) +) + +game ( + name "Robin to the Rescue (World) (Aftermarket) (Unl)" + description "Robin to the Rescue (World) (Aftermarket) (Unl)" + rom ( name "Robin to the Rescue (World) (Aftermarket) (Unl).gbc" size 262144 crc 9cd52c18 sha1 ef3bea9ed0de41e311b5f15fccbb0f451848d56c ) +) + +game ( + name "Robo Knight (World) (Aftermarket) (Unl)" + description "Robo Knight (World) (Aftermarket) (Unl)" + rom ( name "Robo Knight (World) (Aftermarket) (Unl).gbc" size 524288 crc 8d4507f0 sha1 6012f9a3ae6201e363f46a75e0100552ecb91335 ) +) + +game ( + name "Rockets Vs Cars (World) (GB Compatible) (Aftermarket) (Unl)" + description "Rockets Vs Cars (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Rockets Vs Cars (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc eaae6f3e sha1 446e688f42e886c51c74719b93a326ae5b56920d ) +) + +game ( + name "Rockman (World) (Aftermarket) (Unl)" + description "Rockman (World) (Aftermarket) (Unl)" + rom ( name "Rockman (World) (Aftermarket) (Unl).gbc" size 262144 crc 490b5676 sha1 6f78200acb6698e268e26c1912d64a002cbd3d89 ) +) + +game ( + name "Rootin' Tootin' Cowboy Wizard Lizards (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Rootin' Tootin' Cowboy Wizard Lizards (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Rootin' Tootin' Cowboy Wizard Lizards (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 1fcdc59e sha1 e741ac0918ce14df473600d34836f744c2507fa0 ) +) + +game ( + name "Ruby & Rusty Save the Crows (World) (Beta 1) (GB Compatible) (Aftermarket) (Unl)" + description "Ruby & Rusty Save the Crows (World) (Beta 1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ruby & Rusty Save the Crows (World) (Beta 1) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc a46baa15 sha1 87dd5a6ccb5db59dae09f1953062420977ad2d92 ) +) + +game ( + name "Ruby & Rusty Save the Crows (World) (Beta 2) (GB Compatible) (Aftermarket) (Unl)" + description "Ruby & Rusty Save the Crows (World) (Beta 2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ruby & Rusty Save the Crows (World) (Beta 2) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 5602ca84 sha1 49d692796a6d0f3dcfc988648b446c0934f0e794 ) +) + +game ( + name "Ruby & Rusty Save the Crows (World) (Beta 3) (GB Compatible) (Aftermarket) (Unl)" + description "Ruby & Rusty Save the Crows (World) (Beta 3) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ruby & Rusty Save the Crows (World) (Beta 3) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc b2547aa6 sha1 981a464d6e1c9e5ac59549845b41dae4817ed3b8 ) +) + +game ( + name "Ruby & Rusty Save the Crows (World) (v2.6) (GB Compatible) (Aftermarket) (Unl)" + description "Ruby & Rusty Save the Crows (World) (v2.6) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ruby & Rusty Save the Crows (World) (v2.6) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc c18f82cb sha1 bd8cd5822dcc61f7eb0cf2584c9a5b5a94bde14a ) +) + +game ( + name "Ruin Run (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Ruin Run (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ruin Run (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc ddbfb0ce sha1 fb4730afe4e10529015513cc1dec8889c00cb373 ) +) + +game ( + name "RunieStory (World) (GB Showdown) (Aftermarket) (Unl)" + description "RunieStory (World) (GB Showdown) (Aftermarket) (Unl)" + rom ( name "RunieStory (World) (GB Showdown) (Aftermarket) (Unl).gbc" size 2097152 crc 96b1ceec sha1 771135edfbc64f7332a9cbd0d72af7a9d0d71f82 ) +) + +game ( + name "RunieStory (World) (Aftermarket) (Unl)" + description "RunieStory (World) (Aftermarket) (Unl)" + rom ( name "RunieStory (World) (Aftermarket) (Unl).gbc" size 2097152 crc 2249b449 sha1 0f6a391d7e05f66092a98e411069fab8e3f24221 ) +) + +game ( + name "RunieStory (World) (v1.1) (Aftermarket) (Unl)" + description "RunieStory (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "RunieStory (World) (v1.1) (Aftermarket) (Unl).gbc" size 2097152 crc dd81f722 sha1 f2ad05b15a4ed1611b0d5b52525d16a5f00867bc ) +) + +game ( + name "RunieStory (World) (Aftermarket) (Unl) (Alt)" + description "RunieStory (World) (Aftermarket) (Unl) (Alt)" + rom ( name "RunieStory (World) (Aftermarket) (Unl) (Alt).gbc" size 2097152 crc 367c802d sha1 b9ec81a8c71ea13b553b478535071715a2ab07d9 ) +) + +game ( + name "Runner (World) (Aftermarket) (Unl)" + description "Runner (World) (Aftermarket) (Unl)" + rom ( name "Runner (World) (Aftermarket) (Unl).gbc" size 262144 crc 4cd8ccb2 sha1 da735d415ed463a953bac45f4793342bd9be2e96 ) +) + +game ( + name "Sam the Optimistic Hedgehog (World) (2023-01-16) (GB Compatible) (Aftermarket) (Unl)" + description "Sam the Optimistic Hedgehog (World) (2023-01-16) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Sam the Optimistic Hedgehog (World) (2023-01-16) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 4e4af60b sha1 ab8d49a99d02eb5c97d75f62dfb3720eec2b5abd ) +) + +game ( + name "Sam the Optimistic Hedgehog (World) (2023-01-21) (GB Compatible) (Aftermarket) (Unl)" + description "Sam the Optimistic Hedgehog (World) (2023-01-21) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Sam the Optimistic Hedgehog (World) (2023-01-21) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 40dc168d sha1 af25acc86f0eef4ce72199383b96fcb4c9f0115e ) +) + +game ( + name "Sapphire Hotel - The Little Tales of (World) (v1.2) (Demo) (MBC5) (GB Compatible) (Aftermarket) (Unl)" + description "Sapphire Hotel - The Little Tales of (World) (v1.2) (Demo) (MBC5) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Sapphire Hotel - The Little Tales of (World) (v1.2) (Demo) (MBC5) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc db928e22 sha1 e175d35e6112c347ecd1e0a379e98f430823ba94 ) +) + +game ( + name "Sergio Kidd (World) (En,Es) (v2.013) (Aftermarket) (Unl)" + description "Sergio Kidd (World) (En,Es) (v2.013) (Aftermarket) (Unl)" + rom ( name "Sergio Kidd (World) (En,Es) (v2.013) (Aftermarket) (Unl).gbc" size 1048576 crc e23bc705 sha1 986708b9cb96c56e3592030d45dc5433d3aa63c5 ) +) + +game ( + name "Sergio Kidd (World) (En,Es) (v1.995) (Aftermarket) (Unl)" + description "Sergio Kidd (World) (En,Es) (v1.995) (Aftermarket) (Unl)" + rom ( name "Sergio Kidd (World) (En,Es) (v1.995) (Aftermarket) (Unl).gbc" size 1048576 crc 1d871322 sha1 e57357be09657bc42e5ccee937edcf1653468402 ) +) + +game ( + name "Shark Attack (World) (Aftermarket) (Unl)" + description "Shark Attack (World) (Aftermarket) (Unl)" + rom ( name "Shark Attack (World) (Aftermarket) (Unl).gbc" size 262144 crc cf80a2ba sha1 291f453a185f836fcafbd7e41945a409638980c0 ) +) + +game ( + name "Shoot It (World) (Aftermarket) (Unl)" + description "Shoot It (World) (Aftermarket) (Unl)" + rom ( name "Shoot It (World) (Aftermarket) (Unl).gbc" size 262144 crc 54afa0ff sha1 f3c574e274d1531e3f53511da0d57751e989a665 ) +) + +game ( + name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-12-09) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Silent Hill 2 - 20th Anniversary Demake (World) (2021-12-09) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-12-09) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 599132ec sha1 762087df0e5820f1e50da2a22f9ee3b8d16c3e49 ) +) + +game ( + name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-04-16) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Silent Hill 2 - 20th Anniversary Demake (World) (2021-04-16) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-04-16) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 5370b1bf sha1 966e2d79ab4930039c3d6c43fdbb8cdc068ba347 ) +) + +game ( + name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-08-24) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Silent Hill 2 - 20th Anniversary Demake (World) (2021-08-24) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-08-24) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 16f34bcc sha1 c34e744b9120e3a1b2b054d3708e4ab594726c5a ) +) + +game ( + name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-09-13) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Silent Hill 2 - 20th Anniversary Demake (World) (2021-09-13) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-09-13) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 31ce3f27 sha1 c33d685d5ea5cd6cd954af3bc9ee92719b9578b1 ) +) + +game ( + name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-11-07) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Silent Hill 2 - 20th Anniversary Demake (World) (2021-11-07) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-11-07) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc d54b53cb sha1 08948befa0227b795d00fe60e9eede6a1f56597b ) +) + +game ( + name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-12-03) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Silent Hill 2 - 20th Anniversary Demake (World) (2021-12-03) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Silent Hill 2 - 20th Anniversary Demake (World) (2021-12-03) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 314be6b5 sha1 37978f85ae92e7d9a53611659513fd360f57a5b1 ) +) + +game ( + name "Silent Hill 2 - Born From a Wish (World) (2023-10-03) (Demo) (Aftermarket) (Unl)" + description "Silent Hill 2 - Born From a Wish (World) (2023-10-03) (Demo) (Aftermarket) (Unl)" + rom ( name "Silent Hill 2 - Born From a Wish (World) (2023-10-03) (Demo) (Aftermarket) (Unl).gbc" size 524288 crc 7ebcdd4e sha1 b99f43719155cafbc3dbd7df0ade281c3c7ba171 ) +) + +game ( + name "Sir Knight (World) (Aftermarket) (Unl)" + description "Sir Knight (World) (Aftermarket) (Unl)" + rom ( name "Sir Knight (World) (Aftermarket) (Unl).gbc" size 262144 crc 8c31c136 sha1 d8be26e0688301a76def8f5fbc246a9c9005862e ) +) + +game ( + name "Skelby (World) (Aftermarket) (Unl)" + description "Skelby (World) (Aftermarket) (Unl)" + rom ( name "Skelby (World) (Aftermarket) (Unl).gbc" size 524288 crc 6ec6c18c sha1 887555aa7e2e61b68a21020237b7d508bb71aded ) +) + +game ( + name "Skull Nightmare (World) (Aftermarket) (Unl)" + description "Skull Nightmare (World) (Aftermarket) (Unl)" + rom ( name "Skull Nightmare (World) (Aftermarket) (Unl).gbc" size 131072 crc c36941d3 sha1 49f03694965f79688aef724308c83988e71fd374 ) +) + +game ( + name "Skycon (World) (Aftermarket) (Unl)" + description "Skycon (World) (Aftermarket) (Unl)" + rom ( name "Skycon (World) (Aftermarket) (Unl).gbc" size 524288 crc 195dbc30 sha1 df29ece6c5f5b14840663495230135dd79c5163a ) +) + +game ( + name "Slime Dungeon (World) (GB Compatible) (Aftermarket) (Unl)" + description "Slime Dungeon (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Slime Dungeon (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 3967fb31 sha1 926e584b8952aba86761b430daedc5b91177e408 ) +) + +game ( + name "Slime's Adventure (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Slime's Adventure (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Slime's Adventure (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 61b14549 sha1 87b84c85bb32a1d0874053cdf749f8391a275324 ) +) + +game ( + name "Sludge & Sorcery (World) (GB Compatible) (Aftermarket) (Unl)" + description "Sludge & Sorcery (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Sludge & Sorcery (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc c906c5af sha1 0e0d472b282e3ea590e0f126baf633ef0d9298fa ) +) + +game ( + name "Smickeonn - The Game 2 - Virtual Boy Edition (World) (Aftermarket) (Unl)" + description "Smickeonn - The Game 2 - Virtual Boy Edition (World) (Aftermarket) (Unl)" + rom ( name "Smickeonn - The Game 2 - Virtual Boy Edition (World) (Aftermarket) (Unl).gbc" size 1048576 crc 71ed0db8 sha1 e7b39b17e3e8e7ac1cf2e0b179e2c14874533835 ) +) + +game ( + name "Smickeonn - The Game Boy Adventure (World) (Aftermarket) (Unl)" + description "Smickeonn - The Game Boy Adventure (World) (Aftermarket) (Unl)" + rom ( name "Smickeonn - The Game Boy Adventure (World) (Aftermarket) (Unl).gbc" size 1048576 crc 96efbfb9 sha1 3900ab947af4c582cd34cec7f2977219115d65e4 ) +) + +game ( + name "Smickeonn - The Game Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" + description "Smickeonn - The Game Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Smickeonn - The Game Deluxe (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 02bb005e sha1 0c1bf424968530a70ecbe382d002fc6bd629962c ) +) + +game ( + name "Snail DX, The (World) (GB Compatible) (Aftermarket) (Unl)" + description "Snail DX, The (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Snail DX, The (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 1aecd096 sha1 8ce256d963a55badf71fd45047c173a74d76a92c ) +) + +game ( + name "Snail DX, The (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + description "Snail DX, The (World) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Snail DX, The (World) (v1.2) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 6cf39388 sha1 9cf5a1d3e8119303a1f4b04b8f4d8b683aee699e ) +) + +game ( + name "Snooze (World) (GB Compatible) (Aftermarket) (Unl)" + description "Snooze (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Snooze (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc b246095f sha1 b7fdcc006c9c06dd391ee26d44b278d9d3793f6d ) +) + +game ( + name "Sofia the Witch - Curse of the Monster Moon (World) (Demo) (Aftermarket) (Unl)" + description "Sofia the Witch - Curse of the Monster Moon (World) (Demo) (Aftermarket) (Unl)" + rom ( name "Sofia the Witch - Curse of the Monster Moon (World) (Demo) (Aftermarket) (Unl).gbc" size 2097152 crc 9e864f1c sha1 ce5dc23c04ff18dfac2367e53d241e81c4bbc3a3 ) +) + +game ( + name "Space Fleet (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Space Fleet (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Space Fleet (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc d9244730 sha1 6987a43315abca95b85d84c278a6b1ae5dea185a ) +) + +game ( + name "Space War (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Space War (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Space War (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc c54f07e1 sha1 de6107573654309805bbb0ac86a748311ae70d4e ) +) + +game ( + name "Spectipede (World) (Aftermarket) (Unl)" + description "Spectipede (World) (Aftermarket) (Unl)" + rom ( name "Spectipede (World) (Aftermarket) (Unl).gbc" size 262144 crc 9c33f76e sha1 834a450d9ceb78b9d89d551300d4d0ea08cd8a6a ) +) + +game ( + name "Spiky Harold (World) (Aftermarket) (Unl)" + description "Spiky Harold (World) (Aftermarket) (Unl)" + rom ( name "Spiky Harold (World) (Aftermarket) (Unl).gbc" size 262144 crc 7e9eda35 sha1 486d294b8cf226876581d543e3a08018321bc402 ) +) + +game ( + name "Star Hunt (World) (GB Compatible) (Aftermarket) (Unl)" + description "Star Hunt (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Star Hunt (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 29320841 sha1 890fda255106ea64bac4973e2e9f4b31bb925d35 ) +) + +game ( + name "StarFox - Grounded (World) (GB Compatible) (Aftermarket) (Unl)" + description "StarFox - Grounded (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "StarFox - Grounded (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 82658661 sha1 dd45b0e3f346ce33668d49092b29a44597686061 ) +) + +game ( + name "Stars of Zureon (World) (Proto 2) (GB Compatible) (Aftermarket) (Unl)" + description "Stars of Zureon (World) (Proto 2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Stars of Zureon (World) (Proto 2) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc ce90a95b sha1 75457c5affd0c126f2c916e857950b5cde46a95e ) +) + +game ( + name "Stars of Zureon (World) (Proto 1) (GB Compatible) (Aftermarket) (Unl)" + description "Stars of Zureon (World) (Proto 1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Stars of Zureon (World) (Proto 1) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc b3a04b44 sha1 b16f21b46dfe4e6ce0368e3c5a3fae397274ebbf ) +) + +game ( + name "Starseed (World) (GB Compatible) (Aftermarket) (Unl)" + description "Starseed (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Starseed (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc e21ff9e0 sha1 3479e222263814374a557870034bc215aea3408d ) +) + +game ( + name "Starseed 2 (World) (GB Compatible) (Aftermarket) (Unl)" + description "Starseed 2 (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Starseed 2 (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc dd4528d2 sha1 43a02f79fd5da23cfeccc13aa5970265f428dddc ) +) + +game ( + name "Stellar Wars (World) (Aftermarket) (Unl)" + description "Stellar Wars (World) (Aftermarket) (Unl)" + rom ( name "Stellar Wars (World) (Aftermarket) (Unl).gbc" size 262144 crc e0b96256 sha1 ba2d10a2a5f3f073aea11e26ae5c53c9cf7866f8 ) +) + +game ( + name "Stratacombo (World) (v1.2) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Stratacombo (World) (v1.2) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Stratacombo (World) (v1.2) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 43c70a69 sha1 9931a9e3a0e4a0edcd336acfb433713991a50ad2 ) +) + +game ( + name "Stratacombo (World) (v1.0) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "Stratacombo (World) (v1.0) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Stratacombo (World) (v1.0) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 06575da1 sha1 3c621c921d7995acb88754634328de8ec32b444b ) +) + +game ( + name "Stratagem Hero (World) (GB Compatible) (Aftermarket) (Unl)" + description "Stratagem Hero (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Stratagem Hero (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc ff118db9 sha1 f89ff66e8e593729ed9605b0107ed6d12d9b858d ) +) + +game ( + name "Suicide Run (World) (GB Compatible) (Aftermarket) (Unl)" + description "Suicide Run (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Suicide Run (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 2dc3fdae sha1 a551d904c4af661bd4b6e88063cb5541900117b0 ) +) + +game ( + name "Suicide Run (World) (Aftermarket) (Unl)" + description "Suicide Run (World) (Aftermarket) (Unl)" + rom ( name "Suicide Run (World) (Aftermarket) (Unl).gbc" size 262144 crc d29ab1aa sha1 df373f58e51155e32fb81825a9082150f6d263c8 ) +) + +game ( + name "Super Bunny Mission (World) (GB Compatible) (Aftermarket) (Unl)" + description "Super Bunny Mission (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Super Bunny Mission (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc c47330e2 sha1 6151286e93b2e2fb92f583371e650e36ab91aaf7 ) +) + +game ( + name "Super Gran (World) (Aftermarket) (Unl)" + description "Super Gran (World) (Aftermarket) (Unl)" + rom ( name "Super Gran (World) (Aftermarket) (Unl).gbc" size 262144 crc 98ee2e8a sha1 5afe9c7ab1b9d86048a570e7a37a0c244cb84e43 ) +) + +game ( + name "Super Impostor Bros. (World) (GB Compatible) (Aftermarket) (Unl)" + description "Super Impostor Bros. (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Super Impostor Bros. (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc a38d702f sha1 301f93da4e5b0cd8dc3f1bf3e66e38176b8a909b ) +) + +game ( + name "Super Jacked Up Tomato Face Johnson (World) (v2.2) (Aftermarket) (Unl)" + description "Super Jacked Up Tomato Face Johnson (World) (v2.2) (Aftermarket) (Unl)" + rom ( name "Super Jacked Up Tomato Face Johnson (World) (v2.2) (Aftermarket) (Unl).gbc" size 524288 crc 8e1f6bb0 sha1 27522a35211b0f015fa9550c2520f1da1c346886 ) +) + +game ( + name "Super Jacked Up Tomato Face Johnson (World) (v2.3) (Aftermarket) (Unl)" + description "Super Jacked Up Tomato Face Johnson (World) (v2.3) (Aftermarket) (Unl)" + rom ( name "Super Jacked Up Tomato Face Johnson (World) (v2.3) (Aftermarket) (Unl).gbc" size 524288 crc f9731ee2 sha1 23855b95d04a6c7c6d2ce7977bb31dbe6c0e68a0 ) +) + +game ( + name "Super Jacked Up Tomato Face Johnson (World) (Jam Version) (Aftermarket) (Unl)" + description "Super Jacked Up Tomato Face Johnson (World) (Jam Version) (Aftermarket) (Unl)" + rom ( name "Super Jacked Up Tomato Face Johnson (World) (Jam Version) (Aftermarket) (Unl).gbc" size 524288 crc 87956ddf sha1 b23320d5d3fde2a55b301f7bea324833c31c32d5 ) +) + +game ( + name "Super JetPak DX (World) (GB Compatible) (Aftermarket) (Unl)" + description "Super JetPak DX (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Super JetPak DX (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 22def6f9 sha1 e7438db01fbbdeea2404dbf3d093370421ec4e1c flags verified ) +) + +game ( + name "Swordbird Song - The Iron Owl Tower (World) (v3.1) (GB Compatible) (Aftermarket) (Unl)" + description "Swordbird Song - The Iron Owl Tower (World) (v3.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Swordbird Song - The Iron Owl Tower (World) (v3.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 64921bb1 sha1 b36ec89e0299c19767cc5c6467fa3664abbc3017 ) +) + +game ( + name "Swordbird Song - The Iron Owl Tower (World) (v3.0) (GB Compatible) (Aftermarket) (Unl)" + description "Swordbird Song - The Iron Owl Tower (World) (v3.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Swordbird Song - The Iron Owl Tower (World) (v3.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc b2b5dc4b sha1 aaa66863b2e68865359d1c0db2047bab6f64f9ee ) +) + +game ( + name "Swordsman on the Eternal Journey (World) (En,Ja) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + description "Swordsman on the Eternal Journey (World) (En,Ja) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Swordsman on the Eternal Journey (World) (En,Ja) (v1.01) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc f2762fb0 sha1 b4d33ac2e410a55d27edb2abe6fc2268ca18ae26 ) +) + +game ( + name "Swordsman on the Eternal Journey (World) (En,Ja) (v1.00) (GB Compatible) (Aftermarket) (Unl)" + description "Swordsman on the Eternal Journey (World) (En,Ja) (v1.00) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Swordsman on the Eternal Journey (World) (En,Ja) (v1.00) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc bc3a78de sha1 54f9f0caa96edac7d336d85548e099a4e5110bdd ) +) + +game ( + name "Swordsman on the Eternal Journey (World) (It) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + description "Swordsman on the Eternal Journey (World) (It) (v1.01) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Swordsman on the Eternal Journey (World) (It) (v1.01) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 4a733a47 sha1 a45a31e6491a5d8a9288dc64823d7266060681b3 ) +) + +game ( + name "Take Your Medicine (World) (En,Pt) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Take Your Medicine (World) (En,Pt) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Take Your Medicine (World) (En,Pt) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 31a6b0ff sha1 baa07cfb71e42487eb57490c5b6cdec72e6893f7 ) +) + +game ( + name "Take Your Medicine (World) (En,Pt) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + description "Take Your Medicine (World) (En,Pt) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Take Your Medicine (World) (En,Pt) (v1.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 255f67de sha1 8c973fafc9576e57a7714bda6425d30cdf7edd2c ) +) + +game ( + name "Tales of Monsterland (World) (v2.83) (GB Compatible) (Aftermarket) (Unl)" + description "Tales of Monsterland (World) (v2.83) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Tales of Monsterland (World) (v2.83) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc a685f89a sha1 15a709d4300464b03ede4d774ce69cfb699c0fcf ) +) + +game ( + name "Tamarindo's Freaking Dinner DX (World) (Aftermarket) (Unl)" + description "Tamarindo's Freaking Dinner DX (World) (Aftermarket) (Unl)" + rom ( name "Tamarindo's Freaking Dinner DX (World) (Aftermarket) (Unl).gbc" size 262144 crc 257d9201 sha1 d78e0b03a3915531e780057c4ad7ed2b3f849825 ) +) + +game ( + name "Tank Attack (World) (Aftermarket) (Unl)" + description "Tank Attack (World) (Aftermarket) (Unl)" + rom ( name "Tank Attack (World) (Aftermarket) (Unl).gbc" size 262144 crc c77dc518 sha1 4751a6999f4dbe7e66b997372588f6bd15e4d9d0 ) +) + +game ( + name "Tazz (World) (2022-10-13) (Aftermarket) (Unl)" + description "Tazz (World) (2022-10-13) (Aftermarket) (Unl)" + rom ( name "Tazz (World) (2022-10-13) (Aftermarket) (Unl).gbc" size 262144 crc 1d97b754 sha1 39226ed715ae8d94f9187c3e5e8a849eac92ca26 ) +) + +game ( + name "Tazz (World) (2022-10-17) (Aftermarket) (Unl)" + description "Tazz (World) (2022-10-17) (Aftermarket) (Unl)" + rom ( name "Tazz (World) (2022-10-17) (Aftermarket) (Unl).gbc" size 262144 crc 6fb0ba23 sha1 543118e54b166ea2b8b5979f8468cc2f5662161f ) +) + +game ( + name "Tiledentity (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Tiledentity (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Tiledentity (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 678383d3 sha1 a97c2b31ce138e81e0bfabee89aa58426d41e0a9 ) +) + +game ( + name "Tiledentity (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + description "Tiledentity (World) (v1.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Tiledentity (World) (v1.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc a9a24479 sha1 59b1d66807141ca42809189544e1104bd8d0454b ) +) + +game ( + name "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.4) (GB Compatible) (Aftermarket) (Unl)" + description "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.4) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.4) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc af13e718 sha1 307e51664db2101755b6c617f3d81ee58676c485 ) +) + +game ( + name "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + description "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Tiny Grasshopper Goes Away (World) (En,Hu) (v1.2) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 0518f5aa sha1 85e5cd0cf7a6cc4a5946c93fa8665235a686e554 ) +) + +game ( + name "Tir Na Nog (World) (Aftermarket) (Unl)" + description "Tir Na Nog (World) (Aftermarket) (Unl)" + rom ( name "Tir Na Nog (World) (Aftermarket) (Unl).gbc" size 1048576 crc 44524c90 sha1 ac712228460e9d4268f90ec4cf9ac2137fa667c4 ) +) + +game ( + name "To The Stars (World) (GB Compatible) (Aftermarket) (Unl)" + description "To The Stars (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "To The Stars (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 2e1ca159 sha1 fb8269ff0377ac755b95e8e1ed935ad00d4476ee ) +) + +game ( + name "Tobu Tobu Girl Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" + description "Tobu Tobu Girl Deluxe (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Tobu Tobu Girl Deluxe (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 16650a8b sha1 fe6eef70d48dda741f7ad3b6cc5e753e8cd13239 ) +) + +game ( + name "Tomte Trouble (World) (Aftermarket) (Unl)" + description "Tomte Trouble (World) (Aftermarket) (Unl)" + rom ( name "Tomte Trouble (World) (Aftermarket) (Unl).gbc" size 262144 crc a43d6b82 sha1 99730fe00703d655b1c806f49c9e3c2fb3dec58e flags verified ) +) + +game ( + name "Tools of Nexaura (World) (v0.4) (Demo) (SGB Enhanced) (GB Compatible) (Aftermarket) (Unl)" + description "Tools of Nexaura (World) (v0.4) (Demo) (SGB Enhanced) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Tools of Nexaura (World) (v0.4) (Demo) (SGB Enhanced) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 50707e43 sha1 4a50327514554f075178f4d6342a4497d3122f31 ) +) + +game ( + name "Tower of Evil (World) (Aftermarket) (Unl)" + description "Tower of Evil (World) (Aftermarket) (Unl)" + rom ( name "Tower of Evil (World) (Aftermarket) (Unl).gbc" size 524288 crc aeb6e36f sha1 e9a6a007e935afb522c67d355e0354b0fb9af3c6 ) +) + +game ( + name "Traumatarium (World) (Demo) (2023-06-01) (GB Compatible) (Aftermarket) (Unl)" + description "Traumatarium (World) (Demo) (2023-06-01) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Traumatarium (World) (Demo) (2023-06-01) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc b0a32d51 sha1 4c0d639722d1cd8393e008d174b8f7266d089ead ) +) + +game ( + name "Treasure Island Color (World) (Aftermarket) (Unl)" + description "Treasure Island Color (World) (Aftermarket) (Unl)" + rom ( name "Treasure Island Color (World) (Aftermarket) (Unl).gbc" size 262144 crc 4ab0eb5a sha1 3ebddd4e1f5b3a87726ef34a5b7d36de8c722f36 ) +) + +game ( + name "Tristam Island (World) (v1.6) (GB Compatible) (Aftermarket) (Unl)" + description "Tristam Island (World) (v1.6) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Tristam Island (World) (v1.6) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc f6449829 sha1 5f1a11c4de8635fd5247ebb7f26273a40048567e flags verified ) +) + +game ( + name "Trouble City - Pocket Mission (World) (GB Compatible) (Aftermarket) (Unl)" + description "Trouble City - Pocket Mission (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Trouble City - Pocket Mission (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 4b9143ad sha1 0e51e398d44aaad74a7c622f7818b56a3b34db56 ) +) + +game ( + name "Tutti Frutti (World) (Aftermarket) (Unl)" + description "Tutti Frutti (World) (Aftermarket) (Unl)" + rom ( name "Tutti Frutti (World) (Aftermarket) (Unl).gbc" size 262144 crc ca377ca6 sha1 53d97b93b9d190de40ed2d81e18b4cbe44f99a23 ) +) + +game ( + name "TV-Chan's Great Escape! (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + description "TV-Chan's Great Escape! (World) (Proto) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "TV-Chan's Great Escape! (World) (Proto) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 01239312 sha1 4f21c3539ef40a7630581fe50533371e0d1a1ba9 ) +) + +game ( + name "Tycoon Tex (World) (Aftermarket) (Unl)" + description "Tycoon Tex (World) (Aftermarket) (Unl)" + rom ( name "Tycoon Tex (World) (Aftermarket) (Unl).gbc" size 262144 crc fa8436ba sha1 d37bcd93d647ac7efb761c539785a4ef570cdcc8 ) +) + +game ( + name "Tynesoft Commodore 16 Classics (World) (Aftermarket) (Unl)" + description "Tynesoft Commodore 16 Classics (World) (Aftermarket) (Unl)" + rom ( name "Tynesoft Commodore 16 Classics (World) (Aftermarket) (Unl).gbc" size 2097152 crc 8067298a sha1 e44280161ca9d482fae08de844ccc9754abf68b0 ) +) + +game ( + name "Tynesoft Commodore 16 Classics II (World) (Aftermarket) (Unl)" + description "Tynesoft Commodore 16 Classics II (World) (Aftermarket) (Unl)" + rom ( name "Tynesoft Commodore 16 Classics II (World) (Aftermarket) (Unl).gbc" size 1048576 crc 0ce45101 sha1 f61677146ef67b026c636742f0109b8c478d0942 ) +) + +game ( + name "Tyrannosaurus Tex (World) (Aftermarket) (Unl)" + description "Tyrannosaurus Tex (World) (Aftermarket) (Unl)" + rom ( name "Tyrannosaurus Tex (World) (Aftermarket) (Unl).gbc" size 2097152 crc e90504c1 sha1 7e41e92f92ff06101e48dee758420f1bd3959013 ) +) + +game ( + name "Unearthed (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + description "Unearthed (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Unearthed (World) (v1.3) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc 29bb9238 sha1 39fbfb220e9be0120090f770249049b3f3583f64 ) +) + +game ( + name "Ungrateful Son, The (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Ungrateful Son, The (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Ungrateful Son, The (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 977b54f4 sha1 016dde406896d827dcad682d40b52d0e9eeefa88 ) +) + +game ( + name "Unholy Friend (World) (GB Compatible) (Aftermarket) (Unl)" + description "Unholy Friend (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Unholy Friend (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 36e4ff4c sha1 b5c9b5f07e31729678637d883b2564c1448b0e57 ) +) + +game ( + name "Usurper Ghoul (World) (v1.9) (GB Compatible) (Aftermarket) (Unl)" + description "Usurper Ghoul (World) (v1.9) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Usurper Ghoul (World) (v1.9) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc fc94dbf3 sha1 5be7317929c81780f478f745111f8f45798da866 ) +) + +game ( + name "UXB (World) (Aftermarket) (Unl)" + description "UXB (World) (Aftermarket) (Unl)" + rom ( name "UXB (World) (Aftermarket) (Unl).gbc" size 262144 crc dd42be4c sha1 6ef7abb689b1c75f613ed253644fbb0f377b7a95 ) +) + +game ( + name "Varmit (World) (Aftermarket) (Unl)" + description "Varmit (World) (Aftermarket) (Unl)" + rom ( name "Varmit (World) (Aftermarket) (Unl).gbc" size 2097152 crc e4827006 sha1 b61876c714c47f62a77304b79f6e34b8d0e7f8a2 ) +) + +game ( + name "Vixen (World) (Aftermarket) (Unl)" + description "Vixen (World) (Aftermarket) (Unl)" + rom ( name "Vixen (World) (Aftermarket) (Unl).gbc" size 524288 crc 0c347734 sha1 90f251f8f481f157de5b3efe3c8e3356ed1314b4 ) +) + +game ( + name "VOX (World) (Aftermarket) (Unl)" + description "VOX (World) (Aftermarket) (Unl)" + rom ( name "VOX (World) (Aftermarket) (Unl).gbc" size 262144 crc 346561fb sha1 54a03c77653a19eb1b0d8a6ac82f498f83f35ef2 ) +) + +game ( + name "Wacky Painter (World) (Aftermarket) (Unl)" + description "Wacky Painter (World) (Aftermarket) (Unl)" + rom ( name "Wacky Painter (World) (Aftermarket) (Unl).gbc" size 262144 crc 09daa18d sha1 5425dc675101d63bea03b1c8f46f86fe200ad392 ) +) + +game ( + name "Walaki (World) (Hu) (Aftermarket) (Unl)" + description "Walaki (World) (Hu) (Aftermarket) (Unl)" + rom ( name "Walaki (World) (Hu) (Aftermarket) (Unl).gbc" size 262144 crc 254875ac sha1 388d6c339b8d62db18e540f59a2930af4088ca7e ) +) + +game ( + name "Warp Coin Catastrophe, The (World) (GB Compatible) (Aftermarket) (Unl)" + description "Warp Coin Catastrophe, The (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Warp Coin Catastrophe, The (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 1bfe1bf9 sha1 fae12dbbb75ae024e96a7ee21ad4077fdb5ed9a1 ) +) + +game ( + name "Warp Coin Catastrophe, The (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + description "Warp Coin Catastrophe, The (World) (v1.1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Warp Coin Catastrophe, The (World) (v1.1) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc a381c914 sha1 adf37c5d2f706743b2a4946378df49ed19212039 ) +) + +game ( + name "Warp Coin Catastrophe, The (World) (v1.1.2) (GB Compatible) (Aftermarket) (Unl)" + description "Warp Coin Catastrophe, The (World) (v1.1.2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Warp Coin Catastrophe, The (World) (v1.1.2) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 5519c167 sha1 04a53af6a77b884af91f8047d70fc0331bf23913 ) +) + +game ( + name "Water Grandprix (World) (Aftermarket) (Unl)" + description "Water Grandprix (World) (Aftermarket) (Unl)" + rom ( name "Water Grandprix (World) (Aftermarket) (Unl).gbc" size 262144 crc 82f54e7e sha1 4029e003870b2afb78a3644e24397d80fc5a3210 ) +) + +game ( + name "Waternet (World) (GB Compatible) (Aftermarket) (Unl)" + description "Waternet (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Waternet (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 32768 crc ef202121 sha1 a11f931b18ba42f48a91e817b7117fa0e3e79518 ) +) + +game ( + name "Waternet (World) (Batteryless Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl)" + description "Waternet (World) (Batteryless Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Waternet (World) (Batteryless Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 75591760 sha1 e04b01ada17e6924503029cd09a107b7f5d06f17 ) +) + +game ( + name "Waternet (World) (Batteryless Generic Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl)" + description "Waternet (World) (Batteryless Generic Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Waternet (World) (Batteryless Generic Save Flash Cartridge Version) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc f8402dc5 sha1 6feb4178589e87c6267683078201f0630cca23d6 ) +) + +game ( + name "Wayfarer Boo - Pushing Through (World) (v1.1) (Aftermarket) (Unl)" + description "Wayfarer Boo - Pushing Through (World) (v1.1) (Aftermarket) (Unl)" + rom ( name "Wayfarer Boo - Pushing Through (World) (v1.1) (Aftermarket) (Unl).gbc" size 262144 crc 903d1b1a sha1 12b8a0bdadd503f6114fcf28a43652d5d69749f4 ) +) + +game ( + name "Wayfarer Boo - Pushing Through (World) (v1.0) (Aftermarket) (Unl)" + description "Wayfarer Boo - Pushing Through (World) (v1.0) (Aftermarket) (Unl)" + rom ( name "Wayfarer Boo - Pushing Through (World) (v1.0) (Aftermarket) (Unl).gbc" size 262144 crc b5d0ab10 sha1 7451a93a3a2f17b5187883ad2b59c4dda99a2ac7 ) +) + +game ( + name "What Friends Are For (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" + description "What Friends Are For (World) (v2.0) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "What Friends Are For (World) (v2.0) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 776fc18e sha1 5c4a227c0b2f53e4a349e482c5ba87cb83404f8e ) +) + +game ( + name "What's Updog (World) (2022-11-23) (GB Compatible) (Aftermarket) (Unl)" + description "What's Updog (World) (2022-11-23) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "What's Updog (World) (2022-11-23) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 2c3d5cbf sha1 a235c0915ac2b826eeb5884d0eccd321236fdb0c ) +) + +game ( + name "Where's My Cake (World) (GB Compatible) (Aftermarket) (Unl)" + description "Where's My Cake (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Where's My Cake (World) (GB Compatible) (Aftermarket) (Unl).GBC" size 65536 crc 28114b89 sha1 05b90f0a7e92d42b3008c749d5edeab2a2eae973 ) +) + +game ( + name "Who Dares Wins II (World) (Aftermarket) (Unl)" + description "Who Dares Wins II (World) (Aftermarket) (Unl)" + rom ( name "Who Dares Wins II (World) (Aftermarket) (Unl).gbc" size 262144 crc d12ea4bd sha1 cd91248bc0efd4fd3f182eda4559b1d6b720e3d9 ) +) + +game ( + name "Wicked Plague (World) (v0.1.2) (Proto) (Aftermarket) (Unl)" + description "Wicked Plague (World) (v0.1.2) (Proto) (Aftermarket) (Unl)" + rom ( name "Wicked Plague (World) (v0.1.2) (Proto) (Aftermarket) (Unl).gbc" size 524288 crc 80e43cec sha1 dee4f074029352efb3e6683e0c31c9350bdb8199 ) +) + +game ( + name "Wicked Plague (World) (v0.1.1) (Proto) (Aftermarket) (Unl)" + description "Wicked Plague (World) (v0.1.1) (Proto) (Aftermarket) (Unl)" + rom ( name "Wicked Plague (World) (v0.1.1) (Proto) (Aftermarket) (Unl).gbc" size 524288 crc 4029708f sha1 2279270c9a0d28934c5b5efda9c047ab27ffccb8 ) +) + +game ( + name "Wing Warriors (World) (En,Fr,Es) (Beta 2) (GB Compatible) (Aftermarket) (Unl)" + description "Wing Warriors (World) (En,Fr,Es) (Beta 2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Wing Warriors (World) (En,Fr,Es) (Beta 2) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 04e04980 sha1 574cf911d6d8f73699203cd6db42ceec777f7f93 ) +) + +game ( + name "Wing Warriors (World) (En,Fr,Es) (EGS) (GB Compatible) (Aftermarket) (Unl)" + description "Wing Warriors (World) (En,Fr,Es) (EGS) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Wing Warriors (World) (En,Fr,Es) (EGS) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 7328cfb6 sha1 039874148f27ffe533de4ef086f29e724a3217a9 ) +) + +game ( + name "Wing Warriors (World) (En,Fr,Es) (Beta 1) (GB Compatible) (Aftermarket) (Unl)" + description "Wing Warriors (World) (En,Fr,Es) (Beta 1) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Wing Warriors (World) (En,Fr,Es) (Beta 1) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 6bc9de3d sha1 12d55dad39a9663083f9ad176563576a5cc44069 ) +) + +game ( + name "Wing Warriors (World) (En,Fr,Es) (Kitmaker) (GB Compatible) (Aftermarket) (Unl)" + description "Wing Warriors (World) (En,Fr,Es) (Kitmaker) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Wing Warriors (World) (En,Fr,Es) (Kitmaker) (GB Compatible) (Aftermarket) (Unl).gbc" size 131072 crc 5179988b sha1 20e8daa159ceddace966afd3cd19eae71bb3bf6f ) +) + +game ( + name "Witches and Butchers (World) (Demo 2) (GB Compatible) (Aftermarket) (Unl)" + description "Witches and Butchers (World) (Demo 2) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Witches and Butchers (World) (Demo 2) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 321aecca sha1 90541cd5b08f6030b5b2fe4f1e0ac7c0b616e01e ) +) + +game ( + name "Witches and Butchers (World) (Demo 4) (GB Compatible) (Aftermarket) (Unl)" + description "Witches and Butchers (World) (Demo 4) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Witches and Butchers (World) (Demo 4) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 9b53a90f sha1 77210d3c0825d913f4aebf09a10897a84ca23881 ) +) + +game ( + name "Wizard of Wor (World) (Aftermarket) (Unl)" + description "Wizard of Wor (World) (Aftermarket) (Unl)" + rom ( name "Wizard of Wor (World) (Aftermarket) (Unl).gbc" size 524288 crc 492a9529 sha1 a391646d259a39e7026574145e0a2bacf5f6937b ) +) + +game ( + name "Wolf Pack (World) (Aftermarket) (Unl)" + description "Wolf Pack (World) (Aftermarket) (Unl)" + rom ( name "Wolf Pack (World) (Aftermarket) (Unl).gbc" size 262144 crc ae35b80b sha1 56b20f0ab63a1459c1271e4cd062e8f92f7d10a4 ) +) + +game ( + name "World Cup (World) (Aftermarket) (Unl)" + description "World Cup (World) (Aftermarket) (Unl)" + rom ( name "World Cup (World) (Aftermarket) (Unl).gbc" size 262144 crc 56b3ab5f sha1 075890510b3ef205ca50ebbbcf7c0a0c56032cb9 ) +) + +game ( + name "Wrestling Thunder City (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Wrestling Thunder City (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Wrestling Thunder City (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc 4fc94f1c sha1 3c5e6ec96c1110ef9c21a8d92cc24c0c721fddd3 ) +) + +game ( + name "Xzap (World) (Aftermarket) (Unl)" + description "Xzap (World) (Aftermarket) (Unl)" + rom ( name "Xzap (World) (Aftermarket) (Unl).gbc" size 262144 crc 68ceec9c sha1 35ae73d3ec93c95fdad9a358ccc34bcfc12445b1 ) +) + +game ( + name "Year After, The (World) (En,Fr,Pt) (GB Compatible) (Aftermarket) (Unl)" + description "Year After, The (World) (En,Fr,Pt) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Year After, The (World) (En,Fr,Pt) (GB Compatible) (Aftermarket) (Unl).gbc" size 2097152 crc b304833d sha1 c2be46b8230bfcf509d031902c9bf144de97ef58 ) +) + +game ( + name "Year After, The (World) (En) (Beta) (GB Compatible) (Aftermarket) (Unl)" + description "Year After, The (World) (En) (Beta) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Year After, The (World) (En) (Beta) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc f15351c8 sha1 a78ff2eef780287bbdc37df122cfc1c504526662 ) +) + +game ( + name "Year After, The (World) (Pt) (Beta) (GB Compatible) (Aftermarket) (Unl)" + description "Year After, The (World) (Pt) (Beta) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Year After, The (World) (Pt) (Beta) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc b70c1c7f sha1 ce25cdf6a6264586423e76e34dc42779d39a1cb1 ) +) + +game ( + name "YiYa - The Digital Pet Game (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "YiYa - The Digital Pet Game (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "YiYa - The Digital Pet Game (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc b2c84c00 sha1 8bf1843102bc5a8577a8d0b44a16e46ade14bd16 ) +) + +game ( + name "YiYa - The Digital Pet Game DX (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "YiYa - The Digital Pet Game DX (World) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "YiYa - The Digital Pet Game DX (World) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc 21e80905 sha1 b372eb9d049c962392868d7abfcb7b7e4ab2d40f ) +) + +game ( + name "Yurivania - Uhaul of the Night (World) (v1.5) (GB Compatible) (Aftermarket) (Unl)" + description "Yurivania - Uhaul of the Night (World) (v1.5) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Yurivania - Uhaul of the Night (World) (v1.5) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc c5447011 sha1 8197ed0ac5591893b7d04ed3f02529f120daab7e ) +) + +game ( + name "Yurivania 0 - Soul Night Prelude (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + description "Yurivania 0 - Soul Night Prelude (World) (v1.3) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Yurivania 0 - Soul Night Prelude (World) (v1.3) (GB Compatible) (Aftermarket) (Unl).gbc" size 262144 crc 8cdf4b90 sha1 9df6bf7c2babc47cc9e461d16a7ab1a24d898003 ) +) + +game ( + name "Yurivania II - Josette's Quest (World) (v1.3) (Aftermarket) (Unl)" + description "Yurivania II - Josette's Quest (World) (v1.3) (Aftermarket) (Unl)" + rom ( name "Yurivania II - Josette's Quest (World) (v1.3) (Aftermarket) (Unl).gbc" size 1048576 crc b80d7525 sha1 05c7256bf9f12f60f453a0627d813904c8713378 ) +) + +game ( + name "Yurivania II - Josette's Quest (World) (v1.2) (Aftermarket) (Unl)" + description "Yurivania II - Josette's Quest (World) (v1.2) (Aftermarket) (Unl)" + rom ( name "Yurivania II - Josette's Quest (World) (v1.2) (Aftermarket) (Unl).gbc" size 1048576 crc c3a76413 sha1 6b6dac77795148d7eba6f7c8fa1c65a6d1e404c3 ) +) + +game ( + name "Yurivania III - Circle of the Polycule (World) (v1.4) (Aftermarket) (Unl)" + description "Yurivania III - Circle of the Polycule (World) (v1.4) (Aftermarket) (Unl)" + rom ( name "Yurivania III - Circle of the Polycule (World) (v1.4) (Aftermarket) (Unl).gbc" size 2097152 crc 439b087f sha1 91178b5ba17e891060badf0c7681e6a76052de97 ) +) + +game ( + name "Zagan Warrior (World) (Aftermarket) (Unl)" + description "Zagan Warrior (World) (Aftermarket) (Unl)" + rom ( name "Zagan Warrior (World) (Aftermarket) (Unl).gbc" size 262144 crc e770f71a sha1 99d9267946e7bf26942a8276863ba50ef0b8f90e ) +) + +game ( + name "Zap'em (World) (Aftermarket) (Unl)" + description "Zap'em (World) (Aftermarket) (Unl)" + rom ( name "Zap'em (World) (Aftermarket) (Unl).gbc" size 262144 crc 66f17c5e sha1 63d44c8c2492dc32bcf632feb2d994e9af25fc97 ) +) + +game ( + name "Zephyr's Pass (World) (v1.02) (Demo) (Aftermarket) (Unl)" + description "Zephyr's Pass (World) (v1.02) (Demo) (Aftermarket) (Unl)" + rom ( name "Zephyr's Pass (World) (v1.02) (Demo) (Aftermarket) (Unl).gbc" size 2097152 crc db0951d3 sha1 7b74c658f24894659cfda1fc3c7775fd9f7b6013 ) +) + +game ( + name "Zippy The Pinecone (World) (GB Compatible) (Aftermarket) (Unl)" + description "Zippy The Pinecone (World) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Zippy The Pinecone (World) (GB Compatible) (Aftermarket) (Unl).gbc" size 1048576 crc d1854d92 sha1 ba5f1a020f39ecd29669fc38ca4b23dd4f3dc061 ) +) + +game ( + name "Zippy The Pinecone (World) (v2.7) (Demo) (GB Compatible) (Aftermarket) (Unl)" + description "Zippy The Pinecone (World) (v2.7) (Demo) (GB Compatible) (Aftermarket) (Unl)" + rom ( name "Zippy The Pinecone (World) (v2.7) (Demo) (GB Compatible) (Aftermarket) (Unl).gbc" size 524288 crc fc555c4d sha1 ad3e95a917c4572c150b4b7cc49d17f1b20a0408 ) +) + +game ( + name "Zodiac (World) (Aftermarket) (Unl)" + description "Zodiac (World) (Aftermarket) (Unl)" + rom ( name "Zodiac (World) (Aftermarket) (Unl).gbc" size 262144 crc c4d86c05 sha1 73bd9e6e3bede8de489680ba84129e8fd17abbc0 ) +) + +game ( + name "Zone Control (World) (Aftermarket) (Unl)" + description "Zone Control (World) (Aftermarket) (Unl)" + rom ( name "Zone Control (World) (Aftermarket) (Unl).gbc" size 262144 crc 856ed536 sha1 a191d41fd86a7c17015e04156ffff8222302d36e ) +) + +game ( + name "Zork + Harris (World) (v0.0.1.0) (Proto) (Aftermarket) (Unl)" + description "Zork + Harris (World) (v0.0.1.0) (Proto) (Aftermarket) (Unl)" + rom ( name "Zork + Harris (World) (v0.0.1.0) (Proto) (Aftermarket) (Unl).gbc" size 262144 crc 38282614 sha1 2507cfd5414c45b8a2f9839552d6115730da6bf8 ) +) + diff --git a/res/patrons.txt b/res/patrons.txt index 5126cc891..8e61ae237 100644 --- a/res/patrons.txt +++ b/res/patrons.txt @@ -1,14 +1,14 @@ Akatsuki -AVjoyu__Chan Benedikt Feih Brandon Emily A. Bellows -G +EmuDeck gocha Jaime J. Denizard MichaelK__ Miras Absar -Nic Losby +Molly Howell +Nic Losby (blurbdust) Petru-Sebastian Toader Stevoisiak William K. Leung diff --git a/res/scripts/color-mask.lua b/res/scripts/color-mask.lua new file mode 100644 index 000000000..25a51f805 --- /dev/null +++ b/res/scripts/color-mask.lua @@ -0,0 +1,34 @@ +local state = {} +state.wheel = image.load(script.dir .. "/wheel.png") +state.overlay = canvas:newLayer(state.wheel.width, state.wheel.height) +state.painter = image.newPainter(state.overlay.image) +state.phase = 0 +state.speed = 0.01 +state.painter:setFill(true) +state.painter:setStrokeWidth(0) + +function state.update() + local r = math.fmod(state.phase * 3, math.pi * 2) + local g = math.fmod(state.phase * 5, math.pi * 2) + local b = math.fmod(state.phase * 7, math.pi * 2) + local color = 0xFF000000 + color = color | math.floor((math.sin(r) + 1) * 127.5) << 16 + color = color | math.floor((math.sin(g) + 1) * 127.5) << 8 + color = color | math.floor((math.sin(b) + 1) * 127.5) + + -- Clear image + state.painter:setBlend(false) + state.painter:setFillColor(0) + state.painter:drawRectangle(0, 0, state.wheel.width, state.wheel.height) + -- Draw mask + state.painter:setBlend(true) + state.painter:setFillColor(color | 0xFF000000) + state.painter:drawMask(state.wheel, 0, 0) + + state.overlay:update() + state.phase = math.fmod(state.phase + state.speed, math.pi * 2 * 3 * 5 * 7) +end + +callbacks:add("frame", state.update) + + diff --git a/res/scripts/input-display.lua b/res/scripts/input-display.lua new file mode 100644 index 000000000..e3db0340c --- /dev/null +++ b/res/scripts/input-display.lua @@ -0,0 +1,122 @@ +input_display = { + anchor = "top", + offset = { + x = 0, + y = 0, + } +} + +local state = { + drawButton = { + [0] = function(state) -- A + state.painter:drawCircle(27, 6, 4) + end, + [1] = function(state) -- B + state.painter:drawCircle(23, 8, 4) + end, + [2] = function(state) -- Select + state.painter:drawCircle(13, 11, 3) + end, + [3] = function(state) -- Start + state.painter:drawCircle(18, 11, 3) + end, + [4] = function(state) -- Right + state.painter:drawRectangle(9, 7, 4, 3) + end, + [5] = function(state) -- Left + state.painter:drawRectangle(2, 7, 4, 3) + end, + [6] = function(state) -- Up + state.painter:drawRectangle(6, 3, 3, 4) + end, + [7] = function(state) -- Down + state.painter:drawRectangle(6, 10, 3, 4) + end, + [8] = function(state) -- R + state.painter:drawRectangle(28, 0, 4, 3) + end, + [9] = function(state) -- L + state.painter:drawRectangle(0, 0, 4, 3) + end + }, + maxKey = { + [C.PLATFORM.GBA] = 9, + [C.PLATFORM.GB] = 7, + } +} +state.overlay = canvas:newLayer(32, 16) +state.painter = image.newPainter(state.overlay.image) +state.painter:setBlend(false) +state.painter:setFill(true) + +function state.update() + local keys = util.expandBitmask(emu:getKeys()) + local maxKey = state.maxKey[emu:platform()] + + for key = 0, maxKey do + if emu:getKey(key) ~= 0 then + state.painter:setFillColor(0x80FFFFFF) + else + state.painter:setFillColor(0x40404040) + end + state.drawButton[key](state) + end + state.overlay:update() +end + +function state.reset() + local endX = canvas:screenWidth() - 32 + local endY = canvas:screenHeight() - 16 + + local anchors = { + topLeft = { + x = 0, + y = 0 + }, + top = { + x = endX / 2, + y = 0 + }, + topRight = { + x = endX, + y = 0 + }, + left = { + x = 0, + y = endY / 2 + }, + center = { + x = endX / 2, + y = endY / 2 + }, + right = { + x = endX, + y = endY / 2 + }, + bottomLeft = { + x = 0, + y = endY + }, + bottom = { + x = endX / 2, + y = endY + }, + bottomRight = { + x = endX, + y = endY + }, + } + + local pos = anchors[input_display.anchor]; + pos.x = pos.x + input_display.offset.x; + pos.y = pos.y + input_display.offset.y; + + state.overlay:setPosition(pos.x, pos.y); + state.painter:setFillColor(0x40808080) + state.painter:drawRectangle(0, 0, 32, 16) + state.overlay:update() +end + +state.reset() +callbacks:add("frame", state.update) +callbacks:add("start", state.reset) diff --git a/res/scripts/logo-bg.png b/res/scripts/logo-bg.png new file mode 100644 index 000000000..908e410d9 Binary files /dev/null and b/res/scripts/logo-bg.png differ diff --git a/res/scripts/logo-bounce.lua b/res/scripts/logo-bounce.lua index c8192638c..aae32ce40 100644 --- a/res/scripts/logo-bounce.lua +++ b/res/scripts/logo-bounce.lua @@ -1,44 +1,61 @@ math.randomseed(os.time()) local state = {} -state.logo = image.load(script.dir .. "/logo.png") -state.overlay = canvas:newLayer(state.logo.width, state.logo.height) -state.overlay.image:drawImageOpaque(state.logo, 0, 0) -state.x = math.random() * (canvas:screenWidth() - state.logo.width) -state.y = math.random() * (canvas:screenHeight() - state.logo.height) +state.logo_fg = image.load(script.dir .. "/logo-fg.png") +state.logo_bg = image.load(script.dir .. "/logo-bg.png") +state.overlay = canvas:newLayer(state.logo_fg.width, state.logo_fg.height) +state.x = math.random() * (canvas:screenWidth() - state.logo_fg.width) +state.y = math.random() * (canvas:screenHeight() - state.logo_fg.height) +state.overlay:setPosition(math.floor(state.x), math.floor(state.y)) state.direction = math.floor(math.random() * 3) state.speed = 0.5 -state.overlay:setPosition(math.floor(state.x), math.floor(state.y)) -state.overlay:update() +function state.recolor() + local r = math.floor(math.random() * 255) + local g = math.floor(math.random() * 255) + local b = math.floor(math.random() * 255) + local color = 0xFF000000 | (r << 16) | (g << 8) | b + state.overlay.image:drawImageOpaque(state.logo_bg, 0, 0) + local painter = image.newPainter(state.overlay.image) + painter:setFill(true) + painter:setFillColor(color) + painter:setBlend(true) + painter:drawMask(state.logo_fg, 0, 0) + state.overlay:update() +end function state.update() if state.direction & 1 == 1 then state.x = state.x + 1 - if state.x > canvas:screenWidth() - state.logo.width then - state.x = (canvas:screenWidth() - state.logo.width) * 2 - state.x + if state.x > canvas:screenWidth() - state.logo_fg.width then + state.x = (canvas:screenWidth() - state.logo_fg.width) * 2 - state.x state.direction = state.direction ~ 1 + state.recolor() end else state.x = state.x - 1 if state.x < 0 then state.x = -state.x state.direction = state.direction ~ 1 + state.recolor() end end if state.direction & 2 == 2 then state.y = state.y + 1 - if state.y > canvas:screenHeight() - state.logo.height then - state.y = (canvas:screenHeight() - state.logo.height) * 2 - state.y + if state.y > canvas:screenHeight() - state.logo_fg.height then + state.y = (canvas:screenHeight() - state.logo_fg.height) * 2 - state.y state.direction = state.direction ~ 2 + state.recolor() end else state.y = state.y - 1 if state.y < 0 then state.y = -state.y state.direction = state.direction ~ 2 + state.recolor() end end state.overlay:setPosition(math.floor(state.x), math.floor(state.y)) end +state.recolor() callbacks:add("frame", state.update) diff --git a/res/scripts/logo-fg.png b/res/scripts/logo-fg.png new file mode 100644 index 000000000..c401fb011 Binary files /dev/null and b/res/scripts/logo-fg.png differ diff --git a/res/scripts/wheel.png b/res/scripts/wheel.png new file mode 100644 index 000000000..5e7bcca12 Binary files /dev/null and b/res/scripts/wheel.png differ diff --git a/res/shaders/gba-color.shader/gba-color.fs b/res/shaders/gba-color.shader/gba-color.fs index 09177ddfe..461228c20 100644 --- a/res/shaders/gba-color.shader/gba-color.fs +++ b/res/shaders/gba-color.shader/gba-color.fs @@ -1,34 +1,21 @@ +// Shader that replicates the LCD Colorspace from Gameboy Advance -- varying vec2 texCoord; +varying mat4 profile; uniform sampler2D tex; uniform vec2 texSize; uniform float darken_screen; -const float target_gamma = 2.2; -const float display_gamma = 2.5; -const float sat = 1.0; -const float lum = 0.99; -const float contrast = 1.0; -const vec3 bl = vec3(0.0, 0.0, 0.0); -const vec3 r = vec3(0.84, 0.09, 0.15); -const vec3 g = vec3(0.18, 0.67, 0.10); -const vec3 b = vec3(0.0, 0.26, 0.73); +const float target_gamma = 2.0; +const float display_gamma = 2.0; void main() { + // bring out our stored luminance value + float lum = profile[3].w; + + // our adjustments need to happen in linear gamma vec4 screen = pow(texture2D(tex, texCoord), vec4(target_gamma + darken_screen)).rgba; - vec4 avglum = vec4(0.5); - screen = mix(screen, avglum, (1.0 - contrast)); - - mat4 color = mat4( r.r, r.g, r.b, 0.0, - g.r, g.g, g.b, 0.0, - b.r, b.g, b.b, 0.0, - bl.r, bl.g, bl.b, 1.0); - - mat4 adjust = mat4( (1.0 - sat) * 0.3086 + sat, (1.0 - sat) * 0.3086, (1.0 - sat) * 0.3086, 1.0, - (1.0 - sat) * 0.6094, (1.0 - sat) * 0.6094 + sat, (1.0 - sat) * 0.6094, 1.0, - (1.0 - sat) * 0.0820, (1.0 - sat) * 0.0820, (1.0 - sat) * 0.0820 + sat, 1.0, - 0.0, 0.0, 0.0, 1.0); - color *= adjust; + screen = clamp(screen * lum, 0.0, 1.0); - screen = color * screen; - gl_FragColor = pow(screen, vec4(1.0 / display_gamma + (darken_screen * 0.125))); + screen = profile * screen; + gl_FragColor = pow(screen, vec4(1.0 / display_gamma)); } diff --git a/res/shaders/gba-color.shader/gba-color.vs b/res/shaders/gba-color.shader/gba-color.vs new file mode 100644 index 000000000..bbf406278 --- /dev/null +++ b/res/shaders/gba-color.shader/gba-color.vs @@ -0,0 +1,34 @@ +uniform int color_mode; +attribute vec4 position; +varying vec2 texCoord; +varying mat4 profile; + +const mat4 GBA_sRGB = mat4( + 0.80, 0.135, 0.195, 0.0, //red channel + 0.275, 0.64, 0.155, 0.0, //green channel + -0.075, 0.225, 0.65, 0.0, //blue channel + 0.0, 0.0, 0.0, 0.93 //alpha channel +); + +const mat4 GBA_DCI = mat4( + 0.685, 0.16, 0.20, 0.0, //red channel + 0.34, 0.629, 0.19, 0.0, //green channel + -0.025, 0.211, 0.61, 0.0, //blue channel + 0.0, 0.0, 0.0, 0.975 //alpha channel +); + +const mat4 GBA_Rec2020 = mat4( + 0.555, 0.1825, 0.20, 0.0, //red channel + 0.395, 0.61, 0.195, 0.0, //green channel + 0.05, 0.2075, 0.605, 0.0, //blue channel + 0.0, 0.0, 0.0, 1.0 //alpha channel +); + +void main() { + if (color_mode == 1) profile = GBA_sRGB; + else if (color_mode == 2) profile = GBA_DCI; + else if (color_mode == 3) profile = GBA_Rec2020; + + gl_Position = position; + texCoord = (position.st + vec2(1.0, 1.0)) * vec2(0.5, 0.5); +} diff --git a/res/shaders/gba-color.shader/manifest.ini b/res/shaders/gba-color.shader/manifest.ini index 8f9735aa3..ed16900cd 100644 --- a/res/shaders/gba-color.shader/manifest.ini +++ b/res/shaders/gba-color.shader/manifest.ini @@ -6,6 +6,7 @@ passes=1 [pass.0] fragmentShader=gba-color.fs +vertexShader=gba-color.vs blend=1 width=-1 height=-1 @@ -14,3 +15,10 @@ height=-1 type=float default=0.5 readableName=Darken Screen + +[pass.0.uniform.color_mode] +type=int +default=1 +min=1 +max=3 +readableName=Color Profile (1=sRGB, 2=DCI, 3=Rec2020) diff --git a/res/shaders/gbc-lcd.shader/gbc-lcd-light.fs b/res/shaders/gbc-lcd.shader/gbc-lcd-light.fs new file mode 100644 index 000000000..cb583f4da --- /dev/null +++ b/res/shaders/gbc-lcd.shader/gbc-lcd-light.fs @@ -0,0 +1,119 @@ +/** + * This shader creates a backlight bleeding effect, + * and an internal reflection or ghosting effect. + */ + +varying vec2 texCoord; +uniform sampler2D tex; + +/** + * Determines the color of the backlight bleed. + * Lower values produce less, dimmer light. + * Higher values produce brighter or more colorful light. + * You'll normally want each of these numbers to be close + * to 1, and not normally lower than 0. + */ +uniform vec3 LightColor; + +/** + * Affects the shape of the backlight bleed glow. + * Lower values cause the light bleed to fade out quickly + * from the edges. + * Higher values cause the light bleed to fade out more + * softly and gradually toward the center. + * You'll normally want this to be a number from 0 to 1. + */ +uniform float LightSoftness; + +/** + * Lower values result in a less visible or intense + * backlight bleed. + * Higher values make the backlight bleed more pronounced. + * You'll normally want this to be a number close to 0, + * and not normally higher than 1. + */ +uniform float LightIntensity; + +/** + * Lower values cause the internal reflection or ghosting + * effect to be less visible. + * Higher values cause the effect to be brighter and more + * visible. + * You'll normally want this to be a number close to 0, + * and not normally higher than 1. + */ +uniform float ReflectionBrightness; + +/** + * Lower values have the internal reflection or ghosting + * effect appear offset by a lesser distance. + * Higher values have the effect offset by a greater + * distance. + * You'll normally want each of these numbers to be close + * to 0, and not normally higher than 1. + */ +uniform vec2 ReflectionDistance; + +#define M_PI 3.1415926535897932384626433832795 + +/** + * Helper to compute backlight bleed intensity + * for a texCoord input. + */ +float getLightIntensity(vec2 coord) { + vec2 coordCentered = coord - vec2(0.5, 0.5); + float coordDistCenter = ( + length(coordCentered) / sqrt(0.5) + ); + vec2 coordQuadrant = vec2( + 1.0 - (1.5 * min(coord.x, 1.0 - coord.x)), + 1.0 - (1.5 * min(coord.y, 1.0 - coord.y)) + ); + float lightIntensityEdges = ( + pow(coordQuadrant.x, 5.0) + + pow(coordQuadrant.y, 5.0) + ); + float lightIntensity = ( + (1.0 - LightSoftness) * lightIntensityEdges + + LightSoftness * coordDistCenter + ); + return clamp(lightIntensity, 0.0, 1.0); +} + +/** + * Helper to convert an intensity value into a white + * gray color with that intensity. A radial distortion + * effect with subtle chromatic abberation is applied that + * makes it look a little more like a real old or cheap + * backlight, and also helps to reduce color banding. + */ +vec3 getWhiteVector(float intensity) { + const float DeformAmount = 0.0025; + vec2 texCoordCentered = texCoord - vec2(0.5, 0.5); + float radians = atan(texCoordCentered.y, texCoordCentered.x); + float rot = pow(2.0, 4.0 + floor(6.0 * length(texCoordCentered))); + float deformRed = cos(rot * radians + (2.0 / 3.0 * M_PI)); + float deformGreen = cos(rot * radians); + float deformBlue = cos(rot * radians + (4.0 / 3.0 * M_PI)); + return clamp(vec3( + intensity + (deformRed * DeformAmount), + intensity + (deformGreen * DeformAmount), + intensity + (deformBlue * DeformAmount) + ), 0.0, 1.0); +} + +void main() { + vec3 colorSource = texture2D(tex, texCoord).rgb; + vec3 lightWhiteVector = getWhiteVector(getLightIntensity(texCoord)); + vec3 colorLight = LightColor * lightWhiteVector; + vec3 colorReflection = texture2D(tex, texCoord - ReflectionDistance).rgb; + vec3 colorResult = ( + colorSource + + (colorLight * LightIntensity) + + (colorReflection * ReflectionBrightness) + ); + gl_FragColor = vec4( + colorResult, + 1.0 + ); +} diff --git a/res/shaders/gbc-lcd.shader/gbc-lcd.fs b/res/shaders/gbc-lcd.shader/gbc-lcd.fs new file mode 100644 index 000000000..4b88ad3aa --- /dev/null +++ b/res/shaders/gbc-lcd.shader/gbc-lcd.fs @@ -0,0 +1,421 @@ +/** + * This shader imitates the GameBoy Color subpixel + * arrangement. + */ + +varying vec2 texCoord; +uniform sampler2D tex; +uniform vec2 texSize; + +/** + * Adds a base color to everything. + * Lower values make black colors darker. + * Higher values make black colors lighter. + * You'll normally want each of these numbers to be close + * to 0, and not normally higher than 1. + */ +uniform vec3 BaseColor; + +/** + * Modifies the contrast or saturation of the image. + * Lower values make the image more gray and higher values + * make it more colorful. + * A value of 1 represents a normal, baseline level of + * contrast. + * You'll normally want this to be somewhere around 1. + */ +uniform float SourceContrast; + +/** + * Modifies the luminosity of the image. + * Lower values make the image darker and higher values make + * it lighter. + * A value of 1 represents normal, baseline luminosity. + * You'll normally want this to be somewhere around 1. + */ +uniform float SourceLuminosity; + +/** + * Lower values look more like a sharp, unshaded image. + * Higher values look more like an LCD display with subpixels. + * You'll normally want this to be a number from 0 to 1. + */ +uniform float SubpixelBlendAmount; + +/** + * Lower values make subpixels darker. + * Higher values make them lighter and over-bright. + * A value of 1 represents a normal, baseline gamma value. + * You'll normally want this to be somewhere around 1. + */ +uniform float SubpixelGamma; + +/** + * Higher values allow subpixels to be more blended-together + * and brighter. + * Lower values keep subpixel colors more separated. + * You'll normally want this to be a number from 0 to 1. + */ +uniform float SubpixelColorBleed; + +/** + * Determines the distance between subpixels. + * Lower values put the red, green, and blue subpixels + * within a single pixel closer together. + * Higher values put them farther apart. + * You'll normally want this to be a number from 0 to 1. + */ +uniform float SubpixelSpread; + +/** + * Determines the vertical offset of subpixels within + * a pixel. + * Lower values put the red, green, and blue subpixels + * within a single pixel higher up. + * Higher values put them further down. + * You'll normally want this to be a number from 0 to 1. + */ +uniform float SubpixelVerticalOffset; + +/** + * Lower values make the subpixels horizontally thinner, + * and higher values make them thicker. + * You'll normally want this to be a number from 0 to 1. + */ +uniform float SubpixelLightWidth; + +/** + * Lower values make the subpixels vertically taller, + * and higher values make them shorter. + * You'll normally want this to be a number from 0 to 1. + */ +uniform float SubpixelLightHeight; + +/** + * Lower values make the subpixels sharper and more + * individually distinct. + * Higher values add an increasingly intense glowing + * effect around each subpixel. + * You'll normally want this to be a number from 0 to 1. + */ +uniform float SubpixelLightGlow; + +/** + * Scale the size of pixels up or down. + * Useful for looking at larger than 8x8 subpixel sizes. + * You'll normally want this number to be exactly 1, + * meaning that every group of 3 subpixels corresponds + * to one pixel in the display. + */ +uniform float SubpixelScale; + +/** + * GBC subpixels are roughly rectangular shaped, but + * with a rectangular gap in the lower-right corner. + * Lower values make the lower-right gap in each GBC + * subpixel less distinct. A value of 0 results in no + * gap being shown at all. + * Higher values make the gap more distinct. + * You'll normally want this to be a number from 0 to 1. + */ +uniform float SubpixelTabHeight; + +/** + * The following three uniforms decide the base colors + * of each of the subpixels. + * + * Default subpixel colors are based on this resource: + * https://gbcc.dev/technology/ + * R: #FF7145 (1.00, 0.44, 0.27) + * G: #C1D650 (0.75, 0.84, 0.31) + * B: #3BCEFF (0.23, 0.81, 1.00) + */ +uniform vec3 SubpixelColorRed; // vec3(1.00, 0.38, 0.22); +uniform vec3 SubpixelColorGreen; // vec3(0.60, 0.88, 0.30); +uniform vec3 SubpixelColorBlue; // vec3(0.23, 0.65, 1.00); + +/** + * Helper to get luminosity of an RGB color. + * Used with HCL color space related code. + */ +float getColorLumosity(in vec3 rgb) { + return ( + (rgb.r * (5.0 / 16.0)) + + (rgb.g * (9.0 / 16.0)) + + (rgb.b * (2.0 / 16.0)) + ); +} + +/** + * Helper to convert RGB color to HCL. (Hue, Chroma, Luma) + */ +vec3 convertRgbToHcl(in vec3 rgb) { + float xMin = min(rgb.r, min(rgb.g, rgb.b)); + float xMax = max(rgb.r, max(rgb.g, rgb.b)); + float c = xMax - xMin; + float l = getColorLumosity(rgb); + float h = mod(( + c == 0 ? 0.0 : + xMax == rgb.r ? ((rgb.g - rgb.b) / c) : + xMax == rgb.g ? ((rgb.b - rgb.r) / c) + 2.0 : + xMax == rgb.b ? ((rgb.r - rgb.g) / c) + 4.0 : + 0.0 + ), 6.0); + return vec3(h, c, l); +} + +/** + * Helper to convert HCL color to RGB. (Hue, Chroma, Luma) + */ +vec3 convertHclToRgb(in vec3 hcl) { + vec3 rgb; + float h = mod(hcl.x, 6.0); + float c = hcl.y; + float l = hcl.z; + float x = c * (1.0 - abs(mod(h, 2.0) - 1.0)); + if(h <= 1.0) { + rgb = vec3(c, x, 0.0); + } + else if(h <= 2.0) { + rgb = vec3(x, c, 0.0); + } + else if(h <= 3.0) { + rgb = vec3(0.0, c, x); + } + else if(h <= 4.0) { + rgb = vec3(0.0, x, c); + } + else if(h <= 5.0) { + rgb = vec3(x, 0.0, c); + } + else { + rgb = vec3(c, 0.0, x); + } + float lRgb = getColorLumosity(rgb); + float m = l - lRgb; + return clamp(vec3(m, m, m) + rgb, 0.0, 1.0); +} + +/** + * Helper to check if a point is contained within + * a rectangular area. + */ +bool getPointInRect( + vec2 point, + vec2 rectTopLeft, + vec2 rectBottomRight +) { + return ( + point.x >= rectTopLeft.x && + point.y >= rectTopLeft.y && + point.x <= rectBottomRight.x && + point.y <= rectBottomRight.y + ); +} + +/** + * Helper to get the nearest offset vector from a + * point to a line segment. + * (The length of this offset vector is the nearest + * distance from the point to the line segment.) + * Thank you to https://stackoverflow.com/a/1501725 + */ +vec2 getPointLineDistance( + vec2 point, + vec2 line0, + vec2 line1 +) { + vec2 lineDelta = line0 - line1; + float lineLengthSq = dot(lineDelta, lineDelta); + if(lineLengthSq <= 0) { + return line0 - point; + } + float t = ( + dot(point - line0, line1 - line0) / lineLengthSq + ); + vec2 projection = ( + line0 + clamp(t, 0.0, 1.0) * (line1 - line0) + ); + return projection - point; +} + +/** + * Helper to get the nearest offset vector from a + * point to a rectangle. + * Returns (0, 0) for points within the rectangle. + */ +vec2 getPointRectDistance( + vec2 point, + vec2 rectTopLeft, + vec2 rectBottomRight +) { + if(getPointInRect(point, rectTopLeft, rectBottomRight)) { + return vec2(0.0, 0.0); + } + vec2 rectTopRight = vec2(rectBottomRight.x, rectTopLeft.y); + vec2 rectBottomLeft = vec2(rectTopLeft.x, rectBottomRight.y); + vec2 v0 = getPointLineDistance(point, rectTopLeft, rectTopRight); + vec2 v1 = getPointLineDistance(point, rectBottomLeft, rectBottomRight); + vec2 v2 = getPointLineDistance(point, rectTopLeft, rectBottomLeft); + vec2 v3 = getPointLineDistance(point, rectTopRight, rectBottomRight); + float v0LengthSq = dot(v0, v0); + float v1LengthSq = dot(v1, v1); + float v2LengthSq = dot(v2, v2); + float v3LengthSq = dot(v3, v3); + float minLengthSq = min( + min(v0LengthSq, v1LengthSq), + min(v2LengthSq, v3LengthSq) + ); + if(minLengthSq == v0LengthSq) { + return v0; + } + else if(minLengthSq == v1LengthSq) { + return v1; + } + else if(minLengthSq == v2LengthSq) { + return v2; + } + else { + return v3; + } +} + +/** + * Helper to get the nearest offset vector from a + * point to a subpixel. + * GBC subpixels are roughly rectangular in shape, + * but have a rectangular gap in their bottom-left + * corner. + * Returns (0, 0) for points within the subpixel. + */ +vec2 getPointSubpixelDistance( + vec2 point, + vec2 subpixelCenter, + vec2 subpixelSizeHalf +) { + float rectLeft = subpixelCenter.x - subpixelSizeHalf.x; + float rectRight = subpixelCenter.x + subpixelSizeHalf.x; + float rectTop = subpixelCenter.y - subpixelSizeHalf.y; + float rectBottom = subpixelCenter.y + subpixelSizeHalf.y; + vec2 offsetLeft = getPointRectDistance( + point, + vec2(rectLeft, rectTop + SubpixelTabHeight), + vec2(subpixelCenter.x, rectBottom) + ); + vec2 offsetRight = getPointRectDistance( + point, + vec2(subpixelCenter.x, rectTop), + vec2(rectRight, rectBottom) + ); + float offsetLeftLengthSq = dot(offsetLeft, offsetLeft); + float offsetRightLengthSq = dot(offsetRight, offsetRight); + if(offsetLeftLengthSq <= offsetRightLengthSq) { + return offsetLeft; + } + else { + return offsetRight; + } +} + +/** + * Helper to get the intensity of light from a + * subpixel. + * The pixelPosition argument represents a + * fragment's position within a pixel. + * Spread represents the subpixel's horizontal + * position within the pixel. + */ +float getSubpixelIntensity( + vec2 pixelPosition, + float spread +) { + vec2 subpixelCenter = vec2( + 0.5 + (spread * SubpixelSpread), + 1.0 - SubpixelVerticalOffset + ); + vec2 subpixelSizeHalf = 0.5 * vec2( + SubpixelLightWidth, + SubpixelLightHeight + ); + vec2 offset = getPointSubpixelDistance( + pixelPosition, + subpixelCenter, + subpixelSizeHalf + ); + if(SubpixelLightGlow <= 0) { + return dot(offset, offset) <= 0.0 ? 1.0 : 0.0; + } + else { + float dist = length(offset); + float glow = max(0.0, + 1.0 - (dist / SubpixelLightGlow) + ); + return glow; + } +} + +/** + * Helper to apply SubpixelColorBleed to the intensity + * value computed for a fragment and subpixel. + * Subpixel color bleed allows subpixel colors to be + * more strongly coerced to more accurately represent + * the underlying pixel color. + */ +float applySubpixelBleed( + float subpixelIntensity, + float colorSourceChannel +) { + return subpixelIntensity * ( + SubpixelColorBleed + + ((1.0 - SubpixelColorBleed) * colorSourceChannel) + ); +} + +void main() { + // Get base color of the pixel, adjust based on + // contrast and luminosity settings. + vec3 colorSource = texture2D(tex, texCoord).rgb; + vec3 colorSourceHcl = convertRgbToHcl(colorSource); + vec3 colorSourceAdjusted = convertHclToRgb(vec3( + colorSourceHcl.x, + colorSourceHcl.y * SourceContrast, + colorSourceHcl.z * SourceLuminosity + )); + // Determine how much each subpixel's light should + // affect this fragment. + vec2 pixelPosition = ( + mod(texCoord * texSize * SubpixelScale, 1.0) + ); + float subpixelIntensityRed = applySubpixelBleed( + getSubpixelIntensity(pixelPosition, -1.0), + colorSourceAdjusted.r + ); + float subpixelIntensityGreen = applySubpixelBleed( + getSubpixelIntensity(pixelPosition, +0.0), + colorSourceAdjusted.g + ); + float subpixelIntensityBlue = applySubpixelBleed( + getSubpixelIntensity(pixelPosition, +1.0), + colorSourceAdjusted.b + ); + vec3 subpixelLightColor = SubpixelGamma * ( + (subpixelIntensityRed * SubpixelColorRed) + + (subpixelIntensityGreen * SubpixelColorGreen) + + (subpixelIntensityBlue * SubpixelColorBlue) + ); + // Compute final color + vec3 colorResult = clamp( + subpixelLightColor * colorSourceAdjusted, 0.0, 1.0 + ); + vec3 colorResultBlended = ( + ((1.0 - SubpixelBlendAmount) * colorSourceAdjusted) + + (SubpixelBlendAmount * colorResult) + ); + colorResultBlended = BaseColor + ( + (colorResultBlended * (vec3(1.0, 1.0, 1.0) - BaseColor)) + ); + gl_FragColor = vec4( + colorResultBlended, + 1.0 + ); +} diff --git a/res/shaders/gbc-lcd.shader/license.txt b/res/shaders/gbc-lcd.shader/license.txt new file mode 100644 index 000000000..68a49daad --- /dev/null +++ b/res/shaders/gbc-lcd.shader/license.txt @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/res/shaders/gbc-lcd.shader/manifest.ini b/res/shaders/gbc-lcd.shader/manifest.ini new file mode 100644 index 000000000..3af7e9e2f --- /dev/null +++ b/res/shaders/gbc-lcd.shader/manifest.ini @@ -0,0 +1,129 @@ +[shader] +name=gbc-lcd +author=Sophie Kirschner +description=Imitates the GameBoy Color LCD screen subpixel arrangement, with an optional backlight effect. +passes=2 + +[pass.0] +integerScaling=1 +fragmentShader=gbc-lcd.fs +blend=1 + +[pass.1] +fragmentShader=gbc-lcd-light.fs + +[pass.0.uniform.BaseColor] +type=float3 +default[0]=0.130 +default[1]=0.128 +default[2]=0.101 +readableName=Screen base color + +[pass.0.uniform.SubpixelColorRed] +type=float3 +default[0]=1.00 +default[1]=0.38 +default[2]=0.22 +readableName=Red subpixel color + +[pass.0.uniform.SubpixelColorGreen] +type=float3 +default[0]=0.60 +default[1]=0.88 +default[2]=0.30 +readableName=Green subpixel color + +[pass.0.uniform.SubpixelColorBlue] +type=float3 +default[0]=0.23 +default[1]=0.65 +default[2]=1.00 +readableName=Blue subpixel color + +[pass.0.uniform.SourceContrast] +type=float +default=0.85 +readableName=Screen contrast + +[pass.0.uniform.SourceLuminosity] +type=float +default=0.88 +readableName=Screen luminosity + +[pass.0.uniform.SubpixelBlendAmount] +type=float +default=1.0 +readableName=Subpixel effect amount + +[pass.0.uniform.SubpixelColorBleed] +type=float +default=0.31 +readableName=Subpixel color bleeding + +[pass.0.uniform.SubpixelSpread] +type=float +default=0.333 +readableName=Subpixel spread X + +[pass.0.uniform.SubpixelVerticalOffset] +type=float +default=0.48 +readableName=Subpixel offset Y + +[pass.0.uniform.SubpixelGamma] +type=float +default=1.040 +readableName=Subpixel brightness + +[pass.0.uniform.SubpixelLightWidth] +type=float +default=0.220 +readableName=Subpixel width + +[pass.0.uniform.SubpixelLightHeight] +type=float +default=0.850 +readableName=Subpixel height + +[pass.0.uniform.SubpixelLightGlow] +type=float +default=0.195 +readableName=Subpixel glow size + +[pass.0.uniform.SubpixelTabHeight] +type=float +default=0.175 +readableName=Subpixel tab shaping + +[pass.0.uniform.SubpixelScale] +type=float +default=1.0 +readableName=Subpixel scale + +[pass.1.uniform.LightColor] +type=float3 +default[0]=1.000 +default[1]=0.968 +default[2]=0.882 +readableName=Backlight color + +[pass.1.uniform.LightIntensity] +type=float +default=0.06 +readableName=Backlight intensity + +[pass.1.uniform.LightSoftness] +type=float +default=0.67 +readableName=Backlight softness + +[pass.1.uniform.ReflectionDistance] +type=float2 +default[0]=0 +default[1]=0.025 +readableName=Internal reflection distance + +[pass.1.uniform.ReflectionBrightness] +type=float +default=0.032 +readableName=Internal reflection brightness diff --git a/res/shaders/nso-gba-color.shader/manifest.ini b/res/shaders/nso-gba-color.shader/manifest.ini new file mode 100644 index 000000000..42faa25bd --- /dev/null +++ b/res/shaders/nso-gba-color.shader/manifest.ini @@ -0,0 +1,24 @@ +[shader] +name=NSO GBA Color +author=Pokefan531 and hunterk +description=Shader that replicates the Nintendo Switch Online's GBA color filter. +passes=1 + +[pass.0] +fragmentShader=nso-gba-color.fs +vertexShader=nso-gba-color.vs +blend=1 +width=-1 +height=-1 + +[pass.0.uniform.darken_screen] +type=float +default=0.8 +readableName=Darken Screen + +[pass.0.uniform.color_mode] +type=int +default=1 +min=1 +max=3 +readableName=Color Profile (1=sRGB, 2=DCI, 3=Rec2020) diff --git a/res/shaders/nso-gba-color.shader/nso-gba-color.fs b/res/shaders/nso-gba-color.shader/nso-gba-color.fs new file mode 100644 index 000000000..8d8a0ec92 --- /dev/null +++ b/res/shaders/nso-gba-color.shader/nso-gba-color.fs @@ -0,0 +1,21 @@ +// Shader that replicates the LCD Colorspace from Gameboy Advance -- +varying vec2 texCoord; +varying mat4 profile; +uniform sampler2D tex; +uniform vec2 texSize; + +uniform float darken_screen; +const float target_gamma = 2.2; +const float display_gamma = 2.2; + +void main() { + // bring out our stored luminance value + float lum = profile[3].w; + + // our adjustments need to happen in linear gamma + vec4 screen = pow(texture2D(tex, texCoord), vec4(target_gamma + darken_screen)).rgba; + + screen = clamp(screen * lum, 0.0, 1.0); + screen = profile * screen; + gl_FragColor = pow(screen, vec4(1.0 / display_gamma)); +} diff --git a/res/shaders/nso-gba-color.shader/nso-gba-color.vs b/res/shaders/nso-gba-color.shader/nso-gba-color.vs new file mode 100644 index 000000000..c9c89181b --- /dev/null +++ b/res/shaders/nso-gba-color.shader/nso-gba-color.vs @@ -0,0 +1,34 @@ +uniform int color_mode; +attribute vec4 position; +varying vec2 texCoord; +varying mat4 profile; + +const mat4 GBA_sRGB = mat4( + 0.865, 0.0575, 0.0575, 0.0, //red channel + 0.1225, 0.925, 0.1225, 0.0, //green channel + 0.0125, 0.0125, 0.82, 0.0, //blue channel + 0.0, 0.0, 0.0, 1.0 //alpha channel +); + +const mat4 GBA_DCI = mat4( + 0.72, 0.0875, 0.0725, 0.0, //red channel + 0.2675, 0.9, 0.185, 0.0, //green channel + 0.0125, 0.0125, 0.7425, 0.0, //blue channel + 0.0, 0.0, 0.0, 1.0 //alpha channel +); + +const mat4 GBA_Rec2020 = mat4( + 0.57, 0.115, 0.0725, 0.0, //red channel + 0.3825, 0.8625, 0.195, 0.0, //green channel + 0.0475, 0.0225, 0.7325, 0.0, //blue channel + 0.0, 0.0, 0.0, 1.0 //alpha channel +); + +void main() { + if (color_mode == 1) profile = GBA_sRGB; + else if (color_mode == 2) profile = GBA_DCI; + else if (color_mode == 3) profile = GBA_Rec2020; + + gl_Position = position; + texCoord = (position.st + vec2(1.0, 1.0)) * vec2(0.5, 0.5); +} diff --git a/src/arm/arm.c b/src/arm/arm.c index cb93136aa..0b92d7f55 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -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) { diff --git a/src/arm/decoder.c b/src/arm/decoder.c index 01622cc9d..21ea0e872 100644 --- a/src/arm/decoder.c +++ b/src/arm/decoder.c @@ -9,7 +9,7 @@ #include #include -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS #define ADVANCE(AMOUNT) \ if (AMOUNT >= blen) { \ buffer[blen - 1] = '\0'; \ diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index 7f158dc6e..aaecf2517 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -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 diff --git a/src/arm/isa-thumb.c b/src/arm/isa-thumb.c index 0bc8fcb12..30fcfde9d 100644 --- a/src/arm/isa-thumb.c +++ b/src/arm/isa-thumb.c @@ -88,7 +88,7 @@ DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(LSR1, } THUMB_NEUTRAL_S( , , cpu->gprs[rd]);) -DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(ASR1, +DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(ASR1, if (!immediate) { cpu->cpsr.c = ARM_SIGN(cpu->gprs[rm]); if (cpu->cpsr.c) { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 184445023..e86e4fe55 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -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) diff --git a/src/core/bitmap-cache.c b/src/core/bitmap-cache.c index 6cb14eaf0..f42da90c5 100644 --- a/src/core/bitmap-cache.c +++ b/src/core/bitmap-cache.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; } diff --git a/src/core/cache-set.c b/src/core/cache-set.c index 04d42a233..098844bd9 100644 --- a/src/core/cache-set.c +++ b/src/core/cache-set.c @@ -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); diff --git a/src/core/cheats.c b/src/core/cheats.c index 60f73abcc..2fc97c3ac 100644 --- a/src/core/cheats.c +++ b/src/core/cheats.c @@ -37,7 +37,7 @@ static uint32_t _patchMakeKey(struct mCheatPatch* patch) { patchKey >>= 2; break; default: - break; + break; } // TODO: More than one segment if (patch->segment > 0) { @@ -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,11 +622,14 @@ 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; } + if (!device->p->dirs.cheats) { + return; + } struct VFile* vf = mDirectorySetOpenSuffix(&device->p->dirs, device->p->dirs.cheats, ".cheats", O_WRONLY | O_CREAT | O_TRUNC); if (!vf) { return; diff --git a/src/core/config.c b/src/core/config.c index 78a527332..4fa27ba55 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -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); @@ -198,38 +198,46 @@ bool mCoreConfigSaveVFile(const struct mCoreConfig* config, struct VFile* vf) { return ConfigurationWriteVFile(&config->configTable, vf); } -void mCoreConfigMakePortable(const struct mCoreConfig* config) { +void mCoreConfigMakePortable(const struct mCoreConfig* config, const char* path) { struct VFile* portable = NULL; + struct Configuration portableConfig; char out[PATH_MAX]; - mCoreConfigPortablePath(out, sizeof(out)); + mCoreConfigPortableIniPath(out, sizeof(out)); if (!out[0]) { // Cannot be made portable return; } - portable = VFileOpen(out, O_WRONLY | O_CREAT); + + ConfigurationInit(&portableConfig); + + portable = VFileOpen(out, O_RDONLY); if (portable) { + ConfigurationReadVFile(&portableConfig, portable); portable->close(portable); - mCoreConfigSave(config); } + + if (path && path[0]) { + ConfigurationSetValue(&portableConfig, "portable", "path", path); + } else { + ConfigurationClearValue(&portableConfig, "portable", "path"); + } + + portable = VFileOpen(out, O_WRONLY | O_CREAT | O_TRUNC); + if (portable) { + ConfigurationWriteVFile(&portableConfig, portable); + portable->close(portable); + } + + ConfigurationDeinit(&portableConfig); + mCoreConfigSave(config); } void mCoreConfigDirectory(char* out, size_t outLength) { - struct VFile* portable; char portableDir[PATH_MAX]; mCoreConfigPortablePath(portableDir, sizeof(portableDir)); if (portableDir[0]) { - portable = VFileOpen(portableDir, O_RDONLY); - if (portable) { - portable->close(portable); - if (outLength < PATH_MAX) { - char outTmp[PATH_MAX]; - separatePath(portableDir, outTmp, NULL, NULL); - strlcpy(out, outTmp, outLength); - } else { - separatePath(portableDir, out, NULL, NULL); - } - return; - } + strlcpy(out, portableDir, outLength); + return; } #ifdef _WIN32 WCHAR wpath[MAX_PATH]; @@ -276,7 +284,7 @@ void mCoreConfigDirectory(char* out, size_t outLength) { #endif } -void mCoreConfigPortablePath(char* out, size_t outLength) { +void mCoreConfigPortableIniPath(char* out, size_t outLength) { #ifdef _WIN32 wchar_t wpath[MAX_PATH]; GetModuleFileNameW(NULL, wpath, MAX_PATH); @@ -290,6 +298,7 @@ void mCoreConfigPortablePath(char* out, size_t outLength) { WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, outLength, 0, 0); StringCchCatA(out, outLength, PATH_SEP "portable.ini"); #elif defined(PSP2) || defined(GEKKO) || defined(__SWITCH__) || defined(__3DS__) + UNUSED(outLength); out[0] = '\0'; #else getcwd(out, outLength); @@ -307,18 +316,44 @@ void mCoreConfigPortablePath(char* out, size_t outLength) { #endif } -bool mCoreConfigIsPortable(void) { - struct VFile* portable; - char portableDir[PATH_MAX]; - mCoreConfigPortablePath(portableDir, sizeof(portableDir)); - if (portableDir[0]) { - portable = VFileOpen(portableDir, O_RDONLY); - if (portable) { - portable->close(portable); - return true; +void mCoreConfigPortablePath(char* out, size_t outLength) { + struct VFile* portableIni; + char portableIniPath[PATH_MAX]; + mCoreConfigPortableIniPath(portableIniPath, sizeof(portableIniPath)); + out[0] = '\0'; + if (portableIniPath[0]) { + portableIni = VFileOpen(portableIniPath, O_RDONLY); + if (portableIni) { + // Start with the path that the portable.ini file exists in. + char iniDir[PATH_MAX]; + separatePath(portableIniPath, iniDir, NULL, NULL); + strlcpy(out, iniDir, outLength); + + struct Configuration portableConfig; + ConfigurationInit(&portableConfig); + if (ConfigurationReadVFile(&portableConfig, portableIni)) { + const char* path = ConfigurationGetValue(&portableConfig, "portable", "path"); + if (path) { + if (path[0] == '/') { + // User specified an absolute path. + strlcpy(out, path, outLength); + } else { + // User specified a relative path, append to the portable.ini path. + snprintf(out, outLength, "%s" PATH_SEP "%s", iniDir, path); + } + } + } + ConfigurationDeinit(&portableConfig); + + portableIni->close(portableIni); } } - return false; +} + +bool mCoreConfigIsPortable(void) { + char portableDir[PATH_MAX]; + mCoreConfigPortablePath(portableDir, sizeof(portableDir)); + return portableDir[0]; } #endif diff --git a/src/core/core.c b/src/core/core.c index a7de23943..ba7ef914c 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -15,6 +15,10 @@ #include #endif +#ifdef USE_PNG +#include +#endif + #ifdef M_CORE_GB #include #include @@ -86,9 +90,7 @@ struct mCore* mCoreCreate(enum mPlatform platform) { return NULL; } -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 -#include - +#ifdef ENABLE_VFS #ifdef PSP2 #include #endif @@ -237,20 +239,35 @@ bool mCoreAutoloadPatch(struct mCore* core) { if (!core->dirs.patch) { return false; } - return core->loadPatch(core, mDirectorySetOpenSuffix(&core->dirs, core->dirs.patch, ".ups", O_RDONLY)) || - core->loadPatch(core, mDirectorySetOpenSuffix(&core->dirs, core->dirs.patch, ".ips", O_RDONLY)) || - core->loadPatch(core, mDirectorySetOpenSuffix(&core->dirs, core->dirs.patch, ".bps", O_RDONLY)); + struct VFile* vf = NULL; + if (!vf) { + vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.patch, ".bps", O_RDONLY); + } + if (!vf) { + vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.patch, ".ups", O_RDONLY); + } + if (!vf) { + vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.patch, ".ips", O_RDONLY); + } + if (!vf) { + return false; + } + bool result = core->loadPatch(core, vf); + vf->close(vf); + return result; } bool mCoreAutoloadCheats(struct mCore* core) { - bool success = true; + bool success = !!core->dirs.cheats; int cheatAuto; - if (!mCoreConfigGetIntValue(&core->config, "cheatAutoload", &cheatAuto) || cheatAuto) { + if (success && (!mCoreConfigGetIntValue(&core->config, "cheatAutoload", &cheatAuto) || cheatAuto)) { struct VFile* vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.cheats, ".cheats", O_RDONLY); if (vf) { struct mCheatDevice* device = core->cheatDevice(core); success = mCheatParseFile(device, vf); vf->close(vf); + } else { + success = false; } } if (!mCoreConfigGetIntValue(&core->config, "cheatAutosave", &cheatAuto) || cheatAuto) { @@ -381,7 +398,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 +406,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 +459,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 +490,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"); diff --git a/src/core/directories.c b/src/core/directories.c index c35773f1e..e0748f829 100644 --- a/src/core/directories.c +++ b/src/core/directories.c @@ -8,7 +8,7 @@ #include #include -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#ifdef ENABLE_VFS void mDirectorySetInit(struct mDirectorySet* dirs) { dirs->base = NULL; dirs->archive = NULL; @@ -110,6 +110,9 @@ struct VFile* mDirectorySetOpenPath(struct mDirectorySet* dirs, const char* path } struct VFile* mDirectorySetOpenSuffix(struct mDirectorySet* dirs, struct VDir* dir, const char* suffix, int mode) { + if (!dir) { + return NULL; + } char name[PATH_MAX + 1] = ""; snprintf(name, sizeof(name) - 1, "%s%s", dirs->baseName, suffix); return dir->openFile(dir, name, mode); diff --git a/src/core/flags.h.in b/src/core/flags.h.in index 3bd142a44..3507df032 100644 --- a/src/core/flags.h.in +++ b/src/core/flags.h.in @@ -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 diff --git a/src/core/interface.c b/src/core/interface.c index d63754895..5771d80e1 100644 --- a/src/core/interface.c +++ b/src/core/interface.c @@ -101,11 +101,54 @@ 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; +} + +void mRumbleIntegratorReset(struct mRumbleIntegrator* integrator) { + _mRumbleIntegratorReset(&integrator->d, false); +} diff --git a/src/core/library.c b/src/core/library.c index 44148f7f5..1c92a0cbc 100644 --- a/src/core/library.c +++ b/src/core/library.c @@ -6,6 +6,7 @@ #include #include +#include #include #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; diff --git a/src/core/lockstep.c b/src/core/lockstep.c index 587cff2b5..c058a80fc 100644 --- a/src/core/lockstep.c +++ b/src/core/lockstep.c @@ -1,10 +1,14 @@ -/* Copyright (c) 2013-2016 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 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#ifndef DISABLE_THREADING +#include +#endif + void mLockstepInit(struct mLockstep* lockstep) { lockstep->attached = 0; lockstep->transferActive = 0; @@ -19,4 +23,21 @@ void mLockstepDeinit(struct mLockstep* lockstep) { UNUSED(lockstep); } -// TODO: Migrate nodes +#ifndef DISABLE_THREADING +static void mLockstepThreadUserSleep(struct mLockstepUser* user) { + struct mLockstepThreadUser* lockstep = (struct mLockstepThreadUser*) user; + mCoreThreadWaitFromThread(lockstep->thread); +} + +static void mLockstepThreadUserWake(struct mLockstepUser* user) { + struct mLockstepThreadUser* lockstep = (struct mLockstepThreadUser*) user; + mCoreThreadStopWaiting(lockstep->thread); +} + +void mLockstepThreadUserInit(struct mLockstepThreadUser* lockstep, struct mCoreThread* thread) { + memset(lockstep, 0, sizeof(*lockstep)); + lockstep->d.sleep = mLockstepThreadUserSleep; + lockstep->d.wake = mLockstepThreadUserWake; + lockstep->thread = thread; +} +#endif diff --git a/src/core/log.c b/src/core/log.c index 5fe2fe9ee..39d6db88c 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #define MAX_CATEGORY 64 @@ -14,11 +14,56 @@ static struct mLogger* _defaultLogger = NULL; -struct mLogger* mLogGetContext(void) { - struct mLogger* logger = NULL; #ifndef DISABLE_THREADING - logger = mCoreThreadLogger(); +static ThreadLocal _contextKey; + +#ifdef USE_PTHREADS +static pthread_once_t _contextOnce = PTHREAD_ONCE_INIT; + +static void _createTLS(void) { + ThreadLocalInitKey(&_contextKey); +} +#elif _WIN32 +static INIT_ONCE _contextOnce = INIT_ONCE_STATIC_INIT; + +static BOOL CALLBACK _createTLS(PINIT_ONCE once, PVOID param, PVOID* context) { + UNUSED(once); + UNUSED(param); + UNUSED(context); + ThreadLocalInitKey(&_contextKey); + return TRUE; +} #endif + +static void _setupTLS(void) { +#ifdef USE_PTHREADS + pthread_once(&_contextOnce, _createTLS); +#elif _WIN32 + InitOnceExecuteOnce(&_contextOnce, _createTLS, NULL, 0); +#endif +} +#endif + +void mLogSetThreadLogger(struct mLogger* logger) { +#ifndef DISABLE_THREADING + _setupTLS(); + ThreadLocalSetKey(_contextKey, logger); +#else + UNUSED(logger); +#endif +} + +struct mLogger* mLogGetThreadLogger(void) { +#ifndef DISABLE_THREADING + _setupTLS(); + return ThreadLocalGetValue(_contextKey); +#else + return NULL; +#endif +} + +struct mLogger* mLogGetContext(void) { + struct mLogger* logger = mLogGetThreadLogger(); if (logger) { return logger; } @@ -233,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); } diff --git a/src/core/map-cache.c b/src/core/map-cache.c index d51800780..5668d82f3 100644 --- a/src/core/map-cache.c +++ b/src/core/map-cache.c @@ -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]; } diff --git a/src/core/rewind.c b/src/core/rewind.c index 21120ec21..b8ba752dd 100644 --- a/src/core/rewind.c +++ b/src/core/rewind.c @@ -115,7 +115,7 @@ void _rewindDiff(struct mCoreRewindContext* context) { context->currentState->unmap(context->currentState, next, size); } -bool mCoreRewindRestore(struct mCoreRewindContext* context, struct mCore* core) { +bool mCoreRewindRestore(struct mCoreRewindContext* context, struct mCore* core, unsigned count) { #ifndef DISABLE_THREADING if (context->onThread) { MutexLock(&context->mutex); @@ -129,30 +129,34 @@ bool mCoreRewindRestore(struct mCoreRewindContext* context, struct mCore* core) #endif return false; } - --context->size; - mCoreLoadStateNamed(core, context->previousState, SAVESTATE_SAVEDATA | SAVESTATE_RTC); - if (context->current == 0) { - context->current = mCoreRewindPatchesSize(&context->patchMemory); - } - --context->current; - - if (context->size) { - struct PatchFast* patch = mCoreRewindPatchesGetPointer(&context->patchMemory, context->current); - size_t size2 = context->previousState->size(context->previousState); - size_t size = context->currentState->size(context->currentState); - if (size2 < size) { - size = size2; + for (; count && context->size; --count, --context->size) { + if (context->current == 0) { + context->current = mCoreRewindPatchesSize(&context->patchMemory); } - void* current = context->currentState->map(context->currentState, size, MAP_READ); - void* previous = context->previousState->map(context->previousState, size, MAP_WRITE); - patch->d.applyPatch(&patch->d, previous, size, current, size); - context->currentState->unmap(context->currentState, current, size); - context->previousState->unmap(context->previousState, previous, size); + --context->current; + + if (context->size > 1) { + struct PatchFast* patch = mCoreRewindPatchesGetPointer(&context->patchMemory, context->current); + size_t size2 = context->previousState->size(context->previousState); + size_t size = context->currentState->size(context->currentState); + if (size2 < size) { + size = size2; + } + void* current = context->currentState->map(context->currentState, size, MAP_READ); + void* previous = context->previousState->map(context->previousState, size, MAP_WRITE); + patch->d.applyPatch(&patch->d, previous, size, current, size); + context->currentState->unmap(context->currentState, current, size); + context->previousState->unmap(context->previousState, previous, size); + } + struct VFile* nextState = context->previousState; + context->previousState = context->currentState; + context->currentState = nextState; } - struct VFile* nextState = context->previousState; - context->previousState = context->currentState; - context->currentState = nextState; + + mCoreLoadStateNamed(core, context->currentState, SAVESTATE_SAVEDATA | SAVESTATE_RTC); + + #ifndef DISABLE_THREADING if (context->onThread) { MutexUnlock(&context->mutex); diff --git a/src/core/scripting.c b/src/core/scripting.c index 5b1f39a63..dc56c1783 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -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); @@ -518,31 +520,35 @@ mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mCore, busWrite16, 2, U32, address, U16, va mSCRIPT_DECLARE_STRUCT_VOID_D_METHOD(mCore, busWrite32, 2, U32, address, U32, value); // Register functions -mSCRIPT_DECLARE_STRUCT_METHOD(mCore, WSTR, readRegister, _mScriptCoreReadRegister, 1, CHARP, regName); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, WRAPPER, readRegister, _mScriptCoreReadRegister, 1, CHARP, regName); 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; -} diff --git a/src/core/serialize.c b/src/core/serialize.c index b721cdafa..4f7c07a4a 100644 --- a/src/core/serialize.c +++ b/src/core/serialize.c @@ -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); diff --git a/src/core/sync.c b/src/core/sync.c index b2a65493b..e46e7dcda 100644 --- a/src/core/sync.c +++ b/src/core/sync.c @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#include +#include 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; diff --git a/src/core/test/core.c b/src/core/test/core.c index 10c566b2c..645a45486 100644 --- a/src/core/test/core.c +++ b/src/core/test/core.c @@ -8,7 +8,7 @@ #include #include -#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), diff --git a/src/core/test/scripting.c b/src/core/test/scripting.c index c2593bf14..63927effe 100644 --- a/src/core/test/scripting.c +++ b/src/core/test/scripting.c @@ -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), diff --git a/src/core/thread.c b/src/core/thread.c index 983395c12..2b16a03c7 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -5,7 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#include #include #ifdef ENABLE_SCRIPTING #include @@ -42,18 +41,14 @@ static BOOL CALLBACK _createTLS(PINIT_ONCE once, PVOID param, PVOID* context) { static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args); -static void _changeState(struct mCoreThreadInternal* threadContext, enum mCoreThreadState newState, bool broadcast) { - MutexLock(&threadContext->stateMutex); +static void _changeState(struct mCoreThreadInternal* threadContext, enum mCoreThreadState newState) { threadContext->state = newState; - if (broadcast) { - ConditionWake(&threadContext->stateCond); - } - MutexUnlock(&threadContext->stateMutex); + 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); } } @@ -107,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) { @@ -144,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) { @@ -153,7 +148,7 @@ void _frameStarted(void* context) { return; } if (thread->core->opts.rewindEnable && thread->core->opts.rewindBufferCapacity > 0) { - if (!thread->impl->rewinding || !mCoreRewindRestore(&thread->impl->rewind, thread->core)) { + if (!thread->impl->rewinding || !mCoreRewindRestore(&thread->impl->rewind, thread->core, 1)) { if (thread->impl->rewind.rewindFrameCounter == 0) { mCoreRewindAppend(&thread->impl->rewind, thread->core); thread->impl->rewind.rewindFrameCounter = thread->core->opts.rewindBufferInterval; @@ -178,7 +173,9 @@ void _crashed(void* context) { if (!thread) { return; } - _changeState(thread->impl, mTHREAD_CRASHED, true); + MutexLock(&thread->impl->stateMutex); + _changeState(thread->impl, mTHREAD_CRASHED); + MutexUnlock(&thread->impl->stateMutex); } void _coreSleep(void* context) { @@ -196,7 +193,9 @@ void _coreShutdown(void* context) { if (!thread) { return; } - _changeState(thread->impl, mTHREAD_EXITING, true); + MutexLock(&thread->impl->stateMutex); + _changeState(thread->impl, mTHREAD_EXITING); + MutexUnlock(&thread->impl->stateMutex); } #ifdef ENABLE_SCRIPTING @@ -218,17 +217,17 @@ ADD_CALLBACK(savedataUpdated) ADD_CALLBACK(alarm) #undef ADD_CALLBACK -#define CALLBACK(NAME) _script_ ## NAME +#define SCRIPT(NAME) _script_ ## NAME static void _mCoreThreadAddCallbacks(struct mCoreThread* threadContext) { struct mCoreCallbacks callbacks = { - .videoFrameEnded = CALLBACK(frame), - .coreCrashed = CALLBACK(crashed), - .sleep = CALLBACK(sleep), - .shutdown = CALLBACK(stop), - .keysRead = CALLBACK(keysRead), - .savedataUpdated = CALLBACK(savedataUpdated), - .alarm = CALLBACK(alarm), + .videoFrameEnded = SCRIPT(frame), + .coreCrashed = SCRIPT(crashed), + .sleep = SCRIPT(sleep), + .shutdown = SCRIPT(stop), + .keysRead = SCRIPT(keysRead), + .savedataUpdated = SCRIPT(savedataUpdated), + .alarm = SCRIPT(alarm), .context = threadContext }; threadContext->core->addCoreCallbacks(threadContext->core, &callbacks); @@ -246,6 +245,8 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { ThreadLocalSetKey(_contextKey, threadContext); ThreadSetName("CPU Thread"); + mLogSetThreadLogger(&threadContext->logger.d); + #if !defined(_WIN32) && defined(USE_PTHREADS) sigset_t signals; sigemptyset(&signals); @@ -301,7 +302,9 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { core->reset(core); threadContext->impl->core = core; - _changeState(threadContext->impl, mTHREAD_RUNNING, true); + MutexLock(&threadContext->impl->stateMutex); + _changeState(threadContext->impl, mTHREAD_RUNNING); + MutexUnlock(&threadContext->impl->stateMutex); if (threadContext->resetCallback) { threadContext->resetCallback(threadContext); @@ -324,44 +327,47 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { bool wasPaused = false; int pendingRequests = 0; + MutexLock(&impl->stateMutex); while (impl->state < mTHREAD_EXITING) { -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS struct mDebugger* debugger = core->debugger; if (debugger) { + MutexUnlock(&impl->stateMutex); mDebuggerRun(debugger); + MutexLock(&impl->stateMutex); if (debugger->state == DEBUGGER_SHUTDOWN) { - _changeState(impl, mTHREAD_EXITING, false); + impl->state = mTHREAD_EXITING; } } else #endif { while (impl->state == mTHREAD_RUNNING) { + MutexUnlock(&impl->stateMutex); core->runLoop(core); + MutexLock(&impl->stateMutex); } } - MutexLock(&impl->stateMutex); 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); } } @@ -384,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); @@ -425,11 +430,14 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { threadContext->run(threadContext); } } + MutexLock(&impl->stateMutex); } - while (impl->state < mTHREAD_SHUTDOWN) { - _changeState(impl, mTHREAD_SHUTDOWN, false); + if (impl->state < mTHREAD_SHUTDOWN) { + impl->state = mTHREAD_SHUTDOWN; } + ConditionWake(&threadContext->impl->stateOffThreadCond); + MutexUnlock(&impl->stateMutex); if (core->opts.rewindEnable) { mCoreRewindContextDeinit(&impl->rewind); @@ -451,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; @@ -467,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); @@ -488,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); @@ -534,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); } @@ -542,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); } @@ -551,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; @@ -580,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); @@ -632,7 +643,6 @@ void mCoreThreadInterruptFromThread(struct mCoreThread* threadContext) { return; } threadContext->impl->state = mTHREAD_INTERRUPTING; - ConditionWake(&threadContext->impl->stateCond); MutexUnlock(&threadContext->impl->stateMutex); } @@ -646,9 +656,9 @@ void mCoreThreadContinue(struct mCoreThread* threadContext) { if (threadContext->impl->requested) { threadContext->impl->state = mTHREAD_REQUEST; } else { - threadContext->impl->state = mTHREAD_RUNNING; + threadContext->impl->state = mTHREAD_RUNNING; } - ConditionWake(&threadContext->impl->stateCond); + ConditionWake(&threadContext->impl->stateOnThreadCond); } MutexUnlock(&threadContext->impl->stateMutex); } @@ -708,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); } @@ -762,12 +772,3 @@ struct mCoreThread* mCoreThreadGet(void) { return NULL; } #endif - -struct mLogger* mCoreThreadLogger(void) { - struct mCoreThread* thread = mCoreThreadGet(); - if (thread) { - return &thread->logger.d; - } - return NULL; -} - diff --git a/src/core/tile-cache.c b/src/core/tile-cache.c index 249cd0116..26ea86416 100644 --- a/src/core/tile-cache.c +++ b/src/core/tile-cache.c @@ -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)]; } diff --git a/src/debugger/CMakeLists.txt b/src/debugger/CMakeLists.txt index 8bdc952de..976f88c93 100644 --- a/src/debugger/CMakeLists.txt +++ b/src/debugger/CMakeLists.txt @@ -11,6 +11,14 @@ if(ENABLE_SCRIPTING) list(APPEND SOURCE_FILES cli-debugger-scripting.c) endif() +if(USE_EDITLINE) + list(APPEND SOURCE_FILES cli-el-backend.c) +endif() + +if(ENABLE_GDB_STUB) + list(APPEND SOURCE_FILES gdb-stub.c) +endif() + set(TEST_FILES test/lexer.c test/parser.c) diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index 9c9696f9f..c21d17a72 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -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; diff --git a/src/feature/editline/cli-el-backend.c b/src/debugger/cli-el-backend.c similarity index 98% rename from src/feature/editline/cli-el-backend.c rename to src/debugger/cli-el-backend.c index c76bb5d67..b32afb159 100644 --- a/src/feature/editline/cli-el-backend.c +++ b/src/debugger/cli-el-backend.c @@ -3,7 +3,7 @@ * 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/. */ -#include "cli-el-backend.h" +#include #include #include @@ -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); diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index cc0b32683..a03f106d9 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -10,7 +10,7 @@ #include #include -#ifdef USE_GDB_STUB +#ifdef ENABLE_GDB_STUB #include #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,16 +52,21 @@ 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); - GDBStubListen(&debugger->gdb, 2345, 0, GDB_WATCHPOINT_STANDARD_LOGIC); + struct Address localHost = { + .version = IPV4, + .ipv4 = 0x7F000001 + }; + GDBStubListen(&debugger->gdb, 2345, &localHost, GDB_WATCHPOINT_STANDARD_LOGIC); break; #endif case DEBUGGER_NONE: + case DEBUGGER_ACCESS_LOGGER: case DEBUGGER_CUSTOM: case DEBUGGER_MAX: free(debugger); - return 0; + return NULL; break; } diff --git a/src/feature/CMakeLists.txt b/src/feature/CMakeLists.txt index b692338f4..966c25520 100644 --- a/src/feature/CMakeLists.txt +++ b/src/feature/CMakeLists.txt @@ -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 diff --git a/src/feature/commandline.c b/src/feature/commandline.c index e529a2eb3..fca5c7747 100644 --- a/src/feature/commandline.c +++ b/src/feature/commandline.c @@ -5,9 +5,19 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include +#include #include #include +#include + +#ifdef ENABLE_GDB_STUB +#include +#endif +#ifdef USE_EDITLINE +#include +#endif #include #ifdef _MSC_VER @@ -30,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' }, @@ -75,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 ; @@ -141,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; @@ -206,6 +216,66 @@ 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 + if (args->debugCli) { + struct mDebuggerModule* module = mDebuggerCreateModule(DEBUGGER_CLI, core); + if (module) { + struct CLIDebugger* cliDebugger = (struct CLIDebugger*) module; + CLIDebuggerAttachBackend(cliDebugger, CLIDebuggerEditLineBackendCreate()); + mDebuggerAttachModule(debugger, module); + hasDebugger = true; + } + } +#endif + +#ifdef ENABLE_GDB_STUB + if (args->debugGdb) { + struct mDebuggerModule* module = mDebuggerCreateModule(DEBUGGER_GDB, core); + if (module) { + mDebuggerAttachModule(debugger, module); + hasDebugger = true; + } + } +#endif + + return hasDebugger; +} + +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) { + core->loadPatch(core, patch); + patch->close(patch); + } + } else { + mCoreAutoloadPatch(core); + } + + struct mCheatDevice* device = NULL; + if (args->cheatsFile && (device = core->cheatDevice(core))) { + struct VFile* vf = VFileOpen(args->cheatsFile, O_RDONLY); + if (vf) { + mCheatDeviceClear(device); + mCheatParseFile(device, vf); + vf->close(vf); + } + } else { + mCoreAutoloadCheats(core); + } +#else + UNUSED(args); + UNUSED(core); +#endif +} + void mArgumentsDeinit(struct mArguments* args) { free(args->fname); args->fname = 0; @@ -293,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" diff --git a/src/feature/ffmpeg/ffmpeg-decoder.c b/src/feature/ffmpeg/ffmpeg-decoder.c index daa47fbf2..189fb312f 100644 --- a/src/feature/ffmpeg/ffmpeg-decoder.c +++ b/src/feature/ffmpeg/ffmpeg-decoder.c @@ -71,7 +71,7 @@ bool FFmpegDecoderOpen(struct FFmpegDecoder* decoder, const char* infile) { codec = avcodec_find_decoder(context->codec_id); if (!codec) { FFmpegDecoderClose(decoder); - return false; + return false; } if (avcodec_open2(context, codec, NULL) < 0) { FFmpegDecoderClose(decoder); @@ -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); } } } diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index 220ce4d86..6202e0fcd 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -34,7 +34,7 @@ #endif #include -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; @@ -893,7 +893,7 @@ void FFmpegEncoderSetInputFrameRate(struct FFmpegEncoder* encoder, int numerator void FFmpegEncoderSetInputSampleRate(struct FFmpegEncoder* encoder, int sampleRate) { encoder->isampleRate = sampleRate; - if (encoder->resampleContext) { + if (encoder->resampleContext) { av_freep(&encoder->audioBuffer); #ifdef USE_LIBAVRESAMPLE avresample_close(encoder->resampleContext); diff --git a/src/feature/gui/gui-config.c b/src/feature/gui/gui-config.c index 4a6c79871..6214abc15 100644 --- a/src/feature/gui/gui-config.c +++ b/src/feature/gui/gui-config.c @@ -12,7 +12,7 @@ #include #ifdef M_CORE_GB #include -#include +#include #endif #include #include @@ -295,7 +295,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t test.v.s = mCoreConfigGetValue(&runner->config, item->data.v.s); if (test.v.s && strcmp(test.v.s, v->v.s) == 0) { item->state = j; - break; + break; } break; case GUI_VARIANT_POINTER: diff --git a/src/feature/gui/gui-runner.c b/src/feature/gui/gui-runner.c index 267b0e0b0..035522f02 100644 --- a/src/feature/gui/gui-runner.c +++ b/src/feature/gui/gui-runner.c @@ -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) { @@ -500,15 +500,15 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) { } mLOG(GUI_RUNNER, INFO, "Game starting"); runner->fps = 0; + bool fastForward = false; while (running) { - CircleBufferClear(&runner->fpsBuffer); + mCircleBufferClear(&runner->fpsBuffer); runner->totalDelta = 0; struct timeval tv; gettimeofday(&tv, 0); runner->lastFpsCheck = 1000000LL * tv.tv_sec + tv.tv_usec; int frame = 0; - bool fastForward = false; while (running) { if (runner->running) { running = runner->running(runner); @@ -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) { diff --git a/src/feature/gui/gui-runner.h b/src/feature/gui/gui-runner.h index 0dc412838..e65ced52f 100644 --- a/src/feature/gui/gui-runner.h +++ b/src/feature/gui/gui-runner.h @@ -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*); diff --git a/src/feature/proxy-backend.c b/src/feature/proxy-backend.c index fb6e555ed..540034227 100644 --- a/src/feature/proxy-backend.c +++ b/src/feature/proxy-backend.c @@ -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; } diff --git a/src/feature/sqlite3/no-intro.c b/src/feature/sqlite3/no-intro.c index 649364de6..463a2fe5e 100644 --- a/src/feature/sqlite3/no-intro.c +++ b/src/feature/sqlite3/no-intro.c @@ -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); diff --git a/src/feature/updater.c b/src/feature/updater.c index e50ed0fa2..ea9cea3c1 100644 --- a/src/feature/updater.c +++ b/src/feature/updater.c @@ -46,7 +46,7 @@ static void _updateList(const char* key, const char* value, void* user) { if (strncmp("medusa.", key, 7) == 0) { dotLoc = strchr(&key[7], '.'); } else { - dotLoc = strchr(key, '.'); + dotLoc = strchr(key, '.'); } if (!dotLoc) { return; diff --git a/src/feature/video-backend.c b/src/feature/video-backend.c index ae2f0257d..ba13bbe7d 100644 --- a/src/feature/video-backend.c +++ b/src/feature/video-backend.c @@ -23,3 +23,23 @@ void VideoBackendGetFrameSize(const struct VideoBackend* v, unsigned* width, uns *width = frame.width; *height = frame.height; } + +void VideoBackendRecenter(struct VideoBackend* v, unsigned scale) { + static const int centeredLayers[] = {VIDEO_LAYER_BACKGROUND, -1}; + struct mRectangle frame = {0}; + v->imageSize(v, VIDEO_LAYER_IMAGE, &frame.width, &frame.height); + if (scale == 0) { + scale = 1; + } + + size_t i; + for (i = 0; centeredLayers[i] >= 0; ++i) { + int width, height; + struct mRectangle dims = {0}; + v->imageSize(v, centeredLayers[i], &width, &height); + dims.width = width * scale; + dims.height = height * scale; + mRectangleCenter(&frame, &dims); + v->setLayerDimensions(v, centeredLayers[i], &dims); + } +} diff --git a/src/feature/video-logger.c b/src/feature/video-logger.c index fb2065b42..ac5ef1777 100644 --- a/src/feature/video-logger.c +++ b/src/feature/video-logger.c @@ -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 { @@ -339,17 +339,17 @@ bool mVideoLoggerRendererRunInjected(struct mVideoLogger* logger) { channel->injecting = true; bool res = mVideoLoggerRendererRun(logger, false); channel->injecting = false; - return res; + return res; } void mVideoLoggerInjectionPoint(struct mVideoLogger* logger, enum mVideoLoggerInjectionPoint injectionPoint) { struct mVideoLogChannel* channel = logger->dataContext; - channel->injectionPoint = injectionPoint; + channel->injectionPoint = injectionPoint; } void mVideoLoggerIgnoreAfterInjection(struct mVideoLogger* logger, uint32_t mask) { struct mVideoLogChannel* channel = logger->dataContext; - channel->ignorePackets = mask; + channel->ignorePackets = mask; } static bool _writeData(struct mVideoLogger* logger, const void* data, size_t length) { @@ -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; diff --git a/src/gb/audio.c b/src/gb/audio.c index e9c014d05..783b1fcb9 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -5,7 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#include #include #include #include @@ -15,15 +14,10 @@ #include #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; @@ -33,10 +27,10 @@ static void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value); static bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudioStyle style); static void _resetSweep(struct GBAudioSweep* sweep); -static bool _resetEnvelope(struct GBAudioEnvelope* sweep); +static bool _resetEnvelope(struct GBAudioEnvelope* sweep, enum GBAudioStyle style); static void _updateEnvelope(struct GBAudioEnvelope* envelope); -static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope); +static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope, enum GBAudioStyle style); static bool _updateSweep(struct GBAudioSquareChannel* sweep, bool initial); static void _updateSquareSample(struct GBAudioSquareChannel* ch); @@ -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); } @@ -192,7 +172,7 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { } } if (GBAudioRegisterControlIsRestart(value << 8)) { - audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope); + audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope, audio->style); audio->ch1.sweep.realFrequency = audio->ch1.control.frequency; _resetSweep(&audio->ch1.sweep); if (audio->playingCh1 && audio->ch1.sweep.shift) { @@ -243,7 +223,7 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { } } if (GBAudioRegisterControlIsRestart(value << 8)) { - audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope); + audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope, audio->style); if (!audio->ch2.control.length) { audio->ch2.control.length = 64; @@ -383,7 +363,7 @@ void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) { } } if (GBAudioRegisterNoiseControlIsRestart(value)) { - audio->playingCh4 = _resetEnvelope(&audio->ch4.envelope); + audio->playingCh4 = _resetEnvelope(&audio->ch4.envelope, audio->style); audio->ch4.lfsr = 0; if (!audio->ch4.length) { @@ -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,47 +822,33 @@ 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); } -bool _resetEnvelope(struct GBAudioEnvelope* envelope) { +bool _resetEnvelope(struct GBAudioEnvelope* envelope, enum GBAudioStyle style) { envelope->currentVolume = envelope->initialVolume; - _updateEnvelopeDead(envelope); - if (!envelope->dead) { - envelope->nextStep = envelope->stepTime; - } + envelope->nextStep = envelope->stepTime; + _updateEnvelopeDead(envelope, style); return envelope->initialVolume || envelope->direction; } @@ -914,15 +880,28 @@ void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value) { } bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudioStyle style) { + bool oldDirection = envelope->direction; envelope->stepTime = GBAudioRegisterSweepGetStepTime(value); envelope->direction = GBAudioRegisterSweepGetDirection(value); envelope->initialVolume = GBAudioRegisterSweepGetInitialVolume(value); - if (style == GB_AUDIO_DMG && !envelope->stepTime) { + if (!envelope->stepTime) { // TODO: Improve "zombie" mode - ++envelope->currentVolume; + if (style == GB_AUDIO_DMG) { + ++envelope->currentVolume; + } else if (style == GB_AUDIO_CGB) { + if (envelope->direction == oldDirection) { + if (envelope->direction) { + ++envelope->currentVolume; + } else { + envelope->currentVolume += 2; + } + } else { + envelope->currentVolume = 0; + } + } envelope->currentVolume &= 0xF; } - _updateEnvelopeDead(envelope); + _updateEnvelopeDead(envelope, style); return envelope->initialVolume || envelope->direction; } @@ -958,14 +937,19 @@ static void _updateEnvelope(struct GBAudioEnvelope* envelope) { } } -static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope) { +static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope, enum GBAudioStyle style) { if (!envelope->stepTime) { envelope->dead = envelope->currentVolume ? 1 : 2; } else if (!envelope->direction && !envelope->currentVolume) { envelope->dead = 2; } else if (envelope->direction && envelope->currentVolume == 0xF) { envelope->dead = 1; - } else { + } else if (envelope->dead) { + // TODO: Figure out if this happens on DMG/CGB or just AGB + // TODO: Figure out the exact circumstances that lead to reloading the step + if (style == GB_AUDIO_GBA) { + envelope->nextStep = envelope->stepTime; + } envelope->dead = 0; } } diff --git a/src/gb/core.c b/src/gb/core.c index 9154221d6..b97e1ee25 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -149,10 +150,10 @@ 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 - + return true; } @@ -161,10 +162,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 +408,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 +429,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 +439,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; @@ -531,6 +530,15 @@ static void _GBCoreChecksum(const struct mCore* core, void* data, enum mCoreChec case mCHECKSUM_CRC32: memcpy(data, &gb->romCrc32, sizeof(gb->romCrc32)); break; + case mCHECKSUM_MD5: + if (gb->romVf) { + md5File(gb->romVf, data); + } else if (gb->memory.rom && gb->isPristine) { + md5Buffer(gb->memory.rom, gb->pristineRomSize, data); + } else { + md5Buffer("", 0, data); + } + break; } return; } @@ -599,7 +607,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 +753,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 +803,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 +1076,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 +1125,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 +1276,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 +1320,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 +1343,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 +1352,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 +1372,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 +1415,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; diff --git a/src/gb/debugger/cli.c b/src/gb/debugger/cli.c index f32f299a3..0b3ec6678 100644 --- a/src/gb/debugger/cli.c +++ b/src/gb/debugger/cli.c @@ -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) { diff --git a/src/gb/debugger/debugger.c b/src/gb/debugger/debugger.c index cc05bb7a5..1a3743e42 100644 --- a/src/gb/debugger/debugger.c +++ b/src/gb/debugger/debugger.c @@ -3,14 +3,14 @@ * 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/. */ - #include +#include - #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include static const struct SM83Segment _GBSegments[] = { { .name = "ROM", .start = GB_BASE_CART_BANK1, .end = GB_BASE_VRAM }, diff --git a/src/gb/extra/proxy.c b/src/gb/extra/proxy.c index 54d46eef3..c0c386f4c 100644 --- a/src/gb/extra/proxy.c +++ b/src/gb/extra/proxy.c @@ -29,7 +29,8 @@ static void GBVideoProxyRendererPutPixels(struct GBVideoRenderer* renderer, size static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* packet); static uint16_t* _vramBlock(struct mVideoLogger* logger, uint32_t address); -void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GBVideoRenderer* backend) { +void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GBVideoRenderer* backend, struct mVideoLogger* logger) { + memset(renderer, 0, sizeof(*renderer)); renderer->d.init = GBVideoProxyRendererInit; renderer->d.deinit = GBVideoProxyRendererDeinit; renderer->d.writeVideoRegister = GBVideoProxyRendererWriteVideoRegister; @@ -57,12 +58,13 @@ void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GB renderer->d.highlightColor = M_COLOR_WHITE; renderer->d.highlightAmount = 0; - renderer->logger->context = renderer; - renderer->logger->parsePacket = _parsePacket; - renderer->logger->vramBlock = _vramBlock; - renderer->logger->paletteSize = 0; - renderer->logger->vramSize = GB_SIZE_VRAM; - renderer->logger->oamSize = GB_SIZE_OAM; + renderer->logger = logger; + logger->context = renderer; + logger->parsePacket = _parsePacket; + logger->vramBlock = _vramBlock; + logger->paletteSize = 0; + logger->vramSize = GB_SIZE_VRAM; + logger->oamSize = GB_SIZE_OAM; renderer->backend = backend; } @@ -265,7 +267,7 @@ void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, _copyExtraState(proxyRenderer); proxyRenderer->backend->drawRange(proxyRenderer->backend, startX, endX, y); } - mVideoLoggerRendererDrawRange(proxyRenderer->logger, startX, endX, y); + mVideoLoggerRendererDrawRange(proxyRenderer->logger, startX, endX, y); } void GBVideoProxyRendererFinishScanline(struct GBVideoRenderer* renderer, int y) { diff --git a/src/gb/gb.c b/src/gb/gb.c index 899d5cfc7..875cbf86e 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -16,6 +16,7 @@ #include #include #include +#include #include const uint32_t CGB_SM83_FREQUENCY = 0x800000; @@ -106,7 +107,7 @@ static void GBDeinit(struct mCPUComponent* component) { bool GBLoadGBX(struct GBXMetadata* metadata, struct VFile* vf) { uint8_t footer[16]; - if (vf->seek(vf, -sizeof(footer), SEEK_END) < 0) { + if (vf->seek(vf, -(off_t) sizeof(footer), SEEK_END) < 0) { return false; } if (vf->read(vf, footer, sizeof(footer)) < (ssize_t) sizeof(footer)) { @@ -151,7 +152,7 @@ bool GBLoadGBX(struct GBXMetadata* metadata, struct VFile* vf) { if (memcmp(footer, "MBC1", 4) == 0) { metadata->mapperVars.u8[0] = 5; } else if (memcmp(footer, "MB1M", 4) == 0) { - metadata->mapperVars.u8[0] = 4; + metadata->mapperVars.u8[0] = 4; } return true; } @@ -260,9 +261,13 @@ void GBResizeSram(struct GB* gb, size_t size) { } struct VFile* vf = gb->sramVf; if (vf) { + // We have a vf + ssize_t vfSize = vf->size(vf); if (vf == gb->sramRealVf) { - ssize_t vfSize = vf->size(vf); + // This is the real save file, not a masked one if (vfSize >= 0 && (size_t) vfSize < size) { + // We need to grow the file + // Make sure to copy the footer data, if any uint8_t extdataBuffer[0x100]; if (vfSize & 0xFF) { vf->seek(vf, -(vfSize & 0xFF), SEEK_END); @@ -270,6 +275,7 @@ void GBResizeSram(struct GB* gb, size_t size) { } if (gb->memory.sram) { vf->unmap(vf, gb->memory.sram, gb->sramSize); + gb->memory.sram = NULL; } vf->truncate(vf, size + (vfSize & 0xFF)); if (vfSize & 0xFF) { @@ -281,24 +287,36 @@ void GBResizeSram(struct GB* gb, size_t size) { memset(&gb->memory.sram[vfSize], 0xFF, size - vfSize); } } else if (size > gb->sramSize || !gb->memory.sram) { + // We aren't growing the file, but we are changing our mapping of it if (gb->memory.sram) { vf->unmap(vf, gb->memory.sram, gb->sramSize); + gb->memory.sram = NULL; } if (size) { gb->memory.sram = vf->map(vf, size, MAP_WRITE); } } } else { + // This is a masked save file if (gb->memory.sram) { vf->unmap(vf, gb->memory.sram, gb->sramSize); } - if (vf->size(vf) < gb->sramSize) { - void* sram = vf->map(vf, vf->size(vf), MAP_READ); - struct VFile* newVf = VFileMemChunk(sram, vf->size(vf)); - vf->unmap(vf, sram,vf->size(vf)); - vf = newVf; - gb->sramVf = newVf; - vf->truncate(vf, size); + if ((vfSize <= 0 && size) || (size_t) vfSize < size) { + // The loaded mask file is too small. Since these can be read-only, + // we need to make a new one of the right size + if (vfSize < 0) { + vfSize = 0; + } + gb->sramVf = VFileMemChunk(NULL, size); + uint8_t* sram = gb->sramVf->map(gb->sramVf, size, MAP_WRITE); + if (vfSize > 0) { + vf->seek(vf, 0, SEEK_SET); + vf->read(vf, sram, vfSize); + } + memset(&sram[vfSize], 0xFF, size - vfSize); + gb->sramVf->unmap(gb->sramVf, sram, size); + vf->close(vf); + vf = gb->sramVf; } if (size) { gb->memory.sram = vf->map(vf, size, MAP_READ); @@ -308,6 +326,8 @@ void GBResizeSram(struct GB* gb, size_t size) { gb->memory.sram = NULL; } } else if (size) { + // There's no vf, so let's make it only memory-backed + // TODO: Investigate just using a VFileMemChunk instead of this hybrid approach uint8_t* newSram = anonymousMemoryMap(size); if (gb->memory.sram) { if (size > gb->sramSize) { @@ -455,17 +475,18 @@ void GBApplyPatch(struct GB* gb, struct Patch* patch) { if (patchedSize > GB_SIZE_CART_MAX) { patchedSize = GB_SIZE_CART_MAX; } + + const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100]; + uint8_t type = cart->type; void* newRom = anonymousMemoryMap(GB_SIZE_CART_MAX); if (!patch->applyPatch(patch, gb->memory.rom, gb->pristineRomSize, newRom, patchedSize)) { mappedMemoryFree(newRom, GB_SIZE_CART_MAX); return; } - if (gb->romVf) { + if (gb->romVf && gb->isPristine) { #ifndef FIXED_ROM_BUFFER gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->pristineRomSize); #endif - gb->romVf->close(gb->romVf); - gb->romVf = NULL; } gb->isPristine = false; if (gb->memory.romBase == gb->memory.rom) { @@ -473,6 +494,12 @@ void GBApplyPatch(struct GB* gb, struct Patch* patch) { } gb->memory.rom = newRom; gb->memory.romSize = patchedSize; + + cart = (const struct GBCartridge*) &gb->memory.rom[0x100]; + if (cart->type != type) { + gb->memory.mbcType = GB_MBC_AUTODETECT; + GBMBCInit(gb); + } gb->romCrc32 = doCrc32(gb->memory.rom, gb->memory.romSize); gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc); } @@ -865,7 +892,7 @@ int GBValidModels(const uint8_t* bank0) { } else if (cart->cgb == 0xC0) { models = GB_MODEL_CGB; } else { - models = GB_MODEL_MGB; + models = GB_MODEL_MGB; } if (cart->sgb == 0x03 && cart->oldLicensee == 0x33) { models |= GB_MODEL_SGB; @@ -912,7 +939,7 @@ void GBProcessEvents(struct SM83Core* cpu) { nextEvent = cycles; do { -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS gb->timing.globalCycles += nextEvent; #endif nextEvent = mTimingTick(&gb->timing, nextEvent); @@ -1029,7 +1056,7 @@ void GBStop(struct SM83Core* cpu) { void GBIllegal(struct SM83Core* cpu) { struct GB* gb = (struct GB*) cpu->master; mLOG(GB, GAME_ERROR, "Hit illegal opcode at address %04X:%02X", cpu->pc, cpu->bus); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS if (cpu->components && cpu->components[CPU_COMPONENT_DEBUGGER]) { struct mDebuggerEntryInfo info = { .address = cpu->pc, @@ -1072,7 +1099,7 @@ bool GBIsROM(struct VFile* vf) { } uint8_t footer[16]; - vf->seek(vf, -sizeof(footer), SEEK_END); + vf->seek(vf, -(off_t) sizeof(footer), SEEK_END); if (vf->read(vf, footer, sizeof(footer)) < (ssize_t) sizeof(footer)) { return false; } @@ -1088,38 +1115,28 @@ bool GBIsROM(struct VFile* vf) { return false; } -void GBGetGameTitle(const struct GB* gb, char* out) { - const struct GBCartridge* cart = NULL; - if (gb->memory.rom) { - cart = (const struct GBCartridge*) &gb->memory.rom[0x100]; - } - if (!cart) { +void GBGetGameInfo(const struct GB* gb, struct mGameInfo* info) { + memset(info, 0, sizeof(*info)); + if (!gb->memory.rom) { return; } - if (cart->oldLicensee != 0x33) { - memcpy(out, cart->titleLong, 16); - } else { - memcpy(out, cart->titleShort, 11); - } -} -void GBGetGameCode(const struct GB* gb, char* out) { - memset(out, 0, 8); - const struct GBCartridge* cart = NULL; - if (gb->memory.rom) { - cart = (const struct GBCartridge*) &gb->memory.rom[0x100]; - } - if (!cart) { - return; - } + const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100]; if (cart->cgb == 0xC0) { - memcpy(out, "CGB-????", 8); + strlcpy(info->system, "CGB", sizeof(info->system)); } else { - memcpy(out, "DMG-????", 8); + strlcpy(info->system, "DMG", sizeof(info->system)); } - if (cart->oldLicensee == 0x33) { - memcpy(&out[4], cart->maker, 4); + + if (cart->oldLicensee != 0x33) { + memcpy(info->title, cart->titleLong, 16); + snprintf(info->maker, sizeof(info->maker), "%02X", cart->oldLicensee); + } else { + memcpy(info->title, cart->titleShort, 11); + memcpy(info->code, cart->maker, 4); + memcpy(info->maker, &cart->licensee, 2); } + info->version = cart->version; } void GBFrameStarted(struct GB* gb) { @@ -1146,9 +1163,15 @@ void GBFrameEnded(struct GB* gb) { } } + struct mRumble* rumble = gb->memory.rumble; + if (rumble && rumble->integrate) { + gb->memory.lastRumble = mTimingCurrentTime(&gb->timing); + rumble->integrate(rumble, GB_VIDEO_TOTAL_LENGTH); + } + // TODO: Move to common code if (gb->stream && gb->stream->postVideoFrame) { - const color_t* pixels; + const mColor* pixels; size_t stride; gb->video.renderer->getPixels(gb->video.renderer, &stride, (const void**) &pixels); gb->stream->postVideoFrame(gb->stream, pixels, stride); diff --git a/src/gb/mbc.c b/src/gb/mbc.c index 76c005f96..397b50088 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -163,7 +163,7 @@ static bool _isMulticart(const uint8_t* mem) { success = GBIsROM(vf); vf->close(vf); } - + return success; } @@ -540,6 +540,7 @@ void GBMBCReset(struct GB* gb) { gb->memory.cartBus = 0xFF; gb->memory.cartBusPc = 0; gb->memory.cartBusDecay = 1; + gb->memory.lastRumble = 0; memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState)); GBMBCInit(gb); diff --git a/src/gb/mbc/mbc.c b/src/gb/mbc/mbc.c index 864b6e9f8..699bdb209 100644 --- a/src/gb/mbc/mbc.c +++ b/src/gb/mbc/mbc.c @@ -253,7 +253,9 @@ void _GBMBC5(struct GB* gb, uint16_t address, uint8_t value) { case 0x4: case 0x5: if (memory->mbcType == GB_MBC5_RUMBLE && memory->rumble) { - memory->rumble->setRumble(memory->rumble, (value >> 3) & 1); + int32_t currentTime = mTimingCurrentTime(&gb->timing); + memory->rumble->setRumble(memory->rumble, (value >> 3) & 1, currentTime - memory->lastRumble); + memory->lastRumble = currentTime; value &= ~8; } GBMBCSwitchSramBank(gb, value & 0xF); diff --git a/src/gb/mbc/pocket-cam.c b/src/gb/mbc/pocket-cam.c index c587dfa6a..0eab34aba 100644 --- a/src/gb/mbc/pocket-cam.c +++ b/src/gb/mbc/pocket-cam.c @@ -95,39 +95,32 @@ void _GBPocketCamCapture(struct GBMemory* memory) { case mCOLOR_XRGB8: case mCOLOR_ARGB8: case mCOLOR_ABGR8: - color = ((const uint32_t*) image)[y * stride + x]; - gray = (color & 0xFF) + ((color >> 8) & 0xFF) + ((color >> 16) & 0xFF); - break; case mCOLOR_BGRX8: case mCOLOR_RGBX8: case mCOLOR_RGBA8: case mCOLOR_BGRA8: color = ((const uint32_t*) image)[y * stride + x]; - gray = ((color >> 8) & 0xFF) + ((color >> 16) & 0xFF) + ((color >> 24) & 0xFF); break; case mCOLOR_BGR5: case mCOLOR_RGB5: case mCOLOR_ARGB5: case mCOLOR_ABGR5: - color = ((const uint16_t*) image)[y * stride + x]; - gray = ((color << 3) & 0xF8) + ((color >> 2) & 0xF8) + ((color >> 7) & 0xF8); - break; case mCOLOR_BGR565: case mCOLOR_RGB565: - color = ((const uint16_t*) image)[y * stride + x]; - gray = ((color << 3) & 0xF8) + ((color >> 3) & 0xFC) + ((color >> 8) & 0xF8); - break; case mCOLOR_BGRA5: case mCOLOR_RGBA5: color = ((const uint16_t*) image)[y * stride + x]; - gray = ((color << 2) & 0xF8) + ((color >> 3) & 0xF8) + ((color >> 8) & 0xF8); + break; + case mCOLOR_L8: + color = ((const uint8_t*) image)[y * stride + x]; break; default: mLOG(GB_MBC, WARN, "Unsupported pixel format: %X", format); return; } uint16_t exposure = (pocketCam->registers[2] << 8) | (pocketCam->registers[3]); - gray = (gray + 1) * exposure / 0x300; + gray = mColorConvert(color, format, mCOLOR_L8); + gray = (gray + 1) * exposure / 0x100; // TODO: Additional processing int matrixEntry = 3 * ((x & 3) + 4 * (y & 3)); if (gray < pocketCam->registers[matrixEntry + 6]) { diff --git a/src/gb/mbc/tama5.c b/src/gb/mbc/tama5.c index 505a35ed8..c4f0a1517 100644 --- a/src/gb/mbc/tama5.c +++ b/src/gb/mbc/tama5.c @@ -131,7 +131,7 @@ static void _latchTAMA6Rtc(struct mRTCSource* rtc, struct GBTAMA5State* tama5, t timerRegs[GBTAMA6_RTC_PA0_HOUR_10] = (diff % 24) / 10; } else { timerRegs[GBTAMA6_RTC_PA0_HOUR_1] = (diff % 12) % 10; - timerRegs[GBTAMA6_RTC_PA0_HOUR_10] = (diff % 12) / 10 + (diff / 12) * 2; + timerRegs[GBTAMA6_RTC_PA0_HOUR_10] = (diff % 12) / 10 + (diff / 12) * 2; } t /= 24; t += diff / 24; diff --git a/src/gb/mbc/unlicensed.c b/src/gb/mbc/unlicensed.c index 1577a15fa..844c0d0cd 100644 --- a/src/gb/mbc/unlicensed.c +++ b/src/gb/mbc/unlicensed.c @@ -228,7 +228,9 @@ void _GBNTOld2(struct GB* gb, uint16_t address, uint8_t value) { } if (mbcState->rumble && memory->rumble) { - memory->rumble->setRumble(memory->rumble, !!(mbcState->swapped ? value & 0x08 : value & 0x02)); + int32_t currentTime = mTimingCurrentTime(&gb->timing); + memory->rumble->setRumble(memory->rumble, !!(mbcState->swapped ? value & 0x08 : value & 0x02), currentTime - memory->lastRumble); + memory->lastRumble = currentTime; } break; } @@ -347,7 +349,7 @@ void _GBHitek(struct GB* gb, uint16_t address, uint8_t value) { break; case 0x300: // See hhugboy src/memory/mbc/MbcUnlHitek.cpp for commentary on this return - return; + return; } _GBMBC5(gb, address, value); } @@ -394,10 +396,10 @@ uint8_t _GBGGB81Read(struct GBMemory* memory, uint16_t address) { } void _GBLiCheng(struct GB* gb, uint16_t address, uint8_t value) { - if (address > 0x2100 && address < 0x3000) { - return; - } - _GBMBC5(gb, address, value); + if (address > 0x2100 && address < 0x3000) { + return; + } + _GBMBC5(gb, address, value); } void _GBSachen(struct GB* gb, uint16_t address, uint8_t value) { diff --git a/src/gb/memory.c b/src/gb/memory.c index e41050784..dccd91e08 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -1017,8 +1017,6 @@ void _pristineCow(struct GB* gb) { } if (gb->romVf) { gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->memory.romSize); - gb->romVf->close(gb->romVf); - gb->romVf = NULL; } gb->memory.rom = newRom; GBMBCSwitchBank(gb, gb->memory.currentBank); diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index d157920fa..76a0c55da 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -44,7 +44,7 @@ static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) { } int y; for (y = 0; y < GB_VIDEO_VERTICAL_PIXELS; ++y) { - color_t* row = &renderer->outputBuffer[renderer->outputBufferStride * y + sgbOffset]; + mColor* row = &renderer->outputBuffer[renderer->outputBufferStride * y + sgbOffset]; int x; for (x = 0; x < GB_VIDEO_HORIZONTAL_PIXELS; x += 4) { row[x + 0] = renderer->palette[0]; @@ -492,7 +492,7 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* render static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value) { struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; - color_t color = mColorFrom555(value); + mColor color = mColorFrom555(value); if (softwareRenderer->model & GB_MODEL_SGB) { if (index >= PAL_SGB_BORDER && !(index & 0xF)) { color = softwareRenderer->palette[0]; @@ -668,7 +668,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i if (softwareRenderer->model & GB_MODEL_SGB && softwareRenderer->sgbBorders) { sgbOffset = softwareRenderer->outputBufferStride * 40 + 48; } - color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y + sgbOffset]; + mColor* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y + sgbOffset]; int x = startX; int p = 0; switch (softwareRenderer->d.sgbRenderMode) { @@ -1161,7 +1161,7 @@ static void GBVideoSoftwareRendererPutPixels(struct GBVideoRenderer* renderer, s struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; // TODO: Share with GBAVideoSoftwareRendererGetPixels - const color_t* colorPixels = pixels; + const mColor* colorPixels = pixels; unsigned i; for (i = 0; i < GB_VIDEO_VERTICAL_PIXELS; ++i) { memmove(&softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * i], &colorPixels[stride * i], GB_VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); diff --git a/src/gb/serialize.c b/src/gb/serialize.c index 0abdc1958..8f874d8eb 100644 --- a/src/gb/serialize.c +++ b/src/gb/serialize.c @@ -122,6 +122,13 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) { mLOG(GB_STATE, WARN, "Savestate is corrupted: video y is out of range"); error = true; } + + GBSerializedVideoFlags videoFlags = state->video.flags; + if (check16 >= GB_VIDEO_VERTICAL_PIXELS && GBSerializedVideoFlagsGetMode(videoFlags) != 1) { + mLOG(GB_STATE, WARN, "Savestate is corrupted: video y is in vblank but mode is not vblank"); + error = true; + } + LOAD_16LE(ucheck16, 0, &state->memory.dmaDest); if (ucheck16 + state->memory.dmaRemaining > GB_SIZE_OAM) { mLOG(GB_STATE, WARN, "Savestate is corrupted: DMA destination is out of range"); diff --git a/src/gb/video.c b/src/gb/video.c index 37c1e3650..d52e43dee 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -756,7 +755,7 @@ void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) { video->ly = 0; video->p->memory.io[GB_REG_LY] = 0; video->renderer->writePalette(video->renderer, 0, video->dmgPalette[0]); - + mTimingDeschedule(&video->p->timing, &video->modeEvent); mTimingDeschedule(&video->p->timing, &video->frameEvent); mTimingSchedule(&video->p->timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH << 1); diff --git a/src/gba/CMakeLists.txt b/src/gba/CMakeLists.txt index 4bf354f3a..01a968a41 100644 --- a/src/gba/CMakeLists.txt +++ b/src/gba/CMakeLists.txt @@ -31,7 +31,6 @@ set(SOURCE_FILES sharkport.c sio.c sio/gbp.c - sio/joybus.c timer.c video.c) @@ -40,7 +39,6 @@ set(SIO_FILES sio/lockstep.c) set(EXTRA_FILES - extra/audio-mixer.c extra/battlechip.c extra/proxy.c) diff --git a/src/gba/audio.c b/src/gba/audio.c index fb0e1b62c..ac394e995 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -16,17 +15,12 @@ #define MP2K_LOCK_MAX 8 -#ifdef __3DS__ -#define blip_add_delta blip_add_delta_fast -#endif - mLOG_DEFINE_CATEGORY(GBA_AUDIO, "GBA Audio", "gba.audio"); const unsigned GBA_AUDIO_SAMPLES = 2048; const int GBA_AUDIO_VOLUME_MAX = 0x100; static const int SAMPLE_INTERVAL = GBA_ARM7TDMI_FREQUENCY / 0x4000; -static const int CLOCKS_PER_FRAME = 0x800; static int _applyBias(struct GBAAudio* audio, int sample); static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate); @@ -41,20 +35,15 @@ void GBAAudioInit(struct GBAAudio* audio, size_t samples) { #ifdef __BIG_ENDIAN__ ++nr52; #endif - GBAudioInit(&audio->psg, 0, nr52, GB_AUDIO_GBA); + GBAudioInit(&audio->psg, samples, nr52, GB_AUDIO_GBA); audio->psg.timing = &audio->p->timing; - audio->psg.clockRate = GBA_ARM7TDMI_FREQUENCY; audio->psg.frameEvent.context = audio; audio->samples = samples; - // Guess too large; we hang producing extra samples if we guess too low - blip_set_rates(audio->psg.left, GBA_ARM7TDMI_FREQUENCY, 96000); - blip_set_rates(audio->psg.right, GBA_ARM7TDMI_FREQUENCY, 96000); - audio->externalMixing = false; audio->forceDisableChA = false; audio->forceDisableChB = false; audio->masterVolume = GBA_AUDIO_VOLUME_MAX; - audio->mixer = NULL; + audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / 0x8000; } void GBAAudioReset(struct GBAAudio* audio) { @@ -93,12 +82,13 @@ void GBAAudioReset(struct GBAAudio* audio) { audio->chBLeft = false; audio->chBTimer = false; audio->enable = false; - audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / 0x8000; + if (audio->sampleInterval != GBA_ARM7TDMI_FREQUENCY / 0x8000) { + audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / 0x8000; + if (audio->p->stream && audio->p->stream->audioRateChanged) { + audio->p->stream->audioRateChanged(audio->p->stream, GBA_ARM7TDMI_FREQUENCY / audio->sampleInterval); + } + } audio->psg.sampleInterval = audio->sampleInterval; - - blip_clear(audio->psg.left); - blip_clear(audio->psg.right); - audio->clock = 0; } void GBAAudioDeinit(struct GBAAudio* audio) { @@ -106,14 +96,9 @@ void GBAAudioDeinit(struct GBAAudio* audio) { } void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) { - if (samples > 0x2000) { - samples = 0x2000; - } mCoreSyncLockAudio(audio->p->sync); audio->samples = samples; - blip_clear(audio->psg.left); - blip_clear(audio->psg.right); - audio->clock = 0; + audio->psg.samples = samples; mCoreSyncConsumeAudio(audio->p->sync); } @@ -131,27 +116,6 @@ void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* mLOG(GBA_AUDIO, GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest); return; } - if (audio->mixer) { - uint32_t source = info->source; - uint32_t offsets[] = { 0x350, 0x980 }; - size_t i; - for (i = 0; i < sizeof(offsets) / sizeof(*offsets); ++i) { - if (source < GBA_BASE_EWRAM + offsets[i]) { - continue; - } - if (source >= GBA_BASE_IO + offsets[i]) { - continue; - } - uint32_t value = GBALoad32(audio->p->cpu, source - offsets[i], NULL); - if (value - MP2K_MAGIC <= MP2K_LOCK_MAX) { - audio->mixer->engage(audio->mixer, source - offsets[i]); - break; - } - } - if (i == sizeof(offsets) / sizeof(*offsets)) { - audio->externalMixing = false; - } - } } void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) { @@ -268,6 +232,9 @@ void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) { if (oldSampleInterval != audio->sampleInterval) { timestamp -= audio->lastSample; audio->sampleIndex = timestamp >> (9 - GBARegisterSOUNDBIASGetResolution(value)); + if (audio->sampleIndex >= GBA_MAX_SAMPLES) { + audio->sampleIndex = 0; + } if (audio->p->stream && audio->p->stream->audioRateChanged) { audio->p->stream->audioRateChanged(audio->p->stream, GBA_ARM7TDMI_FREQUENCY / audio->sampleInterval); } @@ -342,6 +309,7 @@ void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) { if (GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_CUSTOM) { dma->when = mTimingCurrentTime(&audio->p->timing) - cycles; dma->nextCount = 4; + GBADMARecalculateCycles(audio->p); GBADMASchedule(audio->p, channel->dmaSource, dma); } } @@ -357,6 +325,9 @@ void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) { int bits = 2 << GBARegisterSOUNDBIASGetResolution(audio->soundbias); until += 1 << (9 - GBARegisterSOUNDBIASGetResolution(audio->soundbias)); until >>= 9 - GBARegisterSOUNDBIASGetResolution(audio->soundbias); + if (UNLIKELY(bits < until)) { + until = bits; + } int i; for (i = bits - until; i < bits; ++i) { channel->samples[i] = channel->internalSample; @@ -392,28 +363,23 @@ void GBAAudioSample(struct GBAAudio* audio, int32_t timestamp) { sampleLeft >>= psgShift; sampleRight >>= psgShift; - if (audio->mixer) { - audio->mixer->step(audio->mixer); - } - if (!audio->externalMixing) { - if (!audio->forceDisableChA) { - if (audio->chALeft) { - sampleLeft += (audio->chA.samples[sample] << 2) >> !audio->volumeChA; - } - - if (audio->chARight) { - sampleRight += (audio->chA.samples[sample] << 2) >> !audio->volumeChA; - } + if (!audio->forceDisableChA) { + if (audio->chALeft) { + sampleLeft += (audio->chA.samples[sample] << 2) >> !audio->volumeChA; } - if (!audio->forceDisableChB) { - if (audio->chBLeft) { - sampleLeft += (audio->chB.samples[sample] << 2) >> !audio->volumeChB; - } + if (audio->chARight) { + sampleRight += (audio->chA.samples[sample] << 2) >> !audio->volumeChA; + } + } - if (audio->chBRight) { - sampleRight += (audio->chB.samples[sample] << 2) >> !audio->volumeChB; - } + if (!audio->forceDisableChB) { + if (audio->chBLeft) { + sampleLeft += (audio->chB.samples[sample] << 2) >> !audio->volumeChB; + } + + if (audio->chBRight) { + sampleRight += (audio->chB.samples[sample] << 2) >> !audio->volumeChB; } } @@ -439,39 +405,27 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { memset(audio->chB.samples, audio->chB.samples[samples - 1], sizeof(audio->chB.samples)); mCoreSyncLockAudio(audio->p->sync); - unsigned produced; - int i; - for (i = 0; i < samples; ++i) { - int16_t sampleLeft = audio->currentSamples[i].left; - int16_t sampleRight = audio->currentSamples[i].right; - if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) { - blip_add_delta(audio->psg.left, audio->clock, sampleLeft - audio->lastLeft); - blip_add_delta(audio->psg.right, audio->clock, sampleRight - audio->lastRight); - audio->lastLeft = sampleLeft; - audio->lastRight = sampleRight; - audio->clock += audio->sampleInterval; - if (audio->clock >= CLOCKS_PER_FRAME) { - blip_end_frame(audio->psg.left, CLOCKS_PER_FRAME); - blip_end_frame(audio->psg.right, CLOCKS_PER_FRAME); - audio->clock -= CLOCKS_PER_FRAME; + mAudioBufferWrite(&audio->psg.buffer, (int16_t*) audio->currentSamples, samples); + if (audio->p->stream) { + if (audio->p->stream->postAudioFrame) { + int i; + for (i = 0; i < 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->psg.buffer); + bool wait = produced >= audio->samples; + if (wait) { + audio->p->stream->postAudioBuffer(audio->p->stream, &audio->psg.buffer); + } } } - produced = blip_samples_avail(audio->psg.left); - bool wait = produced >= audio->samples; - if (!mCoreSyncProduceAudio(audio->p->sync, audio->psg.left, audio->samples)) { + if (!mCoreSyncProduceAudio(audio->p->sync, &audio->psg.buffer)) { // Interrupted audio->p->earlyExit = true; } - if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) { - audio->p->stream->postAudioBuffer(audio->p->stream, audio->psg.left, audio->psg.right); - } - mTimingSchedule(timing, &audio->sampleEvent, SAMPLE_INTERVAL - cyclesLate); } @@ -528,6 +482,10 @@ void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* GBASerializedAudioFlags2 flags2 = 0; flags2 = GBASerializedAudioFlags2SetSampleIndex(flags2, audio->sampleIndex); + // This flag was introduced in 0.11 and will only ever be 0, 1 or 2, so we + // add 1 and use a non-zero value to mark its presence in the state file + flags2 = GBASerializedAudioFlags2SetChASource(flags2, audio->chA.dmaSource + 1); + flags2 = GBASerializedAudioFlags2SetChBSource(flags2, audio->chB.dmaSource + 1); STORE_32(flags2, 0, &state->audio.gbaFlags2); STORE_32(audio->sampleEvent.when - mTimingCurrentTime(&audio->p->timing), 0, &state->audio.nextSample); @@ -579,6 +537,14 @@ void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState GBASerializedAudioFlags2 flags2; LOAD_32(flags2, 0, &state->audio.gbaFlags2); audio->sampleIndex = GBASerializedAudioFlags2GetSampleIndex(flags2); + // This flag was introduced in 0.11 and will only ever be 0, 1 or 2, so we + // add 1 and use a non-zero value to mark its presence in the state file + if (GBASerializedAudioFlags2GetChASource(flags2) > 0) { + audio->chA.dmaSource = GBASerializedAudioFlags2GetChASource(flags2) - 1; + } + if (GBASerializedAudioFlags2GetChBSource(flags2) > 0) { + audio->chB.dmaSource = GBASerializedAudioFlags2GetChBSource(flags2) - 1; + } uint32_t when; LOAD_32(when, 0, &state->audio.nextSample); @@ -587,7 +553,3 @@ void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState } mTimingSchedule(&audio->p->timing, &audio->sampleEvent, when); } - -float GBAAudioCalculateRatio(float inputSampleRate, float desiredFPS, float desiredSampleRate) { - return desiredSampleRate * GBA_ARM7TDMI_FREQUENCY / (VIDEO_TOTAL_LENGTH * desiredFPS * inputSampleRate); -} diff --git a/src/gba/cart/ereader.c b/src/gba/cart/ereader.c index 6a3ce58b0..1712f2833 100644 --- a/src/gba/cart/ereader.c +++ b/src/gba/cart/ereader.c @@ -371,7 +371,7 @@ void GBACartEReaderScan(struct GBACartEReader* ereader, const void* data, size_t memset(ereader->dots, 0, EREADER_DOTCODE_SIZE); uint8_t blockRS[44][0x10]; - uint8_t block0[0x30]; + uint8_t block0[0x30] = {0}; bool parsed = false; bool bitmap = false; bool reducedHeader = false; @@ -875,7 +875,7 @@ void EReaderScanDestroy(struct EReaderScan* scan) { free(scan); } -#ifdef USE_PNG +#if defined(USE_PNG) && defined(ENABLE_VFS) struct EReaderScan* EReaderScanLoadImagePNG(const char* filename) { struct VFile* vf = VFileOpen(filename, O_RDONLY); if (!vf) { @@ -1564,6 +1564,7 @@ void EReaderScanOutputBitmap(const struct EReaderScan* scan, void* output, size_ } } +#ifdef ENABLE_VFS bool EReaderScanSaveRaw(const struct EReaderScan* scan, const char* filename, bool strict) { size_t blocks = EReaderBlockListSize(&scan->blocks); if (!blocks) { @@ -1633,5 +1634,6 @@ bool EReaderScanSaveRaw(const struct EReaderScan* scan, const char* filename, bo free(data); return true; } +#endif #endif diff --git a/src/gba/cart/gpio.c b/src/gba/cart/gpio.c index 53c14dafd..73ed859c5 100644 --- a/src/gba/cart/gpio.c +++ b/src/gba/cart/gpio.c @@ -320,18 +320,20 @@ void _gyroReadPins(struct GBACartridgeHardware* hw) { return; } + // Write bit on falling edge + bool doOutput = hw->gyroEdge && !(hw->pinState & 2); if (hw->pinState & 1) { if (gyro->sample) { gyro->sample(gyro); } int32_t sample = gyro->readGyroZ(gyro); - // Normalize to ~12 bits, focused on 0x6C0 - hw->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative + // Normalize to ~12 bits, focused on 0x700 + hw->gyroSample = (sample >> 21) + 0x700; // Crop off an extra bit so that we can't go negative + doOutput = true; } - if (hw->gyroEdge && !(hw->pinState & 2)) { - // Write bit on falling edge + if (doOutput) { unsigned bit = hw->gyroSample >> 15; hw->gyroSample <<= 1; _outputPins(hw, bit << 2); @@ -352,7 +354,9 @@ void _rumbleReadPins(struct GBACartridgeHardware* hw) { return; } - rumble->setRumble(rumble, !!(hw->pinState & 8)); + int32_t currentTime = mTimingCurrentTime(&hw->p->timing); + rumble->setRumble(rumble, !!(hw->pinState & 8), currentTime - hw->p->lastRumble); + hw->p->lastRumble = currentTime; } // == Light sensor @@ -482,10 +486,10 @@ void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASeria flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState); flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter); - // GBP stuff is only here for legacy reasons + // GBP/SIO stuff is only here for legacy reasons flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->p->sio.gbp.inputsPosted); flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->p->sio.gbp.txPosition); - STORE_32(hw->p->sio.gbp.event.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent); + STORE_32(hw->p->sio.completeEvent.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.sioNextEvent); state->hw.flags2 = flags2; } @@ -498,6 +502,18 @@ void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASer LOAD_16(hw->direction, 0, &state->hw.pinDirection); hw->devices = state->hw.devices; + if (hw->gpioBase) { + if (hw->readWrite) { + STORE_16(hw->pinState, 0, hw->gpioBase); + STORE_16(hw->direction, 2, hw->gpioBase); + STORE_16(hw->readWrite, 4, hw->gpioBase); + } else { + hw->gpioBase[0] = 0; + hw->gpioBase[1] = 0; + hw->gpioBase[2] = 0; + } + } + LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtcBytesRemaining); LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtcTransferStep); LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtcBitsRead); @@ -516,16 +532,16 @@ void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASer hw->lightSample = state->hw.lightSample; hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1); - // GBP stuff is only here for legacy reasons + // GBP/SIO stuff is only here for legacy reasons hw->p->sio.gbp.inputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2); hw->p->sio.gbp.txPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2); uint32_t when; - LOAD_32(when, 0, &state->hw.gbpNextEvent); + LOAD_32(when, 0, &state->hw.sioNextEvent); if (hw->devices & HW_GB_PLAYER) { - GBASIOSetDriver(&hw->p->sio, &hw->p->sio.gbp.d, SIO_NORMAL_32); - if (hw->p->memory.io[GBA_REG(SIOCNT)] & 0x0080) { - mTimingSchedule(&hw->p->timing, &hw->p->sio.gbp.event, when); - } + GBASIOSetDriver(&hw->p->sio, &hw->p->sio.gbp.d); + } + if ((hw->p->memory.io[GBA_REG(SIOCNT)] & 0x0080) && when < 0x20000) { + mTimingSchedule(&hw->p->timing, &hw->p->sio.completeEvent, when); } } diff --git a/src/gba/cart/vfame.c b/src/gba/cart/vfame.c index aedcf5d3e..260db35b8 100644 --- a/src/gba/cart/vfame.c +++ b/src/gba/cart/vfame.c @@ -18,6 +18,11 @@ static const uint8_t ADDRESS_REORDERING_GEORGE[4][16] = { { 15, 14, 3, 12, 8, 4, 0, 13, 5, 11, 6, 7, 9, 1, 2, 10 }, { 15, 0, 9, 5, 2, 6, 7, 3, 1, 8, 10, 14, 13, 12, 11, 4 } }; +static const uint8_t ADDRESS_REORDERING_ALTERNATE[4][16] = { + { 15, 0, 13, 5, 8, 4, 7, 3, 1, 2, 10, 14, 9, 12, 11, 6 }, + { 15, 7, 9, 1, 2, 6, 14, 13, 12, 11, 4, 0, 3, 5, 8, 10 }, + { 15, 14, 3, 12, 11, 10, 0, 9, 5, 8, 6, 7, 13, 1, 2, 4 } +}; static const uint8_t VALUE_REORDERING[4][16] = { { 5, 4, 3, 2, 1, 0, 7, 6 }, { 3, 2, 1, 0, 7, 6, 5, 4 }, @@ -28,6 +33,11 @@ static const uint8_t VALUE_REORDERING_GEORGE[4][16] = { { 1, 4, 3, 0, 5, 6, 7, 2 }, { 5, 2, 1, 6, 7, 0, 3, 4 } }; +static const uint8_t VALUE_REORDERING_ALTERNATE[4][16] = { + { 5, 4, 7, 2, 1, 0, 3, 6 }, + { 1, 2, 3, 0, 5, 6, 7, 4 }, + { 3, 0, 1, 6, 7, 4, 5, 2 } +}; static const int8_t MODE_CHANGE_START_SEQUENCE[5] = { 0x99, 0x02, 0x05, 0x02, 0x03 }; static const int8_t MODE_CHANGE_END_SEQUENCE[5] = { 0x99, 0x03, 0x62, 0x02, 0x56 }; @@ -49,7 +59,7 @@ void GBAVFameInit(struct GBAVFameCart* cart) { cart->acceptingModeChange = false; } -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) { cart->cartType = VFAME_NO; // The initialisation code is also present & run in the dumps of Digimon Ruby & Sapphire from hacked/deprotected reprint carts, @@ -65,12 +75,16 @@ void GBAVFameDetect(struct GBAVFameCart* cart, uint32_t* rom, size_t romSize) { mLOG(GBA_MEM, INFO, "Vast Fame game detected"); } - // This game additionally operates with a different set of SRAM modes - // Its initialisation seems to be identical so the difference must be in the cart HW itself + // These games additionally operates with a different set of SRAM modes + // Their initialisation seems to be identical so the difference must be in the cart HW itself // Other undumped games may have similar differences if (memcmp("George Sango", &((struct GBACartridge*) rom)->title, 12) == 0) { cart->cartType = VFAME_GEORGE; mLOG(GBA_MEM, INFO, "George mode"); + } else if (crc32 == DIGIMON_SAPPHIRE_CHINESE_CRC32) { + // Chinese version of Digimon Sapphire; header is identical to the English version which uses the normal reordering + // so we have to use some other way to detect it + cart->cartType = VFAME_ALTERNATE; } } @@ -256,6 +270,8 @@ static uint32_t _modifySramAddress(enum GBAVFameCartType type, uint32_t address, return address; } else if (type == VFAME_GEORGE) { return _reorderBits(address, ADDRESS_REORDERING_GEORGE[mode - 1], 16); + } else if (type == VFAME_ALTERNATE) { + return _reorderBits(address, ADDRESS_REORDERING_ALTERNATE[mode - 1], 16); } else { return _reorderBits(address, ADDRESS_REORDERING[mode - 1], 16); } @@ -266,6 +282,8 @@ static int8_t _modifySramValue(enum GBAVFameCartType type, uint8_t value, int mo if (reorderType != 0) { if (type == VFAME_GEORGE) { value = _reorderBits(value, VALUE_REORDERING_GEORGE[reorderType - 1], 8); + } else if (type == VFAME_ALTERNATE) { + value = _reorderBits(value, VALUE_REORDERING_ALTERNATE[reorderType - 1], 8); } else { value = _reorderBits(value, VALUE_REORDERING[reorderType - 1], 8); } diff --git a/src/gba/core.c b/src/gba/core.c index 46ad70f08..1d3fffb9e 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -14,7 +15,6 @@ #include #include #include -#include #include #ifndef DISABLE_THREADING #include @@ -30,6 +30,7 @@ #ifdef USE_ELF #include #endif +#include #include #include #include @@ -191,7 +192,6 @@ static const struct mCoreRegisterInfo _GBARegisters[] = { struct mVideoLogContext; -#define CPU_COMPONENT_AUDIO_MIXER CPU_COMPONENT_MISC_1 #define LOGO_CRC32 0xD0BEB55E struct GBACore { @@ -216,7 +216,6 @@ struct GBACore { bool hasOverride; struct mDebuggerPlatform* debuggerPlatform; struct mCheatDevice* cheatDevice; - struct GBAAudioMixer* audioMixer; struct mCoreMemoryBlock memoryBlocks[12]; size_t nMemoryBlocks; int memoryBlockType; @@ -269,7 +268,6 @@ static bool _GBACoreInit(struct mCore* core) { #ifndef MINIMAL_CORE gbacore->logContext = NULL; #endif - gbacore->audioMixer = NULL; GBACreate(gba); // TODO: Restore cheats @@ -298,7 +296,7 @@ static bool _GBACoreInit(struct mCore* core) { gbacore->proxyRenderer.logger = NULL; #endif -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#ifdef ENABLE_VFS mDirectorySetInit(&core->dirs); #endif @@ -310,10 +308,10 @@ static void _GBACoreDeinit(struct mCore* core) { GBADestroy(core->board); mappedMemoryFree(core->cpu, sizeof(struct ARMCore)); mappedMemoryFree(core->board, sizeof(struct GBA)); -#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); } @@ -324,7 +322,6 @@ static void _GBACoreDeinit(struct mCore* core) { if (gbacore->cheatDevice) { mCheatDeviceDestroy(gbacore->cheatDevice); } - free(gbacore->audioMixer); mCoreConfigFreeOpts(&core->opts); free(core); } @@ -374,7 +371,7 @@ static void _GBACoreLoadConfig(struct mCore* core, const struct mCoreConfig* con } else if (strcasecmp(idleOptimization, "remove") == 0) { gba->idleOptimization = IDLE_LOOP_REMOVE; } else if (strcasecmp(idleOptimization, "detect") == 0) { - if (gba->idleLoop == IDLE_LOOP_NONE) { + if (gba->idleLoop == GBA_IDLE_LOOP_NONE) { gba->idleOptimization = IDLE_LOOP_DETECT; } else { gba->idleOptimization = IDLE_LOOP_REMOVE; @@ -387,7 +384,6 @@ static void _GBACoreLoadConfig(struct mCore* core, const struct mCoreConfig* con mCoreConfigCopyValue(&core->config, config, "allowOpposingDirections"); mCoreConfigCopyValue(&core->config, config, "gba.bios"); mCoreConfigCopyValue(&core->config, config, "gba.forceGbp"); - mCoreConfigCopyValue(&core->config, config, "gba.audioHle"); mCoreConfigCopyValue(&core->config, config, "vbaBugCompat"); #ifndef DISABLE_THREADING @@ -475,8 +471,7 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c #endif #ifndef MINIMAL_CORE if (renderer && core->videoLogger) { - gbacore->proxyRenderer.logger = core->videoLogger; - GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer); + GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer, core->videoLogger); renderer = &gbacore->proxyRenderer.d; } #endif @@ -531,7 +526,7 @@ static size_t _GBACoreScreenRegions(const struct mCore* core, const struct mCore return 1; } -static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) { +static void _GBACoreSetVideoBuffer(struct mCore* core, mColor* buffer, size_t stride) { struct GBACore* gbacore = (struct GBACore*) core; gbacore->renderer.outputBuffer = buffer; gbacore->renderer.outputBufferStride = stride; @@ -559,16 +554,14 @@ static void _GBACorePutPixels(struct mCore* core, const void* buffer, size_t str gba->video.renderer->putPixels(gba->video.renderer, stride, buffer); } -static struct blip_t* _GBACoreGetAudioChannel(struct mCore* core, int ch) { +static unsigned _GBACoreAudioSampleRate(const struct mCore* core) { struct GBA* gba = core->board; - switch (ch) { - case 0: - return gba->audio.psg.left; - case 1: - return gba->audio.psg.right; - default: - return NULL; - } + return GBA_ARM7TDMI_FREQUENCY / gba->audio.sampleInterval; +} + +static struct mAudioBuffer* _GBACoreGetAudioBuffer(struct mCore* core) { + struct GBA* gba = core->board; + return &gba->audio.psg.buffer; } static void _GBACoreSetAudioBufferSize(struct mCore* core, size_t samples) { @@ -675,6 +668,9 @@ static size_t _GBACoreROMSize(const struct mCore* core) { if (gba->romVf) { return gba->romVf->size(gba->romVf); } + if (gba->mbVf) { + return gba->mbVf->size(gba->mbVf); + } return gba->pristineRomSize; } @@ -684,6 +680,19 @@ static void _GBACoreChecksum(const struct mCore* core, void* data, enum mCoreChe case mCHECKSUM_CRC32: memcpy(data, &gba->romCrc32, sizeof(gba->romCrc32)); break; + case mCHECKSUM_MD5: + if (gba->romVf) { + md5File(gba->romVf, data); + } else if (gba->mbVf) { + md5File(gba->mbVf, data); + } else if (gba->memory.rom && gba->isPristine) { + md5Buffer(gba->memory.rom, gba->pristineRomSize, data); + } else if (gba->memory.rom) { + md5Buffer(gba->memory.rom, gba->memory.romSize, data); + } else { + md5Buffer("", 0, data); + } + break; } return; } @@ -719,8 +728,7 @@ static void _GBACoreReset(struct mCore* core) { #endif #ifndef MINIMAL_CORE if (renderer && core->videoLogger) { - gbacore->proxyRenderer.logger = core->videoLogger; - GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer); + GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer, core->videoLogger); renderer = &gbacore->proxyRenderer.d; } #endif @@ -729,16 +737,6 @@ static void _GBACoreReset(struct mCore* core) { } } -#ifndef MINIMAL_CORE - int useAudioMixer; - if (!gbacore->audioMixer && mCoreConfigGetIntValue(&core->config, "gba.audioHle", &useAudioMixer) && useAudioMixer) { - gbacore->audioMixer = malloc(sizeof(*gbacore->audioMixer)); - GBAAudioMixerCreate(gbacore->audioMixer); - ((struct ARMCore*) core->cpu)->components[CPU_COMPONENT_AUDIO_MIXER] = &gbacore->audioMixer->d; - ARMHotplugAttach(core->cpu, CPU_COMPONENT_AUDIO_MIXER); - } -#endif - bool forceGbp = false; bool vbaBugCompat = true; mCoreConfigGetBoolValue(&core->config, "gba.forceGbp", &forceGbp); @@ -759,7 +757,7 @@ static void _GBACoreReset(struct mCore* core) { } gbacore->memoryBlockType = -2; -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#ifdef ENABLE_VFS if (!gba->biosVf && core->opts.useBios) { struct VFile* bios = NULL; bool found = false; @@ -850,6 +848,83 @@ static bool _GBACoreSaveState(struct mCore* core, void* state) { return true; } +static bool _GBACoreLoadExtraState(struct mCore* core, const struct mStateExtdata* extdata) { + struct GBA* gba = core->board; + struct mStateExtdataItem item; + bool ok = true; + if (mStateExtdataGet(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_VIDEO_RENDERER, &item)) { + if ((uint32_t) item.size > sizeof(uint32_t)) { + uint32_t type; + LOAD_32(type, 0, item.data); + if (type == gba->video.renderer->rendererId(gba->video.renderer)) { + ok = gba->video.renderer->loadState(gba->video.renderer, + (void*) ((uintptr_t) item.data + sizeof(uint32_t)), + item.size - sizeof(type)) && ok; + } + } else if (item.data) { + ok = false; + } + } + if (gba->sio.driver && gba->sio.driver->driverId && gba->sio.driver->loadState && + mStateExtdataGet(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_SIO_DRIVER, &item)) { + if ((uint32_t) item.size > sizeof(uint32_t)) { + uint32_t type; + LOAD_32(type, 0, item.data); + if (type == gba->sio.driver->driverId(gba->sio.driver)) { + ok = gba->sio.driver->loadState(gba->sio.driver, + (void*) ((uintptr_t) item.data + sizeof(uint32_t)), + item.size - sizeof(type)) && ok; + } + } else if (item.data) { + ok = false; + } + } + return ok; +} + +static bool _GBACoreSaveExtraState(struct mCore* core, struct mStateExtdata* extdata) { + struct GBA* gba = core->board; + void* buffer = NULL; + size_t size = 0; + gba->video.renderer->saveState(gba->video.renderer, &buffer, &size); + if (size > 0 && buffer) { + struct mStateExtdataItem item; + item.size = size + sizeof(uint32_t); + item.data = malloc(item.size); + item.clean = free; + uint32_t type = gba->video.renderer->rendererId(gba->video.renderer); + STORE_32(type, 0, item.data); + memcpy((void*) ((uintptr_t) item.data + sizeof(uint32_t)), buffer, size); + mStateExtdataPut(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_VIDEO_RENDERER, &item); + } + if (buffer) { + free(buffer); + buffer = NULL; + } + size = 0; + + if (gba->sio.driver && gba->sio.driver->driverId && gba->sio.driver->saveState) { + gba->sio.driver->saveState(gba->sio.driver, &buffer, &size); + if (size > 0 && buffer) { + struct mStateExtdataItem item; + item.size = size + sizeof(uint32_t); + item.data = malloc(item.size); + item.clean = free; + uint32_t type = gba->sio.driver->driverId(gba->sio.driver); + STORE_32(type, 0, item.data); + memcpy((void*) ((uintptr_t) item.data + sizeof(uint32_t)), buffer, size); + mStateExtdataPut(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_SIO_DRIVER, &item); + } + if (buffer) { + free(buffer); + buffer = NULL; + } + size = 0; + } + + return true; +} + static void _GBACoreSetKeys(struct mCore* core, uint32_t keys) { struct GBA* gba = core->board; gba->keysActive = keys; @@ -888,12 +963,8 @@ static int32_t _GBACoreFrequency(const struct mCore* core) { return GBA_ARM7TDMI_FREQUENCY; } -static void _GBACoreGetGameTitle(const struct mCore* core, char* title) { - GBAGetGameTitle(core->board, title); -} - -static void _GBACoreGetGameCode(const struct mCore* core, char* title) { - GBAGetGameCode(core->board, title); +static void _GBACoreGetGameInfo(const struct mCore* core, struct mGameInfo* info) { + GBAGetGameInfo(core->board, info); } static void _GBACoreSetPeripheral(struct mCore* core, int type, void* periph) { @@ -908,9 +979,8 @@ static void _GBACoreSetPeripheral(struct mCore* core, int type, void* periph) { case mPERIPH_GBA_LUMINANCE: gba->luminanceSource = periph; break; - case mPERIPH_GBA_BATTLECHIP_GATE: - GBASIOSetDriver(&gba->sio, periph, SIO_MULTI); - GBASIOSetDriver(&gba->sio, periph, SIO_NORMAL_32); + case mPERIPH_GBA_LINK_PORT: + GBASIOSetDriver(&gba->sio, periph); break; default: return; @@ -1004,27 +1074,27 @@ size_t _GBACoreListMemoryBlocks(const struct mCore* core, const struct mCoreMemo if (gbacore->memoryBlockType != gba->memory.savedata.type) { switch (gba->memory.savedata.type) { - case SAVEDATA_SRAM: + case GBA_SAVEDATA_SRAM: memcpy(gbacore->memoryBlocks, _GBAMemoryBlocksSRAM, sizeof(_GBAMemoryBlocksSRAM)); gbacore->nMemoryBlocks = sizeof(_GBAMemoryBlocksSRAM) / sizeof(*_GBAMemoryBlocksSRAM); break; - case SAVEDATA_SRAM512: + case GBA_SAVEDATA_SRAM512: memcpy(gbacore->memoryBlocks, _GBAMemoryBlocksSRAM512, sizeof(_GBAMemoryBlocksSRAM512)); gbacore->nMemoryBlocks = sizeof(_GBAMemoryBlocksSRAM512) / sizeof(*_GBAMemoryBlocksSRAM512); break; - case SAVEDATA_FLASH512: + case GBA_SAVEDATA_FLASH512: memcpy(gbacore->memoryBlocks, _GBAMemoryBlocksFlash512, sizeof(_GBAMemoryBlocksFlash512)); gbacore->nMemoryBlocks = sizeof(_GBAMemoryBlocksFlash512) / sizeof(*_GBAMemoryBlocksFlash512); break; - case SAVEDATA_FLASH1M: + case GBA_SAVEDATA_FLASH1M: memcpy(gbacore->memoryBlocks, _GBAMemoryBlocksFlash1M, sizeof(_GBAMemoryBlocksFlash1M)); gbacore->nMemoryBlocks = sizeof(_GBAMemoryBlocksFlash1M) / sizeof(*_GBAMemoryBlocksFlash1M); break; - case SAVEDATA_EEPROM: + case GBA_SAVEDATA_EEPROM: memcpy(gbacore->memoryBlocks, _GBAMemoryBlocksEEPROM, sizeof(_GBAMemoryBlocksEEPROM)); gbacore->nMemoryBlocks = sizeof(_GBAMemoryBlocksEEPROM) / sizeof(*_GBAMemoryBlocksEEPROM); break; - case SAVEDATA_EEPROM512: + case GBA_SAVEDATA_EEPROM512: memcpy(gbacore->memoryBlocks, _GBAMemoryBlocksEEPROM512, sizeof(_GBAMemoryBlocksEEPROM512)); gbacore->nMemoryBlocks = sizeof(_GBAMemoryBlocksEEPROM512) / sizeof(*_GBAMemoryBlocksEEPROM512); break; @@ -1076,7 +1146,7 @@ void* _GBACoreGetMemoryBlock(struct mCore* core, size_t id, size_t* sizeOut) { *sizeOut = gba->memory.romSize; return gba->memory.rom; case GBA_REGION_SRAM: - if (gba->memory.savedata.type == SAVEDATA_FLASH1M) { + if (gba->memory.savedata.type == GBA_SAVEDATA_FLASH1M) { *sizeOut = GBA_SIZE_FLASH1M; return gba->memory.savedata.currentBank; } @@ -1218,7 +1288,7 @@ static bool _GBACoreWriteRegister(struct mCore* core, const char* name, const vo return true; } -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS static bool _GBACoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) { UNUSED(core); switch (type) { @@ -1260,9 +1330,17 @@ static void _GBACoreDetachDebugger(struct mCore* core) { } static void _GBACoreLoadSymbols(struct mCore* core, struct VFile* vf) { + struct GBA* gba = core->board; bool closeAfter = false; - core->symbolTable = mDebuggerSymbolTableCreate(); -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 + if (!core->symbolTable) { + core->symbolTable = mDebuggerSymbolTableCreate(); + } + off_t seek; + if (vf) { + seek = vf->seek(vf, 0, SEEK_CUR); + vf->seek(vf, 0, SEEK_SET); + } +#ifdef ENABLE_VFS #ifdef USE_ELF if (!vf && core->dirs.base) { closeAfter = true; @@ -1270,27 +1348,42 @@ static void _GBACoreLoadSymbols(struct mCore* core, struct VFile* vf) { } #endif if (!vf && core->dirs.base) { - closeAfter = true; vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".sym", O_RDONLY); + if (vf) { + mDebuggerLoadARMIPSSymbols(core->symbolTable, vf); + vf->close(vf); + return; + } } #endif + if (!vf && gba->mbVf) { + closeAfter = false; + vf = gba->mbVf; + seek = vf->seek(vf, 0, SEEK_CUR); + vf->seek(vf, 0, SEEK_SET); + } + if (!vf && gba->romVf) { + closeAfter = false; + vf = gba->romVf; + seek = vf->seek(vf, 0, SEEK_CUR); + vf->seek(vf, 0, SEEK_SET); + } if (!vf) { return; } #ifdef USE_ELF struct ELF* elf = ELFOpen(vf); if (elf) { -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS mCoreLoadELFSymbols(core->symbolTable, elf); #endif ELFClose(elf); - } else -#endif - { - mDebuggerLoadARMIPSSymbols(core->symbolTable, vf); } +#endif if (closeAfter) { vf->close(vf); + } else { + vf->seek(vf, seek, SEEK_SET); } } @@ -1472,12 +1565,12 @@ static void _GBACoreStartVideoLog(struct mCore* core, struct mVideoLogContext* c state->cpu.gprs[ARM_PC] = GBA_BASE_EWRAM; int channelId = mVideoLoggerAddChannel(context); - gbacore->vlProxy.logger = malloc(sizeof(struct mVideoLogger)); - mVideoLoggerRendererCreate(gbacore->vlProxy.logger, false); - mVideoLoggerAttachChannel(gbacore->vlProxy.logger, context, channelId); - gbacore->vlProxy.logger->block = false; + struct mVideoLogger* logger = malloc(sizeof(*logger)); + mVideoLoggerRendererCreate(logger, false); + mVideoLoggerAttachChannel(logger, context, channelId); + logger->block = false; - GBAVideoProxyRendererCreate(&gbacore->vlProxy, gba->video.renderer); + GBAVideoProxyRendererCreate(&gbacore->vlProxy, gba->video.renderer, logger); GBAVideoProxyRendererShim(&gba->video, &gbacore->vlProxy); } @@ -1515,7 +1608,8 @@ struct mCore* GBACoreCreate(void) { core->setVideoGLTex = _GBACoreSetVideoGLTex; core->getPixels = _GBACoreGetPixels; core->putPixels = _GBACorePutPixels; - core->getAudioChannel = _GBACoreGetAudioChannel; + core->audioSampleRate = _GBACoreAudioSampleRate; + core->getAudioBuffer = _GBACoreGetAudioBuffer; core->setAudioBufferSize = _GBACoreSetAudioBufferSize; core->getAudioBufferSize = _GBACoreGetAudioBufferSize; core->addCoreCallbacks = _GBACoreAddCoreCallbacks; @@ -1537,6 +1631,8 @@ struct mCore* GBACoreCreate(void) { core->stateSize = _GBACoreStateSize; core->loadState = _GBACoreLoadState; core->saveState = _GBACoreSaveState; + core->loadExtraState = _GBACoreLoadExtraState; + core->saveExtraState = _GBACoreSaveExtraState; core->setKeys = _GBACoreSetKeys; core->addKeys = _GBACoreAddKeys; core->clearKeys = _GBACoreClearKeys; @@ -1544,8 +1640,7 @@ struct mCore* GBACoreCreate(void) { core->frameCounter = _GBACoreFrameCounter; core->frameCycles = _GBACoreFrameCycles; core->frequency = _GBACoreFrequency; - core->getGameTitle = _GBACoreGetGameTitle; - core->getGameCode = _GBACoreGetGameCode; + core->getGameInfo = _GBACoreGetGameInfo; core->setPeripheral = _GBACoreSetPeripheral; core->getPeripheral = _GBACoreGetPeripheral; core->busRead8 = _GBACoreBusRead8; @@ -1565,7 +1660,7 @@ struct mCore* GBACoreCreate(void) { core->listRegisters = _GBACoreListRegisters; core->readRegister = _GBACoreReadRegister; core->writeRegister = _GBACoreWriteRegister; -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS core->supportsDebuggerType = _GBACoreSupportsDebuggerType; core->debuggerPlatform = _GBACoreDebuggerPlatform; core->cliDebuggerSystem = _GBACoreCliDebuggerSystem; @@ -1608,9 +1703,9 @@ static bool _GBAVLPInit(struct mCore* core) { if (!_GBACoreInit(core)) { return false; } - gbacore->vlProxy.logger = malloc(sizeof(struct mVideoLogger)); - mVideoLoggerRendererCreate(gbacore->vlProxy.logger, true); - GBAVideoProxyRendererCreate(&gbacore->vlProxy, NULL); + struct mVideoLogger* logger = malloc(sizeof(*logger)); + mVideoLoggerRendererCreate(logger, true); + GBAVideoProxyRendererCreate(&gbacore->vlProxy, NULL, logger); memset(&gbacore->logCallbacks, 0, sizeof(gbacore->logCallbacks)); gbacore->logCallbacks.videoFrameStarted = _GBAVLPStartFrameCallback; gbacore->logCallbacks.context = core; diff --git a/src/gba/debugger/cli.c b/src/gba/debugger/cli.c index 8538f4515..8cb6c6043 100644 --- a/src/gba/debugger/cli.c +++ b/src/gba/debugger/cli.c @@ -16,14 +16,14 @@ static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*); static bool _GBACLIDebuggerCustom(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 _GBACLIDebuggerCommands[] = { { "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 @@ -77,7 +77,7 @@ static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[GBA_REG(DISPSTAT)]); } -#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) { diff --git a/src/gba/dma.c b/src/gba/dma.c index 7c75184ea..e9044d26a 100644 --- a/src/gba/dma.c +++ b/src/gba/dma.c @@ -256,15 +256,21 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { if (info->count == info->nextCount) { if (width == 4) { cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion]; + info->cycles = memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion]; } else { cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion]; + info->cycles = memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion]; } } else { - if (width == 4) { - cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion]; - } else { - cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion]; + // Crossed region boundary; recalculate cached cycles + if (UNLIKELY(!(source & 0x00FFFFFC) || !(dest & 0x00FFFFFC))) { + if (width == 4) { + info->cycles = memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion]; + } else { + info->cycles = memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion]; + } } + cycles += info->cycles; } info->when += cycles; @@ -274,19 +280,19 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { } cpu->memory.store32(cpu, dest, memory->dmaTransferRegister, 0); } else { - if (sourceRegion == GBA_REGION_ROM2_EX && (memory->savedata.type == SAVEDATA_EEPROM || memory->savedata.type == SAVEDATA_EEPROM512)) { + if (sourceRegion == GBA_REGION_ROM2_EX && (memory->savedata.type == GBA_SAVEDATA_EEPROM || memory->savedata.type == GBA_SAVEDATA_EEPROM512)) { memory->dmaTransferRegister = GBASavedataReadEEPROM(&memory->savedata); memory->dmaTransferRegister |= memory->dmaTransferRegister << 16; } else if (source) { memory->dmaTransferRegister = cpu->memory.load16(cpu, source, 0); memory->dmaTransferRegister |= memory->dmaTransferRegister << 16; } - if (destRegion == GBA_REGION_ROM2_EX) { - if (memory->savedata.type == SAVEDATA_AUTODETECT) { + if (UNLIKELY(destRegion == GBA_REGION_ROM2_EX)) { + if (memory->savedata.type == GBA_SAVEDATA_AUTODETECT) { mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); GBASavedataInitEEPROM(&memory->savedata); } - if (memory->savedata.type == SAVEDATA_EEPROM512 || memory->savedata.type == SAVEDATA_EEPROM) { + if (memory->savedata.type == GBA_SAVEDATA_EEPROM512 || memory->savedata.type == GBA_SAVEDATA_EEPROM) { GBASavedataWriteEEPROM(&memory->savedata, memory->dmaTransferRegister, info->nextCount); } } else { @@ -313,9 +319,11 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { int i; for (i = 0; i < 4; ++i) { struct GBADMA* dma = &memory->dma[i]; - int32_t time = dma->when - info->when; - if (time < 0 && GBADMARegisterIsEnable(dma->reg) && dma->nextCount) { - dma->when = info->when; + if (GBADMARegisterIsEnable(dma->reg) && dma->nextCount) { + int32_t time = dma->when - info->when; + if (time < 0) { + dma->when = info->when; + } } } @@ -327,3 +335,22 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) { } GBADMAUpdate(gba); } + +void GBADMARecalculateCycles(struct GBA* gba) { + int i; + for (i = 0; i < 4; ++i) { + struct GBADMA* dma = &gba->memory.dma[i]; + if (!GBADMARegisterIsEnable(dma->reg)) { + continue; + } + + uint32_t width = GBADMARegisterGetWidth(dma->reg); + uint32_t sourceRegion = dma->nextSource >> BASE_OFFSET; + uint32_t destRegion = dma->nextDest >> BASE_OFFSET; + if (width) { + dma->cycles = gba->memory.waitstatesSeq32[sourceRegion] + gba->memory.waitstatesSeq32[destRegion]; + } else { + dma->cycles = gba->memory.waitstatesSeq16[sourceRegion] + gba->memory.waitstatesSeq16[destRegion]; + } + } +} diff --git a/src/gba/extra/audio-mixer.c b/src/gba/extra/audio-mixer.c deleted file mode 100644 index 2a14f1ce6..000000000 --- a/src/gba/extra/audio-mixer.c +++ /dev/null @@ -1,306 +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/. */ -#include - -#include -#include -#include - -#define OVERSAMPLE 2 - -static void _mp2kInit(void* cpu, struct mCPUComponent* component); -static void _mp2kDeinit(struct mCPUComponent* component); - -static bool _mp2kEngage(struct GBAAudioMixer* mixer, uint32_t address); -static void _mp2kVblank(struct GBAAudioMixer* mixer); -static void _mp2kStep(struct GBAAudioMixer* mixer); - -void GBAAudioMixerCreate(struct GBAAudioMixer* mixer) { - mixer->d.init = _mp2kInit; - mixer->d.deinit = _mp2kDeinit; - mixer->engage = _mp2kEngage; - mixer->vblank = _mp2kVblank; - mixer->step = _mp2kStep; -} - -void _mp2kInit(void* cpu, struct mCPUComponent* component) { - struct ARMCore* arm = cpu; - struct GBA* gba = (struct GBA*) arm->master; - struct GBAAudioMixer* mixer = (struct GBAAudioMixer*) component; - gba->audio.mixer = mixer; - mixer->p = &gba->audio; - mixer->contextAddress = 0; - mixer->tempo = 120.0 / 75.0; - mixer->frame = 0; - mixer->last.left = 0; - mixer->last.right = 0; - memset(&mixer->context, 0, sizeof(mixer->context)); - memset(&mixer->activeTracks, 0, sizeof(mixer->activeTracks)); - - size_t i; - for (i = 0; i < MP2K_MAX_SOUND_CHANNELS; ++i) { - mixer->activeTracks[i].channel = &mixer->context.chans[i]; - CircleBufferInit(&mixer->activeTracks[i].buffer, 0x10000); - } -} - -void _mp2kDeinit(struct mCPUComponent* component) { - struct GBAAudioMixer* mixer = (struct GBAAudioMixer*) component; - size_t i; - for (i = 0; i < MP2K_MAX_SOUND_CHANNELS; ++i) { - CircleBufferDeinit(&mixer->activeTracks[i].buffer); - } -} - -static void _loadInstrument(struct ARMCore* cpu, struct GBAMP2kInstrument* instrument, uint32_t base) { - struct ARMMemory* memory = &cpu->memory; - instrument->type = memory->load8(cpu, base + offsetof(struct GBAMP2kInstrument, type), 0); - instrument->key = memory->load8(cpu, base + offsetof(struct GBAMP2kInstrument, key), 0); - instrument->length = memory->load8(cpu, base + offsetof(struct GBAMP2kInstrument, length), 0); - instrument->ps.pan = memory->load8(cpu, base + offsetof(struct GBAMP2kInstrument, ps.pan), 0); - if (instrument->type == 0x40 || instrument->type == 0x80) { - instrument->data.subTable = memory->load32(cpu, base + offsetof(struct GBAMP2kInstrument, data.subTable), 0); - instrument->extInfo.map = memory->load32(cpu, base + offsetof(struct GBAMP2kInstrument, extInfo.map), 0); - } else { - instrument->data.waveData = memory->load32(cpu, base + offsetof(struct GBAMP2kInstrument, data.waveData), 0); - instrument->extInfo.adsr.attack = memory->load8(cpu, base + offsetof(struct GBAMP2kInstrument, extInfo.adsr.attack), 0); - instrument->extInfo.adsr.decay = memory->load8(cpu, base + offsetof(struct GBAMP2kInstrument, extInfo.adsr.decay), 0); - instrument->extInfo.adsr.sustain = memory->load8(cpu, base + offsetof(struct GBAMP2kInstrument, extInfo.adsr.sustain), 0); - instrument->extInfo.adsr.release = memory->load8(cpu, base + offsetof(struct GBAMP2kInstrument, extInfo.adsr.release), 0); - } -} - -static void _lookupInstrument(struct ARMCore* cpu, struct GBAMP2kInstrument* instrument, uint8_t key) { - struct ARMMemory* memory = &cpu->memory; - if (instrument->type == 0x40) { - uint32_t subInstrumentBase = instrument->data.subTable; - uint32_t keyTable = instrument->extInfo.map; - uint8_t id = memory->load8(cpu, keyTable + key, 0); - subInstrumentBase += 12 * id; - _loadInstrument(cpu, instrument, subInstrumentBase); - } - if (instrument->type == 0x80) { - uint32_t subInstrumentBase = instrument->data.subTable; - subInstrumentBase += 12 * key; - _loadInstrument(cpu, instrument, subInstrumentBase); - } -} - -static void _stepSample(struct GBAAudioMixer* mixer, struct GBAMP2kTrack* track) { - struct ARMCore* cpu = mixer->p->p->cpu; - struct ARMMemory* memory = &cpu->memory; - uint32_t headerAddress; - struct GBAMP2kInstrument instrument = track->track.instrument; - - uint8_t note = track->track.key; - _lookupInstrument(cpu, &instrument, note); - double freq; - - switch (instrument.type) { - case 0x00: - case 0x08: - case 0x40: - case 0x80: - freq = GBA_ARM7TDMI_FREQUENCY / (double) track->channel->freq; - break; - default: - // We don't care about PSG channels - return; - } - headerAddress = instrument.data.waveData; - if (headerAddress < 0x20) { - mLOG(GBA_AUDIO, ERROR, "Audio track has invalid instrument"); - return; - } - uint32_t loopOffset = memory->load32(cpu, headerAddress + 0x8, 0); - uint32_t endOffset = memory->load32(cpu, headerAddress + 0xC, 0); - uint32_t sampleBase = headerAddress + 0x10; - uint32_t sampleI = track->samplePlaying; - double sampleOffset = track->currentOffset; - double updates = VIDEO_TOTAL_LENGTH / (mixer->tempo * mixer->p->sampleInterval / OVERSAMPLE); - int nSample; - for (nSample = 0; nSample < updates; ++nSample) { - int8_t sample = memory->load8(cpu, sampleBase + sampleI, 0); - - struct mStereoSample stereo = { - (sample * track->channel->leftVolume * track->channel->envelopeV) >> 9, - (sample * track->channel->rightVolume * track->channel->envelopeV) >> 9 - }; - - CircleBufferWrite16(&track->buffer, stereo.left); - CircleBufferWrite16(&track->buffer, stereo.right); - - sampleOffset += mixer->p->sampleInterval / OVERSAMPLE; - while (sampleOffset > freq) { - sampleOffset -= freq; - ++sampleI; - if (sampleI >= endOffset) { - sampleI = loopOffset; - } - } - } - - track->samplePlaying = sampleI; - track->currentOffset = sampleOffset; -} - -static void _mp2kReload(struct GBAAudioMixer* mixer) { - struct ARMCore* cpu = mixer->p->p->cpu; - struct ARMMemory* memory = &cpu->memory; - mixer->context.magic = memory->load32(cpu, mixer->contextAddress + offsetof(struct GBAMP2kContext, magic), 0); - int i; - for (i = 0; i < MP2K_MAX_SOUND_CHANNELS; ++i) { - struct GBAMP2kSoundChannel* ch = &mixer->context.chans[i]; - struct GBAMP2kTrack* track = &mixer->activeTracks[i]; - track->waiting = false; - uint32_t base = mixer->contextAddress + offsetof(struct GBAMP2kContext, chans[i]); - - ch->status = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, status), 0); - ch->type = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, type), 0); - ch->rightVolume = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, rightVolume), 0); - ch->leftVolume = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, leftVolume), 0); - ch->adsr.attack = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, adsr.attack), 0); - ch->adsr.decay = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, adsr.decay), 0); - ch->adsr.sustain = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, adsr.sustain), 0); - ch->adsr.release = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, adsr.release), 0); - ch->ky = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, ky), 0); - ch->envelopeV = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, envelopeV), 0); - ch->envelopeRight = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, envelopeRight), 0); - ch->envelopeLeft = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, envelopeLeft), 0); - ch->echoVolume = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, echoVolume), 0); - ch->echoLength = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, echoLength), 0); - ch->d1 = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, d1), 0); - ch->d2 = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, d2), 0); - ch->gt = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, gt), 0); - ch->midiKey = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, midiKey), 0); - ch->ve = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, ve), 0); - ch->pr = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, pr), 0); - ch->rp = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, rp), 0); - ch->d3[0] = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, d3[0]), 0); - ch->d3[1] = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, d3[1]), 0); - ch->d3[2] = memory->load8(cpu, base + offsetof(struct GBAMP2kSoundChannel, d3[2]), 0); - ch->ct = memory->load32(cpu, base + offsetof(struct GBAMP2kSoundChannel, ct), 0); - ch->fw = memory->load32(cpu, base + offsetof(struct GBAMP2kSoundChannel, fw), 0); - ch->freq = memory->load32(cpu, base + offsetof(struct GBAMP2kSoundChannel, freq), 0); - ch->waveData = memory->load32(cpu, base + offsetof(struct GBAMP2kSoundChannel, waveData), 0); - ch->cp = memory->load32(cpu, base + offsetof(struct GBAMP2kSoundChannel, cp), 0); - ch->track = memory->load32(cpu, base + offsetof(struct GBAMP2kSoundChannel, track), 0); - ch->pp = memory->load32(cpu, base + offsetof(struct GBAMP2kSoundChannel, pp), 0); - ch->np = memory->load32(cpu, base + offsetof(struct GBAMP2kSoundChannel, np), 0); - ch->d4 = memory->load32(cpu, base + offsetof(struct GBAMP2kSoundChannel, d4), 0); - ch->xpi = memory->load16(cpu, base + offsetof(struct GBAMP2kSoundChannel, xpi), 0); - ch->xpc = memory->load16(cpu, base + offsetof(struct GBAMP2kSoundChannel, xpc), 0); - - base = ch->track; - if (base) { - track->track.flags = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, flags), 0); - track->track.wait = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, wait), 0); - track->track.patternLevel = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, patternLevel), 0); - track->track.repN = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, repN), 0); - track->track.gateTime = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, gateTime), 0); - track->track.key = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, key), 0); - track->track.velocity = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, velocity), 0); - track->track.runningStatus = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, runningStatus), 0); - track->track.keyM = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, keyM), 0); - track->track.pitM = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, pitM), 0); - track->track.keyShift = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, keyShift), 0); - track->track.keyShiftX = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, keyShiftX), 0); - track->track.tune = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, tune), 0); - track->track.pitX = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, pitX), 0); - track->track.bend = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, bend), 0); - track->track.bendRange = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, bendRange), 0); - track->track.volMR = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, volMR), 0); - track->track.volML = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, volML), 0); - track->track.vol = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, vol), 0); - track->track.volX = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, volX), 0); - track->track.pan = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, pan), 0); - track->track.panX = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, panX), 0); - track->track.modM = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, modM), 0); - track->track.mod = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, mod), 0); - track->track.modT = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, modT), 0); - track->track.lfoSpeed = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, lfoSpeed), 0); - track->track.lfoSpeedC = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, lfoSpeedC), 0); - track->track.lfoDelay = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, lfoDelay), 0); - track->track.lfoDelayC = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, lfoDelayC), 0); - track->track.priority = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, priority), 0); - track->track.echoVolume = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, echoVolume), 0); - track->track.echoLength = memory->load8(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, echoLength), 0); - track->track.chan = memory->load32(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, chan), 0); - _loadInstrument(cpu, &track->track.instrument, base + offsetof(struct GBAMP2kMusicPlayerTrack, instrument)); - track->track.cmdPtr = memory->load32(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, cmdPtr), 0); - track->track.patternStack[0] = memory->load32(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, patternStack[0]), 0); - track->track.patternStack[1] = memory->load32(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, patternStack[1]), 0); - track->track.patternStack[2] = memory->load32(cpu, base + offsetof(struct GBAMP2kMusicPlayerTrack, patternStack[2]), 0); - } else { - memset(&track->track, 0, sizeof(track->track)); - } - if (track->track.runningStatus == 0xCD) { - // XCMD isn't supported - mixer->p->externalMixing = false; - } - } -} - -bool _mp2kEngage(struct GBAAudioMixer* mixer, uint32_t address) { - if (address != mixer->contextAddress) { - mixer->contextAddress = address; - mixer->p->externalMixing = true; - _mp2kReload(mixer); - } - return true; -} - -void _mp2kStep(struct GBAAudioMixer* mixer) { - mixer->frame += mixer->p->sampleInterval; - - while (mixer->frame >= VIDEO_TOTAL_LENGTH / mixer->tempo) { - int i; - for (i = 0; i < MP2K_MAX_SOUND_CHANNELS; ++i) { - struct GBAMP2kTrack* track = &mixer->activeTracks[i]; - if (track->channel->status > 0) { - _stepSample(mixer, track); - } else { - track->currentOffset = 0; - track->samplePlaying = 0; - CircleBufferClear(&track->buffer); - } - } - mixer->frame -= VIDEO_TOTAL_LENGTH / mixer->tempo; - } - - uint32_t interval = mixer->p->sampleInterval / OVERSAMPLE; - int i; - for (i = 0; i < OVERSAMPLE; ++i) { - struct mStereoSample sample = {0}; - size_t track; - for (track = 0; track < MP2K_MAX_SOUND_CHANNELS; ++track) { - if (!mixer->activeTracks[track].channel->status) { - continue; - } - int16_t value; - CircleBufferRead16(&mixer->activeTracks[track].buffer, &value); - sample.left += value; - CircleBufferRead16(&mixer->activeTracks[track].buffer, &value); - sample.right += value; - } - sample.left = (sample.left * mixer->p->masterVolume) >> 8; - sample.right = (sample.right * mixer->p->masterVolume) >> 8; - if (mixer->p->externalMixing) { - blip_add_delta(mixer->p->psg.left, mixer->p->clock + i * interval, sample.left - mixer->last.left); - blip_add_delta(mixer->p->psg.right, mixer->p->clock + i * interval, sample.right - mixer->last.right); - } - mixer->last = sample; - } -} - -void _mp2kVblank(struct GBAAudioMixer* mixer) { - if (!mixer->contextAddress) { - return; - } - mLOG(GBA_AUDIO, DEBUG, "Frame"); - mixer->p->externalMixing = true; - _mp2kReload(mixer); -} diff --git a/src/gba/extra/battlechip.c b/src/gba/extra/battlechip.c index fa6be9796..d7bf35cce 100644 --- a/src/gba/extra/battlechip.c +++ b/src/gba/extra/battlechip.c @@ -33,28 +33,25 @@ enum { BATTLECHIP_CONTINUE = 0xFFFF, }; -static bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver); -static uint16_t GBASIOBattlechipGateWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); - -static void _battlechipTransfer(struct GBASIOBattlechipGate* gate); -static void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cyclesLate); +static bool GBASIOBattlechipGateInit(struct GBASIODriver* driver); +static uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); +static bool GBASIOBattlechipGateHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); +static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver); +static void GBASIOBattlechipGateFinishMultiplayer(struct GBASIODriver* driver, uint16_t data[4]); void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate* gate) { - gate->d.init = NULL; - gate->d.deinit = NULL; - gate->d.load = GBASIOBattlechipGateLoad; - gate->d.unload = NULL; - gate->d.writeRegister = GBASIOBattlechipGateWriteRegister; - - gate->event.context = gate; - gate->event.callback = _battlechipTransferEvent; - gate->event.priority = 0x80; + memset(&gate->d, 0, sizeof(gate->d)); + gate->d.init = GBASIOBattlechipGateInit; + gate->d.writeSIOCNT = GBASIOBattlechipGateWriteSIOCNT; + gate->d.handlesMode = GBASIOBattlechipGateHandlesMode; + gate->d.connectedDevices = GBASIOBattlechipGateConnectedDevices; + gate->d.finishMultiplayer = GBASIOBattlechipGateFinishMultiplayer; gate->chipId = 0; gate->flavor = GBA_FLAVOR_BATTLECHIP_GATE; } -bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver) { +bool GBASIOBattlechipGateInit(struct GBASIODriver* driver) { struct GBASIOBattlechipGate* gate = (struct GBASIOBattlechipGate*) driver; gate->state = BATTLECHIP_STATE_SYNC; gate->data[0] = 0x00FE; @@ -62,58 +59,34 @@ bool GBASIOBattlechipGateLoad(struct GBASIODriver* driver) { return true; } -uint16_t GBASIOBattlechipGateWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { - struct GBASIOBattlechipGate* gate = (struct GBASIOBattlechipGate*) driver; - switch (address) { - case GBA_REG_SIOCNT: - value &= ~0xC; - value |= 0x8; - if (value & 0x80) { - _battlechipTransfer(gate); - } - break; - case GBA_REG_SIOMLT_SEND: - break; - case GBA_REG_RCNT: - break; - default: - break; - } +uint16_t GBASIOBattlechipGateWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { + UNUSED(driver); + value &= ~0xC; + value |= 0x8; return value; } -void _battlechipTransfer(struct GBASIOBattlechipGate* gate) { - int32_t cycles; - if (gate->d.p->mode == SIO_NORMAL_32) { - cycles = GBA_ARM7TDMI_FREQUENCY / 0x40000; - } else { - cycles = GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(gate->d.p->siocnt)][1]; +static bool GBASIOBattlechipGateHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + UNUSED(driver); + switch (mode) { + case GBA_SIO_NORMAL_32: + case GBA_SIO_MULTI: + return true; + default: + return false; } - mTimingDeschedule(&gate->d.p->p->timing, &gate->event); - mTimingSchedule(&gate->d.p->p->timing, &gate->event, cycles); } -void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cyclesLate) { - UNUSED(timing); - struct GBASIOBattlechipGate* gate = user; +static int GBASIOBattlechipGateConnectedDevices(struct GBASIODriver* driver) { + UNUSED(driver); + return 1; +} - if (gate->d.p->mode == SIO_NORMAL_32) { - gate->d.p->p->memory.io[GBA_REG(SIODATA32_LO)] = 0; - gate->d.p->p->memory.io[GBA_REG(SIODATA32_HI)] = 0; - gate->d.p->siocnt = GBASIONormalClearStart(gate->d.p->siocnt); - if (GBASIONormalIsIrq(gate->d.p->siocnt)) { - GBARaiseIRQ(gate->d.p->p, GBA_IRQ_SIO, cyclesLate); - } - return; - } +static void GBASIOBattlechipGateFinishMultiplayer(struct GBASIODriver* driver, uint16_t data[4]) { + struct GBASIOBattlechipGate* gate = (struct GBASIOBattlechipGate*) driver; uint16_t cmd = gate->d.p->p->memory.io[GBA_REG(SIOMLT_SEND)]; uint16_t reply = 0xFFFF; - gate->d.p->p->memory.io[GBA_REG(SIOMULTI0)] = cmd; - gate->d.p->p->memory.io[GBA_REG(SIOMULTI2)] = 0xFFFF; - gate->d.p->p->memory.io[GBA_REG(SIOMULTI3)] = 0xFFFF; - gate->d.p->siocnt = GBASIOMultiplayerClearBusy(gate->d.p->siocnt); - gate->d.p->siocnt = GBASIOMultiplayerSetId(gate->d.p->siocnt, 0); mLOG(GBA_BATTLECHIP, DEBUG, "Game: %04X (%i)", cmd, gate->state); @@ -146,7 +119,7 @@ void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cycle case 0xA3D0: // EXE 4 case 0xA6C0: - mLOG(GBA_BATTLECHIP, DEBUG, "Resync detected"); + mLOG(GBA_BATTLECHIP, DEBUG, "Resync detected"); gate->state = BATTLECHIP_STATE_SYNC; break; } @@ -191,9 +164,8 @@ void _battlechipTransferEvent(struct mTiming* timing, void* user, uint32_t cycle mLOG(GBA_BATTLECHIP, DEBUG, "Gate: %04X (%i)", reply, gate->state); ++gate->state; - gate->d.p->p->memory.io[GBA_REG(SIOMULTI1)] = reply; - - if (GBASIOMultiplayerIsIrq(gate->d.p->siocnt)) { - GBARaiseIRQ(gate->d.p->p, GBA_IRQ_SIO, cyclesLate); - } + data[0] = cmd; + data[1] = reply; + data[2] = 0xFFFF; + data[3] = 0xFFFF; } diff --git a/src/gba/extra/proxy.c b/src/gba/extra/proxy.c index 7842bef1f..e33c7b568 100644 --- a/src/gba/extra/proxy.c +++ b/src/gba/extra/proxy.c @@ -13,6 +13,9 @@ static void GBAVideoProxyRendererInit(struct GBAVideoRenderer* renderer); static void GBAVideoProxyRendererReset(struct GBAVideoRenderer* renderer); static void GBAVideoProxyRendererDeinit(struct GBAVideoRenderer* renderer); +static uint32_t GBAVideoProxyRendererId(const struct GBAVideoRenderer* renderer); +static bool GBAVideoProxyRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size); +static void GBAVideoProxyRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size); static uint16_t GBAVideoProxyRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value); static void GBAVideoProxyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address); static void GBAVideoProxyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value); @@ -26,10 +29,14 @@ static void _handleEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent eve static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* packet); static uint16_t* _vramBlock(struct mVideoLogger* logger, uint32_t address); -void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend) { +void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend, struct mVideoLogger* logger) { + memset(renderer, 0, sizeof(*renderer)); renderer->d.init = GBAVideoProxyRendererInit; renderer->d.reset = GBAVideoProxyRendererReset; renderer->d.deinit = GBAVideoProxyRendererDeinit; + renderer->d.rendererId = GBAVideoProxyRendererId; + renderer->d.loadState = GBAVideoProxyRendererLoadState; + renderer->d.saveState = GBAVideoProxyRendererSaveState; renderer->d.writeVideoRegister = GBAVideoProxyRendererWriteVideoRegister; renderer->d.writeVRAM = GBAVideoProxyRendererWriteVRAM; renderer->d.writeOAM = GBAVideoProxyRendererWriteOAM; @@ -59,13 +66,14 @@ void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct renderer->d.highlightColor = M_COLOR_WHITE; renderer->d.highlightAmount = 0; - renderer->logger->context = renderer; - renderer->logger->parsePacket = _parsePacket; - renderer->logger->handleEvent = _handleEvent; - renderer->logger->vramBlock = _vramBlock; - renderer->logger->paletteSize = GBA_SIZE_PALETTE_RAM; - renderer->logger->vramSize = GBA_SIZE_VRAM; - renderer->logger->oamSize = GBA_SIZE_OAM; + renderer->logger = logger; + logger->context = renderer; + logger->parsePacket = _parsePacket; + logger->handleEvent = _handleEvent; + logger->vramBlock = _vramBlock; + logger->paletteSize = GBA_SIZE_PALETTE_RAM; + logger->vramSize = GBA_SIZE_VRAM; + logger->oamSize = GBA_SIZE_OAM; renderer->backend = backend; } @@ -172,6 +180,11 @@ void GBAVideoProxyRendererDeinit(struct GBAVideoRenderer* renderer) { mVideoLoggerRendererDeinit(proxyRenderer->logger); } +uint32_t GBAVideoProxyRendererId(const struct GBAVideoRenderer* renderer) { + struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; + return proxyRenderer->backend->rendererId(proxyRenderer->backend); +} + static void _handleEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent event) { struct GBAVideoProxyRenderer* proxyRenderer = logger->context; switch (event) { @@ -189,6 +202,12 @@ static void _handleEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent eve case LOGGER_EVENT_GET_PIXELS: proxyRenderer->backend->getPixels(proxyRenderer->backend, &logger->pixelStride, &logger->pixelBuffer); break; + case LOGGER_EVENT_LOAD_STATE: + logger->stateStatus = proxyRenderer->backend->loadState(proxyRenderer->backend, logger->stateBuffer, logger->stateSize); + break; + case LOGGER_EVENT_SAVE_STATE: + proxyRenderer->backend->saveState(proxyRenderer->backend, &logger->stateBuffer, &logger->stateSize); + break; } } @@ -279,6 +298,35 @@ uint16_t GBAVideoProxyRendererWriteVideoRegister(struct GBAVideoRenderer* render return value; } +bool GBAVideoProxyRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size) { + struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; + if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { + proxyRenderer->logger->wait(proxyRenderer->logger); + proxyRenderer->logger->stateBuffer = (void*) state; + proxyRenderer->logger->stateSize = size; + proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_LOAD_STATE); + proxyRenderer->logger->stateBuffer = NULL; + proxyRenderer->logger->stateSize = 0; + return proxyRenderer->logger->stateStatus; + } else { + return proxyRenderer->backend->loadState(proxyRenderer->backend, state, size); + } +} + +void GBAVideoProxyRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size) { + struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; + if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { + proxyRenderer->logger->wait(proxyRenderer->logger); + proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_SAVE_STATE); + *state = proxyRenderer->logger->stateBuffer; + *size = proxyRenderer->logger->stateSize; + proxyRenderer->logger->stateBuffer = NULL; + proxyRenderer->logger->stateSize = 0; + } else { + proxyRenderer->backend->saveState(proxyRenderer->backend, state, size); + } +} + void GBAVideoProxyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) { struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; mVideoLoggerRendererWriteVRAM(proxyRenderer->logger, address); diff --git a/src/gba/gba.c b/src/gba/gba.c index 7586ae66c..6b833838e 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #ifdef USE_ELF @@ -40,6 +41,9 @@ static const uint8_t GBA_ROM_MAGIC2[] = { 0x96 }; static const size_t GBA_MB_MAGIC_OFFSET = 0xC0; static void GBAInit(void* cpu, struct mCPUComponent* component); +static void GBACP0Process(struct ARMCore* cpu, int crn, int crm, int crd, int opcode1, int opcode2); +static int32_t GBACP14Read(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2); +static void GBACP14Write(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2, int32_t value); static void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh); static void GBAProcessEvents(struct ARMCore* cpu); static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode); @@ -49,7 +53,7 @@ static void GBATestIRQNoDelay(struct ARMCore* cpu); static void _triggerIRQ(struct mTiming*, void* user, uint32_t cyclesLate); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS static bool _setSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode); static void _clearSoftwareBreakpoint(struct ARMDebugger*, const struct ARMDebugBreakpoint*); #endif @@ -72,6 +76,9 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) { gba->sync = 0; GBAInterruptHandlerInit(&gba->cpu->irqh); + gba->cpu->cp[0].cdp = GBACP0Process; + gba->cpu->cp[14].mrc = GBACP14Read; + gba->cpu->cp[14].mcr = GBACP14Write; GBAMemoryInit(gba); gba->memory.savedata.timing = &gba->timing; @@ -111,7 +118,7 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) { gba->biosChecksum = GBAChecksum(gba->memory.bios, GBA_SIZE_BIOS); gba->idleOptimization = IDLE_LOOP_REMOVE; - gba->idleLoop = IDLE_LOOP_NONE; + gba->idleLoop = GBA_IDLE_LOOP_NONE; gba->vbaBugCompat = false; gba->hardCrash = true; @@ -165,7 +172,7 @@ void GBAUnloadROM(struct GBA* gba) { gba->memory.savedata.realVf->close(gba->memory.savedata.realVf); gba->memory.savedata.realVf = 0; } - gba->idleLoop = IDLE_LOOP_NONE; + gba->idleLoop = GBA_IDLE_LOOP_NONE; } void GBADestroy(struct GBA* gba) { @@ -186,6 +193,30 @@ void GBADestroy(struct GBA* gba) { mCoreCallbacksListDeinit(&gba->coreCallbacks); } +static void GBACP0Process(struct ARMCore* cpu, int crn, int crm, int crd, int opcode1, int opcode2) { + UNUSED(cpu); + mLOG(GBA, INFO, "Hit Wii U VC opcode: cdp p0, %i, c%i, c%i, c%i, %i", opcode1, crd, crn, crm, opcode2); +} + +static int32_t GBACP14Read(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2) { + UNUSED(crn); + UNUSED(crm); + UNUSED(opcode1); + UNUSED(opcode2); + mLOG(GBA, GAME_ERROR, "Read from missing CP14"); + return GBALoadBad(cpu); +} + +static void GBACP14Write(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2, int32_t value) { + UNUSED(cpu); + UNUSED(crn); + UNUSED(crm); + UNUSED(opcode1); + UNUSED(opcode2); + UNUSED(value); + mLOG(GBA, GAME_ERROR, "Write to missing CP14"); +} + void GBAInterruptHandlerInit(struct ARMInterruptHandler* irqh) { irqh->reset = GBAReset; irqh->processEvents = GBAProcessEvents; @@ -220,6 +251,7 @@ void GBAReset(struct ARMCore* cpu) { gba->memory.romMask = toPow2(gba->memory.romSize) - 1; gba->yankedRomSize = 0; } + gba->lastRumble = 0; mTimingClear(&gba->timing); GBAMemoryReset(gba); GBAVideoReset(&gba->video); @@ -231,8 +263,8 @@ void GBAReset(struct ARMCore* cpu) { // GB Player SIO control should not be engaged before detection, even if we already know it's GBP gba->memory.hw.devices &= ~HW_GB_PLAYER; - if (gba->sio.drivers.normal == &gba->sio.gbp.d) { - GBASIOSetDriver(&gba->sio, NULL, SIO_NORMAL_32); + if (gba->sio.driver == &gba->sio.gbp.d) { + GBASIOSetDriver(&gba->sio, NULL); } bool isELF = false; @@ -305,14 +337,10 @@ static void GBAProcessEvents(struct ARMCore* cpu) { do { int32_t cycles = cpu->cycles; cpu->cycles = 0; -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS gba->timing.globalCycles += cycles < nextEvent ? nextEvent : cycles; #endif -#ifndef NDEBUG - if (cycles < 0) { - mLOG(GBA, FATAL, "Negative cycles passed: %i", cycles); - } -#endif + mASSERT_DEBUG_LOG(GBA, cycles >= 0, "Negative cycles passed: %i", cycles); nextEvent = mTimingTick(&gba->timing, cycles < nextEvent ? nextEvent : cycles); } while (gba->cpuBlocked && !gba->earlyExit); @@ -322,12 +350,9 @@ static void GBAProcessEvents(struct ARMCore* cpu) { if (!gba->memory.io[GBA_REG(IME)] || !gba->memory.io[GBA_REG(IE)]) { break; } + } else { + mASSERT_DEBUG_LOG(GBA, nextEvent >= 0, "Negative cycles will pass: %i", nextEvent); } -#ifndef NDEBUG - else if (nextEvent < 0) { - mLOG(GBA, FATAL, "Negative cycles will pass: %i", nextEvent); - } -#endif if (gba->earlyExit) { break; } @@ -338,7 +363,7 @@ static void GBAProcessEvents(struct ARMCore* cpu) { } } -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger) { gba->debugger = (struct ARMDebugger*) debugger->platform; gba->debugger->setSoftwareBreakpoint = _setSoftwareBreakpoint; @@ -383,10 +408,14 @@ bool GBALoadMB(struct GBA* gba, struct VFile* vf) { gba->mbVf = vf; vf->seek(vf, 0, SEEK_SET); memset(gba->memory.wram, 0, GBA_SIZE_EWRAM); - vf->read(vf, gba->memory.wram, GBA_SIZE_EWRAM); + off_t read = vf->read(vf, gba->memory.wram, GBA_SIZE_EWRAM); + if (read < 0) { + return false; + } if (gba->cpu && gba->memory.activeRegion == GBA_REGION_IWRAM) { gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]); } + gba->romCrc32 = doCrc32(gba->memory.wram, read); return true; } @@ -463,16 +492,16 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) { gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]); } GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]); - GBAVFameDetect(&gba->memory.vfame, gba->memory.rom, gba->memory.romSize); + GBAVFameDetect(&gba->memory.vfame, gba->memory.rom, gba->memory.romSize, gba->romCrc32); // TODO: error check return true; } bool GBALoadSave(struct GBA* gba, struct VFile* sav) { - enum SavedataType type = gba->memory.savedata.type; + enum GBASavedataType type = gba->memory.savedata.type; GBASavedataDeinit(&gba->memory.savedata); GBASavedataInit(&gba->memory.savedata, sav); - if (type != SAVEDATA_AUTODETECT) { + if (type != GBA_SAVEDATA_AUTODETECT) { GBASavedataForceType(&gba->memory.savedata, type); } return sav; @@ -528,16 +557,14 @@ void GBAApplyPatch(struct GBA* gba, struct Patch* patch) { mappedMemoryFree(newRom, GBA_SIZE_ROM0); return; } - if (gba->romVf) { + if (gba->memory.rom) { #ifndef FIXED_ROM_BUFFER if (!gba->isPristine) { - mappedMemoryFree(gba->memory.rom, GBA_SIZE_ROM0); + mappedMemoryFree(gba->memory.rom, gba->memory.romSize); } else { gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize); } #endif - gba->romVf->close(gba->romVf); - gba->romVf = NULL; } gba->isPristine = false; gba->memory.rom = newRom; @@ -825,32 +852,30 @@ bool GBAIsBIOS(struct VFile* vf) { return true; } -void GBAGetGameCode(const struct GBA* gba, char* out) { - memset(out, 0, 8); - if (!gba->memory.rom) { - return; - } - - memcpy(out, "AGB-", 4); - memcpy(&out[4], &((struct GBACartridge*) gba->memory.rom)->id, 4); -} - -void GBAGetGameTitle(const struct GBA* gba, char* out) { +void GBAGetGameInfo(const struct GBA* gba, struct mGameInfo* info) { + memset(info, 0, sizeof(*info)); + strlcpy(info->system, "AGB", sizeof(info->system)); + struct GBACartridge* cart = NULL; if (gba->memory.rom) { - memcpy(out, &((struct GBACartridge*) gba->memory.rom)->title, 12); - return; + cart = (struct GBACartridge*) gba->memory.rom; + } else if (gba->mbVf && gba->memory.wram) { + cart = (struct GBACartridge*) gba->memory.wram; } - if (gba->isPristine && gba->memory.wram) { - memcpy(out, &((struct GBACartridge*) gba->memory.wram)->title, 12); - return; + + if (cart) { + memcpy(info->title, &cart->title, 12); + memcpy(info->code, &cart->id, 4); + memcpy(info->maker, &cart->maker, 2); + info->version = cart->version; + } else { + strlcpy(info->title, "(BIOS)", 12); } - strncpy(out, "(BIOS)", 12); } void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) { struct GBA* gba = (struct GBA*) cpu->master; UNUSED(gba); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS if (gba->debugger) { struct mDebuggerEntryInfo info = { .address = _ARMPCAddress(cpu), @@ -873,7 +898,7 @@ void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) { // TODO: More sensible category? mLOG(GBA, WARN, "Illegal opcode: %08x", opcode); } -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS if (gba->debugger) { struct mDebuggerEntryInfo info = { .address = _ARMPCAddress(cpu), @@ -888,7 +913,7 @@ void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) { void GBABreakpoint(struct ARMCore* cpu, int immediate) { struct GBA* gba = (struct GBA*) cpu->master; switch (immediate) { -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS case CPU_COMPONENT_DEBUGGER: if (gba->debugger) { struct mDebuggerEntryInfo info = { @@ -928,10 +953,6 @@ void GBABreakpoint(struct ARMCore* cpu, int immediate) { void GBAFrameStarted(struct GBA* gba) { GBATestKeypadIRQ(gba); - if (gba->audio.mixer) { - gba->audio.mixer->vblank(gba->audio.mixer); - } - size_t c; for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) { struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c); @@ -957,7 +978,7 @@ void GBAFrameEnded(struct GBA* gba) { } if (gba->stream && gba->stream->postVideoFrame) { - const color_t* pixels; + const mColor* pixels; size_t stride; gba->video.renderer->getPixels(gba->video.renderer, &stride, (const void**) &pixels); gba->stream->postVideoFrame(gba->stream, pixels, stride); @@ -967,6 +988,12 @@ void GBAFrameEnded(struct GBA* gba) { GBASIOPlayerUpdate(gba); } + struct mRumble* rumble = gba->rumble; + if (rumble && rumble->integrate) { + gba->lastRumble = mTimingCurrentTime(&gba->timing); + rumble->integrate(rumble, VIDEO_TOTAL_LENGTH); + } + size_t c; for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) { struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c); @@ -1053,7 +1080,7 @@ void GBAClearBreakpoint(struct GBA* gba, uint32_t address, enum ExecutionMode mo } } -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS static bool _setSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) { GBASetBreakpoint((struct GBA*) debugger->cpu->master, &debugger->d.p->d, address, mode, opcode); return true; diff --git a/src/gba/io.c b/src/gba/io.c index 10eb9fb4c..cb6058f7f 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -214,8 +214,8 @@ static const int _isRSpecialRegister[GBA_REG(INTERNAL_MAX)] = { /* 10 */ 1, 1, 1, 1, 1, 1, 1, 1, /* 11 */ 0, 0, 0, 0, 0, 0, 0, 0, /* SIO */ - /* 12 */ 1, 1, 1, 1, 1, 0, 0, 0, - /* 13 */ 1, 1, 1, 0, 0, 0, 0, 0, + /* 12 */ 1, 1, 1, 1, 0, 0, 0, 0, + /* 13 */ 1, 1, 0, 0, 0, 0, 0, 0, /* 14 */ 1, 0, 0, 0, 0, 0, 0, 0, /* 15 */ 1, 1, 1, 1, 1, 0, 0, 0, /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0, @@ -326,17 +326,19 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { break; case GBA_REG_SOUND1CNT_HI: GBAAudioWriteSOUND1CNT_HI(&gba->audio, value); + value &= 0xFFC0; break; case GBA_REG_SOUND1CNT_X: GBAAudioWriteSOUND1CNT_X(&gba->audio, value); - value &= 0x47FF; + value &= 0x4000; break; case GBA_REG_SOUND2CNT_LO: GBAAudioWriteSOUND2CNT_LO(&gba->audio, value); + value &= 0xFFC0; break; case GBA_REG_SOUND2CNT_HI: GBAAudioWriteSOUND2CNT_HI(&gba->audio, value); - value &= 0x47FF; + value &= 0x4000; break; case GBA_REG_SOUND3CNT_LO: GBAAudioWriteSOUND3CNT_LO(&gba->audio, value); @@ -344,16 +346,15 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { break; case GBA_REG_SOUND3CNT_HI: GBAAudioWriteSOUND3CNT_HI(&gba->audio, value); - value &= 0xE03F; + value &= 0xE000; break; case GBA_REG_SOUND3CNT_X: GBAAudioWriteSOUND3CNT_X(&gba->audio, value); - // TODO: The low bits need to not be readable, but still 8-bit writable - value &= 0x47FF; + value &= 0x4000; break; case GBA_REG_SOUND4CNT_LO: GBAAudioWriteSOUND4CNT_LO(&gba->audio, value); - value &= 0xFF3F; + value &= 0xFF00; break; case GBA_REG_SOUND4CNT_HI: GBAAudioWriteSOUND4CNT_HI(&gba->audio, value); @@ -482,6 +483,7 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { // SIO case GBA_REG_SIOCNT: + value &= 0x7FFF; GBASIOWriteSIOCNT(&gba->sio, value); break; case GBA_REG_RCNT: @@ -531,6 +533,21 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { case GBA_REG_MAX: // Some bad interrupt libraries will write to this break; + case GBA_REG_POSTFLG: + if (gba->memory.activeRegion == GBA_REGION_BIOS) { + if (gba->memory.io[address >> 1]) { + if (value & 0x8000) { + GBAStop(gba); + } else { + GBAHalt(gba); + } + } + value &= ~0x8000; + } else { + mLOG(GBA_IO, GAME_ERROR, "Write to BIOS-only I/O register: %03X", address); + return; + } + break; case GBA_REG_EXWAITCNT_HI: // This register sits outside of the normal I/O block, so we need to stash it somewhere unused address = GBA_REG_INTERNAL_EXWAITCNT_HI; @@ -563,19 +580,6 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { } void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) { - if (address == GBA_REG_HALTCNT) { - value &= 0x80; - if (!value) { - GBAHalt(gba); - } else { - GBAStop(gba); - } - return; - } - if (address == GBA_REG_POSTFLG) { - gba->memory.io[(address & (GBA_SIZE_IO - 1)) >> 1] = value; - return; - } if (address >= GBA_REG_DEBUG_STRING && address - GBA_REG_DEBUG_STRING < sizeof(gba->debugString)) { gba->debugString[address - GBA_REG_DEBUG_STRING] = value; return; @@ -583,9 +587,96 @@ void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) { if (address > GBA_SIZE_IO) { return; } - uint16_t value16 = value << (8 * (address & 1)); - value16 |= (gba->memory.io[(address & (GBA_SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1))); - GBAIOWrite(gba, address & 0xFFFFFFFE, value16); + uint16_t value16; + + switch (address) { + case GBA_REG_SOUND1CNT_HI: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR11(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND1CNT_HI)] &= 0xFF00; + gba->memory.io[GBA_REG(SOUND1CNT_HI)] |= value & 0xC0; + break; + case GBA_REG_SOUND1CNT_HI + 1: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR12(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND1CNT_HI)] &= 0x00C0; + gba->memory.io[GBA_REG(SOUND1CNT_HI)] |= value << 8; + break; + case GBA_REG_SOUND1CNT_X: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR13(&gba->audio.psg, value); + break; + case GBA_REG_SOUND1CNT_X + 1: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR14(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND1CNT_X)] = (value & 0x40) << 8; + break; + case GBA_REG_SOUND2CNT_LO: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR21(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND2CNT_LO)] &= 0xFF00; + gba->memory.io[GBA_REG(SOUND2CNT_LO)] |= value & 0xC0; + break; + case GBA_REG_SOUND2CNT_LO + 1: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR22(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND2CNT_LO)] &= 0x00C0; + gba->memory.io[GBA_REG(SOUND2CNT_LO)] |= value << 8; + break; + case GBA_REG_SOUND2CNT_HI: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR23(&gba->audio.psg, value); + break; + case GBA_REG_SOUND2CNT_HI + 1: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR24(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND2CNT_HI)] = (value & 0x40) << 8; + break; + case GBA_REG_SOUND3CNT_HI: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR31(&gba->audio.psg, value); + break; + case GBA_REG_SOUND3CNT_HI + 1: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + gba->audio.psg.ch3.volume = GBAudioRegisterBankVolumeGetVolumeGBA(value); + gba->memory.io[GBA_REG(SOUND3CNT_HI)] = (value & 0xE0) << 8; + break; + case GBA_REG_SOUND3CNT_X: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR33(&gba->audio.psg, value); + break; + case GBA_REG_SOUND3CNT_X + 1: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR34(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND3CNT_X)] = (value & 0x40) << 8; + break; + case GBA_REG_SOUND4CNT_LO: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR41(&gba->audio.psg, value); + break; + case GBA_REG_SOUND4CNT_LO + 1: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR42(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND4CNT_LO)] = value << 8; + break; + case GBA_REG_SOUND4CNT_HI: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR43(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND4CNT_HI)] &= 0x4000; + gba->memory.io[GBA_REG(SOUND4CNT_HI)] |= value; + break; + case GBA_REG_SOUND4CNT_HI + 1: + GBAAudioSample(&gba->audio, mTimingCurrentTime(&gba->timing)); + GBAudioWriteNR44(&gba->audio.psg, value); + gba->memory.io[GBA_REG(SOUND4CNT_HI)] &= 0x00FF; + gba->memory.io[GBA_REG(SOUND4CNT_HI)] |= (value & 0x40) << 8; + break; + default: + value16 = value << (8 * (address & 1)); + value16 |= (gba->memory.io[(address & (GBA_SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1))); + GBAIOWrite(gba, address & 0xFFFFFFFE, value16); + break; + } } void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) { @@ -806,10 +897,6 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { gba->memory.io[GBA_REG(JOYSTAT)] &= ~JOYSTAT_RECV; break; - case GBA_REG_POSTFLG: - mLOG(GBA_IO, STUB, "Stub I/O register read: %03x", address); - break; - // Wave RAM can be written and read even if the audio hardware is disabled. // However, it is not possible to switch between the two banks because it // isn't possible to write to register SOUND3CNT_LO. @@ -883,6 +970,7 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { case GBA_REG_IF: case GBA_REG_WAITCNT: case GBA_REG_IME: + case GBA_REG_POSTFLG: // Handled transparently by registers break; case 0x066: @@ -897,6 +985,7 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { case 0x142: case 0x15A: case 0x206: + case 0x302: mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address); return 0; // These registers sit outside of the normal I/O block, so we need to stash them somewhere unused @@ -941,6 +1030,7 @@ void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) { STORE_32(gba->memory.dmaTransferRegister, 0, &state->dmaTransferRegister); STORE_32(gba->dmaPC, 0, &state->dmaBlockPC); + STORE_32(gba->bus, 0, &state->bus); GBAHardwareSerialize(&gba->memory.hw, state); } @@ -987,7 +1077,9 @@ void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) { LOAD_32(gba->memory.dmaTransferRegister, 0, &state->dmaTransferRegister); LOAD_32(gba->dmaPC, 0, &state->dmaBlockPC); + LOAD_32(gba->bus, 0, &state->bus); + GBADMARecalculateCycles(gba); GBADMAUpdate(gba); GBAHardwareDeserialize(&gba->memory.hw, state); } diff --git a/src/gba/memory.c b/src/gba/memory.c index 9418a2706..c818c75c8 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -401,7 +401,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { LOAD_32(value, address & 0x0001FFFC, gba->video.vram); \ } \ ++wait; \ - if (gba->video.shouldStall && (address & 0x0001FFFF) < ((GBARegisterDISPCNTGetMode(gba->memory.io[GBA_REG(DISPCNT)]) >= 3) ? 0x00014000 : 0x00010000)) { \ + if (gba->video.stallMask && (address & 0x0001FFFF) < ((GBARegisterDISPCNTGetMode(gba->memory.io[GBA_REG(DISPCNT)]) >= 3) ? 0x00014000 : 0x00010000)) { \ wait += GBAMemoryStallVRAM(gba, wait, 1); \ } @@ -561,7 +561,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } else { LOAD_16(value, address & 0x0001FFFE, gba->video.vram); } - if (gba->video.shouldStall && (address & 0x0001FFFF) < ((GBARegisterDISPCNTGetMode(gba->memory.io[GBA_REG(DISPCNT)]) >= 3) ? 0x00014000 : 0x00010000)) { + if (gba->video.stallMask && (address & 0x0001FFFF) < ((GBARegisterDISPCNTGetMode(gba->memory.io[GBA_REG(DISPCNT)]) >= 3) ? 0x00014000 : 0x00010000)) { wait += GBAMemoryStallVRAM(gba, wait, 0); } break; @@ -595,7 +595,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { break; case GBA_REGION_ROM2_EX: wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; - if (memory->savedata.type == SAVEDATA_EEPROM || memory->savedata.type == SAVEDATA_EEPROM512) { + if (memory->savedata.type == GBA_SAVEDATA_EEPROM || memory->savedata.type == GBA_SAVEDATA_EEPROM512) { value = GBASavedataReadEEPROM(&memory->savedata); } else if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) { value = GBACartEReaderRead(&memory->ereader, address); @@ -676,7 +676,7 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } else { value = ((uint8_t*) gba->video.vram)[address & 0x0001FFFF]; } - if (gba->video.shouldStall) { + if (gba->video.stallMask) { wait += GBAMemoryStallVRAM(gba, wait, 0); } break; @@ -702,7 +702,7 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { case GBA_REGION_SRAM: case GBA_REGION_SRAM_MIRROR: wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; - if (memory->savedata.type == SAVEDATA_AUTODETECT) { + if (memory->savedata.type == GBA_SAVEDATA_AUTODETECT) { mLOG(GBA_MEM, INFO, "Detected SRAM savegame"); GBASavedataInitSRAM(&memory->savedata); } @@ -711,13 +711,13 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) { value = GBACartEReaderReadFlash(&memory->ereader, address); - } else if (memory->savedata.type == SAVEDATA_SRAM) { + } else if (memory->savedata.type == GBA_SAVEDATA_SRAM) { value = memory->savedata.data[address & (GBA_SIZE_SRAM - 1)]; - } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) { + } else if (memory->savedata.type == GBA_SAVEDATA_FLASH512 || memory->savedata.type == GBA_SAVEDATA_FLASH1M) { value = GBASavedataReadFlash(&memory->savedata, address); } else if (memory->hw.devices & HW_TILT) { value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK); - } else if (memory->savedata.type == SAVEDATA_SRAM512) { + } else if (memory->savedata.type == GBA_SAVEDATA_SRAM512) { value = memory->savedata.data[address & (GBA_SIZE_SRAM512 - 1)]; } else { mLOG(GBA_MEM, GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address); @@ -781,7 +781,7 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } \ } \ ++wait; \ - if (gba->video.shouldStall && (address & 0x0001FFFF) < ((GBARegisterDISPCNTGetMode(gba->memory.io[GBA_REG(DISPCNT)]) >= 3) ? 0x00014000 : 0x00010000)) { \ + if (gba->video.stallMask && (address & 0x0001FFFF) < ((GBARegisterDISPCNTGetMode(gba->memory.io[GBA_REG(DISPCNT)]) >= 3) ? 0x00014000 : 0x00010000)) { \ wait += GBAMemoryStallVRAM(gba, wait, 1); \ } @@ -908,7 +908,7 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); } } - if (gba->video.shouldStall && (address & 0x0001FFFF) < ((GBARegisterDISPCNTGetMode(gba->memory.io[GBA_REG(DISPCNT)]) >= 3) ? 0x00014000 : 0x00010000)) { + if (gba->video.stallMask && (address & 0x0001FFFF) < ((GBARegisterDISPCNTGetMode(gba->memory.io[GBA_REG(DISPCNT)]) >= 3) ? 0x00014000 : 0x00010000)) { wait += GBAMemoryStallVRAM(gba, wait, 0); } break; @@ -975,11 +975,11 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) { GBACartEReaderWrite(&memory->ereader, address, value); break; - } else if (memory->savedata.type == SAVEDATA_AUTODETECT) { + } else if (memory->savedata.type == GBA_SAVEDATA_AUTODETECT) { mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); GBASavedataInitEEPROM(&memory->savedata); } - if (memory->savedata.type == SAVEDATA_EEPROM512 || memory->savedata.type == SAVEDATA_EEPROM) { + if (memory->savedata.type == GBA_SAVEDATA_EEPROM512 || memory->savedata.type == GBA_SAVEDATA_EEPROM) { GBASavedataWriteEEPROM(&memory->savedata, value, 1); break; } @@ -1038,7 +1038,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8); gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); } - if (gba->video.shouldStall) { + if (gba->video.stallMask) { wait += GBAMemoryStallVRAM(gba, wait, 0); } break; @@ -1050,7 +1050,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo break; case GBA_REGION_SRAM: case GBA_REGION_SRAM_MIRROR: - if (memory->savedata.type == SAVEDATA_AUTODETECT) { + if (memory->savedata.type == GBA_SAVEDATA_AUTODETECT) { if (address == SAVEDATA_FLASH_BASE) { mLOG(GBA_MEM, INFO, "Detected Flash savegame"); GBASavedataInitFlash(&memory->savedata); @@ -1061,9 +1061,9 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo } if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) { GBACartEReaderWriteFlash(&memory->ereader, address, value); - } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) { + } else if (memory->savedata.type == GBA_SAVEDATA_FLASH512 || memory->savedata.type == GBA_SAVEDATA_FLASH1M) { GBASavedataWriteFlash(&memory->savedata, address, value); - } else if (memory->savedata.type == SAVEDATA_SRAM) { + } else if (memory->savedata.type == GBA_SAVEDATA_SRAM) { if (memory->vfame.cartType) { GBAVFameSramWrite(&memory->vfame, address, value, memory->savedata.data); } else { @@ -1072,7 +1072,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo memory->savedata.dirty |= mSAVEDATA_DIRT_NEW; } else if (memory->hw.devices & HW_TILT) { GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value); - } else if (memory->savedata.type == SAVEDATA_SRAM512) { + } else if (memory->savedata.type == GBA_SAVEDATA_SRAM512) { memory->savedata.data[address & (GBA_SIZE_SRAM512 - 1)] = value; memory->savedata.dirty |= mSAVEDATA_DIRT_NEW; } else { @@ -1118,10 +1118,8 @@ uint32_t GBAView32(struct ARMCore* cpu, uint32_t address) { value = GBALoad32(cpu, address, 0); break; case GBA_REGION_IO: - if ((address & OFFSET_MASK) < GBA_REG_MAX) { - value = gba->memory.io[(address & OFFSET_MASK) >> 1]; - value |= gba->memory.io[((address & OFFSET_MASK) >> 1) + 1] << 16; - } + value = GBAView16(cpu, address); + value |= GBAView16(cpu, address + 2) << 16; break; case GBA_REGION_SRAM: value = GBALoad8(cpu, address, 0); @@ -1159,7 +1157,10 @@ uint16_t GBAView16(struct ARMCore* cpu, uint32_t address) { value = GBALoad16(cpu, address, 0); break; case GBA_REGION_IO: - if ((address & OFFSET_MASK) < GBA_REG_MAX) { + if ((address & OFFSET_MASK) < GBA_REG_MAX || (address & OFFSET_MASK) == GBA_REG_POSTFLG) { + value = gba->memory.io[(address & OFFSET_MASK) >> 1]; + } else if ((address & OFFSET_MASK) == GBA_REG_EXWAITCNT_LO || (address & OFFSET_MASK) == GBA_REG_EXWAITCNT_HI) { + address += GBA_REG_INTERNAL_EXWAITCNT_LO - GBA_REG_EXWAITCNT_LO; value = gba->memory.io[(address & OFFSET_MASK) >> 1]; } break; @@ -1263,7 +1264,7 @@ void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* o break; case GBA_REGION_SRAM: case GBA_REGION_SRAM_MIRROR: - if (memory->savedata.type == SAVEDATA_SRAM) { + if (memory->savedata.type == GBA_SAVEDATA_SRAM) { LOAD_32(oldValue, address & (GBA_SIZE_SRAM - 4), memory->savedata.data); STORE_32(value, address & (GBA_SIZE_SRAM - 4), memory->savedata.data); } else { @@ -1333,7 +1334,7 @@ void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* o break; case GBA_REGION_SRAM: case GBA_REGION_SRAM_MIRROR: - if (memory->savedata.type == SAVEDATA_SRAM) { + if (memory->savedata.type == GBA_SAVEDATA_SRAM) { LOAD_16(oldValue, address & (GBA_SIZE_SRAM - 2), memory->savedata.data); STORE_16(value, address & (GBA_SIZE_SRAM - 2), memory->savedata.data); } else { @@ -1349,10 +1350,22 @@ void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* o } } +#define MUNGE8 \ + if (address & 1) { \ + oldValue = alignedValue >> 8; \ + alignedValue &= 0xFF; \ + alignedValue |= value << 8; \ + } else { \ + oldValue = alignedValue; \ + alignedValue &= 0xFF00; \ + alignedValue |= (uint8_t) value; \ + } + void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) { struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; int8_t oldValue = -1; + int16_t alignedValue; switch (address >> BASE_OFFSET) { case GBA_REGION_EWRAM: @@ -1367,13 +1380,29 @@ void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address); break; case GBA_REGION_PALETTE_RAM: - mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address); + LOAD_16(alignedValue, address & (GBA_SIZE_PALETTE_RAM - 2), gba->video.palette); + MUNGE8; + STORE_16(alignedValue, address & (GBA_SIZE_PALETTE_RAM - 2), gba->video.palette); + gba->video.renderer->writePalette(gba->video.renderer, address & (GBA_SIZE_PALETTE_RAM - 2), alignedValue); break; case GBA_REGION_VRAM: - mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address); + if ((address & 0x0001FFFF) < GBA_SIZE_VRAM) { + LOAD_16(alignedValue, address & 0x0001FFFE, gba->video.vram); + MUNGE8; + STORE_16(alignedValue, address & 0x0001FFFE, gba->video.vram); + gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); + } else { + LOAD_16(alignedValue, address & 0x00017FFE, gba->video.vram); + MUNGE8; + STORE_16(alignedValue, address & 0x00017FFE, gba->video.vram); + gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE); + } break; case GBA_REGION_OAM: - mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address); + LOAD_16(alignedValue, address & (GBA_SIZE_OAM - 2), gba->video.oam.raw); + MUNGE8; + STORE_16(alignedValue, address & (GBA_SIZE_OAM - 2), gba->video.oam.raw); + gba->video.renderer->writeOAM(gba->video.renderer, (address & (GBA_SIZE_OAM - 2)) >> 1); break; case GBA_REGION_ROM0: case GBA_REGION_ROM0_EX: @@ -1391,7 +1420,7 @@ void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) break; case GBA_REGION_SRAM: case GBA_REGION_SRAM_MIRROR: - if (memory->savedata.type == SAVEDATA_SRAM) { + if (memory->savedata.type == GBA_SAVEDATA_SRAM) { oldValue = ((int8_t*) memory->savedata.data)[address & (GBA_SIZE_SRAM - 1)]; ((int8_t*) memory->savedata.data)[address & (GBA_SIZE_SRAM - 1)] = value; } else { @@ -1705,6 +1734,10 @@ void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) { STORE_32(memory->agbPrintFuncBackup, AGB_PRINT_FLUSH_ADDR | base, memory->rom); } } + + if (gba->performingDMA) { + GBADMARecalculateCycles(gba); + } } void GBAAdjustEWRAMWaitstates(struct GBA* gba, uint16_t parameters) { @@ -1777,20 +1810,64 @@ int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) { } int32_t GBAMemoryStallVRAM(struct GBA* gba, int32_t wait, int extra) { - UNUSED(extra); - // TODO - uint16_t dispcnt = gba->memory.io[GBA_REG(DISPCNT)]; - int32_t stall = 0; - switch (GBARegisterDISPCNTGetMode(dispcnt)) { - case 2: - if (GBARegisterDISPCNTIsBg2Enable(dispcnt) && GBARegisterDISPCNTIsBg3Enable(dispcnt)) { - // If both backgrounds are enabled, VRAM access is entirely blocked during hdraw - stall = mTimingUntil(&gba->timing, &gba->video.event); + static const uint16_t stallLUT[32] = { + GBA_VSTALL_T4(0) | GBA_VSTALL_A3, + GBA_VSTALL_T4(1) | GBA_VSTALL_A3, + GBA_VSTALL_T4(2) | GBA_VSTALL_A2, + GBA_VSTALL_T4(3) | GBA_VSTALL_A2 | GBA_VSTALL_B, + + GBA_VSTALL_T4(0) | GBA_VSTALL_A3, + GBA_VSTALL_T4(1) | GBA_VSTALL_A3, + GBA_VSTALL_T4(2) | GBA_VSTALL_A2, + GBA_VSTALL_T4(3) | GBA_VSTALL_A2 | GBA_VSTALL_B, + + GBA_VSTALL_A3, + GBA_VSTALL_A3, + GBA_VSTALL_A2, + GBA_VSTALL_A2 | GBA_VSTALL_B, + + GBA_VSTALL_T8(0) | GBA_VSTALL_A3, + GBA_VSTALL_T8(1) | GBA_VSTALL_A3, + GBA_VSTALL_T8(2) | GBA_VSTALL_A2, + GBA_VSTALL_T8(3) | GBA_VSTALL_A2 | GBA_VSTALL_B, + + GBA_VSTALL_A3, + GBA_VSTALL_A3, + GBA_VSTALL_A2, + GBA_VSTALL_A2 | GBA_VSTALL_B, + + GBA_VSTALL_T4(0) | GBA_VSTALL_A3, + GBA_VSTALL_T4(1) | GBA_VSTALL_A3, + GBA_VSTALL_T4(2) | GBA_VSTALL_A2, + GBA_VSTALL_T4(3) | GBA_VSTALL_A2 | GBA_VSTALL_B, + + GBA_VSTALL_A3, + GBA_VSTALL_A3, + GBA_VSTALL_A2, + GBA_VSTALL_A2 | GBA_VSTALL_B, + + GBA_VSTALL_T8(0) | GBA_VSTALL_A3, + GBA_VSTALL_T8(1) | GBA_VSTALL_A3, + GBA_VSTALL_T8(2) | GBA_VSTALL_A2, + GBA_VSTALL_T8(3) | GBA_VSTALL_A2 | GBA_VSTALL_B, + }; + + int32_t until = mTimingUntil(&gba->timing, &gba->video.event); + int period = -until & 0x1F; + + int32_t stall = until; + + int i; + for (i = 0; i < 16; ++i) { + if (!(stallLUT[(period + i) & 0x1F] & gba->video.stallMask)) { + if (!extra) { + stall = i; + break; + } + --extra; } - break; - default: - return 0; } + stall -= wait; if (stall < 0) { return 0; @@ -1821,8 +1898,6 @@ void _pristineCow(struct GBA* gba) { } if (gba->romVf) { gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->memory.romSize); - gba->romVf->close(gba->romVf); - gba->romVf = NULL; } gba->memory.rom = newRom; gba->memory.hw.gpioBase = &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]; diff --git a/src/gba/overrides.c b/src/gba/overrides.c index 16c66ebd8..30d927ed3 100644 --- a/src/gba/overrides.c +++ b/src/gba/overrides.c @@ -13,210 +13,202 @@ static const struct GBACartridgeOverride _overrides[] = { // Advance Wars - { "AWRE", SAVEDATA_FLASH512, HW_NONE, 0x8038810, false }, - { "AWRP", SAVEDATA_FLASH512, HW_NONE, 0x8038810, false }, + { "AWRE", GBA_SAVEDATA_FLASH512, HW_NONE, 0x8038810 }, + { "AWRP", GBA_SAVEDATA_FLASH512, HW_NONE, 0x8038810 }, // Advance Wars 2: Black Hole Rising - { "AW2E", SAVEDATA_FLASH512, HW_NONE, 0x8036E08, false }, - { "AW2P", SAVEDATA_FLASH512, HW_NONE, 0x803719C, false }, + { "AW2E", GBA_SAVEDATA_FLASH512, HW_NONE, 0x8036E08 }, + { "AW2P", GBA_SAVEDATA_FLASH512, HW_NONE, 0x803719C }, // Boktai: The Sun is in Your Hand - { "U3IJ", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false }, - { "U3IE", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false }, - { "U3IP", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false }, + { "U3IJ", GBA_SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, GBA_IDLE_LOOP_NONE }, + { "U3IE", GBA_SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, GBA_IDLE_LOOP_NONE }, + { "U3IP", GBA_SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, GBA_IDLE_LOOP_NONE }, // Boktai 2: Solar Boy Django - { "U32J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false }, - { "U32E", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false }, - { "U32P", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false }, + { "U32J", GBA_SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, GBA_IDLE_LOOP_NONE }, + { "U32E", GBA_SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, GBA_IDLE_LOOP_NONE }, + { "U32P", GBA_SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, GBA_IDLE_LOOP_NONE }, // Crash Bandicoot 2 - N-Tranced - { "AC8J", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "AC8E", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "AC8P", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, + { "AC8J", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "AC8E", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "AC8P", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, // DigiCommunication Nyo - Datou! Black Gemagema Dan - { "BDKJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, + { "BDKJ", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, // Dragon Ball Z - The Legacy of Goku - { "ALGP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, + { "ALGP", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, // Dragon Ball Z - The Legacy of Goku II - { "ALFJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "ALFE", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "ALFP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, + { "ALFJ", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "ALFE", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "ALFP", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, // Dragon Ball Z - Taiketsu - { "BDBE", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "BDBP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, + { "BDBE", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BDBP", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, // Drill Dozer - { "V49J", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE, false }, - { "V49E", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE, false }, - { "V49P", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE, false }, + { "V49J", GBA_SAVEDATA_SRAM, HW_RUMBLE, GBA_IDLE_LOOP_NONE }, + { "V49E", GBA_SAVEDATA_SRAM, HW_RUMBLE, GBA_IDLE_LOOP_NONE }, + { "V49P", GBA_SAVEDATA_SRAM, HW_RUMBLE, GBA_IDLE_LOOP_NONE }, // e-Reader - { "PEAJ", SAVEDATA_FLASH1M, HW_EREADER, IDLE_LOOP_NONE }, - { "PSAJ", SAVEDATA_FLASH1M, HW_EREADER, IDLE_LOOP_NONE }, - { "PSAE", SAVEDATA_FLASH1M, HW_EREADER, IDLE_LOOP_NONE }, + { "PEAJ", GBA_SAVEDATA_FLASH1M, HW_EREADER, GBA_IDLE_LOOP_NONE }, + { "PSAJ", GBA_SAVEDATA_FLASH1M, HW_EREADER, GBA_IDLE_LOOP_NONE }, + { "PSAE", GBA_SAVEDATA_FLASH1M, HW_EREADER, GBA_IDLE_LOOP_NONE }, // Final Fantasy Tactics Advance - { "AFXE", SAVEDATA_FLASH512, HW_NONE, 0x8000428, false }, + { "AFXE", GBA_SAVEDATA_FLASH512, HW_NONE, 0x8000428 }, // F-Zero - Climax - { "BFTJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, + { "BFTJ", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + + // Goodboy Galaxy + { "2GBP", GBA_SAVEDATA_SRAM, HW_RUMBLE, GBA_IDLE_LOOP_NONE }, // Iridion II - { "AI2E", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false }, - { "AI2P", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false }, + { "AI2E", GBA_SAVEDATA_FORCE_NONE, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "AI2P", GBA_SAVEDATA_FORCE_NONE, HW_NONE, GBA_IDLE_LOOP_NONE }, // Game Boy Wars Advance 1+2 - { "BGWJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, + { "BGWJ", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, // Golden Sun: The Lost Age - { "AGFE", SAVEDATA_FLASH512, HW_NONE, 0x801353A, false }, + { "AGFE", GBA_SAVEDATA_FLASH512, HW_NONE, 0x801353A }, // Koro Koro Puzzle - Happy Panechu! - { "KHPJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false }, + { "KHPJ", GBA_SAVEDATA_EEPROM, HW_TILT, GBA_IDLE_LOOP_NONE }, // Legendz - Yomigaeru Shiren no Shima - { "BLJJ", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false }, - { "BLJK", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false }, + { "BLJJ", GBA_SAVEDATA_FLASH512, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "BLJK", GBA_SAVEDATA_FLASH512, HW_RTC, GBA_IDLE_LOOP_NONE }, // Legendz - Sign of Nekuromu - { "BLVJ", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false }, + { "BLVJ", GBA_SAVEDATA_FLASH512, HW_RTC, GBA_IDLE_LOOP_NONE }, // Mega Man Battle Network - { "AREE", SAVEDATA_SRAM, HW_NONE, 0x800032E, false }, + { "AREE", GBA_SAVEDATA_SRAM, HW_NONE, 0x800032E }, // Mega Man Zero - { "AZCE", SAVEDATA_SRAM, HW_NONE, 0x80004E8, false }, + { "AZCE", GBA_SAVEDATA_SRAM, HW_NONE, 0x80004E8 }, // Metal Slug Advance - { "BSME", SAVEDATA_EEPROM, HW_NONE, 0x8000290, false }, + { "BSME", GBA_SAVEDATA_EEPROM, HW_NONE, 0x8000290 }, // Pokemon Ruby - { "AXVJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXVE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXVP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXVI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXVS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXVD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXVF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, + { "AXVJ", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXVE", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXVP", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXVI", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXVS", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXVD", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXVF", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, // Pokemon Sapphire - { "AXPJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXPE", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXPP", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXPI", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXPS", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXPD", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, - { "AXPF", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, + { "AXPJ", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXPE", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXPP", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXPI", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXPS", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXPD", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, + { "AXPF", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, // Pokemon Emerald - { "BPEJ", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false }, - { "BPEE", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false }, - { "BPEP", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false }, - { "BPEI", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false }, - { "BPES", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false }, - { "BPED", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false }, - { "BPEF", SAVEDATA_FLASH1M, HW_RTC, 0x80008C6, false }, + { "BPEJ", GBA_SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 }, + { "BPEE", GBA_SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 }, + { "BPEP", GBA_SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 }, + { "BPEI", GBA_SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 }, + { "BPES", GBA_SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 }, + { "BPED", GBA_SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 }, + { "BPEF", GBA_SAVEDATA_FLASH1M, HW_RTC, 0x80008C6 }, // Pokemon Mystery Dungeon - { "B24E", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "B24P", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, + { "B24E", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "B24P", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, // Pokemon FireRed - { "BPRJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPRE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPRP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPRI", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPRS", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPRD", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPRF", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, + { "BPRJ", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPRE", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPRP", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPRI", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPRS", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPRD", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPRF", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, // Pokemon LeafGreen - { "BPGJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPGE", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPGP", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPGI", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPGS", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPGD", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, - { "BPGF", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, + { "BPGJ", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPGE", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPGP", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPGI", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPGS", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPGD", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "BPGF", GBA_SAVEDATA_FLASH1M, HW_NONE, GBA_IDLE_LOOP_NONE }, // RockMan EXE 4.5 - Real Operation - { "BR4J", SAVEDATA_FLASH512, HW_RTC, IDLE_LOOP_NONE, false }, + { "BR4J", GBA_SAVEDATA_FLASH512, HW_RTC, GBA_IDLE_LOOP_NONE }, // Rocky - { "AR8E", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "AROP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, + { "AR8E", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "AROP", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, // Sennen Kazoku - { "BKAJ", SAVEDATA_FLASH1M, HW_RTC, IDLE_LOOP_NONE, false }, + { "BKAJ", GBA_SAVEDATA_FLASH1M, HW_RTC, GBA_IDLE_LOOP_NONE }, // Shin Bokura no Taiyou: Gyakushuu no Sabata - { "U33J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false }, + { "U33J", GBA_SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, GBA_IDLE_LOOP_NONE }, // Stuart Little 2 - { "ASLE", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false }, - { "ASLF", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false }, + { "ASLE", GBA_SAVEDATA_FORCE_NONE, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "ASLF", GBA_SAVEDATA_FORCE_NONE, HW_NONE, GBA_IDLE_LOOP_NONE }, // Super Mario Advance 2 - { "AA2J", SAVEDATA_EEPROM, HW_NONE, 0x800052E, false }, - { "AA2E", SAVEDATA_EEPROM, HW_NONE, 0x800052E, false }, - { "AA2P", SAVEDATA_AUTODETECT, HW_NONE, 0x800052E, false }, + { "AA2J", GBA_SAVEDATA_EEPROM, HW_NONE, 0x800052E }, + { "AA2E", GBA_SAVEDATA_EEPROM, HW_NONE, 0x800052E }, + { "AA2P", GBA_SAVEDATA_AUTODETECT, HW_NONE, 0x800052E }, // Super Mario Advance 3 - { "A3AJ", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C, false }, - { "A3AE", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C, false }, - { "A3AP", SAVEDATA_EEPROM, HW_NONE, 0x8002B9C, false }, + { "A3AJ", GBA_SAVEDATA_EEPROM, HW_NONE, 0x8002B9C }, + { "A3AE", GBA_SAVEDATA_EEPROM, HW_NONE, 0x8002B9C }, + { "A3AP", GBA_SAVEDATA_EEPROM, HW_NONE, 0x8002B9C }, // Super Mario Advance 4 - { "AX4J", SAVEDATA_FLASH1M, HW_NONE, 0x800072A, false }, - { "AX4E", SAVEDATA_FLASH1M, HW_NONE, 0x800072A, false }, - { "AX4P", SAVEDATA_FLASH1M, HW_NONE, 0x800072A, false }, + { "AX4J", GBA_SAVEDATA_FLASH1M, HW_NONE, 0x800072A }, + { "AX4E", GBA_SAVEDATA_FLASH1M, HW_NONE, 0x800072A }, + { "AX4P", GBA_SAVEDATA_FLASH1M, HW_NONE, 0x800072A }, // Super Monkey Ball Jr. - { "ALUE", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "ALUP", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, + { "ALUE", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, + { "ALUP", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, // Top Gun - Combat Zones - { "A2YE", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false }, + { "A2YE", GBA_SAVEDATA_FORCE_NONE, HW_NONE, GBA_IDLE_LOOP_NONE }, // Ueki no Housoku - Jingi Sakuretsu! Nouryokusha Battle - { "BUHJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, + { "BUHJ", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE }, // Wario Ware Twisted - { "RZWJ", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE, false }, - { "RZWE", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE, false }, - { "RZWP", SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, IDLE_LOOP_NONE, false }, + { "RZWJ", GBA_SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, GBA_IDLE_LOOP_NONE }, + { "RZWE", GBA_SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, GBA_IDLE_LOOP_NONE }, + { "RZWP", GBA_SAVEDATA_SRAM, HW_RUMBLE | HW_GYRO, GBA_IDLE_LOOP_NONE }, // Yoshi's Universal Gravitation - { "KYGJ", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false }, - { "KYGE", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false }, - { "KYGP", SAVEDATA_EEPROM, HW_TILT, IDLE_LOOP_NONE, false }, + { "KYGJ", GBA_SAVEDATA_EEPROM, HW_TILT, GBA_IDLE_LOOP_NONE }, + { "KYGE", GBA_SAVEDATA_EEPROM, HW_TILT, GBA_IDLE_LOOP_NONE }, + { "KYGP", GBA_SAVEDATA_EEPROM, HW_TILT, GBA_IDLE_LOOP_NONE }, // Aging cartridge - { "TCHK", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, + { "TCHK", GBA_SAVEDATA_EEPROM, HW_NONE, GBA_IDLE_LOOP_NONE, }, - // Famicom Mini series 3 (FDS), some aren't mirrored (22 - 28) - // See https://forum.no-intro.org/viewtopic.php?f=2&t=4221 for discussion - { "FNMJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "FMRJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "FPTJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "FLBJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "FFMJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "FTKJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - { "FTUJ", SAVEDATA_EEPROM, HW_NONE, IDLE_LOOP_NONE, false }, - - { { 0, 0, 0, 0 }, 0, 0, IDLE_LOOP_NONE, false } + { { 0, 0, 0, 0 }, 0, 0, GBA_IDLE_LOOP_NONE, false } }; bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOverride* override) { - override->savetype = SAVEDATA_AUTODETECT; + override->savetype = GBA_SAVEDATA_AUTODETECT; override->hardware = HW_NONE; - override->idleLoop = IDLE_LOOP_NONE; - override->mirroring = false; + override->idleLoop = GBA_IDLE_LOOP_NONE; override->vbaBugCompat = false; bool found = false; @@ -230,7 +222,7 @@ bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOver } if (!found && override->id[0] == 'F') { // Classic NES Series - override->savetype = SAVEDATA_EEPROM; + override->savetype = GBA_SAVEDATA_EEPROM; found = true; } @@ -244,25 +236,25 @@ bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOver if (savetype) { if (strcasecmp(savetype, "SRAM") == 0) { found = true; - override->savetype = SAVEDATA_SRAM; + override->savetype = GBA_SAVEDATA_SRAM; } else if (strcasecmp(savetype, "SRAM512") == 0) { found = true; - override->savetype = SAVEDATA_SRAM512; + override->savetype = GBA_SAVEDATA_SRAM512; } else if (strcasecmp(savetype, "EEPROM") == 0) { found = true; - override->savetype = SAVEDATA_EEPROM; + override->savetype = GBA_SAVEDATA_EEPROM; } else if (strcasecmp(savetype, "EEPROM512") == 0) { found = true; - override->savetype = SAVEDATA_EEPROM512; + override->savetype = GBA_SAVEDATA_EEPROM512; } else if (strcasecmp(savetype, "FLASH512") == 0) { found = true; - override->savetype = SAVEDATA_FLASH512; + override->savetype = GBA_SAVEDATA_FLASH512; } else if (strcasecmp(savetype, "FLASH1M") == 0) { found = true; - override->savetype = SAVEDATA_FLASH1M; + override->savetype = GBA_SAVEDATA_FLASH1M; } else if (strcasecmp(savetype, "NONE") == 0) { found = true; - override->savetype = SAVEDATA_FORCE_NONE; + override->savetype = GBA_SAVEDATA_FORCE_NONE; } } @@ -292,28 +284,28 @@ void GBAOverrideSave(struct Configuration* config, const struct GBACartridgeOver snprintf(sectionName, sizeof(sectionName), "override.%c%c%c%c", override->id[0], override->id[1], override->id[2], override->id[3]); const char* savetype = 0; switch (override->savetype) { - case SAVEDATA_SRAM: + case GBA_SAVEDATA_SRAM: savetype = "SRAM"; break; - case SAVEDATA_SRAM512: + case GBA_SAVEDATA_SRAM512: savetype = "SRAM512"; break; - case SAVEDATA_EEPROM: + case GBA_SAVEDATA_EEPROM: savetype = "EEPROM"; break; - case SAVEDATA_EEPROM512: + case GBA_SAVEDATA_EEPROM512: savetype = "EEPROM512"; break; - case SAVEDATA_FLASH512: + case GBA_SAVEDATA_FLASH512: savetype = "FLASH512"; break; - case SAVEDATA_FLASH1M: + case GBA_SAVEDATA_FLASH1M: savetype = "FLASH1M"; break; - case SAVEDATA_FORCE_NONE: + case GBA_SAVEDATA_FORCE_NONE: savetype = "NONE"; break; - case SAVEDATA_AUTODETECT: + case GBA_SAVEDATA_AUTODETECT: break; } ConfigurationSetValue(config, sectionName, "savetype", savetype); @@ -324,7 +316,7 @@ void GBAOverrideSave(struct Configuration* config, const struct GBACartridgeOver ConfigurationClearValue(config, sectionName, "hardware"); } - if (override->idleLoop != IDLE_LOOP_NONE) { + if (override->idleLoop != GBA_IDLE_LOOP_NONE) { ConfigurationSetUIntValue(config, sectionName, "idleLoop", override->idleLoop); } else { ConfigurationClearValue(config, sectionName, "idleLoop"); @@ -332,7 +324,7 @@ void GBAOverrideSave(struct Configuration* config, const struct GBACartridgeOver } void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* override) { - if (override->savetype != SAVEDATA_AUTODETECT) { + if (override->savetype != GBA_SAVEDATA_AUTODETECT) { GBASavedataForceType(&gba->memory.savedata, override->savetype); } @@ -373,7 +365,7 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* overri } } - if (override->idleLoop != IDLE_LOOP_NONE) { + if (override->idleLoop != GBA_IDLE_LOOP_NONE) { gba->idleLoop = override->idleLoop; if (gba->idleOptimization == IDLE_LOOP_DETECT) { gba->idleOptimization = IDLE_LOOP_REMOVE; @@ -382,7 +374,7 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* overri } void GBAOverrideApplyDefaults(struct GBA* gba, const struct Configuration* overrides) { - struct GBACartridgeOverride override = { .idleLoop = IDLE_LOOP_NONE }; + struct GBACartridgeOverride override = { .idleLoop = GBA_IDLE_LOOP_NONE }; const struct GBACartridge* cart = (const struct GBACartridge*) gba->memory.rom; if (cart) { memcpy(override.id, &cart->id, sizeof(override.id)); @@ -426,7 +418,7 @@ void GBAOverrideApplyDefaults(struct GBA* gba, const struct Configuration* overr if (isPokemon && !isKnownPokemon) { // Enable FLASH1M and RTC on Pokémon ROM hacks - override.savetype = SAVEDATA_FLASH1M; + override.savetype = GBA_SAVEDATA_FLASH1M; override.hardware = HW_RTC; override.vbaBugCompat = true; GBAOverrideApply(gba, &override); diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index c80da2bcb..24fb092c7 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -13,9 +13,14 @@ #include #include +#define OPENGL_MAGIC 0x6E726C67 + static void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer); static void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer); static void GBAVideoGLRendererReset(struct GBAVideoRenderer* renderer); +static uint32_t GBAVideoGLRendererId(const struct GBAVideoRenderer* renderer); +static bool GBAVideoGLRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size); +static void GBAVideoGLRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size); static void GBAVideoGLRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address); static void GBAVideoGLRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam); static void GBAVideoGLRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value); @@ -486,6 +491,8 @@ static const struct GBAVideoGLUniform _uniformsWindow[] = { { "flags", GBA_GL_WIN_FLAGS, }, { "win0", GBA_GL_WIN_WIN0, }, { "win1", GBA_GL_WIN_WIN1, }, + { "circle0", GBA_GL_WIN_CIRCLE0, }, + { "circle1", GBA_GL_WIN_CIRCLE1, }, { 0 } }; @@ -496,6 +503,8 @@ static const char* const _renderWindow = "uniform ivec3 flags;\n" "uniform ivec4 win0[160];\n" "uniform ivec4 win1[160];\n" + "uniform vec3 circle0;\n" + "uniform vec3 circle1;\n" "OUT(0) out ivec4 window;\n" "bool crop(vec4 windowParams) {\n" @@ -529,13 +538,20 @@ static const char* const _renderWindow = " return vec4(mix(bottom.xy, top.xy, fract(texCoord.y)), top.zw);\n" "}\n" + "bool test(vec3 circle, vec4 top, vec4 bottom) {\n" + " if (circle.z > 0) {\n" + " return distance(circle.xy, texCoord.xy) <= circle.z;\n" + " }\n" + " return crop(interpolate(top, bottom));\n" + "}\n" + "void main() {\n" " ivec4 windowFlags = ivec4(flags.z, blend, 0);\n" " int top = int(texCoord.y);\n" " int bottom = max(top - 1, 0);\n" - " if ((dispcnt & 0x20) != 0 && crop(interpolate(vec4(win0[top]), vec4(win0[bottom])))) { \n" + " if ((dispcnt & 0x20) != 0 && test(circle0, vec4(win0[top]), vec4(win0[bottom]))) {\n" " windowFlags.x = flags.x;\n" - " } else if ((dispcnt & 0x40) != 0 && crop(interpolate(vec4(win1[top]), vec4(win1[bottom])))) {\n" + " } else if ((dispcnt & 0x40) != 0 && test(circle1, vec4(win1[top]), vec4(win1[bottom]))) {\n" " windowFlags.x = flags.y;\n" " }\n" " window = windowFlags;\n" @@ -645,9 +661,13 @@ static const GLint _vertices[] = { }; void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer) { + memset(renderer, 0, sizeof(*renderer)); renderer->d.init = GBAVideoGLRendererInit; renderer->d.reset = GBAVideoGLRendererReset; renderer->d.deinit = GBAVideoGLRendererDeinit; + renderer->d.rendererId = GBAVideoGLRendererId; + renderer->d.loadState = GBAVideoGLRendererLoadState; + renderer->d.saveState = GBAVideoGLRendererSaveState; renderer->d.writeVideoRegister = GBAVideoGLRendererWriteVideoRegister; renderer->d.writeVRAM = GBAVideoGLRendererWriteVRAM; renderer->d.writeOAM = GBAVideoGLRendererWriteOAM; @@ -942,6 +962,26 @@ void GBAVideoGLRendererReset(struct GBAVideoRenderer* renderer) { } } +static uint32_t GBAVideoGLRendererId(const struct GBAVideoRenderer* renderer) { + UNUSED(renderer); + return OPENGL_MAGIC; +} + +static bool GBAVideoGLRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size) { + UNUSED(renderer); + UNUSED(state); + UNUSED(size); + // TODO + return false; +} + +static void GBAVideoGLRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size) { + UNUSED(renderer); + *state = NULL; + *size = 0; + // TODO +} + void GBAVideoGLRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) { struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer; if (renderer->cache) { @@ -1924,6 +1964,127 @@ void GBAVideoGLRendererDrawBackgroundMode5(struct GBAVideoGLRenderer* renderer, glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 }); } +static void _detectCircle(struct GBAVideoGLRenderer* renderer, int y, int window) { + int lastStart = 0; + int lastEnd = 0; + + int startX = 0; + int endX = 0; + + int firstY = -1; + float centerX; + float centerY = -1; + float radius = 0; + bool invalid = false; + + int i; + for (i = renderer->firstY; i <= y; ++i) { + lastStart = startX; + lastEnd = endX; + startX = renderer->winNHistory[window][i * 4]; + endX = renderer->winNHistory[window][i * 4 + 1]; + int startY = renderer->winNHistory[window][i * 4 + 2]; + int endY = renderer->winNHistory[window][i * 4 + 3]; + + if (startX == endX || i < startY || i >= endY) { + if (firstY >= 0) { + // The bottom edge of the circle + centerY = (firstY + i) / 2.f; + firstY = -1; + } + continue; + } + if (lastEnd - lastStart <= 0) { + continue; + } + + // The previous segment was non-zero + if (startX >= GBA_VIDEO_HORIZONTAL_PIXELS) { + invalid = true; + break; + } + + int startDiff = lastStart - startX; + int endDiff = endX - lastEnd; + // Make sure the slopes match, otherwise this isn't a circle + if (startDiff - endDiff < -1 || startDiff - endDiff > 1) { + invalid = true; + break; + } + + if (startX < lastStart) { + centerX = (startX + endX) / 2.f; + if (radius > 0) { + // We found two separate shapes, which the interpolation can't handle + invalid = true; + break; + } + } else if (startX > lastStart && radius <= 0) { + radius = (lastEnd - lastStart) / 2.f; + } + + if (firstY < 0 && i - 1 >= startY && i - 1 < endY) { + firstY = i - 1; + } + } + + if (radius <= 0) { + invalid = true; + } + if (centerY < 0) { + invalid = true; + } + + // Check validity + for (i = renderer->firstY; i <= y && !invalid; ++i) { + int startX = renderer->winNHistory[window][i * 4]; + int endX = renderer->winNHistory[window][i * 4 + 1]; + int startY = renderer->winNHistory[window][i * 4 + 2]; + int endY = renderer->winNHistory[window][i * 4 + 3]; + + bool xActive = startX < endX; + bool yActive = i >= startY && i < endY; + + if (xActive && yActive) { + // Real window would be active, make sure simulated window would too + if (centerY - i > radius) { + // y is above the radius + invalid = true; + break; + } + if (i - centerY > radius) { + // y is below the radius + invalid = true; + break; + } + + float cosine = fabsf(i - centerY); + float sine = sqrtf(radius * radius - cosine * cosine); + if (fabsf(centerX - sine - startX) <= 1 && fabsf(centerX + sine - endX) <= 1) { + continue; + } + + if (radius >= cosine + 1) { + sine = sqrtf(radius * radius - (cosine + 1) * (cosine + 1)); + if (fabsf(centerX - sine - startX) <= 1 && fabsf(centerX + sine - endX) <= 1) { + continue; + } + } + // y is active on the wrong parts of the scanline + invalid = true; + } else if (centerY - i < radius && i - centerY < radius) { + // Real window would be inactive, make sure simulated window would too + invalid = true; + } + } + + if (invalid) { + glUniform3f(renderer->windowShader.uniforms[GBA_GL_WIN_CIRCLE0 + window], 0, 0, 0); + } else { + glUniform3f(renderer->windowShader.uniforms[GBA_GL_WIN_CIRCLE0 + window], centerX, centerY, radius - 0.499); + } +} + void GBAVideoGLRendererDrawWindow(struct GBAVideoGLRenderer* renderer, int y) { const struct GBAVideoGLShader* shader = &renderer->windowShader; const GLuint* uniforms = shader->uniforms; @@ -1950,6 +2111,8 @@ void GBAVideoGLRendererDrawWindow(struct GBAVideoGLRenderer* renderer, int y) { glUniform3i(uniforms[GBA_GL_WIN_FLAGS], renderer->winN[0].control, renderer->winN[1].control, renderer->winout); glUniform4iv(uniforms[GBA_GL_WIN_WIN0], GBA_VIDEO_VERTICAL_PIXELS, renderer->winNHistory[0]); glUniform4iv(uniforms[GBA_GL_WIN_WIN1], GBA_VIDEO_VERTICAL_PIXELS, renderer->winNHistory[1]); + _detectCircle(renderer, y, 0); + _detectCircle(renderer, y, 1); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); break; } diff --git a/src/gba/renderers/software-bg.c b/src/gba/renderers/software-bg.c index 8c48b41ad..6fa199b0d 100644 --- a/src/gba/renderers/software-bg.c +++ b/src/gba/renderers/software-bg.c @@ -127,7 +127,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode3(struct GBAVideoSoftwareRenderer } uint32_t current = *pixel; - if (!objwinSlowPath || (!(current & FLAG_OBJWIN)) != objwinOnly) { + if (!objwinSlowPath || (!(current & FLAG_OBJWIN)) != background->objwinOnly) { unsigned mergedFlags = flags; if (current & FLAG_OBJWIN) { mergedFlags = objwinFlags; @@ -172,8 +172,8 @@ void GBAVideoSoftwareRendererDrawBackgroundMode4(struct GBAVideoSoftwareRenderer if (color && IS_WRITABLE(current)) { if (!objwinSlowPath) { _compositeBlendNoObjwin(renderer, pixel, palette[color] | flags, current); - } else if (objwinForceEnable || (!(current & FLAG_OBJWIN)) == objwinOnly) { - color_t* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette; + } else if (background->objwinForceEnable || (!(current & FLAG_OBJWIN)) == background->objwinOnly) { + mColor* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette; unsigned mergedFlags = flags; if (current & FLAG_OBJWIN) { mergedFlags = objwinFlags; @@ -211,7 +211,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode5(struct GBAVideoSoftwareRenderer } uint32_t current = *pixel; - if (!objwinSlowPath || (!(current & FLAG_OBJWIN)) != objwinOnly) { + if (!objwinSlowPath || (!(current & FLAG_OBJWIN)) != background->objwinOnly) { unsigned mergedFlags = flags; if (current & FLAG_OBJWIN) { mergedFlags = objwinFlags; diff --git a/src/gba/renderers/software-mode0.c b/src/gba/renderers/software-mode0.c index aa1d63924..4aada17b0 100644 --- a/src/gba/renderers/software-mode0.c +++ b/src/gba/renderers/software-mode0.c @@ -512,7 +512,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer uint32_t screenBase; uint32_t charBase; - color_t* palette = renderer->normalPalette; + mColor* palette = renderer->normalPalette; if (renderer->d.highlightAmount && background->highlight) { palette = renderer->highlightPalette; } diff --git a/src/gba/renderers/software-obj.c b/src/gba/renderers/software-obj.c index 3b44d86a5..4152685c6 100644 --- a/src/gba/renderers/software-obj.c +++ b/src/gba/renderers/software-obj.c @@ -182,11 +182,11 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re } } - color_t* palette = &renderer->normalPalette[0x100]; + mColor* palette = &renderer->normalPalette[0x100]; if (renderer->d.highlightAmount && renderer->d.highlightOBJ[index]) { palette = &renderer->highlightPalette[0x100]; } - color_t* objwinPalette = palette; + mColor* objwinPalette = palette; if (variant) { palette = &renderer->variantPalette[0x100]; diff --git a/src/gba/renderers/software-private.h b/src/gba/renderers/software-private.h index ec8ef4175..4f7e9f8d6 100644 --- a/src/gba/renderers/software-private.h +++ b/src/gba/renderers/software-private.h @@ -85,7 +85,7 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re } #define COMPOSITE_16_OBJWIN(BLEND, IDX) \ - if (objwinForceEnable || (!(current & FLAG_OBJWIN)) == objwinOnly) { \ + if (background->objwinForceEnable || (!(current & FLAG_OBJWIN)) == background->objwinOnly) { \ unsigned color; \ unsigned mergedFlags = flags; \ if (current & FLAG_OBJWIN) { \ @@ -111,7 +111,7 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re } #define COMPOSITE_256_OBJWIN(BLEND, IDX) \ - if (objwinForceEnable || (!(current & FLAG_OBJWIN)) == objwinOnly) { \ + if (background->objwinForceEnable || (!(current & FLAG_OBJWIN)) == background->objwinOnly) { \ unsigned color; \ unsigned mergedFlags = flags; \ if (current & FLAG_OBJWIN) { \ @@ -155,10 +155,7 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re // TODO: Remove UNUSEDs after implementing OBJWIN for modes 3 - 5 #define PREPARE_OBJWIN \ int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt); \ - int objwinOnly = 0; \ - int objwinForceEnable = 0; \ - UNUSED(objwinForceEnable); \ - color_t* objwinPalette = renderer->normalPalette; \ + mColor* objwinPalette = renderer->normalPalette; \ if (renderer->d.highlightAmount && background->highlight) { \ objwinPalette = renderer->highlightPalette; \ } \ @@ -171,28 +168,6 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re palette = renderer->highlightVariantPalette; \ } \ } \ - switch (background->index) { \ - case 0: \ - objwinForceEnable = GBAWindowControlIsBg0Enable(renderer->objwin.packed) && \ - GBAWindowControlIsBg0Enable(renderer->currentWindow.packed); \ - objwinOnly = !GBAWindowControlIsBg0Enable(renderer->objwin.packed); \ - break; \ - case 1: \ - objwinForceEnable = GBAWindowControlIsBg1Enable(renderer->objwin.packed) && \ - GBAWindowControlIsBg1Enable(renderer->currentWindow.packed); \ - objwinOnly = !GBAWindowControlIsBg1Enable(renderer->objwin.packed); \ - break; \ - case 2: \ - objwinForceEnable = GBAWindowControlIsBg2Enable(renderer->objwin.packed) && \ - GBAWindowControlIsBg2Enable(renderer->currentWindow.packed); \ - objwinOnly = !GBAWindowControlIsBg2Enable(renderer->objwin.packed); \ - break; \ - case 3: \ - objwinForceEnable = GBAWindowControlIsBg3Enable(renderer->objwin.packed) && \ - GBAWindowControlIsBg3Enable(renderer->currentWindow.packed); \ - objwinOnly = !GBAWindowControlIsBg3Enable(renderer->objwin.packed); \ - break; \ - } \ } #define BACKGROUND_BITMAP_INIT \ @@ -219,7 +194,7 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re uint32_t flags = background->flags; \ uint32_t objwinFlags = background->objwinFlags; \ bool variant = background->variant; \ - color_t* palette = renderer->normalPalette; \ + mColor* palette = renderer->normalPalette; \ if (renderer->d.highlightAmount && background->highlight) { \ palette = renderer->highlightPalette; \ } \ diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index 7b9c65623..83550bcfa 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -14,10 +14,14 @@ #define DIRTY_SCANLINE(R, Y) R->scanlineDirty[Y >> 5] |= (1U << (Y & 0x1F)) #define CLEAN_SCANLINE(R, Y) R->scanlineDirty[Y >> 5] &= ~(1U << (Y & 0x1F)) +#define SOFTWARE_MAGIC 0x6E727773 static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer); static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer); static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer); +static uint32_t GBAVideoSoftwareRendererId(const struct GBAVideoRenderer* renderer); +static bool GBAVideoSoftwareRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size); +static void GBAVideoSoftwareRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size); static void GBAVideoSoftwareRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address); static void GBAVideoSoftwareRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam); static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value); @@ -35,20 +39,25 @@ static void GBAVideoSoftwareRendererWriteBGY_LO(struct GBAVideoSoftwareBackgroun static void GBAVideoSoftwareRendererWriteBGY_HI(struct GBAVideoSoftwareBackground* bg, uint16_t value); static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer* renderer, uint16_t value); -static void GBAVideoSoftwareRendererPreprocessBuffer(struct GBAVideoSoftwareRenderer* renderer, int y); +static void GBAVideoSoftwareRendererStepWindow(struct GBAVideoSoftwareRenderer* renderer, int y); +static void GBAVideoSoftwareRendererPreprocessBuffer(struct GBAVideoSoftwareRenderer* renderer); static void GBAVideoSoftwareRendererPostprocessBuffer(struct GBAVideoSoftwareRenderer* renderer); static int GBAVideoSoftwareRendererPreprocessSpriteLayer(struct GBAVideoSoftwareRenderer* renderer, int y); static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer); static void _updateFlags(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* bg); -static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win, int y); +static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win); static void _breakWindowInner(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win); void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) { + memset(renderer, 0, sizeof(*renderer)); renderer->d.init = GBAVideoSoftwareRendererInit; renderer->d.reset = GBAVideoSoftwareRendererReset; renderer->d.deinit = GBAVideoSoftwareRendererDeinit; + renderer->d.rendererId = GBAVideoSoftwareRendererId; + renderer->d.loadState = GBAVideoSoftwareRendererLoadState; + renderer->d.saveState = GBAVideoSoftwareRendererSaveState; renderer->d.writeVideoRegister = GBAVideoSoftwareRendererWriteVideoRegister; renderer->d.writeVRAM = GBAVideoSoftwareRendererWriteVRAM; renderer->d.writeOAM = GBAVideoSoftwareRendererWriteOAM; @@ -78,7 +87,7 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) { renderer->d.highlightColor = M_COLOR_WHITE; renderer->d.highlightAmount = 0; - renderer->temporaryBuffer = 0; + renderer->temporaryBuffer = NULL; } static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer) { @@ -88,7 +97,7 @@ static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer) { int y; for (y = 0; y < GBA_VIDEO_VERTICAL_PIXELS; ++y) { - color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y]; + mColor* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y]; int x; for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; ++x) { row[x] = M_COLOR_WHITE; @@ -154,6 +163,26 @@ static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer) { UNUSED(softwareRenderer); } +static uint32_t GBAVideoSoftwareRendererId(const struct GBAVideoRenderer* renderer) { + UNUSED(renderer); + return SOFTWARE_MAGIC; +} + +static bool GBAVideoSoftwareRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size) { + UNUSED(renderer); + UNUSED(state); + UNUSED(size); + // TODO + return false; +} + +static void GBAVideoSoftwareRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size) { + UNUSED(renderer); + *state = NULL; + *size = 0; + // TODO +} + static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; if (renderer->cache) { @@ -343,28 +372,10 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender case GBA_REG_WIN0V: softwareRenderer->winN[0].v.end = value; softwareRenderer->winN[0].v.start = value >> 8; - if (softwareRenderer->winN[0].v.start > GBA_VIDEO_VERTICAL_PIXELS && softwareRenderer->winN[0].v.start > softwareRenderer->winN[0].v.end) { - softwareRenderer->winN[0].v.start = 0; - } - if (softwareRenderer->winN[0].v.end > GBA_VIDEO_VERTICAL_PIXELS) { - softwareRenderer->winN[0].v.end = GBA_VIDEO_VERTICAL_PIXELS; - if (softwareRenderer->winN[0].v.start > GBA_VIDEO_VERTICAL_PIXELS) { - softwareRenderer->winN[0].v.start = GBA_VIDEO_VERTICAL_PIXELS; - } - } break; case GBA_REG_WIN1V: softwareRenderer->winN[1].v.end = value; softwareRenderer->winN[1].v.start = value >> 8; - if (softwareRenderer->winN[1].v.start > GBA_VIDEO_VERTICAL_PIXELS && softwareRenderer->winN[1].v.start > softwareRenderer->winN[1].v.end) { - softwareRenderer->winN[1].v.start = 0; - } - if (softwareRenderer->winN[1].v.end > GBA_VIDEO_VERTICAL_PIXELS) { - softwareRenderer->winN[1].v.end = GBA_VIDEO_VERTICAL_PIXELS; - if (softwareRenderer->winN[1].v.start > GBA_VIDEO_VERTICAL_PIXELS) { - softwareRenderer->winN[1].v.start = GBA_VIDEO_VERTICAL_PIXELS; - } - } break; case GBA_REG_WININ: value &= 0x3F3F; @@ -411,7 +422,7 @@ static void GBAVideoSoftwareRendererWriteOAM(struct GBAVideoRenderer* renderer, static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; - color_t color = mColorFrom555(value); + mColor color = mColorFrom555(value); softwareRenderer->normalPalette[address >> 1] = color; if (softwareRenderer->blendEffect == BLEND_BRIGHTEN) { softwareRenderer->variantPalette[address >> 1] = _brighten(color, softwareRenderer->bldy); @@ -432,17 +443,7 @@ static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* render memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty)); } -static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win, int y) { - if (win->v.end >= win->v.start) { - if (y >= win->v.end + win->offsetY) { - return; - } - if (y < win->v.start + win->offsetY) { - return; - } - } else if (y >= win->v.end + win->offsetY && y < win->v.start + win->offsetY) { - return; - } +static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win) { if (win->h.end > GBA_VIDEO_HORIZONTAL_PIXELS || win->h.end < win->h.start) { struct WindowN splits[2] = { *win, *win }; splits[0].h.start = 0; @@ -505,6 +506,58 @@ static void _breakWindowInner(struct GBAVideoSoftwareRenderer* softwareRenderer, #endif } +static void GBAVideoSoftwareRendererPrepareWindow(struct GBAVideoSoftwareRenderer* renderer) { + int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt); + if (objwinSlowPath) { + renderer->bg[0].objwinForceEnable = GBAWindowControlIsBg0Enable(renderer->objwin.packed) && + GBAWindowControlIsBg0Enable(renderer->currentWindow.packed); + renderer->bg[0].objwinOnly = !GBAWindowControlIsBg0Enable(renderer->objwin.packed); + renderer->bg[1].objwinForceEnable = GBAWindowControlIsBg1Enable(renderer->objwin.packed) && + GBAWindowControlIsBg1Enable(renderer->currentWindow.packed); + renderer->bg[1].objwinOnly = !GBAWindowControlIsBg1Enable(renderer->objwin.packed); + renderer->bg[2].objwinForceEnable = GBAWindowControlIsBg2Enable(renderer->objwin.packed) && + GBAWindowControlIsBg2Enable(renderer->currentWindow.packed); + renderer->bg[2].objwinOnly = !GBAWindowControlIsBg2Enable(renderer->objwin.packed); + renderer->bg[3].objwinForceEnable = GBAWindowControlIsBg3Enable(renderer->objwin.packed) && + GBAWindowControlIsBg3Enable(renderer->currentWindow.packed); + renderer->bg[3].objwinOnly = !GBAWindowControlIsBg3Enable(renderer->objwin.packed); + } + + switch (GBARegisterDISPCNTGetMode(renderer->dispcnt)) { + case 0: + if (renderer->bg[0].enabled == ENABLED_MAX) { + _updateFlags(renderer, &renderer->bg[0]); + } + if (renderer->bg[1].enabled == ENABLED_MAX) { + _updateFlags(renderer, &renderer->bg[1]); + } + // Fall through + case 2: + if (renderer->bg[3].enabled == ENABLED_MAX) { + _updateFlags(renderer, &renderer->bg[3]); + } + // Fall through + case 3: + case 4: + case 5: + if (renderer->bg[2].enabled == ENABLED_MAX) { + _updateFlags(renderer, &renderer->bg[2]); + } + break; + case 1: + if (renderer->bg[0].enabled == ENABLED_MAX) { + _updateFlags(renderer, &renderer->bg[0]); + } + if (renderer->bg[1].enabled == ENABLED_MAX) { + _updateFlags(renderer, &renderer->bg[1]); + } + if (renderer->bg[2].enabled == ENABLED_MAX) { + _updateFlags(renderer, &renderer->bg[2]); + } + break; + } +} + static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; @@ -533,6 +586,14 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render softwareRenderer->cache[y].scale[1][0] = softwareRenderer->bg[3].sx; softwareRenderer->cache[y].scale[1][1] = softwareRenderer->bg[3].sy; + GBAVideoSoftwareRendererStepWindow(softwareRenderer, y); + if (softwareRenderer->cache[y].windowOn[0] != softwareRenderer->winN[0].on || + softwareRenderer->cache[y].windowOn[1] != softwareRenderer->winN[1].on) { + dirty = true; + } + softwareRenderer->cache[y].windowOn[0] = softwareRenderer->winN[0].on; + softwareRenderer->cache[y].windowOn[1] = softwareRenderer->winN[1].on; + if (!dirty) { if (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt) != 0) { if (softwareRenderer->bg[2].enabled == ENABLED_MAX) { @@ -549,7 +610,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render CLEAN_SCANLINE(softwareRenderer, y); - color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y]; + mColor* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y]; if (GBARegisterDISPCNTIsForcedBlank(softwareRenderer->dispcnt)) { int x; for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; ++x) { @@ -558,7 +619,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render return; } - GBAVideoSoftwareRendererPreprocessBuffer(softwareRenderer, y); + GBAVideoSoftwareRendererPreprocessBuffer(softwareRenderer); softwareRenderer->spriteCyclesRemaining = GBARegisterDISPCNTIsHblankIntervalFree(softwareRenderer->dispcnt) ? OBJ_HBLANK_FREE_LENGTH : OBJ_LENGTH; int spriteLayers = GBAVideoSoftwareRendererPreprocessSpriteLayer(softwareRenderer, y); @@ -569,40 +630,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render softwareRenderer->start = softwareRenderer->end; softwareRenderer->end = softwareRenderer->windows[w].endX; softwareRenderer->currentWindow = softwareRenderer->windows[w].control; - switch (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt)) { - case 0: - if (softwareRenderer->bg[0].enabled == ENABLED_MAX) { - _updateFlags(softwareRenderer, &softwareRenderer->bg[0]); - } - if (softwareRenderer->bg[1].enabled == ENABLED_MAX) { - _updateFlags(softwareRenderer, &softwareRenderer->bg[1]); - } - // Fall through - case 2: - if (softwareRenderer->bg[3].enabled == ENABLED_MAX) { - _updateFlags(softwareRenderer, &softwareRenderer->bg[3]); - } - // Fall through - case 3: - case 4: - case 5: - if (softwareRenderer->bg[2].enabled == ENABLED_MAX) { - _updateFlags(softwareRenderer, &softwareRenderer->bg[2]); - } - break; - case 1: - if (softwareRenderer->bg[0].enabled == ENABLED_MAX) { - _updateFlags(softwareRenderer, &softwareRenderer->bg[0]); - } - if (softwareRenderer->bg[1].enabled == ENABLED_MAX) { - _updateFlags(softwareRenderer, &softwareRenderer->bg[1]); - } - if (softwareRenderer->bg[2].enabled == ENABLED_MAX) { - _updateFlags(softwareRenderer, &softwareRenderer->bg[2]); - } - break; - } - + GBAVideoSoftwareRendererPrepareWindow(softwareRenderer); for (priority = 0; priority < 4; ++priority) { if (spriteLayers & (1 << priority)) { GBAVideoSoftwareRendererPostprocessSprite(softwareRenderer, priority); @@ -728,6 +756,20 @@ static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* rendere if (softwareRenderer->bg[3].enabled > 0) { softwareRenderer->bg[3].enabled = ENABLED_MAX; } + + int i; + for (i = 0; i < 2; ++i) { + struct WindowN* win = &softwareRenderer->winN[i]; + if (win->v.end >= GBA_VIDEO_VERTICAL_PIXELS && win->v.end < VIDEO_VERTICAL_TOTAL_PIXELS) { + win->on = false; + } + + if (win->v.start >= GBA_VIDEO_VERTICAL_PIXELS && + win->v.start < VIDEO_VERTICAL_TOTAL_PIXELS && + win->v.start > win->v.end) { + win->on = true; + } + } } static void GBAVideoSoftwareRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) { @@ -739,7 +781,7 @@ static void GBAVideoSoftwareRendererGetPixels(struct GBAVideoRenderer* renderer, static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; - const color_t* colorPixels = pixels; + const mColor* colorPixels = pixels; unsigned i; for (i = 0; i < GBA_VIDEO_VERTICAL_PIXELS; ++i) { memmove(&softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * i], &colorPixels[stride * i], GBA_VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); @@ -836,7 +878,20 @@ static void GBAVideoSoftwareRendererWriteBLDCNT(struct GBAVideoSoftwareRenderer* } } -void GBAVideoSoftwareRendererPreprocessBuffer(struct GBAVideoSoftwareRenderer* softwareRenderer, int y) { +void GBAVideoSoftwareRendererStepWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, int y) { + int i; + for (i = 0; i < 2; ++i) { + struct WindowN* win = &softwareRenderer->winN[i]; + if (y == win->v.start + win->offsetY) { + win->on = true; + } + if (y == win->v.end + win->offsetY) { + win->on = false; + } + } +} + +void GBAVideoSoftwareRendererPreprocessBuffer(struct GBAVideoSoftwareRenderer* softwareRenderer) { int x; for (x = 0; x < GBA_VIDEO_HORIZONTAL_PIXELS; x += 4) { softwareRenderer->spriteLayer[x] = FLAG_UNWRITTEN; @@ -849,11 +904,11 @@ void GBAVideoSoftwareRendererPreprocessBuffer(struct GBAVideoSoftwareRenderer* s softwareRenderer->nWindows = 1; if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) || GBARegisterDISPCNTIsObjwinEnable(softwareRenderer->dispcnt)) { softwareRenderer->windows[0].control = softwareRenderer->winout; - if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) && !softwareRenderer->d.disableWIN[1]) { - _breakWindow(softwareRenderer, &softwareRenderer->winN[1], y); + if (GBARegisterDISPCNTIsWin1Enable(softwareRenderer->dispcnt) && !softwareRenderer->d.disableWIN[1] && softwareRenderer->winN[1].on) { + _breakWindow(softwareRenderer, &softwareRenderer->winN[1]); } - if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) && !softwareRenderer->d.disableWIN[0]) { - _breakWindow(softwareRenderer, &softwareRenderer->winN[0], y); + if (GBARegisterDISPCNTIsWin0Enable(softwareRenderer->dispcnt) && !softwareRenderer->d.disableWIN[0] && softwareRenderer->winN[0].on) { + _breakWindow(softwareRenderer, &softwareRenderer->winN[0]); } } else { softwareRenderer->windows[0].control.packed = 0xFF; diff --git a/src/gba/savedata.c b/src/gba/savedata.c index 512af02c9..11be3e0ab 100644 --- a/src/gba/savedata.c +++ b/src/gba/savedata.c @@ -44,7 +44,7 @@ static void _ashesToAshes(struct mTiming* timing, void* user, uint32_t cyclesLat } void GBASavedataInit(struct GBASavedata* savedata, struct VFile* vf) { - savedata->type = SAVEDATA_AUTODETECT; + savedata->type = GBA_SAVEDATA_AUTODETECT; savedata->data = 0; savedata->command = EEPROM_COMMAND_NULL; savedata->flashState = FLASH_STATE_RAW; @@ -72,35 +72,35 @@ void GBASavedataDeinit(struct GBASavedata* savedata) { savedata->vf = NULL; } else { switch (savedata->type) { - case SAVEDATA_SRAM: + case GBA_SAVEDATA_SRAM: mappedMemoryFree(savedata->data, GBA_SIZE_SRAM); break; - case SAVEDATA_SRAM512: + case GBA_SAVEDATA_SRAM512: mappedMemoryFree(savedata->data, GBA_SIZE_SRAM512); break; - case SAVEDATA_FLASH512: + case GBA_SAVEDATA_FLASH512: mappedMemoryFree(savedata->data, GBA_SIZE_FLASH512); break; - case SAVEDATA_FLASH1M: + case GBA_SAVEDATA_FLASH1M: mappedMemoryFree(savedata->data, GBA_SIZE_FLASH1M); break; - case SAVEDATA_EEPROM: + case GBA_SAVEDATA_EEPROM: mappedMemoryFree(savedata->data, GBA_SIZE_EEPROM); break; - case SAVEDATA_EEPROM512: + case GBA_SAVEDATA_EEPROM512: mappedMemoryFree(savedata->data, GBA_SIZE_EEPROM512); break; - case SAVEDATA_FORCE_NONE: - case SAVEDATA_AUTODETECT: + case GBA_SAVEDATA_FORCE_NONE: + case GBA_SAVEDATA_AUTODETECT: break; } } savedata->data = 0; - savedata->type = SAVEDATA_AUTODETECT; + savedata->type = GBA_SAVEDATA_AUTODETECT; } void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback) { - enum SavedataType type = savedata->type; + enum GBASavedataType type = savedata->type; struct VFile* oldVf = savedata->vf; GBASavedataDeinit(savedata); if (oldVf && oldVf != savedata->realVf) { @@ -116,7 +116,7 @@ void GBASavedataUnmask(struct GBASavedata* savedata) { if (!savedata->realVf || savedata->vf == savedata->realVf) { return; } - enum SavedataType type = savedata->type; + enum GBASavedataType type = savedata->type; struct VFile* vf = savedata->vf; GBASavedataDeinit(savedata); savedata->vf = savedata->realVf; @@ -132,20 +132,20 @@ void GBASavedataUnmask(struct GBASavedata* savedata) { bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) { if (savedata->data) { switch (savedata->type) { - case SAVEDATA_SRAM: + case GBA_SAVEDATA_SRAM: return out->write(out, savedata->data, GBA_SIZE_SRAM) == GBA_SIZE_SRAM; - case SAVEDATA_SRAM512: + case GBA_SAVEDATA_SRAM512: return out->write(out, savedata->data, GBA_SIZE_SRAM512) == GBA_SIZE_SRAM512; - case SAVEDATA_FLASH512: + case GBA_SAVEDATA_FLASH512: return out->write(out, savedata->data, GBA_SIZE_FLASH512) == GBA_SIZE_FLASH512; - case SAVEDATA_FLASH1M: + case GBA_SAVEDATA_FLASH1M: return out->write(out, savedata->data, GBA_SIZE_FLASH1M) == GBA_SIZE_FLASH1M; - case SAVEDATA_EEPROM: + case GBA_SAVEDATA_EEPROM: return out->write(out, savedata->data, GBA_SIZE_EEPROM) == GBA_SIZE_EEPROM; - case SAVEDATA_EEPROM512: + case GBA_SAVEDATA_EEPROM512: return out->write(out, savedata->data, GBA_SIZE_EEPROM512) == GBA_SIZE_EEPROM512; - case SAVEDATA_AUTODETECT: - case SAVEDATA_FORCE_NONE: + case GBA_SAVEDATA_AUTODETECT: + case GBA_SAVEDATA_FORCE_NONE: return true; } } else if (savedata->vf) { @@ -163,21 +163,21 @@ bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) { size_t GBASavedataSize(const struct GBASavedata* savedata) { switch (savedata->type) { - case SAVEDATA_SRAM: + case GBA_SAVEDATA_SRAM: return GBA_SIZE_SRAM; - case SAVEDATA_SRAM512: + case GBA_SAVEDATA_SRAM512: return GBA_SIZE_SRAM512; - case SAVEDATA_FLASH512: + case GBA_SAVEDATA_FLASH512: return GBA_SIZE_FLASH512; - case SAVEDATA_FLASH1M: + case GBA_SAVEDATA_FLASH1M: return GBA_SIZE_FLASH1M; - case SAVEDATA_EEPROM: + case GBA_SAVEDATA_EEPROM: return GBA_SIZE_EEPROM; - case SAVEDATA_EEPROM512: + case GBA_SAVEDATA_EEPROM512: return GBA_SIZE_EEPROM512; - case SAVEDATA_FORCE_NONE: + case GBA_SAVEDATA_FORCE_NONE: return 0; - case SAVEDATA_AUTODETECT: + case GBA_SAVEDATA_AUTODETECT: default: if (savedata->vf) { return savedata->vf->size(savedata->vf); @@ -188,7 +188,7 @@ size_t GBASavedataSize(const struct GBASavedata* savedata) { bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in) { if (savedata->data) { - if (!in || savedata->type == SAVEDATA_FORCE_NONE) { + if (!in || savedata->type == GBA_SAVEDATA_FORCE_NONE) { return false; } ssize_t size = GBASavedataSize(savedata); @@ -220,11 +220,11 @@ bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in) { return true; } -void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type) { +void GBASavedataForceType(struct GBASavedata* savedata, enum GBASavedataType type) { if (savedata->type == type) { return; } - if (savedata->type != SAVEDATA_AUTODETECT) { + if (savedata->type != GBA_SAVEDATA_AUTODETECT) { struct VFile* vf = savedata->vf; int mapMode = savedata->mapMode; bool maskWriteback = savedata->maskWriteback; @@ -234,40 +234,40 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type) savedata->maskWriteback = maskWriteback; } switch (type) { - case SAVEDATA_FLASH512: - case SAVEDATA_FLASH1M: + case GBA_SAVEDATA_FLASH512: + case GBA_SAVEDATA_FLASH1M: savedata->type = type; GBASavedataInitFlash(savedata); break; - case SAVEDATA_EEPROM: - case SAVEDATA_EEPROM512: + case GBA_SAVEDATA_EEPROM: + case GBA_SAVEDATA_EEPROM512: savedata->type = type; GBASavedataInitEEPROM(savedata); break; - case SAVEDATA_SRAM: + case GBA_SAVEDATA_SRAM: GBASavedataInitSRAM(savedata); break; - case SAVEDATA_SRAM512: + case GBA_SAVEDATA_SRAM512: GBASavedataInitSRAM512(savedata); break; - case SAVEDATA_FORCE_NONE: - savedata->type = SAVEDATA_FORCE_NONE; + case GBA_SAVEDATA_FORCE_NONE: + savedata->type = GBA_SAVEDATA_FORCE_NONE; break; - case SAVEDATA_AUTODETECT: + case GBA_SAVEDATA_AUTODETECT: break; } } void GBASavedataInitFlash(struct GBASavedata* savedata) { - if (savedata->type == SAVEDATA_AUTODETECT) { - savedata->type = SAVEDATA_FLASH512; + if (savedata->type == GBA_SAVEDATA_AUTODETECT) { + savedata->type = GBA_SAVEDATA_FLASH512; } - if (savedata->type != SAVEDATA_FLASH512 && savedata->type != SAVEDATA_FLASH1M) { + if (savedata->type != GBA_SAVEDATA_FLASH512 && savedata->type != GBA_SAVEDATA_FLASH1M) { mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata"); return; } int32_t flashSize = GBA_SIZE_FLASH512; - if (savedata->type == SAVEDATA_FLASH1M) { + if (savedata->type == GBA_SAVEDATA_FLASH1M) { flashSize = GBA_SIZE_FLASH1M; } off_t end; @@ -289,14 +289,14 @@ void GBASavedataInitFlash(struct GBASavedata* savedata) { } void GBASavedataInitEEPROM(struct GBASavedata* savedata) { - if (savedata->type == SAVEDATA_AUTODETECT) { - savedata->type = SAVEDATA_EEPROM512; - } else if (savedata->type != SAVEDATA_EEPROM512 && savedata->type != SAVEDATA_EEPROM) { + if (savedata->type == GBA_SAVEDATA_AUTODETECT) { + savedata->type = GBA_SAVEDATA_EEPROM512; + } else if (savedata->type != GBA_SAVEDATA_EEPROM512 && savedata->type != GBA_SAVEDATA_EEPROM) { mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata"); return; } int32_t eepromSize = GBA_SIZE_EEPROM512; - if (savedata->type == SAVEDATA_EEPROM) { + if (savedata->type == GBA_SAVEDATA_EEPROM) { eepromSize = GBA_SIZE_EEPROM; } off_t end; @@ -316,8 +316,8 @@ void GBASavedataInitEEPROM(struct GBASavedata* savedata) { } void GBASavedataInitSRAM(struct GBASavedata* savedata) { - if (savedata->type == SAVEDATA_AUTODETECT) { - savedata->type = SAVEDATA_SRAM; + if (savedata->type == GBA_SAVEDATA_AUTODETECT) { + savedata->type = GBA_SAVEDATA_SRAM; } else { mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata"); return; @@ -340,8 +340,8 @@ void GBASavedataInitSRAM(struct GBASavedata* savedata) { } void GBASavedataInitSRAM512(struct GBASavedata* savedata) { - if (savedata->type == SAVEDATA_AUTODETECT) { - savedata->type = SAVEDATA_SRAM512; + if (savedata->type == GBA_SAVEDATA_AUTODETECT) { + savedata->type = GBA_SAVEDATA_SRAM512; } else { mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata"); return; @@ -365,11 +365,11 @@ void GBASavedataInitSRAM512(struct GBASavedata* savedata) { uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) { if (savedata->command == FLASH_COMMAND_ID) { - if (savedata->type == SAVEDATA_FLASH512) { + if (savedata->type == GBA_SAVEDATA_FLASH512) { if (address < 2) { return FLASH_MFG_PANASONIC >> (address * 8); } - } else if (savedata->type == SAVEDATA_FLASH1M) { + } else if (savedata->type == GBA_SAVEDATA_FLASH1M) { if (address < 2) { return FLASH_MFG_SANYO >> (address * 8); } @@ -472,10 +472,10 @@ static void _ensureEeprom(struct GBASavedata* savedata, uint32_t size) { if (size < GBA_SIZE_EEPROM512) { return; } - if (savedata->type == SAVEDATA_EEPROM) { + if (savedata->type == GBA_SAVEDATA_EEPROM) { return; } - savedata->type = SAVEDATA_EEPROM; + savedata->type = GBA_SAVEDATA_EEPROM; if (!savedata->vf) { return; } @@ -602,14 +602,23 @@ void GBASavedataRTCWrite(struct GBASavedata* savedata) { size_t size = GBASavedataSize(savedata); savedata->vf->seek(savedata->vf, size & ~0xFF, SEEK_SET); + int bank = 0; if ((savedata->vf->size(savedata->vf) & 0xFF) != sizeof(buffer)) { // Writing past the end of the file can invalidate the file mapping + if (savedata->type == GBA_SAVEDATA_FLASH1M) { + bank = savedata->currentBank == &savedata->data[0x10000]; + } savedata->vf->unmap(savedata->vf, savedata->data, size); savedata->data = NULL; } savedata->vf->write(savedata->vf, &buffer, sizeof(buffer)); if (!savedata->data) { savedata->data = savedata->vf->map(savedata->vf, size, MAP_WRITE); + if (savedata->type == GBA_SAVEDATA_FLASH1M) { + savedata->currentBank = &savedata->data[bank << 16]; + } else if (savedata->type == GBA_SAVEDATA_FLASH512) { + savedata->currentBank = savedata->data; + } } } @@ -721,7 +730,7 @@ void GBASavedataDeserialize(struct GBASavedata* savedata, const struct GBASerial LOAD_32(savedata->writeAddress, 0, &state->savedata.writeAddress); LOAD_16(savedata->settling, 0, &state->savedata.settlingSector); - if (savedata->type == SAVEDATA_FLASH1M) { + if (savedata->type == GBA_SAVEDATA_FLASH1M) { _flashSwitchBank(savedata, GBASerializedSavedataFlagsGetFlashBank(flags)); } @@ -734,9 +743,9 @@ void GBASavedataDeserialize(struct GBASavedata* savedata, const struct GBASerial void _flashSwitchBank(struct GBASavedata* savedata, int bank) { mLOG(GBA_SAVE, DEBUG, "Performing flash bank switch to bank %i", bank); - if (bank > 0 && savedata->type == SAVEDATA_FLASH512) { + if (bank > 0 && savedata->type == GBA_SAVEDATA_FLASH512) { mLOG(GBA_SAVE, INFO, "Updating flash chip from 512kb to 1Mb"); - savedata->type = SAVEDATA_FLASH1M; + savedata->type = GBA_SAVEDATA_FLASH1M; if (savedata->vf) { savedata->vf->unmap(savedata->vf, savedata->data, GBA_SIZE_FLASH512); if (savedata->vf->size(savedata->vf) < GBA_SIZE_FLASH1M) { @@ -755,7 +764,7 @@ void _flashErase(struct GBASavedata* savedata) { mLOG(GBA_SAVE, DEBUG, "Performing flash chip erase"); savedata->dirty |= mSAVEDATA_DIRT_NEW; size_t size = GBA_SIZE_FLASH512; - if (savedata->type == SAVEDATA_FLASH1M) { + if (savedata->type == GBA_SAVEDATA_FLASH1M) { size = GBA_SIZE_FLASH1M; } memset(savedata->data, 0xFF, size); @@ -765,7 +774,7 @@ void _flashEraseSector(struct GBASavedata* savedata, uint16_t sectorStart) { mLOG(GBA_SAVE, DEBUG, "Performing flash sector erase at 0x%04x", sectorStart); savedata->dirty |= mSAVEDATA_DIRT_NEW; size_t size = 0x1000; - if (savedata->type == SAVEDATA_FLASH1M) { + if (savedata->type == GBA_SAVEDATA_FLASH1M) { mLOG(GBA_SAVE, DEBUG, "Performing unknown sector-size erase at 0x%04x", sectorStart); } savedata->settling = sectorStart >> 12; diff --git a/src/gba/serialize.c b/src/gba/serialize.c index 1669eca3d..5eabaedea 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -195,7 +195,7 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) { if (GBASerializedMiscFlagsIsIrqPending(miscFlags)) { int32_t when; LOAD_32(when, 0, &state->nextIrq); - mTimingSchedule(&gba->timing, &gba->irqEvent, when); + mTimingSchedule(&gba->timing, &gba->irqEvent, when); } gba->cpuBlocked = GBASerializedMiscFlagsGetBlocked(miscFlags); gba->keysLast = GBASerializedMiscFlagsGetKeyIRQKeys(miscFlags); diff --git a/src/gba/sharkport.c b/src/gba/sharkport.c index 9e1e64518..f6b908f3a 100644 --- a/src/gba/sharkport.c +++ b/src/gba/sharkport.c @@ -18,9 +18,9 @@ static const int GSV_PAYLOAD_OFFSET = 0x430; static bool _importSavedata(struct GBA* gba, void* payload, size_t size) { bool success = false; switch (gba->memory.savedata.type) { - case SAVEDATA_FLASH512: + case GBA_SAVEDATA_FLASH512: if (size > GBA_SIZE_FLASH512) { - GBASavedataForceType(&gba->memory.savedata, SAVEDATA_FLASH1M); + GBASavedataForceType(&gba->memory.savedata, GBA_SAVEDATA_FLASH1M); } // Fall through default: @@ -28,8 +28,8 @@ static bool _importSavedata(struct GBA* gba, void* payload, size_t size) { size = GBASavedataSize(&gba->memory.savedata); } break; - case SAVEDATA_FORCE_NONE: - case SAVEDATA_AUTODETECT: + case GBA_SAVEDATA_FORCE_NONE: + case GBA_SAVEDATA_AUTODETECT: goto cleanup; } @@ -202,7 +202,7 @@ bool GBASavedataExportSharkPort(const struct GBA* gba, struct VFile* vf) { char c[0x1C]; int32_t i; } buffer; - uint32_t size = strlen(SHARKPORT_HEADER); + int32_t size = strlen(SHARKPORT_HEADER); STORE_32(size, 0, &buffer.i); if (vf->write(vf, &buffer.i, 4) < 4) { return false; @@ -271,12 +271,12 @@ bool GBASavedataExportSharkPort(const struct GBA* gba, struct VFile* vf) { } uint32_t checksum = 0; - size_t i; + ssize_t i; for (i = 0; i < 0x1C; ++i) { checksum += buffer.c[i] << (checksum % 24); } - if (gba->memory.savedata.type == SAVEDATA_EEPROM) { + if (gba->memory.savedata.type == GBA_SAVEDATA_EEPROM) { for (i = 0; i < size; ++i) { char byte = gba->memory.savedata.data[i ^ 7]; checksum += byte << (checksum % 24); diff --git a/src/gba/sio.c b/src/gba/sio.c index 1082d0062..60c7c2286 100644 --- a/src/gba/sio.c +++ b/src/gba/sio.c @@ -11,38 +11,26 @@ mLOG_DEFINE_CATEGORY(GBA_SIO, "GBA Serial I/O", "gba.sio"); -const int GBASIOCyclesPerTransfer[4][MAX_GBAS] = { - { 38326, 73003, 107680, 142356 }, - { 9582, 18251, 26920, 35589 }, - { 6388, 12167, 17947, 23726 }, - { 3194, 6075, 8973, 11863 } +static const int GBASIOCyclesPerTransfer[4][MAX_GBAS] = { + { 31976, 63427, 94884, 125829 }, + { 8378, 16241, 24104, 31457 }, + { 5750, 10998, 16241, 20972 }, + { 3140, 5755, 8376, 10486 } }; -static struct GBASIODriver* _lookupDriver(struct GBASIO* sio, enum GBASIOMode mode) { - switch (mode) { - case SIO_NORMAL_8: - case SIO_NORMAL_32: - return sio->drivers.normal; - case SIO_MULTI: - return sio->drivers.multiplayer; - case SIO_JOYBUS: - return sio->drivers.joybus; - default: - return 0; - } -} +static void _sioFinish(struct mTiming* timing, void* user, uint32_t cyclesLate); static const char* _modeName(enum GBASIOMode mode) { switch (mode) { - case SIO_NORMAL_8: + case GBA_SIO_NORMAL_8: return "NORMAL8"; - case SIO_NORMAL_32: + case GBA_SIO_NORMAL_32: return "NORMAL32"; - case SIO_MULTI: + case GBA_SIO_MULTI: return "MULTI"; - case SIO_JOYBUS: + case GBA_SIO_JOYBUS: return "JOYBUS"; - case SIO_GPIO: + case GBA_SIO_GPIO: return "GPIO"; default: return "(unknown)"; @@ -58,25 +46,36 @@ static void _switchMode(struct GBASIO* sio) { newMode = (enum GBASIOMode) (mode & 0xC); } if (newMode != sio->mode) { - if (sio->activeDriver && sio->activeDriver->unload) { - sio->activeDriver->unload(sio->activeDriver); - } if (sio->mode != (enum GBASIOMode) -1) { mLOG(GBA_SIO, DEBUG, "Switching mode from %s to %s", _modeName(sio->mode), _modeName(newMode)); } sio->mode = newMode; - sio->activeDriver = _lookupDriver(sio, sio->mode); - if (sio->activeDriver && sio->activeDriver->load) { - sio->activeDriver->load(sio->activeDriver); + if (sio->driver && sio->driver->setMode) { + sio->driver->setMode(sio->driver, newMode); + } + + int id = 0; + switch (newMode) { + case GBA_SIO_MULTI: + if (sio->driver && sio->driver->deviceId) { + id = sio->driver->deviceId(sio->driver); + } + sio->rcnt = GBASIORegisterRCNTSetSi(sio->rcnt, !!id); + break; + default: + // TODO + break; } } } void GBASIOInit(struct GBASIO* sio) { - sio->drivers.normal = 0; - sio->drivers.multiplayer = 0; - sio->drivers.joybus = 0; - sio->activeDriver = 0; + sio->driver = NULL; + + sio->completeEvent.context = sio; + sio->completeEvent.name = "GBA SIO Complete"; + sio->completeEvent.callback = _sioFinish; + sio->completeEvent.priority = 0x80; sio->gbp.p = sio->p; GBASIOPlayerInit(&sio->gbp); @@ -85,64 +84,28 @@ void GBASIOInit(struct GBASIO* sio) { } void GBASIODeinit(struct GBASIO* sio) { - if (sio->activeDriver && sio->activeDriver->unload) { - sio->activeDriver->unload(sio->activeDriver); - } - if (sio->drivers.multiplayer && sio->drivers.multiplayer->deinit) { - sio->drivers.multiplayer->deinit(sio->drivers.multiplayer); - } - if (sio->drivers.joybus && sio->drivers.joybus->deinit) { - sio->drivers.joybus->deinit(sio->drivers.joybus); - } - if (sio->drivers.normal && sio->drivers.normal->deinit) { - sio->drivers.normal->deinit(sio->drivers.normal); + if (sio->driver && sio->driver->deinit) { + sio->driver->deinit(sio->driver); } } void GBASIOReset(struct GBASIO* sio) { - if (sio->activeDriver && sio->activeDriver->unload) { - sio->activeDriver->unload(sio->activeDriver); + if (sio->driver && sio->driver->reset) { + sio->driver->reset(sio->driver); } sio->rcnt = RCNT_INITIAL; sio->siocnt = 0; sio->mode = -1; - sio->activeDriver = NULL; _switchMode(sio); GBASIOPlayerReset(&sio->gbp); } -void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers) { - GBASIOSetDriver(sio, drivers->normal, SIO_NORMAL_8); - GBASIOSetDriver(sio, drivers->multiplayer, SIO_MULTI); - GBASIOSetDriver(sio, drivers->joybus, SIO_JOYBUS); -} - -void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode) { - struct GBASIODriver** driverLoc; - switch (mode) { - case SIO_NORMAL_8: - case SIO_NORMAL_32: - driverLoc = &sio->drivers.normal; - break; - case SIO_MULTI: - driverLoc = &sio->drivers.multiplayer; - break; - case SIO_JOYBUS: - driverLoc = &sio->drivers.joybus; - break; - default: - mLOG(GBA_SIO, ERROR, "Setting an unsupported SIO driver: %x", mode); - return; - } - if (*driverLoc) { - if ((*driverLoc)->unload) { - (*driverLoc)->unload(*driverLoc); - } - if ((*driverLoc)->deinit) { - (*driverLoc)->deinit(*driverLoc); - } +void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver) { + if (sio->driver && sio->driver->deinit) { + sio->driver->deinit(sio->driver); } + sio->driver = driver; if (driver) { driver->p = sio; @@ -154,48 +117,122 @@ void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASI } } } - if (sio->activeDriver == *driverLoc) { - sio->activeDriver = driver; - if (driver && driver->load) { - driver->load(driver); - } - } - *driverLoc = driver; } void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) { - sio->rcnt &= 0xF; - sio->rcnt |= value & ~0xF; + sio->rcnt &= 0x1FF; + sio->rcnt |= value & 0xC000; _switchMode(sio); - if (sio->activeDriver && sio->activeDriver->writeRegister) { - sio->activeDriver->writeRegister(sio->activeDriver, GBA_REG_RCNT, value); + if (sio->driver && sio->driver->writeRCNT) { + switch (sio->mode) { + case GBA_SIO_GPIO: + sio->rcnt = (sio->driver->writeRCNT(sio->driver, value) & 0x01FF) | (sio->rcnt & 0xC000); + break; + default: + sio->rcnt = (sio->driver->writeRCNT(sio->driver, value) & 0x01F0) | (sio->rcnt & 0xC00F); + } + } else if (sio->mode == GBA_SIO_GPIO) { + sio->rcnt &= 0xC000; + sio->rcnt |= value & 0x1FF; + } else { + sio->rcnt &= 0xC00F; + sio->rcnt |= value & 0x1F0; } } +static void _startTransfer(struct GBASIO* sio) { + if (sio->driver && sio->driver->start) { + if (!sio->driver->start(sio->driver)) { + // Transfer completion is handled internally to the driver + return; + } + } + int connected = 0; + if (sio->driver && sio->driver->connectedDevices) { + connected = sio->driver->connectedDevices(sio->driver); + } + mTimingDeschedule(&sio->p->timing, &sio->completeEvent); + mTimingSchedule(&sio->p->timing, &sio->completeEvent, GBASIOTransferCycles(sio->mode, sio->siocnt, connected)); +} + void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) { if ((value ^ sio->siocnt) & 0x3000) { sio->siocnt = value & 0x3000; _switchMode(sio); } - if (sio->activeDriver && sio->activeDriver->writeRegister) { - value = sio->activeDriver->writeRegister(sio->activeDriver, GBA_REG_SIOCNT, value); + int id = 0; + int connected = 0; + bool handled = false; + if (sio->driver) { + handled = sio->driver->handlesMode(sio->driver, sio->mode); + if (handled) { + if (sio->driver->deviceId) { + id = sio->driver->deviceId(sio->driver); + } + connected = sio->driver->connectedDevices(sio->driver); + handled = !!sio->driver->writeSIOCNT; + } + } + + switch (sio->mode) { + case GBA_SIO_MULTI: + value &= 0xFF83; + value = GBASIOMultiplayerSetSlave(value, id || !connected); + value = GBASIOMultiplayerSetId(value, id); + value |= sio->siocnt & 0x00FC; + + // SC appears to float in multi mode when not doing a transfer. While + // it does spike at the end of a transfer, it appears to die down after + // around 20-30 microseconds. However, the docs on akkit.org + // (http://www.akkit.org/info/gba_comms.html) say this is high until + // a transfer starts and low while active. Further, the Mario Bros. + // multiplayer expects SC to be high in multi mode. This needs better + // investigation than I managed, apparently. + sio->rcnt = GBASIORegisterRCNTFillSc(sio->rcnt); + + if (GBASIOMultiplayerIsBusy(value) && !GBASIOMultiplayerIsBusy(sio->siocnt)) { + if (!id) { + sio->p->memory.io[GBA_REG(SIOMULTI0)] = 0xFFFF; + sio->p->memory.io[GBA_REG(SIOMULTI1)] = 0xFFFF; + sio->p->memory.io[GBA_REG(SIOMULTI2)] = 0xFFFF; + sio->p->memory.io[GBA_REG(SIOMULTI3)] = 0xFFFF; + sio->rcnt = GBASIORegisterRCNTClearSc(sio->rcnt); + _startTransfer(sio); + } else { + // TODO + } + } + break; + case GBA_SIO_NORMAL_8: + case GBA_SIO_NORMAL_32: + // This line is pulled up by the clock owner while the clock is idle. + // If there is no clock owner it's just hi-Z. + if (GBASIONormalGetSc(value)) { + sio->rcnt = GBASIORegisterRCNTFillSc(sio->rcnt); + } + if (GBASIONormalIsStart(value) && !GBASIONormalIsStart(sio->siocnt)) { + if (GBASIONormalIsSc(value)) { + _startTransfer(sio); + } else { + // TODO + } + } + break; + default: + // TODO + break; + } + if (handled) { + value = sio->driver->writeSIOCNT(sio->driver, value); } else { // Dummy drivers switch (sio->mode) { - case SIO_NORMAL_8: - case SIO_NORMAL_32: + case GBA_SIO_NORMAL_8: + case GBA_SIO_NORMAL_32: value = GBASIONormalFillSi(value); - if ((value & 0x0081) == 0x0081) { - if (GBASIONormalIsIrq(value)) { - // TODO: Test this on hardware to see if this is correct - GBARaiseIRQ(sio->p, GBA_IRQ_SIO, 0); - } - value = GBASIONormalClearStart(value); - } break; - case SIO_MULTI: - value &= 0xFF83; - value |= 0xC; + case GBA_SIO_MULTI: + value = GBASIOMultiplayerFillReady(value); break; default: // TODO @@ -206,22 +243,252 @@ void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) { } uint16_t GBASIOWriteRegister(struct GBASIO* sio, uint32_t address, uint16_t value) { - if (sio->activeDriver && sio->activeDriver->writeRegister) { - return sio->activeDriver->writeRegister(sio->activeDriver, address, value); + int id = 0; + if (sio->driver && sio->driver->deviceId) { + id = sio->driver->deviceId(sio->driver); } - // Dummy drivers + + bool handled = true; switch (sio->mode) { - case SIO_JOYBUS: + case GBA_SIO_JOYBUS: switch (address) { + case GBA_REG_SIODATA8: + mLOG(GBA_SIO, DEBUG, "JOY write: SIODATA8 (?) <- %04X", value); + break; case GBA_REG_JOYCNT: - return (value & 0x0040) | (sio->p->memory.io[GBA_REG(JOYCNT)] & ~(value & 0x7) & ~0x0040); + mLOG(GBA_SIO, DEBUG, "JOY write: CNT <- %04X", value); + value = (value & 0x0040) | (sio->p->memory.io[GBA_REG(JOYCNT)] & ~(value & 0x7) & ~0x0040); + break; case GBA_REG_JOYSTAT: - return (value & 0x0030) | (sio->p->memory.io[GBA_REG(JOYSTAT)] & ~0x30); + mLOG(GBA_SIO, DEBUG, "JOY write: STAT <- %04X", value); + value = (value & 0x0030) | (sio->p->memory.io[GBA_REG(JOYSTAT)] & ~0x30); + break; + case GBA_REG_JOY_TRANS_LO: + mLOG(GBA_SIO, DEBUG, "JOY write: TRANS_LO <- %04X", value); + break; + case GBA_REG_JOY_TRANS_HI: + mLOG(GBA_SIO, DEBUG, "JOY write: TRANS_HI <- %04X", value); + break; + default: + mLOG(GBA_SIO, GAME_ERROR, "JOY write: Unhandled %s <- %04X", GBAIORegisterNames[address >> 1], value); + handled = false; + break; } break; - default: - // TODO + case GBA_SIO_NORMAL_8: + switch (address) { + case GBA_REG_SIODATA8: + mLOG(GBA_SIO, DEBUG, "NORMAL8 %i write: SIODATA8 <- %04X", id, value); + break; + case GBA_REG_JOYCNT: + mLOG(GBA_SIO, DEBUG, "NORMAL8 %i write: JOYCNT (?) <- %04X", id, value); + value = (value & 0x0040) | (sio->p->memory.io[GBA_REG(JOYCNT)] & ~(value & 0x7) & ~0x0040); + break; + default: + mLOG(GBA_SIO, GAME_ERROR, "NORMAL8 %i write: Unhandled %s <- %04X", id, GBAIORegisterNames[address >> 1], value); + handled = false; + break; + } break; + case GBA_SIO_NORMAL_32: + switch (address) { + case GBA_REG_SIODATA32_LO: + mLOG(GBA_SIO, DEBUG, "NORMAL32 %i write: SIODATA32_LO <- %04X", id, value); + break; + case GBA_REG_SIODATA32_HI: + mLOG(GBA_SIO, DEBUG, "NORMAL32 %i write: SIODATA32_HI <- %04X", id, value); + break; + case GBA_REG_SIODATA8: + mLOG(GBA_SIO, DEBUG, "NORMAL32 %i write: SIODATA8 (?) <- %04X", id, value); + break; + case GBA_REG_JOYCNT: + mLOG(GBA_SIO, DEBUG, "NORMAL32 %i write: JOYCNT (?) <- %04X", id, value); + value = (value & 0x0040) | (sio->p->memory.io[GBA_REG(JOYCNT)] & ~(value & 0x7) & ~0x0040); + break; + default: + mLOG(GBA_SIO, GAME_ERROR, "NORMAL32 %i write: Unhandled %s <- %04X", id, GBAIORegisterNames[address >> 1], value); + handled = false; + break; + } + break; + case GBA_SIO_MULTI: + switch (address) { + case GBA_REG_SIOMLT_SEND: + mLOG(GBA_SIO, DEBUG, "MULTI %i write: SIOMLT_SEND <- %04X", id, value); + break; + case GBA_REG_JOYCNT: + mLOG(GBA_SIO, DEBUG, "MULTI %i write: JOYCNT (?) <- %04X", id, value); + value = (value & 0x0040) | (sio->p->memory.io[GBA_REG(JOYCNT)] & ~(value & 0x7) & ~0x0040); + break; + default: + mLOG(GBA_SIO, GAME_ERROR, "MULTI %i write: Unhandled %s <- %04X", id, GBAIORegisterNames[address >> 1], value); + handled = false; + break; + } + break; + case GBA_SIO_UART: + switch (address) { + case GBA_REG_SIODATA8: + mLOG(GBA_SIO, DEBUG, "UART write: SIODATA8 <- %04X", value); + break; + case GBA_REG_JOYCNT: + mLOG(GBA_SIO, DEBUG, "UART write: JOYCNT (?) <- %04X", value); + value = (value & 0x0040) | (sio->p->memory.io[GBA_REG(JOYCNT)] & ~(value & 0x7) & ~0x0040); + break; + default: + mLOG(GBA_SIO, GAME_ERROR, "UART write: Unhandled %s <- %04X", GBAIORegisterNames[address >> 1], value); + handled = false; + break; + } + break; + case GBA_SIO_GPIO: + mLOG(GBA_SIO, STUB, "GPIO write: Unhandled %s <- %04X", GBAIORegisterNames[address >> 1], value); + handled = false; + break; + } + if (!handled) { + value = sio->p->memory.io[address >> 1]; } return value; } + +int32_t GBASIOTransferCycles(enum GBASIOMode mode, uint16_t siocnt, int connected) { + if (connected < 0 || connected >= MAX_GBAS) { + mLOG(GBA_SIO, ERROR, "Invalid device count %i", connected); + return 0; + } + + switch (mode) { + case GBA_SIO_MULTI: + return GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(siocnt)][connected]; + case GBA_SIO_NORMAL_8: + return 8 * GBA_ARM7TDMI_FREQUENCY / ((GBASIONormalIsInternalSc(siocnt) ? 2048 : 256) * 1024); + case GBA_SIO_NORMAL_32: + return 32 * GBA_ARM7TDMI_FREQUENCY / ((GBASIONormalIsInternalSc(siocnt) ? 2048 : 256) * 1024); + default: + mLOG(GBA_SIO, STUB, "No cycle count implemented for mode %s", _modeName(mode)); + break; + } + return 0; +} + +void GBASIOMultiplayerFinishTransfer(struct GBASIO* sio, uint16_t data[4], uint32_t cyclesLate) { + int id = 0; + if (sio->driver && sio->driver->deviceId) { + id = sio->driver->deviceId(sio->driver); + } + sio->p->memory.io[GBA_REG(SIOMULTI0)] = data[0]; + sio->p->memory.io[GBA_REG(SIOMULTI1)] = data[1]; + sio->p->memory.io[GBA_REG(SIOMULTI2)] = data[2]; + sio->p->memory.io[GBA_REG(SIOMULTI3)] = data[3]; + + sio->siocnt = GBASIOMultiplayerClearBusy(sio->siocnt); + sio->siocnt = GBASIOMultiplayerSetId(sio->siocnt, id); + + sio->rcnt = GBASIORegisterRCNTFillSc(sio->rcnt); + + if (GBASIOMultiplayerIsIrq(sio->siocnt)) { + GBARaiseIRQ(sio->p, GBA_IRQ_SIO, cyclesLate); + } +} + +void GBASIONormal8FinishTransfer(struct GBASIO* sio, uint8_t data, uint32_t cyclesLate) { + sio->siocnt = GBASIONormalClearStart(sio->siocnt); + sio->p->memory.io[GBA_REG(SIODATA8)] = data; + if (GBASIONormalIsIrq(sio->siocnt)) { + GBARaiseIRQ(sio->p, GBA_IRQ_SIO, cyclesLate); + } +} + +void GBASIONormal32FinishTransfer(struct GBASIO* sio, uint32_t data, uint32_t cyclesLate) { + sio->siocnt = GBASIONormalClearStart(sio->siocnt); + sio->p->memory.io[GBA_REG(SIODATA32_LO)] = data; + sio->p->memory.io[GBA_REG(SIODATA32_HI)] = data >> 16; + if (GBASIONormalIsIrq(sio->siocnt)) { + GBARaiseIRQ(sio->p, GBA_IRQ_SIO, cyclesLate); + } +} + +static void _sioFinish(struct mTiming* timing, void* user, uint32_t cyclesLate) { + UNUSED(timing); + struct GBASIO* sio = user; + union { + uint16_t multi[4]; + uint8_t normal8; + uint32_t normal32; + } data = {0}; + switch (sio->mode) { + case GBA_SIO_MULTI: + if (sio->driver && sio->driver->finishMultiplayer) { + sio->driver->finishMultiplayer(sio->driver, data.multi); + } + GBASIOMultiplayerFinishTransfer(sio, data.multi, cyclesLate); + break; + case GBA_SIO_NORMAL_8: + if (sio->driver && sio->driver->finishNormal8) { + data.normal8 = sio->driver->finishNormal8(sio->driver); + } + GBASIONormal8FinishTransfer(sio, data.normal8, cyclesLate); + break; + case GBA_SIO_NORMAL_32: + if (sio->driver && sio->driver->finishNormal32) { + data.normal32 = sio->driver->finishNormal32(sio->driver); + } + GBASIONormal32FinishTransfer(sio, data.normal32, cyclesLate); + break; + default: + // TODO + mLOG(GBA_SIO, STUB, "No dummy finish implemented for mode %s", _modeName(sio->mode)); + break; + } +} + +int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data) { + switch (command) { + case JOY_RESET: + sio->p->p->memory.io[GBA_REG(JOYCNT)] |= JOYCNT_RESET; + if (sio->p->p->memory.io[GBA_REG(JOYCNT)] & 0x40) { + GBARaiseIRQ(sio->p->p, GBA_IRQ_SIO, 0); + } + // Fall through + case JOY_POLL: + data[0] = 0x00; + data[1] = 0x04; + data[2] = sio->p->p->memory.io[GBA_REG(JOYSTAT)]; + + mLOG(GBA_SIO, DEBUG, "JOY %s: %02X (%02X)", command == JOY_POLL ? "poll" : "reset", data[2], sio->p->p->memory.io[GBA_REG(JOYCNT)]); + return 3; + case JOY_RECV: + sio->p->p->memory.io[GBA_REG(JOYCNT)] |= JOYCNT_RECV; + sio->p->p->memory.io[GBA_REG(JOYSTAT)] |= JOYSTAT_RECV; + + sio->p->p->memory.io[GBA_REG(JOY_RECV_LO)] = data[0] | (data[1] << 8); + sio->p->p->memory.io[GBA_REG(JOY_RECV_HI)] = data[2] | (data[3] << 8); + + data[0] = sio->p->p->memory.io[GBA_REG(JOYSTAT)]; + + mLOG(GBA_SIO, DEBUG, "JOY recv: %02X (%02X)", data[0], sio->p->p->memory.io[GBA_REG(JOYCNT)]); + + if (sio->p->p->memory.io[GBA_REG(JOYCNT)] & 0x40) { + GBARaiseIRQ(sio->p->p, GBA_IRQ_SIO, 0); + } + return 1; + case JOY_TRANS: + data[0] = sio->p->p->memory.io[GBA_REG(JOY_TRANS_LO)]; + data[1] = sio->p->p->memory.io[GBA_REG(JOY_TRANS_LO)] >> 8; + data[2] = sio->p->p->memory.io[GBA_REG(JOY_TRANS_HI)]; + data[3] = sio->p->p->memory.io[GBA_REG(JOY_TRANS_HI)] >> 8; + data[4] = sio->p->p->memory.io[GBA_REG(JOYSTAT)]; + + sio->p->p->memory.io[GBA_REG(JOYCNT)] |= JOYCNT_TRANS; + sio->p->p->memory.io[GBA_REG(JOYSTAT)] &= ~JOYSTAT_TRANS; + + mLOG(GBA_SIO, DEBUG, "JOY trans: %02X%02X%02X%02X:%02X (%02X)", data[0], data[1], data[2], data[3], data[4], sio->p->p->memory.io[GBA_REG(JOYCNT)]); + + if (sio->p->p->memory.io[GBA_REG(JOYCNT)] & 0x40) { + GBARaiseIRQ(sio->p->p, GBA_IRQ_SIO, 0); + } + return 5; + } + return 0; +} diff --git a/src/gba/sio/dolphin.c b/src/gba/sio/dolphin.c index 896d17d3e..0bb783e76 100644 --- a/src/gba/sio/dolphin.c +++ b/src/gba/sio/dolphin.c @@ -23,18 +23,22 @@ enum { }; static bool GBASIODolphinInit(struct GBASIODriver* driver); -static bool GBASIODolphinLoad(struct GBASIODriver* driver); -static bool GBASIODolphinUnload(struct GBASIODriver* driver); +static void GBASIODolphinReset(struct GBASIODriver* driver); +static void GBASIODolphinSetMode(struct GBASIODriver* driver, enum GBASIOMode mode); +static bool GBASIODolphinHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); +static int GBASIODolphinConnectedDevices(struct GBASIODriver* driver); static void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t cyclesLate); static int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate); static void _flush(struct GBASIODolphin* dol); void GBASIODolphinCreate(struct GBASIODolphin* dol) { - GBASIOJOYCreate(&dol->d); + memset(&dol->d, 0, sizeof(dol->d)); dol->d.init = GBASIODolphinInit; - dol->d.load = GBASIODolphinLoad; - dol->d.unload = GBASIODolphinUnload; + dol->d.reset = GBASIODolphinReset; + dol->d.setMode = GBASIODolphinSetMode; + dol->d.handlesMode = GBASIODolphinHandlesMode; + dol->d.connectedDevices = GBASIODolphinConnectedDevices; dol->event.context = dol; dol->event.name = "GB SIO Lockstep"; dol->event.callback = GBASIODolphinProcessEvents; @@ -94,26 +98,33 @@ bool GBASIODolphinConnect(struct GBASIODolphin* dol, const struct Address* addre static bool GBASIODolphinInit(struct GBASIODriver* driver) { struct GBASIODolphin* dol = (struct GBASIODolphin*) driver; - dol->active = false; dol->clockSlice = 0; dol->state = WAIT_FOR_FIRST_CLOCK; - _flush(dol); + GBASIODolphinReset(driver); return true; } -static bool GBASIODolphinLoad(struct GBASIODriver* driver) { +static void GBASIODolphinReset(struct GBASIODriver* driver) { struct GBASIODolphin* dol = (struct GBASIODolphin*) driver; - dol->active = true; + dol->active = false; _flush(dol); mTimingDeschedule(&dol->d.p->p->timing, &dol->event); mTimingSchedule(&dol->d.p->p->timing, &dol->event, 0); - return true; } -static bool GBASIODolphinUnload(struct GBASIODriver* driver) { +static void GBASIODolphinSetMode(struct GBASIODriver* driver, enum GBASIOMode mode) { struct GBASIODolphin* dol = (struct GBASIODolphin*) driver; - dol->active = false; - return true; + dol->active = mode == GBA_SIO_JOYBUS; +} + +static bool GBASIODolphinHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + UNUSED(driver); + return mode == GBA_SIO_JOYBUS; +} + +static int GBASIODolphinConnectedDevices(struct GBASIODriver* driver) { + UNUSED(driver); + return 1; } void GBASIODolphinProcessEvents(struct mTiming* timing, void* context, uint32_t cyclesLate) { diff --git a/src/gba/sio/gbp.c b/src/gba/sio/gbp.c index 8400cc8b1..977e67de4 100644 --- a/src/gba/sio/gbp.c +++ b/src/gba/sio/gbp.c @@ -13,8 +13,11 @@ #include static uint16_t _gbpRead(struct mKeyCallback*); -static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); -static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate); +static uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); +static bool _gbpSioHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); +static int _gbpSioConnectedDevices(struct GBASIODriver* driver); +static bool _gbpSioStart(struct GBASIODriver* driver); +static uint32_t _gbpSioFinishNormal32(struct GBASIODriver* driver); static const uint8_t _logoPalette[] = { 0xDF, 0xFF, 0x0C, 0x64, 0x0C, 0xE4, 0x2D, 0xE4, 0x4E, 0x64, 0x4E, 0xE4, 0x6E, 0xE4, 0xAF, 0x68, @@ -43,20 +46,17 @@ void GBASIOPlayerInit(struct GBASIOPlayer* gbp) { gbp->callback.d.readKeys = _gbpRead; gbp->callback.d.requireOpposingDirections = true; gbp->callback.p = gbp; - gbp->d.init = 0; - gbp->d.deinit = 0; - gbp->d.load = 0; - gbp->d.unload = 0; - gbp->d.writeRegister = _gbpSioWriteRegister; - gbp->event.context = gbp; - gbp->event.name = "GBA SIO Game Boy Player"; - gbp->event.callback = _gbpSioProcessEvents; - gbp->event.priority = 0x80; + memset(&gbp->d, 0, sizeof(gbp->d)); + gbp->d.writeSIOCNT = _gbpSioWriteSIOCNT; + gbp->d.handlesMode = _gbpSioHandlesMode; + gbp->d.connectedDevices = _gbpSioConnectedDevices; + gbp->d.start = _gbpSioStart; + gbp->d.finishNormal32 = _gbpSioFinishNormal32; } void GBASIOPlayerReset(struct GBASIOPlayer* gbp) { - if (gbp->p->sio.drivers.normal == &gbp->d) { - GBASIOSetDriver(&gbp->p->sio, NULL, SIO_NORMAL_32); + if (gbp->p->sio.driver == &gbp->d) { + GBASIOSetDriver(&gbp->p->sio, NULL); } } @@ -87,8 +87,9 @@ void GBASIOPlayerUpdate(struct GBA* gba) { gba->sio.gbp.inputsPosted = 0; gba->sio.gbp.oldCallback = gba->keyCallback; gba->keyCallback = &gba->sio.gbp.callback.d; - // TODO: Check if the SIO driver is actually used first - GBASIOSetDriver(&gba->sio, &gba->sio.gbp.d, SIO_NORMAL_32); + if (!gba->sio.driver) { + GBASIOSetDriver(&gba->sio, &gba->sio.gbp.d); + } } } @@ -100,34 +101,41 @@ uint16_t _gbpRead(struct mKeyCallback* callback) { return 0; } -uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { - struct GBASIOPlayer* gbp = (struct GBASIOPlayer*) driver; - if (address == GBA_REG_SIOCNT) { - if (value & 0x0080) { - uint32_t rx = gbp->p->memory.io[GBA_REG(SIODATA32_LO)] | (gbp->p->memory.io[GBA_REG(SIODATA32_HI)] << 16); - if (gbp->txPosition < 12 && gbp->txPosition > 0) { - // TODO: Check expected - } else if (gbp->txPosition >= 12) { - uint32_t mask = 0x33; - // 0x00 = Stop - // 0x11 = Hard Stop - // 0x22 = Start - if (gbp->p->rumble) { - gbp->p->rumble->setRumble(gbp->p->rumble, (rx & mask) == 0x22); - } - } - mTimingDeschedule(&gbp->p->timing, &gbp->event); - mTimingSchedule(&gbp->p->timing, &gbp->event, 2048); - } - value &= 0x78FB; - } - return value; +uint16_t _gbpSioWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { + UNUSED(driver); + return value & 0x78FB; } -void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) { - UNUSED(timing); - UNUSED(cyclesLate); - struct GBASIOPlayer* gbp = user; +bool _gbpSioStart(struct GBASIODriver* driver) { + struct GBASIOPlayer* gbp = (struct GBASIOPlayer*) driver; + uint32_t rx = gbp->p->memory.io[GBA_REG(SIODATA32_LO)] | (gbp->p->memory.io[GBA_REG(SIODATA32_HI)] << 16); + if (gbp->txPosition < 12 && gbp->txPosition > 0) { + // TODO: Check expected + } else if (gbp->txPosition >= 12) { + // 0x00 = Stop + // 0x11 = Hard Stop + // 0x22 = Start + if (gbp->p->rumble) { + int32_t currentTime = mTimingCurrentTime(&gbp->p->timing); + gbp->p->rumble->setRumble(gbp->p->rumble, (rx & 0x33) == 0x22, currentTime - gbp->p->lastRumble); + gbp->p->lastRumble = currentTime; + } + } + return true; +} + +static bool _gbpSioHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + UNUSED(driver); + return mode == GBA_SIO_NORMAL_32; +} + +static int _gbpSioConnectedDevices(struct GBASIODriver* driver) { + UNUSED(driver); + return 1; +} + +uint32_t _gbpSioFinishNormal32(struct GBASIODriver* driver) { + struct GBASIOPlayer* gbp = (struct GBASIOPlayer*) driver; uint32_t tx = 0; int txPosition = gbp->txPosition; if (txPosition > 16) { @@ -138,11 +146,5 @@ void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLat } tx = _gbpTxData[txPosition]; ++gbp->txPosition; - gbp->p->memory.io[GBA_REG(SIODATA32_LO)] = tx; - gbp->p->memory.io[GBA_REG(SIODATA32_HI)] = tx >> 16; - if (GBASIONormalIsIrq(gbp->d.p->siocnt)) { - GBARaiseIRQ(gbp->p, GBA_IRQ_SIO, cyclesLate); - } - gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt); - gbp->p->memory.io[GBA_REG(SIOCNT)] = gbp->d.p->siocnt & ~0x0080; + return tx; } diff --git a/src/gba/sio/joybus.c b/src/gba/sio/joybus.c deleted file mode 100644 index 941527439..000000000 --- a/src/gba/sio/joybus.c +++ /dev/null @@ -1,92 +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/. */ -#include - -#include -#include - -static uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value); - -void GBASIOJOYCreate(struct GBASIODriver* sio) { - sio->init = NULL; - sio->deinit = NULL; - sio->load = NULL; - sio->unload = NULL; - sio->writeRegister = GBASIOJOYWriteRegister; -} - -uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value) { - switch (address) { - case GBA_REG_JOYCNT: - mLOG(GBA_SIO, DEBUG, "JOY write: CNT <- %04X", value); - return (value & 0x0040) | (sio->p->p->memory.io[GBA_REG(JOYCNT)] & ~(value & 0x7) & ~0x0040); - case GBA_REG_JOYSTAT: - mLOG(GBA_SIO, DEBUG, "JOY write: STAT <- %04X", value); - return (value & 0x0030) | (sio->p->p->memory.io[GBA_REG(JOYSTAT)] & ~0x30); - case GBA_REG_JOY_TRANS_LO: - mLOG(GBA_SIO, DEBUG, "JOY write: TRANS_LO <- %04X", value); - break; - case GBA_REG_JOY_TRANS_HI: - mLOG(GBA_SIO, DEBUG, "JOY write: TRANS_HI <- %04X", value); - break; - default: - mLOG(GBA_SIO, DEBUG, "JOY write: Unknown reg %03X <- %04X", address, value); - // Fall through - case GBA_REG_RCNT: - break; - } - return value; -} - -int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data) { - switch (command) { - case JOY_RESET: - sio->p->p->memory.io[GBA_REG(JOYCNT)] |= JOYCNT_RESET; - if (sio->p->p->memory.io[GBA_REG(JOYCNT)] & 0x40) { - GBARaiseIRQ(sio->p->p, GBA_IRQ_SIO, 0); - } - // Fall through - case JOY_POLL: - data[0] = 0x00; - data[1] = 0x04; - data[2] = sio->p->p->memory.io[GBA_REG(JOYSTAT)]; - - mLOG(GBA_SIO, DEBUG, "JOY %s: %02X (%02X)", command == JOY_POLL ? "poll" : "reset", data[2], sio->p->p->memory.io[GBA_REG(JOYCNT)]); - return 3; - case JOY_RECV: - sio->p->p->memory.io[GBA_REG(JOYCNT)] |= JOYCNT_RECV; - sio->p->p->memory.io[GBA_REG(JOYSTAT)] |= JOYSTAT_RECV; - - sio->p->p->memory.io[GBA_REG(JOY_RECV_LO)] = data[0] | (data[1] << 8); - sio->p->p->memory.io[GBA_REG(JOY_RECV_HI)] = data[2] | (data[3] << 8); - - data[0] = sio->p->p->memory.io[GBA_REG(JOYSTAT)]; - - mLOG(GBA_SIO, DEBUG, "JOY recv: %02X (%02X)", data[0], sio->p->p->memory.io[GBA_REG(JOYCNT)]); - - if (sio->p->p->memory.io[GBA_REG(JOYCNT)] & 0x40) { - GBARaiseIRQ(sio->p->p, GBA_IRQ_SIO, 0); - } - return 1; - case JOY_TRANS: - data[0] = sio->p->p->memory.io[GBA_REG(JOY_TRANS_LO)]; - data[1] = sio->p->p->memory.io[GBA_REG(JOY_TRANS_LO)] >> 8; - data[2] = sio->p->p->memory.io[GBA_REG(JOY_TRANS_HI)]; - data[3] = sio->p->p->memory.io[GBA_REG(JOY_TRANS_HI)] >> 8; - data[4] = sio->p->p->memory.io[GBA_REG(JOYSTAT)]; - - sio->p->p->memory.io[GBA_REG(JOYCNT)] |= JOYCNT_TRANS; - sio->p->p->memory.io[GBA_REG(JOYSTAT)] &= ~JOYSTAT_TRANS; - - mLOG(GBA_SIO, DEBUG, "JOY trans: %02X%02X%02X%02X:%02X (%02X)", data[0], data[1], data[2], data[3], data[4], sio->p->p->memory.io[GBA_REG(JOYCNT)]); - - if (sio->p->p->memory.io[GBA_REG(JOYCNT)] & 0x40) { - GBARaiseIRQ(sio->p->p, GBA_IRQ_SIO, 0); - } - return 5; - } - return 0; -} diff --git a/src/gba/sio/lockstep.c b/src/gba/sio/lockstep.c index 4b7ff858d..a429a31e2 100644 --- a/src/gba/sio/lockstep.c +++ b/src/gba/sio/lockstep.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015 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 @@ -8,569 +8,1056 @@ #include #include -#define LOCKSTEP_INCREMENT 2000 -#define LOCKSTEP_TRANSFER 512 +#define DRIVER_ID 0x6B636F4C +#define DRIVER_STATE_VERSION 1 +#define LOCKSTEP_INTERVAL 4096 +#define UNLOCKED_INTERVAL 4096 +#define HARD_SYNC_INTERVAL 0x80000 +#define TARGET(P) (1 << (P)) +#define TARGET_ALL 0xF +#define TARGET_PRIMARY 0x1 +#define TARGET_SECONDARY ((TARGET_ALL) & ~(TARGET_PRIMARY)) -static bool GBASIOLockstepNodeInit(struct GBASIODriver* driver); -static void GBASIOLockstepNodeDeinit(struct GBASIODriver* driver); -static bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver); -static bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver); -static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); -static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); -static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* driver, uint32_t cyclesLate); -static void _finishTransfer(struct GBASIOLockstepNode* node); +DECL_BITFIELD(GBASIOLockstepSerializedFlags, uint32_t); +DECL_BITS(GBASIOLockstepSerializedFlags, DriverMode, 0, 3); +DECL_BITS(GBASIOLockstepSerializedFlags, NumEvents, 3, 4); +DECL_BIT(GBASIOLockstepSerializedFlags, Asleep, 7); +DECL_BIT(GBASIOLockstepSerializedFlags, DataReceived, 8); +DECL_BIT(GBASIOLockstepSerializedFlags, EventScheduled, 9); +DECL_BITS(GBASIOLockstepSerializedFlags, Player0Mode, 10, 3); +DECL_BITS(GBASIOLockstepSerializedFlags, Player1Mode, 13, 3); +DECL_BITS(GBASIOLockstepSerializedFlags, Player2Mode, 16, 3); +DECL_BITS(GBASIOLockstepSerializedFlags, Player3Mode, 19, 3); +DECL_BITS(GBASIOLockstepSerializedFlags, TransferMode, 28, 3); +DECL_BIT(GBASIOLockstepSerializedFlags, TransferActive, 31); -void GBASIOLockstepInit(struct GBASIOLockstep* lockstep) { - lockstep->players[0] = 0; - lockstep->players[1] = 0; - lockstep->players[2] = 0; - lockstep->players[3] = 0; - lockstep->multiRecv[0] = 0xFFFF; - lockstep->multiRecv[1] = 0xFFFF; - lockstep->multiRecv[2] = 0xFFFF; - lockstep->multiRecv[3] = 0xFFFF; - lockstep->attachedMulti = 0; - lockstep->attachedNormal = 0; -} +DECL_BITFIELD(GBASIOLockstepSerializedEventFlags, uint32_t); +DECL_BITS(GBASIOLockstepSerializedEventFlags, Type, 0, 3); -void GBASIOLockstepNodeCreate(struct GBASIOLockstepNode* node) { - node->d.init = GBASIOLockstepNodeInit; - node->d.deinit = GBASIOLockstepNodeDeinit; - node->d.load = GBASIOLockstepNodeLoad; - node->d.unload = GBASIOLockstepNodeUnload; - node->d.writeRegister = 0; -} +struct GBASIOLockstepSerializedEvent { + int32_t timestamp; + int32_t playerId; + GBASIOLockstepSerializedEventFlags flags; + int32_t reserved[5]; + union { + int32_t mode; + int32_t finishCycle; + int32_t padding[4]; + }; +}; +static_assert(sizeof(struct GBASIOLockstepSerializedEvent) == 0x30, "GBA lockstep event savestate struct sized wrong"); -bool GBASIOLockstepAttachNode(struct GBASIOLockstep* lockstep, struct GBASIOLockstepNode* node) { - if (lockstep->d.attached == MAX_GBAS) { - return false; - } - mLockstepLock(&lockstep->d); - lockstep->players[lockstep->d.attached] = node; - node->p = lockstep; - node->id = lockstep->d.attached; - node->normalSO = true; - node->transferFinished = true; - ++lockstep->d.attached; - mLockstepUnlock(&lockstep->d); - return true; -} +struct GBASIOLockstepSerializedState { + uint32_t version; + GBASIOLockstepSerializedFlags flags; + uint32_t reserved[2]; -void GBASIOLockstepDetachNode(struct GBASIOLockstep* lockstep, struct GBASIOLockstepNode* node) { - if (lockstep->d.attached == 0) { - return; - } - mLockstepLock(&lockstep->d); + struct { + int32_t nextEvent; + uint32_t reservedDriver[7]; + } driver; + + struct { + int32_t playerId; + int32_t cycleOffset; + uint32_t reservedPlayer[2]; + struct GBASIOLockstepSerializedEvent events[MAX_LOCKSTEP_EVENTS]; + } player; + + // playerId 0 only + struct { + int32_t cycle; + uint32_t waiting; + int32_t nextHardSync; + uint32_t reservedCoordinator[3]; + uint16_t multiData[4]; + uint32_t normalData[4]; + } coordinator; +}; +static_assert(offsetof(struct GBASIOLockstepSerializedState, driver) == 0x10, "GBA lockstep savestate driver offset wrong"); +static_assert(offsetof(struct GBASIOLockstepSerializedState, player) == 0x30, "GBA lockstep savestate player offset wrong"); +static_assert(offsetof(struct GBASIOLockstepSerializedState, coordinator) == 0x1C0, "GBA lockstep savestate coordinator offset wrong"); +static_assert(sizeof(struct GBASIOLockstepSerializedState) == 0x1F0, "GBA lockstep savestate struct sized wrong"); + +static bool GBASIOLockstepDriverInit(struct GBASIODriver* driver); +static void GBASIOLockstepDriverDeinit(struct GBASIODriver* driver); +static void GBASIOLockstepDriverReset(struct GBASIODriver* driver); +static uint32_t GBASIOLockstepDriverId(const struct GBASIODriver* driver); +static bool GBASIOLockstepDriverLoadState(struct GBASIODriver* driver, const void* state, size_t size); +static void GBASIOLockstepDriverSaveState(struct GBASIODriver* driver, void** state, size_t* size); +static void GBASIOLockstepDriverSetMode(struct GBASIODriver* driver, enum GBASIOMode mode); +static bool GBASIOLockstepDriverHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode); +static int GBASIOLockstepDriverConnectedDevices(struct GBASIODriver* driver); +static int GBASIOLockstepDriverDeviceId(struct GBASIODriver* driver); +static uint16_t GBASIOLockstepDriverWriteSIOCNT(struct GBASIODriver* driver, uint16_t value); +static uint16_t GBASIOLockstepDriverWriteRCNT(struct GBASIODriver* driver, uint16_t value); +static bool GBASIOLockstepDriverStart(struct GBASIODriver* driver); +static void GBASIOLockstepDriverFinishMultiplayer(struct GBASIODriver* driver, uint16_t data[4]); +static uint8_t GBASIOLockstepDriverFinishNormal8(struct GBASIODriver* driver); +static uint32_t GBASIOLockstepDriverFinishNormal32(struct GBASIODriver* driver); + +static void GBASIOLockstepCoordinatorWaitOnPlayers(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepPlayer*); +static void GBASIOLockstepCoordinatorAckPlayer(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepPlayer*); +static void GBASIOLockstepCoordinatorWakePlayers(struct GBASIOLockstepCoordinator*); + +static int32_t GBASIOLockstepTime(struct GBASIOLockstepPlayer*); +static void GBASIOLockstepPlayerWake(struct GBASIOLockstepPlayer*); +static void GBASIOLockstepPlayerSleep(struct GBASIOLockstepPlayer*); + +static void _advanceCycle(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepPlayer*); +static void _removePlayer(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepPlayer*); +static void _reconfigPlayers(struct GBASIOLockstepCoordinator*); +static int32_t _untilNextSync(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepPlayer*); +static void _enqueueEvent(struct GBASIOLockstepCoordinator*, const struct GBASIOLockstepEvent*, uint32_t target); +static void _setData(struct GBASIOLockstepCoordinator*, uint32_t id, struct GBASIO* sio); +static void _setReady(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepPlayer* activePlayer, int playerId, enum GBASIOMode mode); +static void _hardSync(struct GBASIOLockstepCoordinator*, struct GBASIOLockstepPlayer*); + +static void _lockstepEvent(struct mTiming*, void* context, uint32_t cyclesLate); + +static void _verifyAwake(struct GBASIOLockstepCoordinator* coordinator) { +#ifdef NDEBUG + UNUSED(coordinator); +#else int i; - for (i = 0; i < lockstep->d.attached; ++i) { - if (lockstep->players[i] != node) { + int asleep = 0; + for (i = 0; i < coordinator->nAttached; ++i) { + if (!coordinator->attachedPlayers[i]) { continue; } - for (++i; i < lockstep->d.attached; ++i) { - lockstep->players[i - 1] = lockstep->players[i]; - lockstep->players[i - 1]->id = i - 1; - } - --lockstep->d.attached; - lockstep->players[lockstep->d.attached] = NULL; - break; + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, coordinator->attachedPlayers[i]); + asleep += player->asleep; } - mLockstepUnlock(&lockstep->d); -} - -bool GBASIOLockstepNodeInit(struct GBASIODriver* driver) { - struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; - node->d.p->siocnt = GBASIOMultiplayerSetSlave(node->d.p->siocnt, node->id > 0); - mLOG(GBA_SIO, DEBUG, "Lockstep %i: Node init", node->id); - node->event.context = node; - node->event.name = "GBA SIO Lockstep"; - node->event.callback = _GBASIOLockstepNodeProcessEvents; - node->event.priority = 0x80; - return true; -} - -void GBASIOLockstepNodeDeinit(struct GBASIODriver* driver) { - UNUSED(driver); -} - -bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) { - struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; - node->nextEvent = 0; - node->eventDiff = 0; - mTimingSchedule(&driver->p->p->timing, &node->event, 0); - - mLockstepLock(&node->p->d); - - node->mode = driver->p->mode; - - switch (node->mode) { - case SIO_MULTI: - node->d.writeRegister = GBASIOLockstepNodeMultiWriteRegister; - node->d.p->rcnt |= 3; - ATOMIC_ADD(node->p->attachedMulti, 1); - node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, node->p->attachedMulti == node->p->d.attached); - if (node->id) { - node->d.p->rcnt |= 4; - node->d.p->siocnt = GBASIOMultiplayerFillSlave(node->d.p->siocnt); - - int try; - for (try = 0; try < 3; ++try) { - uint16_t masterSiocnt; - ATOMIC_LOAD(masterSiocnt, node->p->players[0]->d.p->siocnt); - if (ATOMIC_CMPXCHG(node->p->players[0]->d.p->siocnt, masterSiocnt, GBASIOMultiplayerClearSlave(masterSiocnt))) { - break; - } - } - } else { - node->d.p->rcnt &= ~4; - node->d.p->siocnt = GBASIOMultiplayerClearSlave(node->d.p->siocnt); - } - break; - case SIO_NORMAL_8: - case SIO_NORMAL_32: - if (ATOMIC_ADD(node->p->attachedNormal, 1) > node->id + 1 && node->id > 0) { - node->d.p->siocnt = GBASIONormalSetSi(node->d.p->siocnt, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt)); - } else { - node->d.p->siocnt = GBASIONormalClearSi(node->d.p->siocnt); - } - node->d.writeRegister = GBASIOLockstepNodeNormalWriteRegister; - break; - default: - break; - } -#ifndef NDEBUG - node->phase = node->p->d.transferActive; - node->transferId = node->p->d.transferId; + mASSERT_DEBUG(!asleep || asleep < coordinator->nAttached); #endif +} - mLockstepUnlock(&node->p->d); +void GBASIOLockstepDriverCreate(struct GBASIOLockstepDriver* driver, struct mLockstepUser* user) { + memset(driver, 0, sizeof(*driver)); + driver->d.init = GBASIOLockstepDriverInit; + driver->d.deinit = GBASIOLockstepDriverDeinit; + driver->d.reset = GBASIOLockstepDriverReset; + driver->d.driverId = GBASIOLockstepDriverId; + driver->d.loadState = GBASIOLockstepDriverLoadState; + driver->d.saveState = GBASIOLockstepDriverSaveState; + driver->d.setMode = GBASIOLockstepDriverSetMode; + driver->d.handlesMode = GBASIOLockstepDriverHandlesMode; + driver->d.deviceId = GBASIOLockstepDriverDeviceId; + driver->d.connectedDevices = GBASIOLockstepDriverConnectedDevices; + driver->d.writeSIOCNT = GBASIOLockstepDriverWriteSIOCNT; + driver->d.writeRCNT = GBASIOLockstepDriverWriteRCNT; + driver->d.start = GBASIOLockstepDriverStart; + driver->d.finishMultiplayer = GBASIOLockstepDriverFinishMultiplayer; + driver->d.finishNormal8 = GBASIOLockstepDriverFinishNormal8; + driver->d.finishNormal32 = GBASIOLockstepDriverFinishNormal32; + driver->event.context = driver; + driver->event.callback = _lockstepEvent; + driver->event.name = "GBA SIO Lockstep"; + driver->event.priority = 0x80; + driver->user = user; +} +static bool GBASIOLockstepDriverInit(struct GBASIODriver* driver) { + GBASIOLockstepDriverReset(driver); return true; } -bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver) { - struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; - - mLockstepLock(&node->p->d); - - node->mode = driver->p->mode; - switch (node->mode) { - case SIO_MULTI: - ATOMIC_SUB(node->p->attachedMulti, 1); - break; - case SIO_NORMAL_8: - case SIO_NORMAL_32: - ATOMIC_SUB(node->p->attachedNormal, 1); - break; - default: - break; +static void GBASIOLockstepDriverDeinit(struct GBASIODriver* driver) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + MutexLock(&coordinator->mutex); + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + if (player) { + _removePlayer(coordinator, player); } - - // Flush ongoing transfer - if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { - node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); - mTimingDeschedule(&driver->p->p->timing, &node->event); - } - - node->p->d.unload(&node->p->d, node->id); - - _finishTransfer(node); - - if (!node->id) { - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_IDLE); - } - - // Invalidate SIO mode - node->mode = SIO_GPIO; - - mLockstepUnlock(&node->p->d); - - return true; + MutexUnlock(&coordinator->mutex); + mTimingDeschedule(&lockstep->d.p->p->timing, &lockstep->event); + lockstep->lockstepId = 0; } -static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { - struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; +static void GBASIOLockstepDriverReset(struct GBASIODriver* driver) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + struct GBASIOLockstepPlayer* player; + if (!lockstep->lockstepId) { + unsigned id; + player = calloc(1, sizeof(*player)); + player->driver = lockstep; + player->mode = driver->p->mode; + player->playerId = -1; - mLockstepLock(&node->p->d); + int i; + for (i = 0; i < MAX_LOCKSTEP_EVENTS - 1; ++i) { + player->buffer[i].next = &player->buffer[i + 1]; + } + player->freeList = &player->buffer[0]; - if (address == GBA_REG_SIOCNT) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value); - - enum mLockstepPhase transferActive; - int attached; - ATOMIC_LOAD(transferActive, node->p->d.transferActive); - ATOMIC_LOAD(attached, node->p->d.attached); - - driver->p->siocnt = GBASIOMultiplayerSetSlave(driver->p->siocnt, node->id || attached < 2); - - if (value & 0x0080 && transferActive == TRANSFER_IDLE) { - if (!node->id && attached > 1 && GBASIOMultiplayerIsReady(node->d.p->siocnt)) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id); - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); - ATOMIC_STORE(node->p->d.transferCycles, GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][node->p->d.attached - 1]); - - if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { - node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); - mTimingDeschedule(&driver->p->p->timing, &node->event); - } - mTimingSchedule(&driver->p->p->timing, &node->event, 0); - } else { - value &= ~0x0080; + MutexLock(&coordinator->mutex); + while (true) { + if (coordinator->nextId == UINT_MAX) { + coordinator->nextId = 0; + } + ++coordinator->nextId; + id = coordinator->nextId; + if (!TableLookup(&coordinator->players, id)) { + TableInsert(&coordinator->players, id, player); + lockstep->lockstepId = id; + break; } } - value &= 0xFF83; - value |= driver->p->siocnt & 0x00FC; - } else if (address == GBA_REG_SIOMLT_SEND) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOMLT_SEND <- %04X", node->id, value); + _reconfigPlayers(coordinator); + player->cycleOffset = mTimingCurrentTime(&driver->p->p->timing) - coordinator->cycle; + if (player->playerId != 0) { + struct GBASIOLockstepEvent event = { + .type = SIO_EV_ATTACH, + .playerId = player->playerId, + .timestamp = GBASIOLockstepTime(player), + }; + _enqueueEvent(coordinator, &event, TARGET_ALL & ~TARGET(player->playerId)); + } } else { - mLOG(GBA_SIO, STUB, "Lockstep %i: Unknown reg %03X <- %04X", node->id, address, value); + player = TableLookup(&coordinator->players, lockstep->lockstepId); + player->cycleOffset = mTimingCurrentTime(&driver->p->p->timing) - coordinator->cycle; } - mLockstepUnlock(&node->p->d); - - return value; -} - -static void _finishTransfer(struct GBASIOLockstepNode* node) { - if (node->transferFinished) { + if (mTimingIsScheduled(&lockstep->d.p->p->timing, &lockstep->event)) { + MutexUnlock(&coordinator->mutex); return; } - struct GBASIO* sio = node->d.p; - switch (node->mode) { - case SIO_MULTI: - sio->p->memory.io[GBA_REG(SIOMULTI0)] = node->p->multiRecv[0]; - sio->p->memory.io[GBA_REG(SIOMULTI1)] = node->p->multiRecv[1]; - sio->p->memory.io[GBA_REG(SIOMULTI2)] = node->p->multiRecv[2]; - sio->p->memory.io[GBA_REG(SIOMULTI3)] = node->p->multiRecv[3]; - sio->rcnt |= 1; - sio->siocnt = GBASIOMultiplayerClearBusy(sio->siocnt); - sio->siocnt = GBASIOMultiplayerSetId(sio->siocnt, node->id); - if (GBASIOMultiplayerIsIrq(sio->siocnt)) { - GBARaiseIRQ(sio->p, GBA_IRQ_SIO, 0); - } - break; - case SIO_NORMAL_8: - // TODO - sio->siocnt = GBASIONormalClearStart(sio->siocnt); - if (node->id) { - sio->siocnt = GBASIONormalSetSi(sio->siocnt, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt)); - node->d.p->p->memory.io[GBA_REG(SIODATA8)] = node->p->normalRecv[node->id - 1] & 0xFF; - } else { - node->d.p->p->memory.io[GBA_REG(SIODATA8)] = 0xFFFF; - } - if (GBASIONormalIsIrq(sio->siocnt)) { - GBARaiseIRQ(sio->p, GBA_IRQ_SIO, 0); - } - break; - case SIO_NORMAL_32: - // TODO - sio->siocnt = GBASIONormalClearStart(sio->siocnt); - if (node->id) { - sio->siocnt = GBASIONormalSetSi(sio->siocnt, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt)); - node->d.p->p->memory.io[GBA_REG(SIODATA32_LO)] = node->p->normalRecv[node->id - 1]; - node->d.p->p->memory.io[GBA_REG(SIODATA32_HI)] = node->p->normalRecv[node->id - 1] >> 16; - } else { - node->d.p->p->memory.io[GBA_REG(SIODATA32_LO)] = 0xFFFF; - node->d.p->p->memory.io[GBA_REG(SIODATA32_HI)] = 0xFFFF; - } - if (GBASIONormalIsIrq(sio->siocnt)) { - GBARaiseIRQ(sio->p, GBA_IRQ_SIO, 0); - } - break; - default: - break; + int32_t nextEvent; + _setReady(coordinator, player, player->playerId, player->mode); + if (TableSize(&coordinator->players) == 1) { + coordinator->cycle = mTimingCurrentTime(&lockstep->d.p->p->timing); + nextEvent = LOCKSTEP_INTERVAL; + } else { + _setReady(coordinator, player, 0, coordinator->transferMode); + nextEvent = _untilNextSync(lockstep->coordinator, player); } - node->transferFinished = true; -#ifndef NDEBUG - ++node->transferId; -#endif + MutexUnlock(&coordinator->mutex); + mTimingSchedule(&lockstep->d.p->p->timing, &lockstep->event, nextEvent); } -static int32_t _masterUpdate(struct GBASIOLockstepNode* node) { - bool needsToWait = false; - int i; +static uint32_t GBASIOLockstepDriverId(const struct GBASIODriver* driver) { + UNUSED(driver); + return DRIVER_ID; +} - enum mLockstepPhase transferActive; - int attachedMulti, attached; - - ATOMIC_LOAD(transferActive, node->p->d.transferActive); - ATOMIC_LOAD(attachedMulti, node->p->attachedMulti); - ATOMIC_LOAD(attached, node->p->d.attached); - - switch (transferActive) { - case TRANSFER_IDLE: - // If the master hasn't initiated a transfer, it can keep going. - node->nextEvent += LOCKSTEP_INCREMENT; - if (node->mode == SIO_MULTI) { - node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, attachedMulti == attached); - } - break; - case TRANSFER_STARTING: - // Start the transfer, but wait for the other GBAs to catch up - node->transferFinished = false; - switch (node->mode) { - case SIO_MULTI: - node->p->multiRecv[0] = node->d.p->p->memory.io[GBA_REG(SIOMLT_SEND)]; - node->d.p->p->memory.io[GBA_REG(SIOMULTI0)] = 0xFFFF; - node->d.p->p->memory.io[GBA_REG(SIOMULTI1)] = 0xFFFF; - node->d.p->p->memory.io[GBA_REG(SIOMULTI2)] = 0xFFFF; - node->d.p->p->memory.io[GBA_REG(SIOMULTI3)] = 0xFFFF; - node->p->multiRecv[1] = 0xFFFF; - node->p->multiRecv[2] = 0xFFFF; - node->p->multiRecv[3] = 0xFFFF; - break; - case SIO_NORMAL_8: - node->p->multiRecv[0] = 0xFFFF; - node->p->normalRecv[0] = node->d.p->p->memory.io[GBA_REG(SIODATA8)] & 0xFF; - break; - case SIO_NORMAL_32: - node->p->multiRecv[0] = 0xFFFF; - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_LO <- %04X", node->id, node->d.p->p->memory.io[GBA_REG(SIODATA32_LO)]); - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_HI <- %04X", node->id, node->d.p->p->memory.io[GBA_REG(SIODATA32_HI)]); - node->p->normalRecv[0] = node->d.p->p->memory.io[GBA_REG(SIODATA32_LO)]; - node->p->normalRecv[0] |= node->d.p->p->memory.io[GBA_REG(SIODATA32_HI)] << 16; - break; - default: - node->p->multiRecv[0] = 0xFFFF; - break; - } - needsToWait = true; - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTED); - node->nextEvent += LOCKSTEP_TRANSFER; - break; - case TRANSFER_STARTED: - // All the other GBAs have caught up and are sleeping, we can all continue now - node->nextEvent += LOCKSTEP_TRANSFER; - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_FINISHING); - break; - case TRANSFER_FINISHING: - // Finish the transfer - // We need to make sure the other GBAs catch up so they don't get behind - node->nextEvent += node->p->d.transferCycles - 1024; // Split the cycles to avoid waiting too long -#ifndef NDEBUG - ATOMIC_ADD(node->p->d.transferId, 1); -#endif - needsToWait = true; - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_FINISHED); - break; - case TRANSFER_FINISHED: - // Everything's settled. We're done. - _finishTransfer(node); - node->nextEvent += LOCKSTEP_INCREMENT; - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_IDLE); - break; +static unsigned _modeEnumToInt(enum GBASIOMode mode) { + switch ((int) mode) { + case -1: + default: + return 0; + case GBA_SIO_MULTI: + return 1; + case GBA_SIO_NORMAL_8: + return 2; + case GBA_SIO_NORMAL_32: + return 3; + case GBA_SIO_GPIO: + return 4; + case GBA_SIO_UART: + return 5; + case GBA_SIO_JOYBUS: + return 6; } - int mask = 0; - for (i = 1; i < node->p->d.attached; ++i) { - if (node->p->players[i]->mode == node->mode) { - mask |= 1 << i; +} + +static enum GBASIOMode _modeIntToEnum(unsigned mode) { + const enum GBASIOMode modes[8] = { + -1, GBA_SIO_MULTI, GBA_SIO_NORMAL_8, GBA_SIO_NORMAL_32, GBA_SIO_GPIO, GBA_SIO_UART, GBA_SIO_JOYBUS, -1 + }; + return modes[mode & 7]; +} + +static bool GBASIOLockstepDriverLoadState(struct GBASIODriver* driver, const void* data, size_t size) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + if (size != sizeof(struct GBASIOLockstepSerializedState)) { + mLOG(GBA_SIO, WARN, "Incorrect state size: expected %" PRIz "X, got %" PRIz "X", sizeof(struct GBASIOLockstepSerializedState), size); + return false; + } + const struct GBASIOLockstepSerializedState* state = data; + bool error = false; + uint32_t ucheck; + int32_t check; + LOAD_32LE(ucheck, 0, &state->version); + if (ucheck > DRIVER_STATE_VERSION) { + mLOG(GBA_SIO, WARN, "Invalid or too new save state: expected %u, got %u", DRIVER_STATE_VERSION, ucheck); + return false; + } + + MutexLock(&coordinator->mutex); + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + LOAD_32LE(check, 0, &state->player.playerId); + if (check != player->playerId) { + mLOG(GBA_SIO, WARN, "State is for different player: expected %d, got %d", player->playerId, check); + error = true; + goto out; + } + + GBASIOLockstepSerializedFlags flags = 0; + LOAD_32LE(flags, 0, &state->flags); + LOAD_32LE(player->cycleOffset, 0, &state->player.cycleOffset); + player->dataReceived = GBASIOLockstepSerializedFlagsGetDataReceived(flags); + player->mode = _modeIntToEnum(GBASIOLockstepSerializedFlagsGetDriverMode(flags)); + + player->otherModes[0] = _modeIntToEnum(GBASIOLockstepSerializedFlagsGetPlayer0Mode(flags)); + player->otherModes[1] = _modeIntToEnum(GBASIOLockstepSerializedFlagsGetPlayer1Mode(flags)); + player->otherModes[2] = _modeIntToEnum(GBASIOLockstepSerializedFlagsGetPlayer2Mode(flags)); + player->otherModes[3] = _modeIntToEnum(GBASIOLockstepSerializedFlagsGetPlayer3Mode(flags)); + + if (GBASIOLockstepSerializedFlagsGetEventScheduled(flags)) { + int32_t when; + LOAD_32LE(when, 0, &state->driver.nextEvent); + mTimingSchedule(&driver->p->p->timing, &lockstep->event, when); + } + + if (GBASIOLockstepSerializedFlagsGetAsleep(flags)) { + if (!player->asleep && player->driver->user->sleep) { + player->driver->user->sleep(player->driver->user); + } + player->asleep = true; + } else { + if (player->asleep && player->driver->user->wake) { + player->driver->user->wake(player->driver->user); + } + player->asleep = false; + } + + unsigned i; + for (i = 0; i < MAX_LOCKSTEP_EVENTS - 1; ++i) { + player->buffer[i].next = &player->buffer[i + 1]; + } + player->freeList = &player->buffer[0]; + player->queue = NULL; + + struct GBASIOLockstepEvent** lastEvent = &player->queue; + for (i = 0; i < GBASIOLockstepSerializedFlagsGetNumEvents(flags) && i < MAX_LOCKSTEP_EVENTS; ++i) { + struct GBASIOLockstepEvent* event = player->freeList; + const struct GBASIOLockstepSerializedEvent* stateEvent = &state->player.events[i]; + player->freeList = player->freeList->next; + *lastEvent = event; + lastEvent = &event->next; + + GBASIOLockstepSerializedEventFlags flags; + LOAD_32LE(flags, 0, &stateEvent->flags); + LOAD_32LE(event->timestamp, 0, &stateEvent->timestamp); + LOAD_32LE(event->playerId, 0, &stateEvent->playerId); + event->type = GBASIOLockstepSerializedEventFlagsGetType(flags); + switch (event->type) { + case SIO_EV_ATTACH: + case SIO_EV_DETACH: + case SIO_EV_HARD_SYNC: + break; + case SIO_EV_MODE_SET: + LOAD_32LE(event->mode, 0, &stateEvent->mode); + break; + case SIO_EV_TRANSFER_START: + LOAD_32LE(event->finishCycle, 0, &stateEvent->finishCycle); + break; } } - if (mask) { - if (needsToWait) { - if (!node->p->d.wait(&node->p->d, mask)) { - abort(); - } - } else { - node->p->d.signal(&node->p->d, mask); - } - } - // Tell the other GBAs they can continue up to where we were - node->p->d.addCycles(&node->p->d, 0, node->eventDiff); -#ifndef NDEBUG - node->phase = node->p->d.transferActive; -#endif - if (needsToWait) { + if (player->playerId == 0) { + LOAD_32LE(coordinator->cycle, 0, &state->coordinator.cycle); + LOAD_32LE(coordinator->waiting, 0, &state->coordinator.waiting); + LOAD_32LE(coordinator->nextHardSync, 0, &state->coordinator.nextHardSync); + for (i = 0; i < 4; ++i) { + LOAD_16LE(coordinator->multiData[i], 0, &state->coordinator.multiData[i]); + LOAD_32LE(coordinator->normalData[i], 0, &state->coordinator.normalData[i]); + } + coordinator->transferMode = _modeIntToEnum(GBASIOLockstepSerializedFlagsGetTransferMode(flags)); + coordinator->transferActive = GBASIOLockstepSerializedFlagsGetTransferActive(flags); + } +out: + MutexUnlock(&coordinator->mutex); + if (!error) { + mTimingInterrupt(&driver->p->p->timing); + } + return !error; +} + +static void GBASIOLockstepDriverSaveState(struct GBASIODriver* driver, void** stateOut, size_t* size) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + struct GBASIOLockstepSerializedState* state = calloc(1, sizeof(*state)); + + STORE_32LE(DRIVER_STATE_VERSION, 0, &state->version); + + STORE_32LE(lockstep->event.when - mTimingCurrentTime(&driver->p->p->timing), 0, &state->driver.nextEvent); + + MutexLock(&coordinator->mutex); + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + GBASIOLockstepSerializedFlags flags = 0; + STORE_32LE(player->playerId, 0, &state->player.playerId); + STORE_32LE(player->cycleOffset, 0, &state->player.cycleOffset); + flags = GBASIOLockstepSerializedFlagsSetAsleep(flags, player->asleep); + flags = GBASIOLockstepSerializedFlagsSetDataReceived(flags, player->dataReceived); + flags = GBASIOLockstepSerializedFlagsSetDriverMode(flags, _modeEnumToInt(player->mode)); + flags = GBASIOLockstepSerializedFlagsSetEventScheduled(flags, mTimingIsScheduled(&driver->p->p->timing, &lockstep->event)); + + flags = GBASIOLockstepSerializedFlagsSetPlayer0Mode(flags, _modeEnumToInt(player->otherModes[0])); + flags = GBASIOLockstepSerializedFlagsSetPlayer1Mode(flags, _modeEnumToInt(player->otherModes[1])); + flags = GBASIOLockstepSerializedFlagsSetPlayer2Mode(flags, _modeEnumToInt(player->otherModes[2])); + flags = GBASIOLockstepSerializedFlagsSetPlayer3Mode(flags, _modeEnumToInt(player->otherModes[3])); + + struct GBASIOLockstepEvent* event = player->queue; + size_t i; + for (i = 0; i < MAX_LOCKSTEP_EVENTS && event; ++i, event = event->next) { + struct GBASIOLockstepSerializedEvent* stateEvent = &state->player.events[i]; + GBASIOLockstepSerializedEventFlags flags = GBASIOLockstepSerializedEventFlagsSetType(0, event->type); + STORE_32LE(event->timestamp, 0, &stateEvent->timestamp); + STORE_32LE(event->playerId, 0, &stateEvent->playerId); + switch (event->type) { + case SIO_EV_ATTACH: + case SIO_EV_DETACH: + case SIO_EV_HARD_SYNC: + break; + case SIO_EV_MODE_SET: + STORE_32LE(event->mode, 0, &stateEvent->mode); + break; + case SIO_EV_TRANSFER_START: + STORE_32LE(event->finishCycle, 0, &stateEvent->finishCycle); + break; + } + STORE_32LE(flags, 0, &stateEvent->flags); + } + flags = GBASIOLockstepSerializedFlagsSetNumEvents(flags, i); + + if (player->playerId == 0) { + STORE_32LE(coordinator->cycle, 0, &state->coordinator.cycle); + STORE_32LE(coordinator->waiting, 0, &state->coordinator.waiting); + STORE_32LE(coordinator->nextHardSync, 0, &state->coordinator.nextHardSync); + for (i = 0; i < 4; ++i) { + STORE_16LE(coordinator->multiData[i], 0, &state->coordinator.multiData[i]); + STORE_32LE(coordinator->normalData[i], 0, &state->coordinator.normalData[i]); + } + flags = GBASIOLockstepSerializedFlagsSetTransferMode(flags, _modeEnumToInt(coordinator->transferMode)); + flags = GBASIOLockstepSerializedFlagsSetTransferActive(flags, coordinator->transferActive); + } + MutexUnlock(&lockstep->coordinator->mutex); + + STORE_32LE(flags, 0, &state->flags); + *stateOut = state; + *size = sizeof(*state); +} + +static void GBASIOLockstepDriverSetMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + MutexLock(&coordinator->mutex); + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + if (mode != player->mode) { + player->mode = mode; + struct GBASIOLockstepEvent event = { + .type = SIO_EV_MODE_SET, + .playerId = player->playerId, + .timestamp = GBASIOLockstepTime(player), + .mode = mode, + }; + if (player->playerId == 0) { + mASSERT_DEBUG(!coordinator->transferActive); // TODO + coordinator->transferMode = mode; + GBASIOLockstepCoordinatorWaitOnPlayers(coordinator, player); + } + _setReady(coordinator, player, player->playerId, mode); + _enqueueEvent(coordinator, &event, TARGET_ALL & ~TARGET(player->playerId)); + } + MutexUnlock(&coordinator->mutex); +} + +static bool GBASIOLockstepDriverHandlesMode(struct GBASIODriver* driver, enum GBASIOMode mode) { + UNUSED(driver); + UNUSED(mode); + return true; +} + +static int GBASIOLockstepDriverConnectedDevices(struct GBASIODriver* driver) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + if (!lockstep->lockstepId) { return 0; } - return node->nextEvent; + MutexLock(&coordinator->mutex); + int attached = coordinator->nAttached - 1; + MutexUnlock(&coordinator->mutex); + return attached; } -static uint32_t _slaveUpdate(struct GBASIOLockstepNode* node) { - enum mLockstepPhase transferActive; - int attached; - int attachedMode; - - ATOMIC_LOAD(transferActive, node->p->d.transferActive); - ATOMIC_LOAD(attached, node->p->d.attached); - - if (node->mode == SIO_MULTI) { - ATOMIC_LOAD(attachedMode, node->p->attachedMulti); - node->d.p->siocnt = GBASIOMultiplayerSetReady(node->d.p->siocnt, attachedMode == attached); - } else { - ATOMIC_LOAD(attachedMode, node->p->attachedNormal); +static int GBASIOLockstepDriverDeviceId(struct GBASIODriver* driver) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + int playerId = 0; + MutexLock(&coordinator->mutex); + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + if (player && player->playerId >= 0) { + playerId = player->playerId; } - bool signal = false; - switch (transferActive) { - case TRANSFER_IDLE: - if (attachedMode != attached) { - node->p->d.addCycles(&node->p->d, node->id, LOCKSTEP_INCREMENT); - } - break; - case TRANSFER_STARTING: - case TRANSFER_FINISHING: - break; - case TRANSFER_STARTED: - if (node->p->d.unusedCycles(&node->p->d, node->id) > node->eventDiff) { - break; - } - node->transferFinished = false; - switch (node->mode) { - case SIO_MULTI: - node->d.p->rcnt &= ~1; - node->p->multiRecv[node->id] = node->d.p->p->memory.io[GBA_REG(SIOMLT_SEND)]; - node->d.p->p->memory.io[GBA_REG(SIOMULTI0)] = 0xFFFF; - node->d.p->p->memory.io[GBA_REG(SIOMULTI1)] = 0xFFFF; - node->d.p->p->memory.io[GBA_REG(SIOMULTI2)] = 0xFFFF; - node->d.p->p->memory.io[GBA_REG(SIOMULTI3)] = 0xFFFF; - node->d.p->siocnt = GBASIOMultiplayerFillBusy(node->d.p->siocnt); - break; - case SIO_NORMAL_8: - node->p->multiRecv[node->id] = 0xFFFF; - node->p->normalRecv[node->id] = node->d.p->p->memory.io[GBA_REG(SIODATA8)] & 0xFF; - break; - case SIO_NORMAL_32: - node->p->multiRecv[node->id] = 0xFFFF; - node->p->normalRecv[node->id] = node->d.p->p->memory.io[GBA_REG(SIODATA32_LO)]; - node->p->normalRecv[node->id] |= node->d.p->p->memory.io[GBA_REG(SIODATA32_HI)] << 16; - break; - default: - node->p->multiRecv[node->id] = 0xFFFF; - break; - } - signal = true; - break; - case TRANSFER_FINISHED: - if (node->p->d.unusedCycles(&node->p->d, node->id) > node->eventDiff) { - break; - } - _finishTransfer(node); - signal = true; - break; - } -#ifndef NDEBUG - node->phase = node->p->d.transferActive; -#endif - if (signal) { - node->p->d.signal(&node->p->d, 1 << node->id); - } - - return 0; + MutexUnlock(&coordinator->mutex); + return playerId; } -static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) { - struct GBASIOLockstepNode* node = user; - mLockstepLock(&node->p->d); - - int32_t cycles = node->nextEvent; - node->nextEvent -= cyclesLate; - node->eventDiff += cyclesLate; - if (node->p->d.attached < 2) { - switch (node->mode) { - case SIO_MULTI: - cycles = GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][0]; - break; - case SIO_NORMAL_8: - case SIO_NORMAL_32: - if (node->nextEvent <= 0) { - cycles = _masterUpdate(node); - node->eventDiff = 0; - } - break; - default: - break; - } - } else if (node->nextEvent <= 0) { - if (!node->id) { - cycles = _masterUpdate(node); - } else { - cycles = _slaveUpdate(node); - cycles += node->p->d.useCycles(&node->p->d, node->id, node->eventDiff); - } - node->eventDiff = 0; - } - if (cycles > 0) { - node->nextEvent = 0; - node->eventDiff += cycles; - mTimingDeschedule(timing, &node->event); - mTimingSchedule(timing, &node->event, cycles); - } else { - node->d.p->p->earlyExit = true; - node->eventDiff += 1; - mTimingSchedule(timing, &node->event, 1); - } - - mLockstepUnlock(&node->p->d); -} - -static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { - struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver; - - mLockstepLock(&node->p->d); - - if (address == GBA_REG_SIOCNT) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value); - int attached; - ATOMIC_LOAD(attached, node->p->attachedNormal); - value &= 0xFF8B; - if (node->id > 0) { - value = GBASIONormalSetSi(value, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt)); - } else { - value = GBASIONormalClearSi(value); - } - - enum mLockstepPhase transferActive; - ATOMIC_LOAD(transferActive, node->p->d.transferActive); - if (node->id < 3 && attached > node->id + 1 && transferActive == TRANSFER_IDLE) { - int try; - for (try = 0; try < 3; ++try) { - GBASIONormal nextSiocnct; - ATOMIC_LOAD(nextSiocnct, node->p->players[node->id + 1]->d.p->siocnt); - if (ATOMIC_CMPXCHG(node->p->players[node->id + 1]->d.p->siocnt, nextSiocnct, GBASIONormalSetSi(nextSiocnct, GBASIONormalGetIdleSo(value)))) { - break; - } - } - } - if ((value & 0x0081) == 0x0081) { - if (!node->id) { - // Frequency - int32_t cycles; - if (value & 2) { - cycles = 8 * 8; - } else { - cycles = 64 * 8; - } - if (value & 0x1000) { - cycles *= 4; - } - - if (transferActive == TRANSFER_IDLE) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id); - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); - ATOMIC_STORE(node->p->d.transferCycles, cycles); - - if (mTimingIsScheduled(&driver->p->p->timing, &node->event)) { - node->eventDiff -= node->event.when - mTimingCurrentTime(&driver->p->p->timing); - mTimingDeschedule(&driver->p->p->timing, &node->event); - } - mTimingSchedule(&driver->p->p->timing, &node->event, 0); - } else { - value &= ~0x0080; - } - } else { - // TODO - } - } - } else if (address == GBA_REG_SIODATA32_LO) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_LO <- %04X", node->id, value); - } else if (address == GBA_REG_SIODATA32_HI) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_HI <- %04X", node->id, value); - } else if (address == GBA_REG_SIODATA8) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA8 <- %02X", node->id, value); - } - - mLockstepUnlock(&node->p->d); - +static uint16_t GBASIOLockstepDriverWriteSIOCNT(struct GBASIODriver* driver, uint16_t value) { + UNUSED(driver); + mLOG(GBA_SIO, DEBUG, "Lockstep: SIOCNT <- %04X", value); return value; } + +static uint16_t GBASIOLockstepDriverWriteRCNT(struct GBASIODriver* driver, uint16_t value) { + UNUSED(driver); + mLOG(GBA_SIO, DEBUG, "Lockstep: RCNT <- %04X", value); + return value; +} + +static bool GBASIOLockstepDriverStart(struct GBASIODriver* driver) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + bool ret = false; + MutexLock(&coordinator->mutex); + if (coordinator->transferActive) { + mLOG(GBA_SIO, ERROR, "Transfer restarted unexpectedly"); + goto out; + } + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + if (player->playerId != 0) { + mLOG(GBA_SIO, DEBUG, "Secondary player attempted to start transfer"); + goto out; + } + mLOG(GBA_SIO, DEBUG, "Transfer starting at %08X", coordinator->cycle); + memset(coordinator->multiData, 0xFF, sizeof(coordinator->multiData)); + _setData(coordinator, 0, player->driver->d.p); + + int32_t timestamp = GBASIOLockstepTime(player); + struct GBASIOLockstepEvent event = { + .type = SIO_EV_TRANSFER_START, + .timestamp = timestamp, + .finishCycle = timestamp + GBASIOTransferCycles(player->mode, player->driver->d.p->siocnt, coordinator->nAttached - 1), + }; + _enqueueEvent(coordinator, &event, TARGET_SECONDARY); + GBASIOLockstepCoordinatorWaitOnPlayers(coordinator, player); + coordinator->transferActive = true; + ret = true; +out: + MutexUnlock(&coordinator->mutex); + return ret; +} + +static void GBASIOLockstepDriverFinishMultiplayer(struct GBASIODriver* driver, uint16_t data[4]) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + MutexLock(&coordinator->mutex); + if (coordinator->transferMode == GBA_SIO_MULTI) { + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + if (!player->dataReceived) { + mLOG(GBA_SIO, WARN, "MULTI did not receive data. Are we running behind?"); + memset(data, 0xFF, sizeof(uint16_t) * 4); + } else { + mLOG(GBA_SIO, INFO, "MULTI transfer finished: %04X %04X %04X %04X", + coordinator->multiData[0], + coordinator->multiData[1], + coordinator->multiData[2], + coordinator->multiData[3]); + memcpy(data, coordinator->multiData, sizeof(uint16_t) * 4); + } + player->dataReceived = false; + if (player->playerId == 0) { + _hardSync(coordinator, player); + } + } + MutexUnlock(&coordinator->mutex); +} + +static uint8_t GBASIOLockstepDriverFinishNormal8(struct GBASIODriver* driver) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + uint8_t data = 0xFF; + MutexLock(&coordinator->mutex); + if (coordinator->transferMode == GBA_SIO_NORMAL_8) { + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + if (player->playerId > 0) { + if (!player->dataReceived) { + mLOG(GBA_SIO, WARN, "NORMAL did not receive data. Are we running behind?"); + } else { + data = coordinator->normalData[player->playerId - 1]; + mLOG(GBA_SIO, INFO, "NORMAL8 transfer finished: %02X", data); + } + } + player->dataReceived = false; + if (player->playerId == 0) { + _hardSync(coordinator, player); + } + } + MutexUnlock(&coordinator->mutex); + return data; +} + +static uint32_t GBASIOLockstepDriverFinishNormal32(struct GBASIODriver* driver) { + struct GBASIOLockstepDriver* lockstep = (struct GBASIOLockstepDriver*) driver; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + uint32_t data = 0xFFFFFFFF; + MutexLock(&coordinator->mutex); + if (coordinator->transferMode == GBA_SIO_NORMAL_32) { + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + if (player->playerId > 0) { + if (!player->dataReceived) { + mLOG(GBA_SIO, WARN, "Did not receive data. Are we running behind?"); + } else { + data = coordinator->normalData[player->playerId - 1]; + mLOG(GBA_SIO, INFO, "NORMAL32 transfer finished: %08X", data); + } + } + player->dataReceived = false; + if (player->playerId == 0) { + _hardSync(coordinator, player); + } + } + MutexUnlock(&coordinator->mutex); + return data; +} + +void GBASIOLockstepCoordinatorInit(struct GBASIOLockstepCoordinator* coordinator) { + memset(coordinator, 0, sizeof(*coordinator)); + MutexInit(&coordinator->mutex); + TableInit(&coordinator->players, 8, free); +} + +void GBASIOLockstepCoordinatorDeinit(struct GBASIOLockstepCoordinator* coordinator) { + MutexDeinit(&coordinator->mutex); + TableDeinit(&coordinator->players); +} + +void GBASIOLockstepCoordinatorAttach(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOLockstepDriver* driver) { + if (driver->coordinator && driver->coordinator != coordinator) { + // TODO + abort(); + } + driver->coordinator = coordinator; +} + +void GBASIOLockstepCoordinatorDetach(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOLockstepDriver* driver) { + if (driver->coordinator != coordinator) { + // TODO + abort(); + return; + } + MutexLock(&coordinator->mutex); + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, driver->lockstepId); + if (player) { + _removePlayer(coordinator, player); + } + MutexUnlock(&coordinator->mutex); + driver->coordinator = NULL; +} + +int32_t _untilNextSync(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOLockstepPlayer* player) { + int32_t cycle = coordinator->cycle - GBASIOLockstepTime(player); + if (player->playerId == 0) { + if (coordinator->nAttached < 2) { + cycle += UNLOCKED_INTERVAL; + } else { + cycle += LOCKSTEP_INTERVAL; + } + } + return cycle; +} + +void _advanceCycle(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOLockstepPlayer* player) { + int32_t newCycle = GBASIOLockstepTime(player); + mASSERT_DEBUG(newCycle - coordinator->cycle >= 0); + coordinator->nextHardSync -= newCycle - coordinator->cycle; + coordinator->cycle = newCycle; +} + +void _removePlayer(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOLockstepPlayer* player) { + struct GBASIOLockstepEvent event = { + .type = SIO_EV_DETACH, + .playerId = player->playerId, + .timestamp = GBASIOLockstepTime(player), + }; + _enqueueEvent(coordinator, &event, TARGET_ALL & ~TARGET(player->playerId)); + + coordinator->waiting = 0; + coordinator->transferActive = false; + + TableRemove(&coordinator->players, player->driver->lockstepId); + _reconfigPlayers(coordinator); + + struct GBASIOLockstepPlayer* runner = TableLookup(&coordinator->players, coordinator->attachedPlayers[0]); + if (runner) { + GBASIOLockstepPlayerWake(runner); + } + _verifyAwake(coordinator); +} + +void _reconfigPlayers(struct GBASIOLockstepCoordinator* coordinator) { + size_t players = TableSize(&coordinator->players); + memset(coordinator->attachedPlayers, 0, sizeof(coordinator->attachedPlayers)); + if (players == 0) { + mLOG(GBA_SIO, WARN, "Reconfiguring player IDs with no players attached somehow?"); + } else if (players == 1) { + struct TableIterator iter; + mASSERT(TableIteratorStart(&coordinator->players, &iter)); + unsigned p0 = TableIteratorGetKey(&coordinator->players, &iter); + coordinator->attachedPlayers[0] = p0; + + struct GBASIOLockstepPlayer* player = TableIteratorGetValue(&coordinator->players, &iter); + coordinator->cycle = mTimingCurrentTime(&player->driver->d.p->p->timing); + coordinator->nextHardSync = HARD_SYNC_INTERVAL; + + if (player->playerId != 0) { + player->playerId = 0; + if (player->driver->user->playerIdChanged) { + player->driver->user->playerIdChanged(player->driver->user, player->playerId); + } + } + + if (!coordinator->transferActive) { + coordinator->transferMode = player->mode; + } + } else { + struct UIntList playerPreferences[MAX_GBAS]; + + int i; + for (i = 0; i < MAX_GBAS; ++i) { + UIntListInit(&playerPreferences[i], 4); + } + + // Collect the first four players' requested player IDs so we can sort through them later + int seen = 0; + struct TableIterator iter; + mASSERT(TableIteratorStart(&coordinator->players, &iter)); + do { + unsigned pid = TableIteratorGetKey(&coordinator->players, &iter); + struct GBASIOLockstepPlayer* player = TableIteratorGetValue(&coordinator->players, &iter); + int requested = MAX_GBAS - 1; + if (player->driver->user->requestedId) { + requested = player->driver->user->requestedId(player->driver->user); + } + if (requested < 0) { + continue; + } + if (requested >= MAX_GBAS) { + requested = MAX_GBAS - 1; + } + + *UIntListAppend(&playerPreferences[requested]) = pid; + ++seen; + } while (TableIteratorNext(&coordinator->players, &iter) && seen < MAX_GBAS); + + // Now sort each requested player ID to figure out who gets which ID + seen = 0; + for (i = 0; i < MAX_GBAS; ++i) { + int j; + for (j = 0; j <= i; ++j) { + while (UIntListSize(&playerPreferences[j]) && seen < MAX_GBAS) { + unsigned pid = *UIntListGetPointer(&playerPreferences[j], 0); + UIntListShift(&playerPreferences[j], 0, 1); + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, pid); + if (!player) { + mLOG(GBA_SIO, ERROR, "Player list appears to have changed unexpectedly. PID %u missing.", pid); + continue; + } + coordinator->attachedPlayers[seen] = pid; + if (player->playerId != seen) { + player->playerId = seen; + if (player->driver->user->playerIdChanged) { + player->driver->user->playerIdChanged(player->driver->user, player->playerId); + } + } + ++seen; + } + } + } + + for (i = 0; i < MAX_GBAS; ++i) { + UIntListDeinit(&playerPreferences[i]); + } + } + + int nAttached = 0; + size_t i; + for (i = 0; i < MAX_GBAS; ++i) { + unsigned pid = coordinator->attachedPlayers[i]; + if (!pid) { + continue; + } + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, pid); + if (!player) { + coordinator->attachedPlayers[i] = 0; + } else { + ++nAttached; + } + } + coordinator->nAttached = nAttached; +} + +static void _setData(struct GBASIOLockstepCoordinator* coordinator, uint32_t id, struct GBASIO* sio) { + switch (coordinator->transferMode) { + case GBA_SIO_MULTI: + coordinator->multiData[id] = sio->p->memory.io[GBA_REG(SIOMLT_SEND)]; + break; + case GBA_SIO_NORMAL_8: + coordinator->normalData[id] = sio->p->memory.io[GBA_REG(SIODATA8)]; + break; + case GBA_SIO_NORMAL_32: + coordinator->normalData[id] = sio->p->memory.io[GBA_REG(SIODATA32_LO)]; + coordinator->normalData[id] |= sio->p->memory.io[GBA_REG(SIODATA32_HI)] << 16; + break; + case GBA_SIO_UART: + case GBA_SIO_GPIO: + case GBA_SIO_JOYBUS: + mLOG(GBA_SIO, ERROR, "Unsupported mode %i in lockstep", coordinator->transferMode); + // TODO: Should we handle this or just abort? + break; + } +} + +void _setReady(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOLockstepPlayer* activePlayer, int playerId, enum GBASIOMode mode) { + activePlayer->otherModes[playerId] = mode; + bool ready = true; + int i; + for (i = 0; ready && i < coordinator->nAttached; ++i) { + ready = activePlayer->otherModes[i] == activePlayer->mode; + } + if (activePlayer->mode == GBA_SIO_MULTI) { + struct GBASIO* sio = activePlayer->driver->d.p; + sio->siocnt = GBASIOMultiplayerSetReady(sio->siocnt, ready); + sio->rcnt = GBASIORegisterRCNTSetSd(sio->rcnt, ready); + } +} + +void _hardSync(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOLockstepPlayer* player) { + mASSERT_DEBUG(player->playerId == 0); + struct GBASIOLockstepEvent event = { + .type = SIO_EV_HARD_SYNC, + .playerId = 0, + .timestamp = GBASIOLockstepTime(player), + }; + _enqueueEvent(coordinator, &event, TARGET_SECONDARY); + GBASIOLockstepCoordinatorWaitOnPlayers(coordinator, player); +} + +void _enqueueEvent(struct GBASIOLockstepCoordinator* coordinator, const struct GBASIOLockstepEvent* event, uint32_t target) { + mLOG(GBA_SIO, DEBUG, "Enqueuing event of type %X from %i for target %X at timestamp %X", + event->type, event->playerId, target, event->timestamp); + + int i; + for (i = 0; i < coordinator->nAttached; ++i) { + if (!(target & TARGET(i))) { + continue; + } + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, coordinator->attachedPlayers[i]); + mASSERT_LOG(GBA_SIO, player->freeList, "No free events"); + struct GBASIOLockstepEvent* newEvent = player->freeList; + player->freeList = newEvent->next; + + memcpy(newEvent, event, sizeof(*event)); + struct GBASIOLockstepEvent** previous = &player->queue; + struct GBASIOLockstepEvent* next = player->queue; + while (next) { + int32_t until = newEvent->timestamp - next->timestamp; + if (until < 0) { + break; + } + previous = &next->next; + next = next->next; + } + newEvent->next = next; + *previous = newEvent; + } +} + +void _lockstepEvent(struct mTiming* timing, void* context, uint32_t cyclesLate) { + struct GBASIOLockstepDriver* lockstep = context; + struct GBASIOLockstepCoordinator* coordinator = lockstep->coordinator; + MutexLock(&coordinator->mutex); + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, lockstep->lockstepId); + struct GBASIO* sio = player->driver->d.p; + mASSERT(player->playerId >= 0 && player->playerId < 4); + + bool wasDetach = false; + if (player->queue && player->queue->type == SIO_EV_DETACH) { + mLOG(GBA_SIO, DEBUG, "Player %i detached at timestamp %X, picking up the pieces", + player->queue->playerId, player->queue->timestamp); + wasDetach = true; + } + if (player->playerId == 0 && GBASIOLockstepTime(player) - coordinator->cycle >= 0) { + // We are the clock owner; advance the shared clock. However, if we just became + // the clock owner (by the previous one disconnecting) we might be slightly + // behind the shared clock. We should wait a bit if needed in that case. + _advanceCycle(coordinator, player); + if (!coordinator->transferActive) { + GBASIOLockstepCoordinatorWakePlayers(coordinator); + } + if (coordinator->nextHardSync < 0) { + if (!coordinator->waiting) { + _hardSync(coordinator, player); + } + coordinator->nextHardSync += HARD_SYNC_INTERVAL; + } + } + + int32_t nextEvent = _untilNextSync(coordinator, player); + while (true) { + struct GBASIOLockstepEvent* event = player->queue; + if (!event) { + break; + } + if (event->timestamp > GBASIOLockstepTime(player)) { + break; + } + player->queue = event->next; + struct GBASIOLockstepEvent reply = { + .playerId = player->playerId, + .timestamp = GBASIOLockstepTime(player), + }; + mLOG(GBA_SIO, DEBUG, "Got event of type %X from %i at timestamp %X", + event->type, event->playerId, event->timestamp); + switch (event->type) { + case SIO_EV_ATTACH: + _setReady(coordinator, player, event->playerId, -1); + if (player->playerId == 0) { + struct GBASIO* sio = player->driver->d.p; + sio->siocnt = GBASIOMultiplayerClearSlave(sio->siocnt); + } + reply.mode = player->mode; + reply.type = SIO_EV_MODE_SET; + _enqueueEvent(coordinator, &reply, TARGET(event->playerId)); + break; + case SIO_EV_HARD_SYNC: + GBASIOLockstepCoordinatorAckPlayer(coordinator, player); + break; + case SIO_EV_TRANSFER_START: + _setData(coordinator, player->playerId, sio); + nextEvent = event->finishCycle - GBASIOLockstepTime(player) - cyclesLate; + player->driver->d.p->siocnt |= 0x80; + mTimingDeschedule(&sio->p->timing, &sio->completeEvent); + mTimingSchedule(&sio->p->timing, &sio->completeEvent, nextEvent); + GBASIOLockstepCoordinatorAckPlayer(coordinator, player); + break; + case SIO_EV_MODE_SET: + _setReady(coordinator, player, event->playerId, event->mode); + if (event->playerId == 0) { + GBASIOLockstepCoordinatorAckPlayer(coordinator, player); + } + break; + case SIO_EV_DETACH: + _setReady(coordinator, player, event->playerId, -1); + _setReady(coordinator, player, player->playerId, player->mode); + reply.mode = player->mode; + reply.type = SIO_EV_MODE_SET; + _enqueueEvent(coordinator, &reply, ~TARGET(event->playerId)); + if (player->mode == GBA_SIO_MULTI) { + sio->siocnt = GBASIOMultiplayerSetId(sio->siocnt, player->playerId); + sio->siocnt = GBASIOMultiplayerSetSlave(sio->siocnt, player->playerId || coordinator->nAttached < 2); + } + wasDetach = true; + break; + } + event->next = player->freeList; + player->freeList = event; + } + if (player->queue && player->queue->timestamp - GBASIOLockstepTime(player) < nextEvent) { + nextEvent = player->queue->timestamp - GBASIOLockstepTime(player); + } + + if (player->playerId != 0 && nextEvent <= LOCKSTEP_INTERVAL) { + if (!player->queue || wasDetach) { + GBASIOLockstepPlayerSleep(player); + // XXX: Is there a better way to gain sync lock at the beginning? + if (nextEvent < 4) { + nextEvent = 4; + } + _verifyAwake(coordinator); + } + } + MutexUnlock(&coordinator->mutex); + + mASSERT_DEBUG(nextEvent > 0); + mTimingSchedule(timing, &lockstep->event, nextEvent); +} + +int32_t GBASIOLockstepTime(struct GBASIOLockstepPlayer* player) { + return mTimingCurrentTime(&player->driver->d.p->p->timing) - player->cycleOffset; +} + +void GBASIOLockstepCoordinatorWaitOnPlayers(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOLockstepPlayer* player) { + mASSERT(!coordinator->waiting); + mASSERT(!player->asleep); + mASSERT(player->playerId == 0); + if (coordinator->nAttached < 2) { + return; + } + + _advanceCycle(coordinator, player); + mLOG(GBA_SIO, DEBUG, "Primary waiting for players to ack"); + coordinator->waiting = ((1 << coordinator->nAttached) - 1) & ~TARGET(player->playerId); + GBASIOLockstepPlayerSleep(player); + GBASIOLockstepCoordinatorWakePlayers(coordinator); + + _verifyAwake(coordinator); +} + +void GBASIOLockstepCoordinatorWakePlayers(struct GBASIOLockstepCoordinator* coordinator) { + int i; + for (i = 1; i < coordinator->nAttached; ++i) { + if (!coordinator->attachedPlayers[i]) { + continue; + } + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, coordinator->attachedPlayers[i]); + GBASIOLockstepPlayerWake(player); + } +} + +void GBASIOLockstepPlayerWake(struct GBASIOLockstepPlayer* player) { + if (!player->asleep) { + return; + } + player->asleep = false; + player->driver->user->wake(player->driver->user); +} + +void GBASIOLockstepCoordinatorAckPlayer(struct GBASIOLockstepCoordinator* coordinator, struct GBASIOLockstepPlayer* player) { + if (player->playerId == 0) { + return; + } + coordinator->waiting &= ~TARGET(player->playerId); + if (!coordinator->waiting) { + mLOG(GBA_SIO, DEBUG, "All players acked, waking primary"); + if (coordinator->transferActive) { + int i; + for (i = 0; i < coordinator->nAttached; ++i) { + if (!coordinator->attachedPlayers[i]) { + continue; + } + struct GBASIOLockstepPlayer* player = TableLookup(&coordinator->players, coordinator->attachedPlayers[i]); + player->dataReceived = true; + } + + coordinator->transferActive = false; + } + + struct GBASIOLockstepPlayer* runner = TableLookup(&coordinator->players, coordinator->attachedPlayers[0]); + GBASIOLockstepPlayerWake(runner); + } + GBASIOLockstepPlayerSleep(player); +} + +void GBASIOLockstepPlayerSleep(struct GBASIOLockstepPlayer* player) { + if (player->asleep) { + return; + } + player->asleep = true; + player->driver->user->sleep(player->driver->user); + player->driver->d.p->p->cpu->nextEvent = 0; + player->driver->d.p->p->earlyExit = true; +} + +size_t GBASIOLockstepCoordinatorAttached(struct GBASIOLockstepCoordinator* coordinator) { + size_t count; + MutexLock(&coordinator->mutex); + count = TableSize(&coordinator->players); + MutexUnlock(&coordinator->mutex); + return count; +} diff --git a/src/gba/video.c b/src/gba/video.c index bfe556943..63e7115c1 100644 --- a/src/gba/video.c +++ b/src/gba/video.c @@ -32,6 +32,7 @@ static void GBAVideoDummyRendererPutPixels(struct GBAVideoRenderer* renderer, si static void _startHblank(struct mTiming*, void* context, uint32_t cyclesLate); static void _startHdraw(struct mTiming*, void* context, uint32_t cyclesLate); +static unsigned _calculateStallMask(struct GBA* gba, unsigned dispcnt); MGBA_EXPORT const int GBAVideoObjSizes[16][2] = { { 8, 8 }, @@ -78,7 +79,7 @@ void GBAVideoReset(struct GBAVideo* video) { video->frameCounter = 0; video->frameskipCounter = 0; - video->shouldStall = 0; + video->stallMask = 0; memset(video->palette, 0, sizeof(video->palette)); memset(video->oam.raw, 0, sizeof(video->oam.raw)); @@ -149,7 +150,8 @@ void _startHdraw(struct mTiming* timing, void* context, uint32_t cyclesLate) { video->p->memory.io[GBA_REG(VCOUNT)] = video->vcount; if (video->vcount < GBA_VIDEO_VERTICAL_PIXELS) { - video->shouldStall = 1; + unsigned dispcnt = video->p->memory.io[GBA_REG(DISPCNT)]; + video->stallMask = _calculateStallMask(video->p, dispcnt); } GBARegisterDISPSTAT dispstat = video->p->memory.io[GBA_REG(DISPSTAT)]; @@ -214,7 +216,7 @@ void _startHblank(struct mTiming* timing, void* context, uint32_t cyclesLate) { if (GBARegisterDISPSTATIsHblankIRQ(dispstat)) { GBARaiseIRQ(video->p, GBA_IRQ_HBLANK, cyclesLate - 6); // TODO: Where does this fudge factor come from? } - video->shouldStall = 0; + video->stallMask = 0; video->p->memory.io[GBA_REG(DISPSTAT)] = dispstat; } @@ -224,6 +226,84 @@ void GBAVideoWriteDISPSTAT(struct GBAVideo* video, uint16_t value) { // TODO: Does a VCounter IRQ trigger on write? } +static unsigned _calculateStallMask(struct GBA* gba, unsigned dispcnt) { + unsigned mask = 0; + + if (GBARegisterDISPCNTIsForcedBlank(dispcnt)) { + return 0; + } + + switch (GBARegisterDISPCNTGetMode(dispcnt)) { + case 0: + if (GBARegisterDISPCNTIsBg0Enable(dispcnt)) { + if (GBARegisterBGCNTIs256Color(gba->memory.io[GBA_REG(BG0CNT)])) { + mask |= GBA_VSTALL_T8(0); + } else { + mask |= GBA_VSTALL_T4(0); + } + } + if (GBARegisterDISPCNTIsBg1Enable(dispcnt)) { + if (GBARegisterBGCNTIs256Color(gba->memory.io[GBA_REG(BG1CNT)])) { + mask |= GBA_VSTALL_T8(1); + } else { + mask |= GBA_VSTALL_T4(1); + } + } + if (GBARegisterDISPCNTIsBg2Enable(dispcnt)) { + if (GBARegisterBGCNTIs256Color(gba->memory.io[GBA_REG(BG2CNT)])) { + mask |= GBA_VSTALL_T8(2); + } else { + mask |= GBA_VSTALL_T4(2); + } + } + if (GBARegisterDISPCNTIsBg3Enable(dispcnt)) { + if (GBARegisterBGCNTIs256Color(gba->memory.io[GBA_REG(BG3CNT)])) { + mask |= GBA_VSTALL_T8(3); + } else { + mask |= GBA_VSTALL_T4(3); + } + } + break; + case 1: + if (GBARegisterDISPCNTIsBg0Enable(dispcnt)) { + if (GBARegisterBGCNTIs256Color(gba->memory.io[GBA_REG(BG0CNT)])) { + mask |= GBA_VSTALL_T8(0); + } else { + mask |= GBA_VSTALL_T4(0); + } + } + if (GBARegisterDISPCNTIsBg1Enable(dispcnt)) { + if (GBARegisterBGCNTIs256Color(gba->memory.io[GBA_REG(BG1CNT)])) { + mask |= GBA_VSTALL_T8(1); + } else { + mask |= GBA_VSTALL_T4(1); + } + } + if (GBARegisterDISPCNTIsBg2Enable(dispcnt)) { + mask |= GBA_VSTALL_A2; + } + break; + case 2: + if (GBARegisterDISPCNTIsBg2Enable(dispcnt)) { + mask |= GBA_VSTALL_A2; + } + if (GBARegisterDISPCNTIsBg3Enable(dispcnt)) { + mask |= GBA_VSTALL_A3; + } + break; + case 3: + case 4: + case 5: + if (GBARegisterDISPCNTIsBg2Enable(dispcnt)) { + mask |= GBA_VSTALL_B; + } + break; + default: + break; + } + return mask; +} + static void GBAVideoDummyRendererInit(struct GBAVideoRenderer* renderer) { UNUSED(renderer); // Nothing to do @@ -353,7 +433,7 @@ void GBAVideoDeserialize(struct GBAVideo* video, const struct GBASerializedState } LOAD_32(video->frameCounter, 0, &state->video.frameCounter); - video->shouldStall = 0; + video->stallMask = 0; int32_t flags; LOAD_32(flags, 0, &state->video.flags); GBARegisterDISPSTAT dispstat = state->io[GBA_REG(DISPSTAT)]; @@ -370,7 +450,7 @@ void GBAVideoDeserialize(struct GBAVideo* video, const struct GBASerializedState break; case 2: video->event.callback = _startHblank; - video->shouldStall = 1; + video->stallMask = _calculateStallMask(video->p, state->io[GBA_REG(DISPCNT)]); break; case 3: video->event.callback = _startHdraw; diff --git a/src/platform/3ds/3ds-memory.c b/src/platform/3ds/3ds-memory.c deleted file mode 100644 index c37e4637b..000000000 --- a/src/platform/3ds/3ds-memory.c +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (c) 2013-2014 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/. */ -#include - -#include <3ds.h> - -void* anonymousMemoryMap(size_t size) { - return linearAlloc(size); -} - -void mappedMemoryFree(void* memory, size_t size) { - UNUSED(size); - linearFree(memory); -} diff --git a/src/platform/3ds/3ds-vfs.c b/src/platform/3ds/3ds-vfs.c index f2aaeb84a..88297e9cd 100644 --- a/src/platform/3ds/3ds-vfs.c +++ b/src/platform/3ds/3ds-vfs.c @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#ifdef USE_VFS_3DS +#ifdef ENABLE_VFS_3DS #include #include diff --git a/src/platform/3ds/CMakeLists.txt b/src/platform/3ds/CMakeLists.txt index 893af0317..a52c5e81e 100644 --- a/src/platform/3ds/CMakeLists.txt +++ b/src/platform/3ds/CMakeLists.txt @@ -1,5 +1,5 @@ -set(USE_VFS_3DS OFF CACHE BOOL "Use 3DS-specific file support") -mark_as_advanced(USE_VFS_3DS) +set(ENABLE_VFS_3DS OFF CACHE BOOL "Use 3DS-specific file support") +mark_as_advanced(ENABLE_VFS_3DS) find_program(3DSLINK 3dslink) find_program(3DSXTOOL 3dsxtool) @@ -19,17 +19,22 @@ if(${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDeb else() list(APPEND OS_LIB citro3d ctru) endif() -file(GLOB OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/3ds-*.c ${CMAKE_CURRENT_SOURCE_DIR}/ctru-heap.c ${CMAKE_CURRENT_SOURCE_DIR}/socket.c) -set(OS_SRC ${OS_SRC} PARENT_SCOPE) +set(OS_SRC + ${PROJECT_SOURCE_DIR}/src/util/memory.c + ${CMAKE_CURRENT_SOURCE_DIR}/3ds-vfs.c + ${CMAKE_CURRENT_SOURCE_DIR}/ctru-heap.c + ${CMAKE_CURRENT_SOURCE_DIR}/socket.c + PARENT_SCOPE) set(OS_LIB ${OS_LIB} PARENT_SCOPE) source_group("3DS-specific code" FILES ${OS_SRC}) -if(USE_VFS_3DS) - list(APPEND OS_DEFINES USE_VFS_3DS) +if(ENABLE_VFS_3DS) + list(APPEND OS_DEFINES ENABLE_VFS_3DS) else() - list(APPEND CORE_VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c) + list(APPEND OS_DEFINES ENABLE_VFS_FD) + list(APPEND VFS_SRC ${PROJECT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${PROJECT_SOURCE_DIR}/src/util/vfs/vfs-dirent.c) endif() -set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE) +set(VFS_SRC ${VFS_SRC} PARENT_SCOPE) set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE) list(APPEND GUI_SRC @@ -54,8 +59,8 @@ set_target_properties(${BINARY_NAME}.elf PROPERTIES COMPILE_DEFINITIONS "${OS_DE target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} ${M_LIBRARY} ${OS_LIB}) add_custom_command(OUTPUT ${BINARY_NAME}.smdh - COMMAND ${BANNERTOOL} makesmdh -s "${PROJECT_NAME}" -l "${SUMMARY}" -p "endrift" -i ${CMAKE_SOURCE_DIR}/res/mgba-48.png -o ${BINARY_NAME}.smdh - DEPENDS ${CMAKE_SOURCE_DIR}/res/mgba-48.png) + COMMAND ${BANNERTOOL} makesmdh -s "${PROJECT_NAME}" -l "${SUMMARY}" -p "endrift" -i ${PROJECT_SOURCE_DIR}/res/mgba-48.png -o ${BINARY_NAME}.smdh + DEPENDS ${PROJECT_SOURCE_DIR}/res/mgba-48.png) add_custom_command(OUTPUT ${BINARY_NAME}.xml COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/hbl.xml ${BINARY_NAME}.xml @@ -67,8 +72,8 @@ add_custom_command(OUTPUT ${BINARY_NAME}.bnr # tex3ds binaries as of 2.0.1-3 crash if you try to do this #add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.t3x -# COMMAND ${TEX3DS} -f rgb5551 -o icons.t3x ${CMAKE_SOURCE_DIR}/res/icons.png -# MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/res/icons.png +# COMMAND ${TEX3DS} -f rgb5551 -o icons.t3x ${PROJECT_SOURCE_DIR}/res/icons.png +# MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/res/icons.png # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.c diff --git a/src/platform/3ds/ctr-gpu.c b/src/platform/3ds/ctr-gpu.c index 4a95c4640..d153f84a0 100644 --- a/src/platform/3ds/ctr-gpu.c +++ b/src/platform/3ds/ctr-gpu.c @@ -160,7 +160,7 @@ void ctrActivateTexture(const C3D_Tex* texture) { .m = { // Rows are in the order w z y x, because ctrulib 0.0f, 0.0f, 0.0f, 1.0f / activeTexture->width, - 0.0f, 0.0f, 1.0f / activeTexture->height, 0.0f + 0.0f, 0.0f, 1.0f / activeTexture->height, 0.0f } }; C3D_FVUnifMtx2x4(GPU_GEOMETRY_SHADER, GSH_FVEC_textureMtx, &textureMtx); diff --git a/src/platform/3ds/ctru-heap.c b/src/platform/3ds/ctru-heap.c index 25e606c1d..ea2f4d450 100644 --- a/src/platform/3ds/ctru-heap.c +++ b/src/platform/3ds/ctru-heap.c @@ -7,9 +7,6 @@ #include -u32 __ctru_heap_size = 0x02400000; -u32 __ctru_linear_heap_size = 0x01400000; - uint32_t* romBuffer = NULL; size_t romBufferSize; diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index 470c50db7..2d7f80d15 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -4,7 +4,6 @@ * 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/. */ -#include #include #include #ifdef M_CORE_GBA @@ -47,8 +46,9 @@ static enum FilterMode { FM_NEAREST, FM_LINEAR_1x, FM_LINEAR_2x, + FM_LINEAR_3x, FM_MAX -} filterMode = FM_LINEAR_2x; +} filterMode = FM_LINEAR_3x; static enum DarkenMode { DM_NATIVE, @@ -60,7 +60,7 @@ static enum DarkenMode { #define _3DS_INPUT 0x3344534B -#define AUDIO_SAMPLES 384 +#define AUDIO_SAMPLES 1280 #define AUDIO_SAMPLE_BUFFER (AUDIO_SAMPLES * 16) #define DSP_BUFFERS 4 @@ -85,11 +85,12 @@ static enum { } hasSound; // TODO: Move into context -static color_t* outputBuffer = NULL; -static color_t* screenshotBuffer = NULL; +static mColor* outputBuffer = NULL; +static mColor* screenshotBuffer = NULL; static struct mAVStream stream; static int16_t* audioLeft = 0; static size_t audioPos = 0; +static double fpsRatio; static C3D_Tex outputTexture[2]; static int activeOutputTexture = 0; static ndspWaveBuf dspBuffer[DSP_BUFFERS]; @@ -97,9 +98,8 @@ static int bufferId = 0; static bool frameLimiter = true; static u32 frameCounter; -static C3D_RenderTarget* topScreen[2]; -static C3D_RenderTarget* bottomScreen[2]; -static int doubleBuffer = 0; +static C3D_RenderTarget* topScreen; +static C3D_RenderTarget* bottomScreen; static bool frameStarted = false; static C3D_RenderTarget* upscaleBuffer; @@ -115,28 +115,26 @@ static bool _initGpu(void) { } if (gfxIsWide()) { - topScreen[0] = C3D_RenderTargetCreate(240, 800, GPU_RB_RGB8, 0); - topScreen[1] = C3D_RenderTargetCreate(240, 800, GPU_RB_RGB8, 0); + topScreen = C3D_RenderTargetCreate(240, 800, GPU_RB_RGB8, 0); } else { - topScreen[0] = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, 0); - topScreen[1] = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, 0); + topScreen = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, 0); } - bottomScreen[0] = C3D_RenderTargetCreate(240, 320, GPU_RB_RGB8, 0); - bottomScreen[1] = C3D_RenderTargetCreate(240, 320, GPU_RB_RGB8, 0); - if (!topScreen[0] || !topScreen[1] || !bottomScreen[0] || !bottomScreen[1]) { + bottomScreen = C3D_RenderTargetCreate(240, 320, GPU_RB_RGB8, 0); + if (!topScreen || !bottomScreen) { return false; } C3D_FrameBegin(0); - C3D_FrameDrawOn(bottomScreen[0]); - C3D_RenderTargetClear(bottomScreen[0], C3D_CLEAR_COLOR, 0, 0); - C3D_FrameDrawOn(topScreen[0]); - C3D_RenderTargetClear(topScreen[0], C3D_CLEAR_COLOR, 0, 0); - C3D_RenderTargetSetOutput(topScreen[0], GFX_TOP, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); - C3D_RenderTargetSetOutput(bottomScreen[0], GFX_BOTTOM, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); + C3D_FrameDrawOn(bottomScreen); + C3D_RenderTargetClear(bottomScreen, C3D_CLEAR_COLOR, 0, 0); + C3D_FrameDrawOn(topScreen); + C3D_RenderTargetClear(topScreen, C3D_CLEAR_COLOR, 0, 0); + C3D_RenderTargetSetOutput(topScreen, GFX_TOP, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); + C3D_RenderTargetSetOutput(bottomScreen, GFX_BOTTOM, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); C3D_FrameEnd(0); - if (!C3D_TexInitVRAM(&upscaleBufferTex, 512, 512, GPU_RGB8)) { + if (!C3D_TexInitVRAM(&upscaleBufferTex, 1024, 512, GPU_RGB8)) { + __builtin_trap(); return false; } upscaleBuffer = C3D_RenderTargetCreateFromTex(&upscaleBufferTex, GPU_TEXFACE_2D, 0, 0); @@ -164,10 +162,8 @@ static void _cleanup(void) { screenshotBuffer = NULL; } - C3D_RenderTargetDelete(topScreen[0]); - C3D_RenderTargetDelete(topScreen[1]); - C3D_RenderTargetDelete(bottomScreen[0]); - C3D_RenderTargetDelete(bottomScreen[1]); + C3D_RenderTargetDelete(topScreen); + C3D_RenderTargetDelete(bottomScreen); C3D_RenderTargetDelete(upscaleBuffer); C3D_TexDelete(&upscaleBufferTex); C3D_TexDelete(&outputTexture[0]); @@ -194,8 +190,6 @@ static void _map3DSKey(struct mInputMap* map, int ctrKey, int key) { mInputBindKey(map, _3DS_INPUT, __builtin_ctz(ctrKey), key); } -static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right); - static void _drawStart(void) { if (frameStarted) { return; @@ -216,10 +210,10 @@ static void _drawStart(void) { C3D_FrameBegin(0); ctrStartFrame(); - C3D_FrameDrawOn(bottomScreen[doubleBuffer]); - C3D_RenderTargetClear(bottomScreen[doubleBuffer], C3D_CLEAR_COLOR, 0, 0); - C3D_FrameDrawOn(topScreen[doubleBuffer]); - C3D_RenderTargetClear(topScreen[doubleBuffer], C3D_CLEAR_COLOR, 0, 0); + C3D_FrameDrawOn(bottomScreen); + C3D_RenderTargetClear(bottomScreen, C3D_CLEAR_COLOR, 0, 0); + C3D_FrameDrawOn(topScreen); + C3D_RenderTargetClear(topScreen, C3D_CLEAR_COLOR, 0, 0); } static void _drawEnd(void) { @@ -227,12 +221,10 @@ static void _drawEnd(void) { return; } ctrEndFrame(); - C3D_RenderTargetSetOutput(topScreen[doubleBuffer], GFX_TOP, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); - C3D_RenderTargetSetOutput(bottomScreen[doubleBuffer], GFX_BOTTOM, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); + C3D_RenderTargetSetOutput(topScreen, GFX_TOP, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); + C3D_RenderTargetSetOutput(bottomScreen, GFX_BOTTOM, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); C3D_FrameEnd(0); frameStarted = false; - - doubleBuffer ^= 1; } static int _batteryState(void) { @@ -256,7 +248,7 @@ static int _batteryState(void) { } static void _guiPrepare(void) { - C3D_FrameDrawOn(bottomScreen[doubleBuffer]); + C3D_FrameDrawOn(bottomScreen); ctrSetViewportSize(320, 240, true); } @@ -301,7 +293,7 @@ static void _setup(struct mGUIRunner* runner) { _map3DSKey(&runner->core->inputMap, KEY_L, GBA_KEY_L); _map3DSKey(&runner->core->inputMap, KEY_R, GBA_KEY_R); - memset(outputBuffer, 0, 256 * 224 * sizeof(color_t)); + memset(outputBuffer, 0, 256 * 224 * sizeof(mColor)); runner->core->setVideoBuffer(runner->core, outputBuffer, 256); unsigned mode; @@ -349,13 +341,16 @@ static void _gameLoaded(struct mGUIRunner* runner) { } osSetSpeedupEnable(true); - double ratio = GBAAudioCalculateRatio(1, 268111856.f / 4481136.f, 1); - blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), 32768 * ratio); - blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), 32768 * ratio); if (hasSound != NO_SOUND) { audioPos = 0; } if (hasSound == DSP_SUPPORTED) { + unsigned sampleRate = runner->core->audioSampleRate(runner->core); + if (!sampleRate) { + sampleRate = 32768; + } + fpsRatio = mCoreCalculateFramerateRatio(runner->core, 16756991. / 280095.); + ndspChnSetRate(0, sampleRate * fpsRatio); memset(audioLeft, 0, AUDIO_SAMPLE_BUFFER * 2 * sizeof(int16_t)); } unsigned mode; @@ -476,21 +471,33 @@ static u32 _setupTex(int out, bool faded) { static void _drawTex(struct mCore* core, bool faded, bool both) { unsigned screen_w, screen_h; bool isWide = screenMode >= SM_PA_TOP && gfxIsWide(); + + if (filterMode < FM_LINEAR_1x || filterMode > FM_LINEAR_3x) { + // Out-of-range filtering modes are not supported + filterMode = FM_LINEAR_3x; + } + int mult = 1 + filterMode - FM_LINEAR_1x; + switch (screenMode) { case SM_PA_BOTTOM: - C3D_FrameDrawOn(bottomScreen[doubleBuffer]); + C3D_FrameDrawOn(bottomScreen); screen_w = 320; screen_h = 240; break; case SM_PA_TOP: - C3D_FrameDrawOn(topScreen[doubleBuffer]); + C3D_FrameDrawOn(topScreen); screen_w = isWide ? 800 : 400; screen_h = 240; break; default: C3D_FrameDrawOn(upscaleBuffer); - screen_w = 512; - screen_h = 512; + // PICA200 erratum: if viewport X coord exceeds 1023, entire polygon + // is not rendered. If viewport Y coord exceeds 1016, GPU hangs. + // This can not be mitigated by scissor testing. + // C3D_FrameDrawOn sets the viewport dims to the texture's dims, + // thus we must re-set the viewport ourselves. + screen_w = 256 * mult; + screen_h = 256 * mult; break; } int wide = isWide ? 2 : 1; @@ -523,17 +530,13 @@ static void _drawTex(struct mCore* core, bool faded, bool both) { case SM_AF_BOTTOM: case SM_SF_TOP: case SM_SF_BOTTOM: - default: - if (filterMode == FM_LINEAR_1x) { - w = corew; - h = coreh; - } else { - w = corew * 2; - h = coreh * 2; - } + default: { + w = corew * mult; + h = coreh * mult; ctrSetViewportSize(screen_w, screen_h, false); break; } + } uint32_t color = _setupTex(activeOutputTexture, faded); ctrAddRectEx(color, x, y, w, h, 0, 0, corew, coreh, 0); @@ -549,10 +552,10 @@ static void _drawTex(struct mCore* core, bool faded, bool both) { coreh = h; screen_h = 240; if (screenMode < SM_PA_TOP) { - C3D_FrameDrawOn(bottomScreen[doubleBuffer]); + C3D_FrameDrawOn(bottomScreen); screen_w = 320; } else { - C3D_FrameDrawOn(topScreen[doubleBuffer]); + C3D_FrameDrawOn(topScreen); screen_w = isWide ? 800 : 400; } ctrSetViewportSize(screen_w, screen_h, true); @@ -606,26 +609,25 @@ static void _drawFrame(struct mGUIRunner* runner, bool faded) { GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_FLIP_VERT(1)); if (hasSound == NO_SOUND) { - blip_clear(runner->core->getAudioChannel(runner->core, 0)); - blip_clear(runner->core->getAudioChannel(runner->core, 1)); + mAudioBufferClear(runner->core->getAudioBuffer(runner->core)); } _drawTex(runner->core, faded, interframeBlending); } -static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, unsigned width, unsigned height, bool faded) { +static void _drawScreenshot(struct mGUIRunner* runner, const mColor* pixels, unsigned width, unsigned height, bool faded) { C3D_Tex* tex = &outputTexture[activeOutputTexture]; if (!screenshotBuffer) { - screenshotBuffer = linearMemAlign(256 * 224 * sizeof(color_t), 0x80); + screenshotBuffer = linearMemAlign(256 * 224 * sizeof(mColor), 0x80); } unsigned y; for (y = 0; y < height; ++y) { - memcpy(&screenshotBuffer[y * 256], &pixels[y * width], width * sizeof(color_t)); - memset(&screenshotBuffer[y * 256 + width], 0, (256 - width) * sizeof(color_t)); + memcpy(&screenshotBuffer[y * 256], &pixels[y * width], width * sizeof(mColor)); + memset(&screenshotBuffer[y * 256 + width], 0, (256 - width) * sizeof(mColor)); } - GSPGPU_FlushDataCache(screenshotBuffer, 256 * height * sizeof(color_t)); + GSPGPU_FlushDataCache(screenshotBuffer, 256 * height * sizeof(mColor)); C3D_SyncDisplayTransfer( (u32*) screenshotBuffer, GX_BUFFER_DIM(256, height), tex->data, GX_BUFFER_DIM(256, 256), @@ -702,7 +704,7 @@ static int32_t _readTiltY(struct mRotationSource* source) { static int32_t _readGyroZ(struct mRotationSource* source) { struct m3DSRotationSource* rotation = (struct m3DSRotationSource*) source; - return rotation->gyro.y << 18L; // Yes, y + return rotation->gyro.y << 17L; // Yes, y } static void _startRequestImage(struct mImageSource* source, unsigned w, unsigned h, int colorFormats) { @@ -774,15 +776,14 @@ static void _requestImage(struct mImageSource* source, const void** buffer, size CAMU_SetReceiving(&imageSource->handles[0], imageSource->buffer, PORT_CAM1, imageSource->bufferSize, imageSource->transferSize); } -static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { +static void _postAudioBuffer(struct mAVStream* stream, struct mAudioBuffer* buffer) { UNUSED(stream); if (hasSound == DSP_SUPPORTED) { int startId = bufferId; while (dspBuffer[bufferId].status == NDSP_WBUF_QUEUED || dspBuffer[bufferId].status == NDSP_WBUF_PLAYING) { bufferId = (bufferId + 1) & (DSP_BUFFERS - 1); if (bufferId == startId) { - blip_clear(left); - blip_clear(right); + mAudioBufferClear(buffer); return; } } @@ -790,13 +791,20 @@ static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* rig memset(&dspBuffer[bufferId], 0, sizeof(dspBuffer[bufferId])); dspBuffer[bufferId].data_pcm16 = tmpBuf; dspBuffer[bufferId].nsamples = AUDIO_SAMPLES; - blip_read_samples(left, dspBuffer[bufferId].data_pcm16, AUDIO_SAMPLES, true); - blip_read_samples(right, dspBuffer[bufferId].data_pcm16 + 1, AUDIO_SAMPLES, true); + mAudioBufferRead(buffer, dspBuffer[bufferId].data_pcm16, AUDIO_SAMPLES); DSP_FlushDataCache(dspBuffer[bufferId].data_pcm16, AUDIO_SAMPLES * 2 * sizeof(int16_t)); ndspChnWaveBufAdd(0, &dspBuffer[bufferId]); } } +static void _audioRateChanged(struct mAVStream* stream, unsigned sampleRate) { + UNUSED(stream); + if (!sampleRate) { + sampleRate = 32768; + } + ndspChnSetRate(0, sampleRate * fpsRatio); +} + static enum GUIKeyboardStatus _keyboardRun(struct GUIKeyboardParams* keyboard) { SwkbdState swkbd; swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, keyboard->maxLen); @@ -832,10 +840,11 @@ int main(int argc, char* argv[]) { rotation.d.readTiltY = _readTiltY; rotation.d.readGyroZ = _readGyroZ; - stream.videoDimensionsChanged = 0; - stream.postVideoFrame = 0; - stream.postAudioFrame = 0; + stream.videoDimensionsChanged = NULL; + stream.postVideoFrame = NULL; + stream.postAudioFrame = NULL; stream.postAudioBuffer = _postAudioBuffer; + stream.audioRateChanged = _audioRateChanged; camera.d.startRequestImage = _startRequestImage; camera.d.stopRequestImage = _stopRequestImage; @@ -856,7 +865,6 @@ int main(int argc, char* argv[]) { ndspChnReset(0); ndspChnSetFormat(0, NDSP_FORMAT_STEREO_PCM16); ndspChnSetInterp(0, NDSP_INTERP_NONE); - ndspChnSetRate(0, 0x8000); ndspChnWaveBufClear(0); audioLeft = linearMemAlign(AUDIO_SAMPLES * DSP_BUFFERS * 2 * sizeof(int16_t), 0x80); memset(dspBuffer, 0, sizeof(dspBuffer)); @@ -909,7 +917,7 @@ int main(int argc, char* argv[]) { _cleanup(); return 1; } - outputBuffer = linearMemAlign(256 * 224 * sizeof(color_t), 0x80); + outputBuffer = linearMemAlign(256 * 224 * sizeof(mColor), 0x80); struct mGUIRunner runner = { .params = { @@ -979,13 +987,14 @@ int main(int argc, char* argv[]) { .title = "Filtering", .data = GUI_V_S("filterMode"), .submenu = 0, - .state = FM_LINEAR_2x, + .state = FM_LINEAR_3x, .validStates = (const char*[]) { NULL, // Disable choosing nearest neighbor; it always looks bad "Bilinear (smoother)", "Bilinear (pixelated)", + "Bilinear (ultrasharp)", }, - .nStates = 3 + .nStates = 4 }, { .title = "Screen darkening", diff --git a/src/platform/example/client-server/server.c b/src/platform/example/client-server/server.c index 0dcec9b15..71472a05c 100644 --- a/src/platform/example/client-server/server.c +++ b/src/platform/example/client-server/server.c @@ -53,7 +53,7 @@ int main(int argc, char** argv) { SocketClose(sock); SocketSubsystemDeinit(); didFail = true; - goto cleanup; + goto cleanup; } // Run the server diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index 8c08e7bb6..d2a871546 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -7,7 +7,6 @@ #include -#include #include #include #include @@ -30,17 +29,15 @@ #include "libretro_core_options.h" #define GB_SAMPLES 512 -#define SAMPLE_RATE 32768 /* An alpha factor of 1/180 is *somewhat* equivalent * to calculating the average for the last 180 * frames, or 3 seconds of runtime... */ #define SAMPLES_PER_FRAME_MOVING_AVG_ALPHA (1.0f / 180.0f) -#define RUMBLE_PWM 35 #define EVENT_RATE 60 #define VIDEO_WIDTH_MAX 256 #define VIDEO_HEIGHT_MAX 224 -#define VIDEO_BUFF_SIZE (VIDEO_WIDTH_MAX * VIDEO_HEIGHT_MAX * sizeof(color_t)) +#define VIDEO_BUFF_SIZE (VIDEO_WIDTH_MAX * VIDEO_HEIGHT_MAX * sizeof(mColor)) static retro_environment_t environCallback; static retro_video_refresh_t videoCallback; @@ -54,8 +51,9 @@ static retro_set_sensor_state_t sensorStateCallback; static void GBARetroLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args); -static void _postAudioBuffer(struct mAVStream*, blip_t* left, blip_t* right); -static void _setRumble(struct mRumble* rumble, int enable); +static void _postAudioBuffer(struct mAVStream*, struct mAudioBuffer*); +static void _audioRateChanged(struct mAVStream*, unsigned rate); +static void _setRumble(struct mRumbleIntegrator*, float level); static uint8_t _readLux(struct GBALuminanceSource* lux); static void _updateLux(struct GBALuminanceSource* lux); static void _updateCamera(const uint32_t* buffer, unsigned width, unsigned height, size_t pitch); @@ -68,7 +66,7 @@ static int32_t _readTiltY(struct mRotationSource* source); static int32_t _readGyroZ(struct mRotationSource* source); static struct mCore* core; -static color_t* outputBuffer = NULL; +static mColor* outputBuffer = NULL; static int16_t *audioSampleBuffer = NULL; static size_t audioSampleBufferSize; static float audioSamplesPerFrameAvg; @@ -78,9 +76,7 @@ static void* savedata; static struct mAVStream stream; static bool sensorsInitDone; static bool rumbleInitDone; -static int rumbleUp; -static int rumbleDown; -static struct mRumble rumble; +static struct mRumbleIntegrator rumble; static struct GBALuminanceSource lux; static struct mRotationSource rotation; static bool tiltEnabled; @@ -270,6 +266,8 @@ static void _reloadSettings(void) { model = GB_MODEL_SGB; } else if (strcmp(var.value, "Game Boy Color") == 0) { model = GB_MODEL_CGB; + } else if (strcmp(var.value, "Super Game Boy Color") == 0) { + model = GB_MODEL_SCGB; } else if (strcmp(var.value, "Game Boy Advance") == 0) { model = GB_MODEL_AGB; } else { @@ -280,6 +278,8 @@ static void _reloadSettings(void) { mCoreConfigSetDefaultValue(&core->config, "gb.model", modelName); mCoreConfigSetDefaultValue(&core->config, "sgb.model", modelName); mCoreConfigSetDefaultValue(&core->config, "cgb.model", modelName); + mCoreConfigSetDefaultValue(&core->config, "cgb.hybridModel", modelName); + mCoreConfigSetDefaultValue(&core->config, "cgb.sgbModel", modelName); } var.key = "mgba_sgb_borders"; @@ -424,7 +424,7 @@ void retro_get_system_av_info(struct retro_system_av_info* info) { info->geometry.aspect_ratio = width / (double) height; info->timing.fps = core->frequency(core) / (float) core->frameCycles(core); - info->timing.sample_rate = SAMPLE_RATE; + info->timing.sample_rate = core->audioSampleRate(core); } void retro_init(void) { @@ -464,6 +464,7 @@ void retro_init(void) { // TODO: RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME when BIOS booting is supported rumbleInitDone = false; + mRumbleIntegratorInit(&rumble); rumble.setRumble = _setRumble; rumbleCallback = 0; @@ -496,10 +497,11 @@ void retro_init(void) { logger.log = GBARetroLog; mLogSetDefaultLogger(&logger); - stream.videoDimensionsChanged = 0; - stream.postAudioFrame = 0; - stream.postAudioBuffer = _postAudioBuffer; - stream.postVideoFrame = 0; + stream.videoDimensionsChanged = NULL; + stream.postAudioFrame = NULL; + stream.postAudioBuffer = NULL; + stream.postVideoFrame = NULL; + stream.audioRateChanged = _audioRateChanged; imageSource.startRequestImage = _startImage; imageSource.stopRequestImage = _stopImage; @@ -613,9 +615,8 @@ void retro_run(void) { #ifdef M_CORE_GBA if (core->platform(core) == mPLATFORM_GBA) { - blip_t *audioChannelLeft = core->getAudioChannel(core, 0); - blip_t *audioChannelRight = core->getAudioChannel(core, 1); - int samplesAvail = blip_samples_avail(audioChannelLeft); + struct mAudioBuffer *buffer = core->getAudioBuffer(core); + int samplesAvail = mAudioBufferAvailable(buffer); if (samplesAvail > 0) { /* Update 'running average' of number of * samples per frame. @@ -632,8 +633,7 @@ void retro_run(void) { audioSampleBufferSize = (samplesToRead * 2); audioSampleBuffer = realloc(audioSampleBuffer, audioSampleBufferSize * sizeof(int16_t)); } - int produced = blip_read_samples(audioChannelLeft, audioSampleBuffer, samplesToRead, true); - blip_read_samples(audioChannelRight, audioSampleBuffer + 1, samplesToRead, true); + int produced = mAudioBufferRead(buffer, audioSampleBuffer, samplesToRead); if (produced > 0) { if (audioLowPassEnabled) { _audioLowPassFilter(audioSampleBuffer, produced); @@ -643,18 +643,6 @@ void retro_run(void) { } } #endif - - if (rumbleCallback) { - if (rumbleUp) { - rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); - rumbleCallback(0, RETRO_RUMBLE_WEAK, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); - } else { - rumbleCallback(0, RETRO_RUMBLE_STRONG, 0); - rumbleCallback(0, RETRO_RUMBLE_WEAK, 0); - } - rumbleUp = 0; - rumbleDown = 0; - } } static void _setupMaps(struct mCore* core) { @@ -742,7 +730,7 @@ static void _setupMaps(struct mCore* core) { #ifdef M_CORE_GB if (core->platform(core) == mPLATFORM_GB) { struct GB* gb = core->board; - struct retro_memory_descriptor descs[11]; + struct retro_memory_descriptor descs[12]; struct retro_memory_map mmaps; memset(descs, 0, sizeof(descs)); @@ -812,8 +800,16 @@ static void _setupMaps(struct mCore* core) { if (savedataSize) { descs[i].ptr = savedata; descs[i].start = GB_BASE_EXTERNAL_RAM; - descs[i].len = savedataSize; + descs[i].len = savedataSize < GB_SIZE_EXTERNAL_RAM ? savedataSize : GB_SIZE_EXTERNAL_RAM; i++; + + if ((savedataSize & ~0xFF) > GB_SIZE_EXTERNAL_RAM) { + descs[i].ptr = savedata; + descs[i].offset = GB_SIZE_EXTERNAL_RAM; + descs[i].start = 0x16000; + descs[i].len = savedataSize - GB_SIZE_EXTERNAL_RAM; + i++; + } } if (gb->model >= GB_MODEL_CGB) { @@ -823,7 +819,6 @@ static void _setupMaps(struct mCore* core) { descs[i].ptr = gb->memory.wram + 0x2000; descs[i].start = 0x10000; descs[i].len = GB_SIZE_WORKING_RAM - 0x2000; - descs[i].select = 0xFFFFA000; i++; } @@ -839,10 +834,8 @@ static void _setupMaps(struct mCore* core) { void retro_reset(void) { core->reset(core); + mRumbleIntegratorReset(&rumble); _setupMaps(core); - - rumbleUp = 0; - rumbleDown = 0; } bool retro_load_game(const struct retro_game_info* game) { @@ -852,9 +845,11 @@ bool retro_load_game(const struct retro_game_info* game) { dataSize = game->size; memcpy(data, game->data, game->size); rom = VFileFromMemory(data, game->size); +#ifdef ENABLE_VFS } else { - data = 0; + data = NULL; rom = VFileOpen(game->path, O_RDONLY); +#endif } if (!rom) { return false; @@ -884,9 +879,9 @@ bool retro_load_game(const struct retro_game_info* game) { * to nominal number of samples per frame. * Buffer will be resized as required in * retro_run(). */ - size_t audioSamplesPerFrame = (size_t)((float) SAMPLE_RATE * (float) core->frameCycles(core) / + size_t audioSamplesPerFrame = (size_t)((float) core->audioSampleRate(core) * (float) core->frameCycles(core) / (float)core->frequency(core)); - audioSampleBufferSize = audioSamplesPerFrame * 2; + audioSampleBufferSize = ceil(audioSamplesPerFrame) * 2; audioSampleBuffer = malloc(audioSampleBufferSize * sizeof(int16_t)); audioSamplesPerFrameAvg = (float) audioSamplesPerFrame; /* Internal audio buffer size should be @@ -911,16 +906,14 @@ bool retro_load_game(const struct retro_game_info* game) { * using the regular stream-set _postAudioBuffer() * callback with a fixed buffer size, which seems * (historically) to produce adequate results */ - core->setAVStream(core, &stream); + stream.postAudioBuffer = _postAudioBuffer; audioSampleBufferSize = GB_SAMPLES * 2; audioSampleBuffer = malloc(audioSampleBufferSize * sizeof(int16_t)); audioSamplesPerFrameAvg = GB_SAMPLES; core->setAudioBufferSize(core, GB_SAMPLES); } - blip_set_rates(core->getAudioChannel(core, 0), core->frequency(core), SAMPLE_RATE); - blip_set_rates(core->getAudioChannel(core, 1), core->frequency(core), SAMPLE_RATE); - + core->setAVStream(core, &stream); core->setPeripheral(core, mPERIPH_RUMBLE, &rumble); core->setPeripheral(core, mPERIPH_ROTATION, &rotation); @@ -980,6 +973,7 @@ bool retro_load_game(const struct retro_game_info* game) { } #endif +#ifdef ENABLE_VFS if (core->opts.useBios && sysDir && biosName) { snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, biosName); struct VFile* bios = VFileOpen(biosPath, O_RDONLY); @@ -987,6 +981,7 @@ bool retro_load_game(const struct retro_game_info* game) { core->loadBIOS(core, bios, 0); } } +#endif core->reset(core); _setupMaps(core); @@ -1156,7 +1151,7 @@ size_t retro_get_memory_size(unsigned id) { #ifdef M_CORE_GBA case mPLATFORM_GBA: switch (((struct GBA*) core->board)->memory.savedata.type) { - case SAVEDATA_AUTODETECT: + case GBA_SAVEDATA_AUTODETECT: return GBA_SIZE_FLASH1M; default: return GBASavedataSize(&((struct GBA*) core->board)->memory.savedata); @@ -1238,10 +1233,9 @@ void GBARetroLog(struct mLogger* logger, int category, enum mLogLevel level, con } /* Used only for GB/GBC content */ -static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { +static void _postAudioBuffer(struct mAVStream* stream, struct mAudioBuffer* buffer) { UNUSED(stream); - int produced = blip_read_samples(left, audioSampleBuffer, GB_SAMPLES, true); - blip_read_samples(right, audioSampleBuffer + 1, GB_SAMPLES, true); + int produced = mAudioBufferRead(buffer, audioSampleBuffer, GB_SAMPLES); if (produced > 0) { if (audioLowPassEnabled) { _audioLowPassFilter(audioSampleBuffer, produced); @@ -1250,7 +1244,14 @@ static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* rig } } -static void _setRumble(struct mRumble* rumble, int enable) { +static void _audioRateChanged(struct mAVStream* stream, unsigned rate) { + UNUSED(stream); + struct retro_system_av_info info; + retro_get_system_av_info(&info); + environCallback(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &info); +} + +static void _setRumble(struct mRumbleIntegrator* rumble, float level) { UNUSED(rumble); if (!rumbleInitDone) { _initRumble(); @@ -1258,11 +1259,9 @@ static void _setRumble(struct mRumble* rumble, int enable) { if (!rumbleCallback) { return; } - if (enable) { - ++rumbleUp; - } else { - ++rumbleDown; - } + + rumbleCallback(0, RETRO_RUMBLE_STRONG, level * 0xFFFF); + rumbleCallback(0, RETRO_RUMBLE_WEAK, level * 0xFFFF); } static void _updateLux(struct GBALuminanceSource* lux) { @@ -1390,7 +1389,7 @@ static void _updateRotation(struct mRotationSource* source) { tiltY = sensorGetCallback(0, RETRO_SENSOR_ACCELEROMETER_Y) * 2e8f; } if (gyroEnabled) { - gyroZ = sensorGetCallback(0, RETRO_SENSOR_GYROSCOPE_Z) * -1.1e9f; + gyroZ = sensorGetCallback(0, RETRO_SENSOR_GYROSCOPE_Z) * -5.5e8f; } } diff --git a/src/platform/libretro/libretro_core_options.h b/src/platform/libretro/libretro_core_options.h index 76ca634f9..f0a4b3f04 100644 --- a/src/platform/libretro/libretro_core_options.h +++ b/src/platform/libretro/libretro_core_options.h @@ -87,11 +87,12 @@ struct retro_core_option_v2_definition option_defs_us[] = { NULL, "system", { - { "Autodetect", NULL }, - { "Game Boy", NULL }, - { "Super Game Boy", NULL }, - { "Game Boy Color", NULL }, - { "Game Boy Advance", NULL }, + { "Autodetect", NULL }, + { "Game Boy", NULL }, + { "Super Game Boy", NULL }, + { "Game Boy Color", NULL }, + { "Super Game Boy Color", NULL }, + { "Game Boy Advance", NULL }, { NULL, NULL }, }, "Autodetect" diff --git a/src/platform/openemu/Info.plist.in b/src/platform/openemu/Info.plist.in deleted file mode 100644 index b4ecfa95e..000000000 --- a/src/platform/openemu/Info.plist.in +++ /dev/null @@ -1,52 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${PROJECT_NAME} - CFBundleIconFile - mGBA - CFBundleIdentifier - com.endrift.mgba - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - BNDL - CFBundleSignature - ???? - CFBundleVersion - ${VERSION_STRING} - NSPrincipalClass - OEGameCoreController - OEGameCoreClass - mGBAGameCore - OEGameCoreOptions - - openemu.system.gba - - OEGameCoreRewindBufferSeconds - 60 - OEGameCoreRewindInterval - 0 - OEGameCoreSupportsRewinding - - OEGameCoreSupportsCheatCode - - - - OEGameCorePlayerCount - 1 - OEProjectURL - https://mgba.io/ - OESystemIdentifiers - - openemu.system.gba - - SUEnableAutomaticChecks - 1 - SUFeedURL - https://raw.github.com/OpenEmu/OpenEmu-Update/master/mgba_appcast.xml - - diff --git a/src/platform/openemu/OEGBASystemResponderClient.h b/src/platform/openemu/OEGBASystemResponderClient.h deleted file mode 100644 index 4fc0179d1..000000000 --- a/src/platform/openemu/OEGBASystemResponderClient.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (c) 2011, OpenEmu Team - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the OpenEmu Team nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL OpenEmu Team BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -@protocol OESystemResponderClient; - -typedef enum _OEGBAButton -{ - OEGBAButtonUp, - OEGBAButtonDown, - OEGBAButtonLeft, - OEGBAButtonRight, - OEGBAButtonA, - OEGBAButtonB, - OEGBAButtonL, - OEGBAButtonR, - OEGBAButtonStart, - OEGBAButtonSelect, - OEGBAButtonCount -} OEGBAButton; - -@protocol OEGBASystemResponderClient - -- (oneway void)didPushGBAButton:(OEGBAButton)button forPlayer:(NSUInteger)player; -- (oneway void)didReleaseGBAButton:(OEGBAButton)button forPlayer:(NSUInteger)player; - -@end diff --git a/src/platform/openemu/mGBAGameCore.h b/src/platform/openemu/mGBAGameCore.h deleted file mode 100644 index 744fdecfe..000000000 --- a/src/platform/openemu/mGBAGameCore.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import - -OE_EXPORTED_CLASS -@interface mGBAGameCore : OEGameCore -@end diff --git a/src/platform/openemu/mGBAGameCore.m b/src/platform/openemu/mGBAGameCore.m deleted file mode 100644 index 7656a8945..000000000 --- a/src/platform/openemu/mGBAGameCore.m +++ /dev/null @@ -1,298 +0,0 @@ -/* - Copyright (c) 2016, Jeffrey Pfau - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -#import "mGBAGameCore.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#import -#import "OEGBASystemResponderClient.h" -#import - -#define SAMPLES 1024 - -@interface mGBAGameCore () -{ - struct mCore* core; - void* outputBuffer; - NSMutableDictionary *cheatSets; -} -@end - -@implementation mGBAGameCore - -- (id)init -{ - if ((self = [super init])) - { - core = GBACoreCreate(); - mCoreInitConfig(core, nil); - - struct mCoreOptions opts = { - .useBios = true, - }; - mCoreConfigLoadDefaults(&core->config, &opts); - core->init(core); - outputBuffer = nil; - - unsigned width, height; - core->baseVideoSize(core, &width, &height); - outputBuffer = malloc(width * height * BYTES_PER_PIXEL); - core->setVideoBuffer(core, outputBuffer, width); - core->setAudioBufferSize(core, SAMPLES); - cheatSets = [[NSMutableDictionary alloc] init]; - } - - return self; -} - -- (void)dealloc -{ - mCoreConfigDeinit(&core->config); - core->deinit(core); - free(outputBuffer); -} - -#pragma mark - Execution - -- (BOOL)loadFileAtPath:(NSString *)path error:(NSError **)error -{ - NSString *batterySavesDirectory = [self batterySavesDirectoryPath]; - [[NSFileManager defaultManager] createDirectoryAtURL:[NSURL fileURLWithPath:batterySavesDirectory] - withIntermediateDirectories:YES - attributes:nil - error:nil]; - if (core->dirs.save) { - core->dirs.save->close(core->dirs.save); - } - core->dirs.save = VDirOpen([batterySavesDirectory fileSystemRepresentation]); - - if (!mCoreLoadFile(core, [path fileSystemRepresentation])) { - *error = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotLoadROMError userInfo:nil]; - return NO; - } - mCoreAutoloadSave(core); - - core->reset(core); - - return YES; -} - -- (void)executeFrame -{ - core->runFrame(core); - - int16_t samples[SAMPLES * 2]; - size_t available = 0; - available = blip_samples_avail(core->getAudioChannel(core, 0)); - blip_read_samples(core->getAudioChannel(core, 0), samples, available, true); - blip_read_samples(core->getAudioChannel(core, 1), samples + 1, available, true); - [[self ringBufferAtIndex:0] write:samples maxLength:available * 4]; -} - -- (void)resetEmulation -{ - core->reset(core); -} - -- (void)setupEmulation -{ - blip_set_rates(core->getAudioChannel(core, 0), core->frequency(core), 32768); - blip_set_rates(core->getAudioChannel(core, 1), core->frequency(core), 32768); -} - -#pragma mark - Video - -- (OEIntSize)aspectSize -{ - return OEIntSizeMake(3, 2); -} - -- (OEIntRect)screenRect -{ - unsigned width, height; - core->currentVideoSize(core, &width, &height); - return OEIntRectMake(0, 0, width, height); -} - -- (OEIntSize)bufferSize -{ - unsigned width, height; - core->baseVideoSize(core, &width, &height); - return OEIntSizeMake(width, height); -} - -- (const void *)getVideoBufferWithHint:(void *)hint -{ - OEIntSize bufferSize = [self bufferSize]; - - if (!hint) { - hint = outputBuffer; - } - - outputBuffer = hint; - core->setVideoBuffer(core, hint, bufferSize.width); - - return hint; -} - -- (GLenum)pixelFormat -{ - return GL_RGBA; -} - -- (GLenum)pixelType -{ - return GL_UNSIGNED_INT_8_8_8_8_REV; -} - -- (NSTimeInterval)frameInterval -{ - return core->frequency(core) / (double) core->frameCycles(core); -} - -#pragma mark - Audio - -- (NSUInteger)channelCount -{ - return 2; -} - -- (double)audioSampleRate -{ - return 32768; -} - -#pragma mark - Save State - -- (NSData *)serializeStateWithError:(NSError **)outError -{ - struct VFile* vf = VFileMemChunk(nil, 0); - if (!mCoreSaveStateNamed(core, vf, SAVESTATE_SAVEDATA)) { - *outError = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotLoadStateError userInfo:nil]; - vf->close(vf); - return nil; - } - size_t size = vf->size(vf); - void* data = vf->map(vf, size, MAP_READ); - NSData *nsdata = [NSData dataWithBytes:data length:size]; - vf->unmap(vf, data, size); - vf->close(vf); - return nsdata; -} - -- (BOOL)deserializeState:(NSData *)state withError:(NSError **)outError -{ - struct VFile* vf = VFileFromConstMemory(state.bytes, state.length); - if (!mCoreLoadStateNamed(core, vf, SAVESTATE_SAVEDATA)) { - *outError = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotLoadStateError userInfo:nil]; - vf->close(vf); - return NO; - } - vf->close(vf); - return YES; -} - -- (void)saveStateToFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block -{ - struct VFile* vf = VFileOpen([fileName fileSystemRepresentation], O_CREAT | O_TRUNC | O_RDWR); - block(mCoreSaveStateNamed(core, vf, 0), nil); - vf->close(vf); -} - -- (void)loadStateFromFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block -{ - struct VFile* vf = VFileOpen([fileName fileSystemRepresentation], O_RDONLY); - block(mCoreLoadStateNamed(core, vf, 0), nil); - vf->close(vf); -} - -#pragma mark - Input - -const int GBAMap[] = { - GBA_KEY_UP, - GBA_KEY_DOWN, - GBA_KEY_LEFT, - GBA_KEY_RIGHT, - GBA_KEY_A, - GBA_KEY_B, - GBA_KEY_L, - GBA_KEY_R, - GBA_KEY_START, - GBA_KEY_SELECT -}; - -- (oneway void)didPushGBAButton:(OEGBAButton)button forPlayer:(NSUInteger)player -{ - UNUSED(player); - core->addKeys(core, 1 << GBAMap[button]); -} - -- (oneway void)didReleaseGBAButton:(OEGBAButton)button forPlayer:(NSUInteger)player -{ - UNUSED(player); - core->clearKeys(core, 1 << GBAMap[button]); -} - -#pragma mark - Cheats - -- (void)setCheat:(NSString *)code setType:(NSString *)type setEnabled:(BOOL)enabled -{ - code = [code stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - code = [code stringByReplacingOccurrencesOfString:@" " withString:@""]; - - NSString *codeId = [code stringByAppendingFormat:@"/%@", type]; - struct mCheatSet* cheatSet = [[cheatSets objectForKey:codeId] pointerValue]; - if (cheatSet) { - cheatSet->enabled = enabled; - return; - } - struct mCheatDevice* cheats = core->cheatDevice(core); - cheatSet = cheats->createSet(cheats, [codeId UTF8String]); - size_t size = mCheatSetsSize(&cheats->cheats); - if (size) { - cheatSet->copyProperties(cheatSet, *mCheatSetsGetPointer(&cheats->cheats, size - 1)); - } - int codeType = GBA_CHEAT_AUTODETECT; - NSArray *codeSet = [code componentsSeparatedByString:@"+"]; - for (id c in codeSet) { - mCheatAddLine(cheatSet, [c UTF8String], codeType); - } - cheatSet->enabled = enabled; - [cheatSets setObject:[NSValue valueWithPointer:cheatSet] forKey:codeId]; - mCheatAddSet(cheats, cheatSet); -} -@end - diff --git a/src/platform/opengl/gl.c b/src/platform/opengl/gl.c index fe24d04cf..de8354c1c 100644 --- a/src/platform/opengl/gl.c +++ b/src/platform/opengl/gl.c @@ -103,20 +103,29 @@ static void mGLContextDeinit(struct VideoBackend* v) { glDeleteTextures(VIDEO_LAYER_MAX, context->layers); } -static void mGLContextResized(struct VideoBackend* v, unsigned w, unsigned h) { +static void mGLContextResized(struct VideoBackend* v, unsigned w, unsigned h, unsigned maxW, unsigned maxH) { unsigned drawW = w; unsigned drawH = h; - unsigned maxW; - unsigned maxH; - VideoBackendGetFrameSize(v, &maxW, &maxH); + + if (maxW && drawW > maxW) { + drawW = maxW; + } + + if (maxH && drawH > maxH) { + drawH = maxH; + } + + unsigned lockW; + unsigned lockH; + VideoBackendGetFrameSize(v, &lockW, &lockH); if (v->lockAspectRatio) { - lockAspectRatioUInt(maxW, maxH, &drawW, &drawH); + lockAspectRatioUInt(lockW, lockH, &drawW, &drawH); } if (v->lockIntegerScaling) { - lockIntegerRatioUInt(maxW, &drawW); - lockIntegerRatioUInt(maxH, &drawH); + lockIntegerRatioUInt(lockW, &drawW); + lockIntegerRatioUInt(lockH, &drawH); } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -244,7 +253,7 @@ static void mGLContextImageSize(struct VideoBackend* v, enum VideoLayer layer, i *height = context->layerDims[layer].height; } else { *width = context->imageSizes[layer].width; - *height = context->imageSizes[layer].height; + *height = context->imageSizes[layer].height; } } @@ -257,7 +266,7 @@ void mGLContextPostFrame(struct VideoBackend* v, enum VideoLayer layer, const vo context->activeTex ^= 1; glBindTexture(GL_TEXTURE_2D, context->tex[context->activeTex]); } else { - glBindTexture(GL_TEXTURE_2D, context->layers[layer]); + glBindTexture(GL_TEXTURE_2D, context->layers[layer]); } int width = context->imageSizes[layer].width; diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index 469047b19..e5ee98767 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -271,20 +271,28 @@ static void mGLES2ContextDeinit(struct VideoBackend* v) { free(context->initialShader.uniforms); } -static void mGLES2ContextResized(struct VideoBackend* v, unsigned w, unsigned h) { +static void mGLES2ContextResized(struct VideoBackend* v, unsigned w, unsigned h, unsigned maxW, unsigned maxH) { struct mGLES2Context* context = (struct mGLES2Context*) v; unsigned drawW = w; unsigned drawH = h; - unsigned maxW = context->width; - unsigned maxH = context->height; + if (maxW && drawW > maxW) { + drawW = maxW; + } + + if (maxH && drawH > maxH) { + drawH = maxH; + } + + unsigned lockW = context->width; + unsigned lockH = context->height; if (v->lockAspectRatio) { - lockAspectRatioUInt(maxW, maxH, &drawW, &drawH); + lockAspectRatioUInt(lockW, lockH, &drawW, &drawH); } if (v->lockIntegerScaling) { - lockIntegerRatioUInt(maxW, &drawW); - lockIntegerRatioUInt(maxH, &drawH); + lockIntegerRatioUInt(lockW, &drawW); + lockIntegerRatioUInt(lockH, &drawH); } size_t n; for (n = 0; n < context->nShaders; ++n) { @@ -293,6 +301,7 @@ static void mGLES2ContextResized(struct VideoBackend* v, unsigned w, unsigned h) } } context->finalShader.dirty = true; + context->interframeShader.dirty = true; glBindTexture(GL_TEXTURE_2D, context->finalShader.tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, drawW, drawH, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glBindFramebuffer(GL_FRAMEBUFFER, context->finalShader.fbo); @@ -520,7 +529,7 @@ static void mGLES2ContextImageSize(struct VideoBackend* v, enum VideoLayer layer *height = context->layerDims[layer].height; } else { *width = context->imageSizes[layer].width; - *height = context->imageSizes[layer].height; + *height = context->imageSizes[layer].height; } } @@ -608,7 +617,7 @@ void mGLES2ShaderInit(struct mGLES2Shader* shader, const char* vs, const char* f if (shader->width > 0 && shader->height > 0) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, shader->width, shader->height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shader->tex, 0); @@ -1072,6 +1081,7 @@ static bool _loadUniform(struct Configuration* description, size_t pass, struct return true; } +#ifdef ENABLE_VFS bool mGLES2ShaderLoad(struct VideoShader* shader, struct VDir* dir) { struct VFile* manifest = dir->openFile(dir, "manifest.ini", O_RDONLY); if (!manifest) { @@ -1195,6 +1205,7 @@ bool mGLES2ShaderLoad(struct VideoShader* shader, struct VDir* dir) { ConfigurationDeinit(&description); return success; } +#endif void mGLES2ShaderFree(struct VideoShader* shader) { free((void*) shader->name); diff --git a/src/platform/opengl/gles2.h b/src/platform/opengl/gles2.h index e53a1bab5..e3f46a9c0 100644 --- a/src/platform/opengl/gles2.h +++ b/src/platform/opengl/gles2.h @@ -106,8 +106,10 @@ void mGLES2ShaderDeinit(struct mGLES2Shader*); void mGLES2ShaderAttach(struct mGLES2Context*, struct mGLES2Shader*, size_t nShaders); void mGLES2ShaderDetach(struct mGLES2Context*); +#ifdef ENABLE_VFS struct VDir; bool mGLES2ShaderLoad(struct VideoShader*, struct VDir*); +#endif void mGLES2ShaderFree(struct VideoShader*); CXX_GUARD_END diff --git a/src/platform/psp2/CMakeLists.txt b/src/platform/psp2/CMakeLists.txt index 3e638aa64..9653205fb 100644 --- a/src/platform/psp2/CMakeLists.txt +++ b/src/platform/psp2/CMakeLists.txt @@ -10,8 +10,8 @@ file(GLOB OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/psp2-*.c) set(OS_SRC ${OS_SRC} PARENT_SCOPE) source_group("PS Vita-specific code" FILES ${OS_SRC}) -list(APPEND CORE_VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sce-vfs.c) -set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE) +list(APPEND VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sce-vfs.c) +set(VFS_SRC ${VFS_SRC} PARENT_SCOPE) set(OS_LIB -lvita2d -l${M_LIBRARY} -lSceAppMgr_stub @@ -47,7 +47,7 @@ target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} ${OS_LIB}) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.o COMMAND ${OBJCOPY_CMD} icons2x.png ${CMAKE_CURRENT_BINARY_DIR}/icons.o - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/res) + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/res) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/backdrop.o COMMAND ${OBJCOPY_CMD} backdrop.png ${CMAKE_CURRENT_BINARY_DIR}/backdrop.o diff --git a/src/platform/psp2/psp2-common.h b/src/platform/psp2/psp2-common.h index 7f34d1d10..dcb67b700 100644 --- a/src/platform/psp2/psp2-common.h +++ b/src/platform/psp2/psp2-common.h @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef PSP2_COMMON_H #define PSP2_COMMON_H - + #include #define PSP2_HORIZONTAL_PIXELS 960 diff --git a/src/platform/psp2/psp2-context.c b/src/platform/psp2/psp2-context.c index a7504f7cc..be9ff4495 100644 --- a/src/platform/psp2/psp2-context.c +++ b/src/platform/psp2/psp2-context.c @@ -5,7 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "psp2-context.h" -#include #include #ifdef M_CORE_GBA @@ -18,9 +17,10 @@ #include "feature/gui/gui-runner.h" #include -#include +#include #include #include +#include #include #include #include @@ -36,7 +36,6 @@ #include -#define RUMBLE_PWM 8 #define CDRAM_ALIGN 0x40000 mLOG_DECLARE_CATEGORY(GUI_PSP2); @@ -54,6 +53,7 @@ static int currentTex; static vita2d_texture* tex[2]; static vita2d_texture* screenshot; static Thread audioThread; +static double fpsRatio = 1; static bool interframeBlending = false; static bool sgbCrop = false; static bool blurry = false; @@ -63,11 +63,7 @@ static struct mSceRotationSource { struct SceMotionSensorState state; } rotation; -static struct mSceRumble { - struct mRumble d; - struct CircleBuffer history; - int current; -} rumble; +static struct mRumbleIntegrator rumble; static struct mSceImageSource { struct mImageSource d; @@ -84,14 +80,21 @@ bool frameLimiter = true; extern const uint8_t _binary_backdrop_png_start[]; static vita2d_texture* backdrop = 0; +#define BUFFERS 16 #define PSP2_SAMPLES 512 -#define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 16) +#define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * BUFFERS) + +struct mPSP2AudioBuffer { + int16_t samples[PSP2_SAMPLES * 2] __attribute__((__aligned__(64))); + bool full; +}; static struct mPSP2AudioContext { - struct mStereoSample buffer[PSP2_AUDIO_BUFFER_SIZE]; - size_t writeOffset; - size_t readOffset; - size_t samples; + struct mPSP2AudioBuffer outputBuffers[BUFFERS]; + int currentAudioBuffer; + int nextAudioBuffer; + struct mAudioBuffer buffer; + struct mAudioResampler resampler; Mutex mutex; Condition cond; bool running; @@ -103,29 +106,26 @@ void mPSP2MapKey(struct mInputMap* map, int pspKey, int key) { static THREAD_ENTRY _audioThread(void* context) { struct mPSP2AudioContext* audio = (struct mPSP2AudioContext*) context; - uint32_t zeroBuffer[PSP2_SAMPLES] = {0}; - void* buffer = zeroBuffer; + const int16_t zeroBuffer[PSP2_SAMPLES * 2] __attribute__((__aligned__(64))) = {0}; + const void* buffer = zeroBuffer; int audioPort = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, PSP2_SAMPLES, 48000, SCE_AUDIO_OUT_MODE_STEREO); + struct mPSP2AudioBuffer* outputBuffer = NULL; while (audio->running) { MutexLock(&audio->mutex); - if (buffer != zeroBuffer) { + if (outputBuffer) { // Can only happen in successive iterations - audio->samples -= PSP2_SAMPLES; + outputBuffer->full = false; ConditionWake(&audio->cond); } - if (audio->samples >= PSP2_SAMPLES) { - buffer = &audio->buffer[audio->readOffset]; - audio->readOffset += PSP2_SAMPLES; - if (audio->readOffset >= PSP2_AUDIO_BUFFER_SIZE) { - audio->readOffset = 0; - } - // Don't mark samples as read until the next loop iteration to prevent - // writing to the buffer while being read (see above) + outputBuffer = &audio->outputBuffers[audio->currentAudioBuffer]; + if (outputBuffer->full) { + buffer = outputBuffer->samples; + audio->currentAudioBuffer = (audio->currentAudioBuffer + 1) % BUFFERS; } else { buffer = zeroBuffer; + outputBuffer = NULL; } MutexUnlock(&audio->mutex); - sceAudioOutOutput(audioPort, buffer); } sceAudioOutReleasePort(audioPort); @@ -149,20 +149,13 @@ static int32_t _readTiltY(struct mRotationSource* source) { static int32_t _readGyroZ(struct mRotationSource* source) { struct mSceRotationSource* rotation = (struct mSceRotationSource*) source; - return rotation->state.gyro.z * -0x10000000; + return rotation->state.gyro.z * -0x8000000; } -static void _setRumble(struct mRumble* source, int enable) { - struct mSceRumble* rumble = (struct mSceRumble*) source; - rumble->current += enable; - if (CircleBufferSize(&rumble->history) == RUMBLE_PWM) { - int8_t oldLevel; - CircleBufferRead8(&rumble->history, &oldLevel); - rumble->current -= oldLevel; - } - CircleBufferWrite8(&rumble->history, enable); - int small = (rumble->current << 21) / 65793; - int big = ((rumble->current * rumble->current) << 18) / 65793; +static void _setRumble(struct mRumbleIntegrator* source, float level) { + UNUSED(source); + int small = level * 255; + int big = (level * level) * 255; struct SceCtrlActuator state = { small, big @@ -243,26 +236,36 @@ static void _requestImage(struct mImageSource* source, const void** buffer, size sceCameraRead(imageSource->cam - 1, &read); } -static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { +static void _postAudioBuffer(struct mAVStream* stream, struct mAudioBuffer* buf) { UNUSED(stream); MutexLock(&audioContext.mutex); - while (audioContext.samples + PSP2_SAMPLES >= PSP2_AUDIO_BUFFER_SIZE) { - if (!frameLimiter) { - blip_clear(left); - blip_clear(right); - MutexUnlock(&audioContext.mutex); - return; + mAudioResamplerProcess(&audioContext.resampler); + while (mAudioBufferAvailable(&audioContext.buffer) >= PSP2_SAMPLES) { + struct mPSP2AudioBuffer* buffer = &audioContext.outputBuffers[audioContext.nextAudioBuffer]; + while (buffer->full) { + if (!frameLimiter) { + break; + } + ConditionWait(&audioContext.cond, &audioContext.mutex); } - ConditionWait(&audioContext.cond, &audioContext.mutex); + mAudioBufferRead(&audioContext.buffer, buffer->samples, PSP2_SAMPLES); + buffer->full = true; + audioContext.nextAudioBuffer = (audioContext.nextAudioBuffer + 1) % BUFFERS; } - struct mStereoSample* samples = &audioContext.buffer[audioContext.writeOffset]; - blip_read_samples(left, &samples[0].left, PSP2_SAMPLES, true); - blip_read_samples(right, &samples[0].right, PSP2_SAMPLES, true); - audioContext.samples += PSP2_SAMPLES; - audioContext.writeOffset += PSP2_SAMPLES; - if (audioContext.writeOffset >= PSP2_AUDIO_BUFFER_SIZE) { - audioContext.writeOffset = 0; + MutexUnlock(&audioContext.mutex); +} + +static void _audioRateChanged(struct mAVStream* stream, unsigned sampleRate) { + UNUSED(stream); + if (!sampleRate) { + return; } + if (!audioContext.resampler.source || !audioContext.resampler.destination) { + return; + } + MutexLock(&audioContext.mutex); + mAudioResamplerProcess(&audioContext.resampler); + mAudioResamplerSetSource(&audioContext.resampler, audioContext.resampler.source, sampleRate / fpsRatio, true); MutexUnlock(&audioContext.mutex); } @@ -294,7 +297,11 @@ void mPSP2SetFrameLimiter(struct mGUIRunner* runner, bool limit) { UNUSED(runner); if (!frameLimiter && limit) { MutexLock(&audioContext.mutex); - while (audioContext.samples) { + while (true) { + struct mPSP2AudioBuffer* buffer = &audioContext.outputBuffers[audioContext.currentAudioBuffer]; + if (!buffer->full) { + break; + } ConditionWait(&audioContext.cond, &audioContext.mutex); } MutexUnlock(&audioContext.mutex); @@ -334,6 +341,9 @@ void mPSP2Setup(struct mGUIRunner* runner) { runner->core->setVideoBuffer(runner->core, vita2d_texture_get_datap(tex[currentTex]), 256); runner->core->setAudioBufferSize(runner->core, PSP2_SAMPLES); + mAudioBufferInit(&audioContext.buffer, PSP2_AUDIO_BUFFER_SIZE, 2); + mAudioResamplerInit(&audioContext.resampler, mINTERPOLATOR_COSINE); + mAudioResamplerSetDestination(&audioContext.resampler, &audioContext.buffer, 48000); rotation.d.sample = _sampleRotation; rotation.d.readTiltX = _readTiltX; @@ -341,8 +351,8 @@ void mPSP2Setup(struct mGUIRunner* runner) { rotation.d.readGyroZ = _readGyroZ; runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation.d); - rumble.d.setRumble = _setRumble; - CircleBufferInit(&rumble.history, RUMBLE_PWM); + mRumbleIntegratorInit(&rumble); + rumble.setRumble = _setRumble; runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble.d); camera.d.startRequestImage = _startRequestImage; @@ -357,6 +367,7 @@ void mPSP2Setup(struct mGUIRunner* runner) { stream.postAudioFrame = NULL; stream.postAudioBuffer = _postAudioBuffer; stream.postVideoFrame = NULL; + stream.audioRateChanged = _audioRateChanged; runner->core->setAVStream(runner->core, &stream); frameLimiter = true; @@ -374,12 +385,6 @@ void mPSP2Setup(struct mGUIRunner* runner) { } void mPSP2LoadROM(struct mGUIRunner* runner) { - float rate = 60.0f / 1.001f; - sceDisplayGetRefreshRate(&rate); - double ratio = GBAAudioCalculateRatio(1, rate, 1); - blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), 48000 * ratio); - blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), 48000 * ratio); - switch (runner->core->platform(runner->core)) { #ifdef M_CORE_GBA case mPLATFORM_GBA: @@ -415,10 +420,20 @@ void mPSP2LoadROM(struct mGUIRunner* runner) { MutexInit(&audioContext.mutex); ConditionInit(&audioContext.cond); - memset(audioContext.buffer, 0, sizeof(audioContext.buffer)); - audioContext.readOffset = 0; - audioContext.writeOffset = 0; + mAudioBufferClear(&audioContext.buffer); + audioContext.nextAudioBuffer = 0; + audioContext.currentAudioBuffer = 0; audioContext.running = true; + + float rate = 60.0f / 1.001f; + sceDisplayGetRefreshRate(&rate); + fpsRatio = mCoreCalculateFramerateRatio(runner->core, rate); + unsigned sampleRate = runner->core->audioSampleRate(runner->core); + if (!sampleRate) { + sampleRate = 32768; + } + mAudioBufferClear(&audioContext.buffer); + mAudioResamplerSetSource(&audioContext.resampler, runner->core->getAudioBuffer(runner->core), sampleRate / fpsRatio, true); ThreadCreate(&audioThread, _audioThread, &audioContext); } @@ -482,7 +497,8 @@ void mPSP2Unpaused(struct mGUIRunner* runner) { void mPSP2Teardown(struct mGUIRunner* runner) { UNUSED(runner); - CircleBufferDeinit(&rumble.history); + mAudioResamplerDeinit(&audioContext.resampler); + mAudioBufferDeinit(&audioContext.buffer); vita2d_free_texture(tex[0]); vita2d_free_texture(tex[1]); vita2d_free_texture(screenshot); diff --git a/src/platform/psp2/psp2-context.h b/src/platform/psp2/psp2-context.h index 2c9a47e09..316dbd434 100644 --- a/src/platform/psp2/psp2-context.h +++ b/src/platform/psp2/psp2-context.h @@ -22,7 +22,7 @@ void mPSP2Paused(struct mGUIRunner* runner); void mPSP2Unpaused(struct mGUIRunner* runner); void mPSP2Swap(struct mGUIRunner* runner); void mPSP2Draw(struct mGUIRunner* runner, bool faded); -void mPSP2DrawScreenshot(struct mGUIRunner* runner, const color_t* pixels, unsigned width, unsigned height, bool faded); +void mPSP2DrawScreenshot(struct mGUIRunner* runner, const mColor* pixels, unsigned width, unsigned height, bool faded); void mPSP2IncrementScreenMode(struct mGUIRunner* runner); void mPSP2SetFrameLimiter(struct mGUIRunner* runner, bool limit); uint16_t mPSP2PollInput(struct mGUIRunner* runner); diff --git a/src/platform/psp2/sce-vfs.c b/src/platform/psp2/sce-vfs.c index 621fd1f67..a98e9943d 100644 --- a/src/platform/psp2/sce-vfs.c +++ b/src/platform/psp2/sce-vfs.c @@ -153,11 +153,10 @@ ssize_t _vfsceSize(struct VFile* vf) { bool _vfsceSync(struct VFile* vf, void* buffer, size_t size) { struct VFileSce* vfsce = (struct VFileSce*) vf; if (buffer && size) { - SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR); - sceIoLseek(vfsce->fd, 0, SEEK_SET); - int res = sceIoWrite(vfsce->fd, buffer, size); - sceIoLseek(vfsce->fd, cur, SEEK_SET); - return res == size; + int res = sceIoPwrite(vfsce->fd, buffer, size, 0); + if (res < 0 || (size_t) res != size) { + return false; + } } return sceIoSyncByFd(vfsce->fd, 0) >= 0; } @@ -284,7 +283,10 @@ struct VDirSceDevList { static const char* _devs[] = { "ux0:", "ur0:", - "uma0:" + "uma0:", + "imc0:", + "xmc0:", + NULL }; struct VDir* VDeviceList() { @@ -322,7 +324,7 @@ static void _vdlsceRewind(struct VDir* vd) { static struct VDirEntry* _vdlsceListNext(struct VDir* vd) { struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd; - while (vdl->vde.index < 3) { + while (vdl->vde.index < 0 || _devs[vdl->vde.index]) { ++vdl->vde.index; vdl->vde.name = _devs[vdl->vde.index]; SceUID dir = sceIoDopen(vdl->vde.name); diff --git a/src/platform/python/_builder.h b/src/platform/python/_builder.h index eef4cf046..c39fcf143 100644 --- a/src/platform/python/_builder.h +++ b/src/platform/python/_builder.h @@ -22,8 +22,7 @@ #define CXX_GUARD_END #define PYCPARSE -#define va_list void* - +typedef ... va_list; typedef int... time_t; typedef int... off_t; typedef ...* png_structp; @@ -36,7 +35,6 @@ void free(void*); #include -#include #include #include #include @@ -47,7 +45,6 @@ void free(void*); #define PYEXPORT extern "Python+C" #include "platform/python/core.h" #include "platform/python/log.h" -#include "platform/python/sio.h" #include "platform/python/vfs-py.h" #undef PYEXPORT @@ -67,7 +64,7 @@ void free(void*); #include #include #endif -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS #include #include #endif diff --git a/src/platform/python/_builder.py b/src/platform/python/_builder.py index 1e21cc82f..f18a3c95e 100644 --- a/src/platform/python/_builder.py +++ b/src/platform/python/_builder.py @@ -21,7 +21,6 @@ ffi.set_source("mgba._pylib", """ #define MGBA_EXPORT #include #define OPAQUE_THREADING -#include #include #include #include @@ -46,7 +45,6 @@ ffi.set_source("mgba._pylib", """ #define PYEXPORT #include "platform/python/core.h" #include "platform/python/log.h" -#include "platform/python/sio.h" #include "platform/python/vfs-py.h" #undef PYEXPORT """, include_dirs=[incdir, srcdir], @@ -54,7 +52,7 @@ ffi.set_source("mgba._pylib", """ libraries=["mgba"], library_dirs=[bindir], runtime_library_dirs=[libdir], - sources=[os.path.join(pydir, path) for path in ["vfs-py.c", "core.c", "log.c", "sio.c"]]) + sources=[os.path.join(pydir, path) for path in ["vfs-py.c", "core.c", "log.c"]]) preprocessed = subprocess.check_output(cpp + ["-fno-inline", "-P"] + cppflags + [os.path.join(pydir, "_builder.h")], universal_newlines=True) diff --git a/src/platform/python/engine.c b/src/platform/python/engine.c index 67d1d7b49..86ec2cf5c 100644 --- a/src/platform/python/engine.c +++ b/src/platform/python/engine.c @@ -9,7 +9,7 @@ #include #include -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS #include #endif @@ -23,7 +23,7 @@ static bool mPythonScriptEngineLoadScript(struct mScriptEngine*, const char* nam static void mPythonScriptEngineRun(struct mScriptEngine*); static bool mPythonScriptEngineLookupSymbol(struct mScriptEngine*, const char* name, int32_t* out); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS static void mPythonScriptDebuggerEntered(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); #endif @@ -41,7 +41,7 @@ struct mPythonScriptEngine* mPythonCreateScriptEngine(void) { engine->d.loadScript = mPythonScriptEngineLoadScript; engine->d.run = mPythonScriptEngineRun; engine->d.lookupSymbol = mPythonScriptEngineLookupSymbol; -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS engine->d.debuggerEntered = mPythonScriptDebuggerEntered; #endif engine->sb = NULL; @@ -82,7 +82,7 @@ bool mPythonScriptEngineLoadScript(struct mScriptEngine* se, const char* name, s void mPythonScriptEngineRun(struct mScriptEngine* se) { struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se; -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS struct mDebugger* debugger = mScriptBridgeGetDebugger(engine->sb); if (debugger) { mPythonSetDebugger(debugger); @@ -97,7 +97,7 @@ bool mPythonScriptEngineLookupSymbol(struct mScriptEngine* se, const char* name, return mPythonLookupSymbol(name, out); } -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS void mPythonScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se; diff --git a/src/platform/python/lib.h b/src/platform/python/lib.h index 0dd8754ed..d0893101f 100644 --- a/src/platform/python/lib.h +++ b/src/platform/python/lib.h @@ -6,7 +6,7 @@ extern bool mPythonLoadScript(const char*, struct VFile*); extern void mPythonRunPending(); extern bool mPythonLookupSymbol(const char* name, int32_t* out); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS extern void mPythonSetDebugger(struct mDebugger*); extern void mPythonDebuggerEntered(enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); #endif diff --git a/src/platform/python/mgba/audio.py b/src/platform/python/mgba/audio.py deleted file mode 100644 index a833d0827..000000000 --- a/src/platform/python/mgba/audio.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2013-2018 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/. -from ._pylib import ffi, lib # pylint: disable=no-name-in-module - - -class Buffer(object): - def __init__(self, native, internal_rate): - self._native = native - self._internal_rate = internal_rate - - @property - def available(self): - return lib.blip_samples_avail(self._native) - - def set_rate(self, rate): - lib.blip_set_rates(self._native, self._internal_rate, rate) - - def read(self, samples): - buffer = ffi.new("short[%i]" % samples) - count = self.read_into(buffer, samples, 1, 0) - return buffer[:count] - - def read_into(self, buffer, samples, channels=1, interleave=0): - return lib.blip_read_samples(self._native, ffi.addressof(buffer, interleave), samples, channels == 2) - - def clear(self): - lib.blip_clear(self._native) - - -class StereoBuffer(object): - def __init__(self, left, right): - self._left = left - self._right = right - - @property - def available(self): - return min(self._left.available, self._right.available) - - def set_rate(self, rate): - self._left.set_rate(rate) - self._right.set_rate(rate) - - def read(self, samples): - buffer = ffi.new("short[%i]" % (2 * samples)) - count = self.read_into(buffer, samples) - return buffer[0:2 * count] - - def read_into(self, buffer, samples): - samples = self._left.read_into(buffer, samples, 2, 0) - return self._right.read_into(buffer, samples, 2, 1) - - def clear(self): - self._left.clear() - self._right.clear() diff --git a/src/platform/python/mgba/core.py b/src/platform/python/mgba/core.py index 51f543d3a..22965b3f9 100644 --- a/src/platform/python/mgba/core.py +++ b/src/platform/python/mgba/core.py @@ -4,7 +4,7 @@ # 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/. from ._pylib import ffi, lib # pylint: disable=no-name-in-module -from . import tile, audio +from . import tile from cached_property import cached_property from functools import wraps @@ -242,22 +242,6 @@ class Core(object): def set_video_buffer(self, image): self._core.setVideoBuffer(self._core, image.buffer, image.stride) - @protected - def set_audio_buffer_size(self, size): - self._core.setAudioBufferSize(self._core, size) - - @property - def audio_buffer_size(self): - return self._core.getAudioBufferSize(self._core) - - @protected - def get_audio_channels(self): - return audio.StereoBuffer(self.get_audio_channel(0), self.get_audio_channel(1)); - - @protected - def get_audio_channel(self, channel): - return audio.Buffer(self._core.getAudioChannel(self._core, channel), self.frequency) - @protected def reset(self): self._core.reset(self._core) diff --git a/src/platform/python/mgba/gba.py b/src/platform/python/mgba/gba.py index a0c86ac84..0c249cec5 100644 --- a/src/platform/python/mgba/gba.py +++ b/src/platform/python/mgba/gba.py @@ -23,12 +23,12 @@ class GBA(Core): KEY_L = lib.GBA_KEY_L KEY_R = lib.GBA_KEY_R - SIO_NORMAL_8 = lib.SIO_NORMAL_8 - SIO_NORMAL_32 = lib.SIO_NORMAL_32 - SIO_MULTI = lib.SIO_MULTI - SIO_UART = lib.SIO_UART - SIO_JOYBUS = lib.SIO_JOYBUS - SIO_GPIO = lib.SIO_GPIO + SIO_NORMAL_8 = lib.GBA_SIO_NORMAL_8 + SIO_NORMAL_32 = lib.GBA_SIO_NORMAL_32 + SIO_MULTI = lib.GBA_SIO_MULTI + SIO_UART = lib.GBA_SIO_UART + SIO_JOYBUS = lib.GBA_SIO_JOYBUS + SIO_GPIO = lib.GBA_SIO_GPIO def __init__(self, native): super(GBA, self).__init__(native) @@ -52,72 +52,6 @@ class GBA(Core): super(GBA, self)._load() self.memory = GBAMemory(self._core, self._native.memory.romSize) - def attach_sio(self, link, mode=lib.SIO_MULTI): - self._sio.add(mode) - lib.GBASIOSetDriver(ffi.addressof(self._native.sio), link._native, mode) - - def __del__(self): - for mode in self._sio: - lib.GBASIOSetDriver(ffi.addressof(self._native.sio), ffi.NULL, mode) - - -create_callback("GBASIOPythonDriver", "init") -create_callback("GBASIOPythonDriver", "deinit") -create_callback("GBASIOPythonDriver", "load") -create_callback("GBASIOPythonDriver", "unload") -create_callback("GBASIOPythonDriver", "writeRegister") - - -class GBASIODriver(object): - def __init__(self): - super(GBASIODriver, self).__init__() - - self._handle = ffi.new_handle(self) - self._native = ffi.gc(lib.GBASIOPythonDriverCreate(self._handle), lib.free) - - def init(self): - return True - - def deinit(self): - pass - - def load(self): - return True - - def unload(self): - return True - - def write_register(self, address, value): - return value - - -class GBASIOJOYDriver(GBASIODriver): - RESET = lib.JOY_RESET - POLL = lib.JOY_POLL - TRANS = lib.JOY_TRANS - RECV = lib.JOY_RECV - - def __init__(self): - super(GBASIOJOYDriver, self).__init__() - - self._native = ffi.gc(lib.GBASIOJOYPythonDriverCreate(self._handle), lib.free) - - def send_command(self, cmd, data): - buffer = ffi.new('uint8_t[5]') - try: - buffer[0] = data[0] - buffer[1] = data[1] - buffer[2] = data[2] - buffer[3] = data[3] - buffer[4] = data[4] - except IndexError: - pass - - outlen = lib.GBASIOJOYSendCommand(self._native, cmd, buffer) - if outlen > 0 and outlen <= 5: - return bytes(buffer[0:outlen]) - return None - class GBAMemory(Memory): def __init__(self, core, romSize=lib.SIZE_CART0): diff --git a/src/platform/python/mgba/image.py b/src/platform/python/mgba/image.py index 3b6679524..a67801021 100644 --- a/src/platform/python/mgba/image.py +++ b/src/platform/python/mgba/image.py @@ -23,7 +23,7 @@ class Image: def constitute(self): if self.stride <= 0: self.stride = self.width - self.buffer = ffi.new("color_t[{}]".format(self.stride * self.height)) + self.buffer = ffi.new("mColor[{}]".format(self.stride * self.height)) def save_png(self, fileobj): png_file = png.PNG(fileobj, mode=png.MODE_RGBA if self.alpha else png.MODE_RGB) @@ -65,7 +65,7 @@ def u32_to_u16(color): return abgr -if ffi.sizeof("color_t") == 2: +if ffi.sizeof("mColor") == 2: def color_to_u16(color): return color diff --git a/src/platform/python/mgba/tile.py b/src/platform/python/mgba/tile.py index 48812930c..5a9e5d713 100644 --- a/src/platform/python/mgba/tile.py +++ b/src/platform/python/mgba/tile.py @@ -18,7 +18,7 @@ class Tile: def composite(self, i, x, y): for iy in range(8): - ffi.memmove(ffi.addressof(i.buffer, x + (iy + y) * i.stride), ffi.addressof(self.buffer, iy * 8), 8 * ffi.sizeof("color_t")) + ffi.memmove(ffi.addressof(i.buffer, x + (iy + y) * i.stride), ffi.addressof(self.buffer, iy * 8), 8 * ffi.sizeof("mColor")) class CacheSet: @@ -55,7 +55,7 @@ class MapView: if not y & 7: lib.mMapCacheCleanRow(self.cache, y >> 3) row = lib.mMapCacheGetRow(self.cache, y) - ffi.memmove(ffi.addressof(i.buffer, i.stride * y), row, self.width * 8 * ffi.sizeof("color_t")) + ffi.memmove(ffi.addressof(i.buffer, i.stride * y), row, self.width * 8 * ffi.sizeof("mColor")) return i diff --git a/src/platform/python/sio.c b/src/platform/python/sio.c deleted file mode 100644 index fbb407831..000000000 --- a/src/platform/python/sio.c +++ /dev/null @@ -1,88 +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/. */ -#include - -#define CREATE_SHIM(PLAT, NAME, RETURN) \ - RETURN _py ## PLAT ## SIOPythonDriver ## NAME (void* driver); \ - static RETURN _py ## PLAT ## SIOPythonDriver ## NAME ## Shim(struct PLAT ## SIODriver* driver) { \ - struct PLAT ## SIODriver* py = (struct PLAT ## SIODriver*) driver; \ - return _py ## PLAT ## SIOPythonDriver ## NAME(py); \ - } - -#define CREATE_SHIM_ARGS(PLAT, NAME, RETURN, TYPES, ...) \ - RETURN _py ## PLAT ## SIOPythonDriver ## NAME TYPES; \ - static RETURN _py ## PLAT ## SIOPythonDriver ## NAME ## Shim TYPES { \ - struct PLAT ## SIODriver* py = (struct PLAT ## SIODriver*) driver; \ - return _py ## PLAT ## SIOPythonDriver ## NAME(py, __VA_ARGS__); \ - } - -#ifdef M_CORE_GBA - -#include - -struct GBASIOPythonDriver { - struct GBASIODriver d; - void* pyobj; -}; - -CREATE_SHIM(GBA, Init, bool); -CREATE_SHIM(GBA, Deinit, void); -CREATE_SHIM(GBA, Load, bool); -CREATE_SHIM(GBA, Unload, bool); -CREATE_SHIM_ARGS(GBA, WriteRegister, uint16_t, (struct GBASIODriver* driver, uint32_t address, uint16_t value), address, value); - -struct GBASIODriver* GBASIOPythonDriverCreate(void* pyobj) { - struct GBASIOPythonDriver* driver = malloc(sizeof(*driver)); - driver->d.init = _pyGBASIOPythonDriverInitShim; - driver->d.deinit = _pyGBASIOPythonDriverDeinitShim; - driver->d.load = _pyGBASIOPythonDriverLoadShim; - driver->d.unload = _pyGBASIOPythonDriverUnloadShim; - driver->d.writeRegister = _pyGBASIOPythonDriverWriteRegisterShim; - - driver->pyobj = pyobj; - return &driver->d; -} - -struct GBASIODriver* GBASIOJOYPythonDriverCreate(void* pyobj) { - struct GBASIOPythonDriver* driver = malloc(sizeof(*driver)); - GBASIOJOYCreate(&driver->d); - driver->d.init = _pyGBASIOPythonDriverInitShim; - driver->d.deinit = _pyGBASIOPythonDriverDeinitShim; - driver->d.load = _pyGBASIOPythonDriverLoadShim; - driver->d.unload = _pyGBASIOPythonDriverUnloadShim; - - driver->pyobj = pyobj; - return &driver->d; -} - -#endif - -#ifdef M_CORE_GB - -#include - -struct GBSIOPythonDriver { - struct GBSIODriver d; - void* pyobj; -}; - -CREATE_SHIM(GB, Init, bool); -CREATE_SHIM(GB, Deinit, void); -CREATE_SHIM_ARGS(GB, WriteSB, void, (struct GBSIODriver* driver, uint8_t value), value); -CREATE_SHIM_ARGS(GB, WriteSC, uint8_t, (struct GBSIODriver* driver, uint8_t value), value); - -struct GBSIODriver* GBSIOPythonDriverCreate(void* pyobj) { - struct GBSIOPythonDriver* driver = malloc(sizeof(*driver)); - driver->d.init = _pyGBSIOPythonDriverInitShim; - driver->d.deinit = _pyGBSIOPythonDriverDeinitShim; - driver->d.writeSB = _pyGBSIOPythonDriverWriteSBShim; - driver->d.writeSC = _pyGBSIOPythonDriverWriteSCShim; - - driver->pyobj = pyobj; - return &driver->d; -} - -#endif diff --git a/src/platform/python/sio.h b/src/platform/python/sio.h deleted file mode 100644 index 23b059427..000000000 --- a/src/platform/python/sio.h +++ /dev/null @@ -1,42 +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/. */ -#ifdef M_CORE_GBA - -#include - -struct GBASIOPythonDriver { - struct GBASIODriver d; - void* pyobj; -}; - -struct GBASIODriver* GBASIOPythonDriverCreate(void* pyobj); -struct GBASIODriver* GBASIOJOYPythonDriverCreate(void* pyobj); - -PYEXPORT bool _pyGBASIOPythonDriverInit(void* driver); -PYEXPORT void _pyGBASIOPythonDriverDeinit(void* driver); -PYEXPORT bool _pyGBASIOPythonDriverLoad(void* driver); -PYEXPORT bool _pyGBASIOPythonDriverUnload(void* driver); -PYEXPORT uint16_t _pyGBASIOPythonDriverWriteRegister(void* driver, uint32_t address, uint16_t value); - -#endif - -#ifdef M_CORE_GB - -#include - -struct GBSIOPythonDriver { - struct GBSIODriver d; - void* pyobj; -}; - -struct GBSIODriver* GBSIOPythonDriverCreate(void* pyobj); - -PYEXPORT bool _pyGBSIOPythonDriverInit(void* driver); -PYEXPORT void _pyGBSIOPythonDriverDeinit(void* driver); -PYEXPORT void _pyGBSIOPythonDriverWriteSB(void* driver, uint8_t value); -PYEXPORT uint8_t _pyGBSIOPythonDriverWriteSC(void* driver, uint8_t value); - -#endif diff --git a/src/platform/qt/Action.cpp b/src/platform/qt/Action.cpp index e5d6600d4..850b64934 100644 --- a/src/platform/qt/Action.cpp +++ b/src/platform/qt/Action.cpp @@ -12,17 +12,17 @@ Action::Action(QObject* parent) { } -Action::Action(Function function, const QString& name, const QString& visibleName, QObject* parent) +Action::Action(Function&& function, const QString& name, const QString& visibleName, QObject* parent) : QObject(parent) - , m_function(function) + , m_function(std::move(function)) , m_name(name) , m_visibleName(visibleName) { } -Action::Action(Action::BooleanFunction function, const QString& name, const QString& visibleName, QObject* parent) +Action::Action(Action::BooleanFunction&& function, const QString& name, const QString& visibleName, QObject* parent) : QObject(parent) - , m_booleanFunction(function) + , m_booleanFunction(std::move(function)) , m_name(name) , m_visibleName(visibleName) { @@ -57,9 +57,9 @@ Action::Action(Action& other) { } -void Action::connect(Function func) { +void Action::connect(Function&& func) { m_booleanFunction = {}; - m_function = func; + m_function = std::move(func); } void Action::trigger(bool active) { diff --git a/src/platform/qt/Action.h b/src/platform/qt/Action.h index 9fe2f6aa2..ee3d4587d 100644 --- a/src/platform/qt/Action.h +++ b/src/platform/qt/Action.h @@ -24,8 +24,8 @@ public: QUIT, }; - Action(Function, const QString& name, const QString& visibleName, QObject* parent = nullptr); - Action(BooleanFunction, const QString& name, const QString& visibleName, QObject* parent = nullptr); + Action(Function&&, const QString& name, const QString& visibleName, QObject* parent = nullptr); + Action(BooleanFunction&&, const QString& name, const QString& visibleName, QObject* parent = nullptr); Action(const QString& name, const QString& visibleName, QObject* parent = nullptr); Action(QObject* parent = nullptr); @@ -45,7 +45,7 @@ public: return m_name == other.m_name; } - void connect(Function); + void connect(Function&&); bool isEnabled() const { return m_enabled; } bool isActive() const { return m_active; } diff --git a/src/platform/qt/ActionMapper.cpp b/src/platform/qt/ActionMapper.cpp index cb96ab6dc..90302c350 100644 --- a/src/platform/qt/ActionMapper.cpp +++ b/src/platform/qt/ActionMapper.cpp @@ -93,7 +93,13 @@ void ActionMapper::rebuildMenu(const QString& menu, QMenu* qmenu, QWidget* conte qaction->setMenuRole(QAction::QuitRole); break; } - QObject::connect(qaction, &QAction::triggered, [qaction, action](bool enabled) { + + std::weak_ptr weakAction(action); + QObject::connect(qaction, &QAction::triggered, [qaction, weakAction](bool enabled) { + if (weakAction.expired()) { + return; + } + std::shared_ptr action(weakAction.lock()); if (qaction->isCheckable()) { action->trigger(enabled); } else { @@ -101,7 +107,8 @@ void ActionMapper::rebuildMenu(const QString& menu, QMenu* qmenu, QWidget* conte } }); QObject::connect(action.get(), &Action::enabled, qaction, &QAction::setEnabled); - QObject::connect(action.get(), &Action::activated, [qaction, action](bool active) { + QObject::connect(action.get(), &Action::activated, [qaction, weakAction = std::move(weakAction)](bool active) { + std::shared_ptr action(weakAction.lock()); if (qaction->isCheckable()) { qaction->setChecked(active); } else if (active) { @@ -134,8 +141,8 @@ std::shared_ptr ActionMapper::addAction(const Action& act, const QString return getAction(name); } -std::shared_ptr ActionMapper::addAction(const QString& visibleName, const QString& name, Action::Function action, const QString& menu, const QKeySequence& shortcut) { - return addAction(Action(action, name, visibleName), name, menu, shortcut); +std::shared_ptr ActionMapper::addAction(const QString& visibleName, const QString& name, Action::Function&& action, const QString& menu, const QKeySequence& shortcut) { + return addAction(Action(std::move(action), name, visibleName), name, menu, shortcut); } std::shared_ptr ActionMapper::addAction(const QString& visibleName, ConfigOption* option, const QVariant& variant, const QString& menu) { @@ -144,8 +151,8 @@ std::shared_ptr ActionMapper::addAction(const QString& visibleName, Conf }, option->name(), visibleName), QString("%1.%2").arg(option->name()).arg(variant.toString()), menu, {}); } -std::shared_ptr ActionMapper::addBooleanAction(const QString& visibleName, const QString& name, Action::BooleanFunction action, const QString& menu, const QKeySequence& shortcut) { - return addAction(Action(action, name, visibleName), name, menu, shortcut); +std::shared_ptr ActionMapper::addBooleanAction(const QString& visibleName, const QString& name, Action::BooleanFunction&& action, const QString& menu, const QKeySequence& shortcut) { + return addAction(Action(std::move(action), name, visibleName), name, menu, shortcut); } std::shared_ptr ActionMapper::addBooleanAction(const QString& visibleName, ConfigOption* option, const QString& menu) { @@ -154,15 +161,15 @@ std::shared_ptr ActionMapper::addBooleanAction(const QString& visibleNam }, option->name(), visibleName), option->name(), menu, {}); } -std::shared_ptr ActionMapper::addHeldAction(const QString& visibleName, const QString& name, Action::BooleanFunction action, const QString& menu, const QKeySequence& shortcut) { +std::shared_ptr ActionMapper::addHeldAction(const QString& visibleName, const QString& name, Action::BooleanFunction&& action, const QString& menu, const QKeySequence& shortcut) { m_hiddenActions.insert(name); m_heldActions.insert(name); - return addBooleanAction(visibleName, name, action, menu, shortcut); + return addBooleanAction(visibleName, name, std::move(action), menu, shortcut); } -std::shared_ptr ActionMapper::addHiddenAction(const QString& visibleName, const QString& name, Action::Function action, const QString& menu, const QKeySequence& shortcut) { +std::shared_ptr ActionMapper::addHiddenAction(const QString& visibleName, const QString& name, Action::Function&& action, const QString& menu, const QKeySequence& shortcut) { m_hiddenActions.insert(name); - return addAction(visibleName, name, action, menu, shortcut); + return addAction(visibleName, name, std::move(action), menu, shortcut); } QStringList ActionMapper::menuItems(const QString& menu) const { diff --git a/src/platform/qt/ActionMapper.h b/src/platform/qt/ActionMapper.h index 0b690e32b..f1cc3262f 100644 --- a/src/platform/qt/ActionMapper.h +++ b/src/platform/qt/ActionMapper.h @@ -34,16 +34,16 @@ public: void addSeparator(const QString& menu); - std::shared_ptr addAction(const QString& visibleName, const QString& name, Action::Function action, const QString& menu = {}, const QKeySequence& = {}); + std::shared_ptr addAction(const QString& visibleName, const QString& name, Action::Function&& action, const QString& menu = {}, const QKeySequence& = {}); template std::shared_ptr addAction(const QString& visibleName, const QString& name, T* obj, V (T::*method)(), const QString& menu = {}, const QKeySequence& = {}); std::shared_ptr addAction(const QString& visibleName, ConfigOption* option, const QVariant& variant, const QString& menu = {}); - std::shared_ptr addBooleanAction(const QString& visibleName, const QString& name, Action::BooleanFunction action, const QString& menu = {}, const QKeySequence& = {}); + std::shared_ptr addBooleanAction(const QString& visibleName, const QString& name, Action::BooleanFunction&& action, const QString& menu = {}, const QKeySequence& = {}); std::shared_ptr addBooleanAction(const QString& visibleName, ConfigOption* option, const QString& menu = {}); - std::shared_ptr addHeldAction(const QString& visibleName, const QString& name, Action::BooleanFunction action, const QString& menu = {}, const QKeySequence& = {}); + std::shared_ptr addHeldAction(const QString& visibleName, const QString& name, Action::BooleanFunction&& action, const QString& menu = {}, const QKeySequence& = {}); - std::shared_ptr addHiddenAction(const QString& visibleName, const QString& name, Action::Function action, const QString& menu = {}, const QKeySequence& = {}); + std::shared_ptr addHiddenAction(const QString& visibleName, const QString& name, Action::Function&& action, const QString& menu = {}, const QKeySequence& = {}); template std::shared_ptr addHiddenAction(const QString& visibleName, const QString& name, T* obj, V (T::*method)(), const QString& menu = {}, const QKeySequence& = {}); bool isHeld(const QString& name) const { return m_heldActions.contains(name); } diff --git a/src/platform/qt/AssetTile.cpp b/src/platform/qt/AssetTile.cpp index 78db4ccd9..2661c9fde 100644 --- a/src/platform/qt/AssetTile.cpp +++ b/src/platform/qt/AssetTile.cpp @@ -86,7 +86,7 @@ void AssetTile::selectIndex(int index) { return; } m_index = index; - const color_t* data; + const mColor* data; mTileCache* tileCache = m_tileCaches[index >= m_boundary]; unsigned bpp = 8 << tileCache->bpp; @@ -130,10 +130,10 @@ void AssetTile::setFlip(bool h, bool v) { } void AssetTile::selectColor(int index) { - const color_t* data; + const mColor* data; mTileCache* tileCache = m_tileCaches[m_index >= m_boundary]; data = mTileCacheGetTile(tileCache, m_index >= m_boundary ? m_index - m_boundary : m_index, m_paletteId); - color_t color = data[index]; + mColor color = data[index]; m_ui.color->setColor(0, color); m_ui.color->update(); diff --git a/src/platform/qt/AssetView.cpp b/src/platform/qt/AssetView.cpp index f79111734..17b745100 100644 --- a/src/platform/qt/AssetView.cpp +++ b/src/platform/qt/AssetView.cpp @@ -135,7 +135,7 @@ QImage AssetView::compositeMap(int map, QVector* mapStatus) { QImage AssetView::compositeObj(const ObjInfo& objInfo) { mTileCache* tileCache = mTileCacheSetGetPointer(&m_cacheSet->tiles, objInfo.paletteSet); unsigned maxTiles = mTileCacheSystemInfoGetMaxTiles(tileCache->sysConfig); - const color_t* rawPalette = mTileCacheGetPalette(tileCache, objInfo.paletteId); + const mColor* rawPalette = mTileCacheGetPalette(tileCache, objInfo.paletteId); unsigned colors = 1 << objInfo.bits; QVector palette; @@ -199,7 +199,7 @@ bool AssetView::lookupObjGBA(int id, struct ObjInfo* info) { paletteSet = 2; bits = 4; } - ObjInfo newInfo{ + *info = ObjInfo{ tile, width / 8, height / 8, @@ -218,16 +218,15 @@ bool AssetView::lookupObjGBA(int id, struct ObjInfo* info) { int matIndex = GBAObjAttributesBGetMatIndex(obj->b); const GBAOAMMatrix* mat = &gba->video.oam.mat[matIndex]; QTransform invXform(mat->a / 256., mat->c / 256., mat->b / 256., mat->d / 256., 0, 0); - newInfo.xform = invXform.inverted(); + info->xform = invXform.inverted(); } else { - newInfo.hflip = bool(GBAObjAttributesBIsHFlip(obj->b)); - newInfo.vflip = bool(GBAObjAttributesBIsVFlip(obj->b)); + info->hflip = bool(GBAObjAttributesBIsHFlip(obj->b)); + info->vflip = bool(GBAObjAttributesBIsVFlip(obj->b)); } GBARegisterDISPCNT dispcnt = gba->memory.io[0]; // FIXME: Register name can't be imported due to namespacing issues if (!GBARegisterDISPCNTIsObjCharacterMapping(dispcnt)) { - newInfo.stride = 0x20 >> (GBAObjAttributesAGet256Color(obj->a)); + info->stride = 0x20 >> (GBAObjAttributesAGet256Color(obj->a)); }; - *info = newInfo; return true; } #endif @@ -258,7 +257,7 @@ bool AssetView::lookupObjGB(int id, struct ObjInfo* info) { } palette += 8; - ObjInfo newInfo{ + *info = ObjInfo{ tile, 1, height / 8, @@ -273,7 +272,6 @@ bool AssetView::lookupObjGB(int id, struct ObjInfo* info) { bool(GBObjAttributesIsXFlip(obj->attr)), bool(GBObjAttributesIsYFlip(obj->attr)), }; - *info = newInfo; return true; } #endif diff --git a/src/platform/qt/AudioDevice.cpp b/src/platform/qt/AudioDevice.cpp index 74f863444..bf027cd43 100644 --- a/src/platform/qt/AudioDevice.cpp +++ b/src/platform/qt/AudioDevice.cpp @@ -7,11 +7,12 @@ #include "LogController.h" -#include #include #include #include +#include + using namespace QGBA; AudioDevice::AudioDevice(QObject* parent) @@ -19,6 +20,13 @@ AudioDevice::AudioDevice(QObject* parent) , m_context(nullptr) { setOpenMode(ReadOnly); + mAudioBufferInit(&m_buffer, 0x4000, 2); + mAudioResamplerInit(&m_resampler, mINTERPOLATOR_SINC); +} + +AudioDevice::~AudioDevice() { + mAudioResamplerDeinit(&m_resampler); + mAudioBufferDeinit(&m_buffer); } void AudioDevice::setFormat(const QAudioFormat& format) { @@ -26,15 +34,18 @@ void AudioDevice::setFormat(const QAudioFormat& format) { LOG(QT, INFO) << tr("Can't set format of context-less audio device"); return; } - double fauxClock = GBAAudioCalculateRatio(1, m_context->impl->sync.fpsTarget, 1); mCoreSyncLockAudio(&m_context->impl->sync); - blip_set_rates(m_context->core->getAudioChannel(m_context->core, 0), - m_context->core->frequency(m_context->core), format.sampleRate() * fauxClock); - blip_set_rates(m_context->core->getAudioChannel(m_context->core, 1), - m_context->core->frequency(m_context->core), format.sampleRate() * fauxClock); + mCore* core = m_context->core; + mAudioResamplerSetSource(&m_resampler, core->getAudioBuffer(core), core->audioSampleRate(core), true); + m_format = format; + adjustResampler(); mCoreSyncUnlockAudio(&m_context->impl->sync); } +void AudioDevice::setBufferSamples(int samples) { + m_samples = samples; +} + void AudioDevice::setInput(mCoreThread* input) { m_context = input; } @@ -45,15 +56,25 @@ qint64 AudioDevice::readData(char* data, qint64 maxSize) { return 0; } - maxSize /= sizeof(mStereoSample); + if (!maxSize) { + return 0; + } + mCoreSyncLockAudio(&m_context->impl->sync); - int available = std::min({ - blip_samples_avail(m_context->core->getAudioChannel(m_context->core, 0)), - maxSize, + mAudioResamplerProcess(&m_resampler); + if (mAudioBufferAvailable(&m_buffer) < 128) { + mCoreSyncConsumeAudio(&m_context->impl->sync); + // Audio is running slow...let's wait a tiny bit for more to come in + QThread::usleep(100); + mCoreSyncLockAudio(&m_context->impl->sync); + mAudioResamplerProcess(&m_resampler); + } + quint64 available = std::min({ + mAudioBufferAvailable(&m_buffer), + static_cast(maxSize / sizeof(mStereoSample)), std::numeric_limits::max() }); - blip_read_samples(m_context->core->getAudioChannel(m_context->core, 0), &reinterpret_cast(data)->left, available, true); - blip_read_samples(m_context->core->getAudioChannel(m_context->core, 1), &reinterpret_cast(data)->right, available, true); + mAudioBufferRead(&m_buffer, reinterpret_cast(data), available); mCoreSyncConsumeAudio(&m_context->impl->sync); return available * sizeof(mStereoSample); } @@ -62,3 +83,35 @@ qint64 AudioDevice::writeData(const char*, qint64) { LOG(QT, WARN) << tr("Writing data to read-only audio device"); return 0; } + +bool AudioDevice::atEnd() const { + return false; +} + +qint64 AudioDevice::bytesAvailable() const { + if (!m_context->core) { + return true; + } + int available = mAudioBufferAvailable(&m_buffer); + return available * sizeof(mStereoSample); +} + +qint64 AudioDevice::bytesAvailable() { + if (!m_context->core) { + return true; + } + mCoreSyncLockAudio(&m_context->impl->sync); + adjustResampler(); + mAudioResamplerProcess(&m_resampler); + int available = mAudioBufferAvailable(&m_buffer); + mCoreSyncUnlockAudio(&m_context->impl->sync); + return available * sizeof(mStereoSample); +} + +void AudioDevice::adjustResampler() { + mCore* core = m_context->core; + double fauxClock = mCoreCalculateFramerateRatio(m_context->core, m_context->impl->sync.fpsTarget); + mAudioResamplerSetDestination(&m_resampler, &m_buffer, m_format.sampleRate() * fauxClock); + m_context->impl->sync.audioHighWater = m_samples + m_resampler.highWaterMark + m_resampler.lowWaterMark; + m_context->impl->sync.audioHighWater *= core->audioSampleRate(core) / (m_format.sampleRate() * fauxClock); +} diff --git a/src/platform/qt/AudioDevice.h b/src/platform/qt/AudioDevice.h index 0794b3743..04247cf98 100644 --- a/src/platform/qt/AudioDevice.h +++ b/src/platform/qt/AudioDevice.h @@ -8,6 +8,9 @@ #include #include +#include +#include + struct mCoreThread; namespace QGBA { @@ -17,16 +20,28 @@ Q_OBJECT public: AudioDevice(QObject* parent = nullptr); + virtual ~AudioDevice(); void setInput(mCoreThread* input); void setFormat(const QAudioFormat& format); + void setBufferSamples(int samples); + bool atEnd() const override; + qint64 bytesAvailable() const override; + qint64 bytesAvailable(); + bool isSequential() const override { return true; } protected: virtual qint64 readData(char* data, qint64 maxSize) override; virtual qint64 writeData(const char* data, qint64 maxSize) override; private: + size_t m_samples = 512; + QAudioFormat m_format; mCoreThread* m_context; + mAudioBuffer m_buffer; + mAudioResampler m_resampler; + + void adjustResampler(); }; } diff --git a/src/platform/qt/AudioProcessor.cpp b/src/platform/qt/AudioProcessor.cpp index d0b2b1f24..f46e63529 100644 --- a/src/platform/qt/AudioProcessor.cpp +++ b/src/platform/qt/AudioProcessor.cpp @@ -60,11 +60,11 @@ void AudioProcessor::configure(ConfigController* config) { } void AudioProcessor::setInput(std::shared_ptr input) { - m_context = input; - connect(input.get(), &CoreController::stopping, this, &AudioProcessor::stop); - connect(input.get(), &CoreController::fastForwardChanged, this, &AudioProcessor::inputParametersChanged); - connect(input.get(), &CoreController::paused, this, &AudioProcessor::pause); - connect(input.get(), &CoreController::unpaused, this, &AudioProcessor::start); + m_context = std::move(input); + connect(m_context.get(), &CoreController::stopping, this, &AudioProcessor::stop); + connect(m_context.get(), &CoreController::fastForwardChanged, this, &AudioProcessor::inputParametersChanged); + connect(m_context.get(), &CoreController::paused, this, &AudioProcessor::pause); + connect(m_context.get(), &CoreController::unpaused, this, &AudioProcessor::start); } void AudioProcessor::stop() { diff --git a/src/platform/qt/AudioProcessorQt.cpp b/src/platform/qt/AudioProcessorQt.cpp index 3b12d2e07..87ad5b5ac 100644 --- a/src/platform/qt/AudioProcessorQt.cpp +++ b/src/platform/qt/AudioProcessorQt.cpp @@ -9,6 +9,9 @@ #include "LogController.h" #include +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +#include +#endif #include #include @@ -18,10 +21,14 @@ using namespace QGBA; AudioProcessorQt::AudioProcessorQt(QObject* parent) : AudioProcessor(parent) { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + m_recheckTimer.setInterval(1); + connect(&m_recheckTimer, &QTimer::timeout, this, &AudioProcessorQt::recheckUnderflow); +#endif } void AudioProcessorQt::setInput(std::shared_ptr controller) { - AudioProcessor::setInput(controller); + AudioProcessor::setInput(std::move(controller)); if (m_device) { m_device->setInput(input()); if (m_audioOutput) { @@ -31,10 +38,16 @@ void AudioProcessorQt::setInput(std::shared_ptr controller) { } void AudioProcessorQt::stop() { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + m_recheckTimer.stop(); +#endif + if (m_audioOutput) { + m_audioOutput->stop(); + m_audioOutput.reset(); + } if (m_device) { m_device.reset(); } - pause(); AudioProcessor::stop(); } @@ -52,34 +65,61 @@ bool AudioProcessorQt::start() { QAudioFormat format; format.setSampleRate(m_sampleRate); format.setChannelCount(2); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) format.setSampleSize(16); format.setCodec("audio/pcm"); format.setByteOrder(QAudioFormat::Endian(QSysInfo::ByteOrder)); format.setSampleType(QAudioFormat::SignedInt); - m_audioOutput = new QAudioOutput(format, this); + m_audioOutput = std::make_unique(format); m_audioOutput->setCategory("game"); +#else + format.setSampleFormat(QAudioFormat::Int16); + + QAudioDevice device(QMediaDevices::defaultAudioOutput()); + m_audioOutput = std::make_unique(device, format); + LOG(QT, INFO) << "Audio outputting to " << device.description(); + connect(m_audioOutput.get(), &QAudioSink::stateChanged, this, [this](QAudio::State state) { + if (state != QAudio::IdleState) { + return; + } + recheckUnderflow(); + m_recheckTimer.start(); + }); +#endif } - m_device->setInput(input()); - m_device->setFormat(m_audioOutput->format()); - - m_audioOutput->start(m_device.get()); - return m_audioOutput->state() == QAudio::ActiveState; + if (m_audioOutput->state() == QAudio::SuspendedState) { + m_audioOutput->resume(); + } else { + m_device->setBufferSamples(m_samples); + m_device->setInput(input()); + m_device->setFormat(m_audioOutput->format()); + m_audioOutput->start(m_device.get()); + } + return m_audioOutput->state() == QAudio::ActiveState && m_audioOutput->error() == QAudio::NoError; } void AudioProcessorQt::pause() { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + m_recheckTimer.stop(); +#endif if (m_audioOutput) { - m_audioOutput->stop(); + m_audioOutput->suspend(); } } -void AudioProcessorQt::setBufferSamples(int) { +void AudioProcessorQt::setBufferSamples(int samples) { + m_samples = samples; + if (m_device) { + m_device->setBufferSamples(samples); + } } void AudioProcessorQt::inputParametersChanged() { if (m_device) { m_device->setFormat(m_audioOutput->format()); + m_device->setBufferSamples(m_samples); } } @@ -98,3 +138,16 @@ unsigned AudioProcessorQt::sampleRate() const { } return m_audioOutput->format().sampleRate(); } + +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +void AudioProcessorQt::recheckUnderflow() { + if (!m_device) { + m_recheckTimer.stop(); + return; + } + if (m_device->bytesAvailable()) { + start(); + m_recheckTimer.stop(); + } +} +#endif diff --git a/src/platform/qt/AudioProcessorQt.h b/src/platform/qt/AudioProcessorQt.h index 0e56907e1..bc01a8c07 100644 --- a/src/platform/qt/AudioProcessorQt.h +++ b/src/platform/qt/AudioProcessorQt.h @@ -7,6 +7,13 @@ #include "AudioProcessor.h" +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) +#include +#else +#include +#include +#endif + class QAudioOutput; namespace QGBA { @@ -32,9 +39,19 @@ public slots: virtual void requestSampleRate(unsigned) override; +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +private slots: + void recheckUnderflow(); + private: - QAudioOutput* m_audioOutput = nullptr; + QTimer m_recheckTimer; + std::unique_ptr m_audioOutput; +#else +private: + std::unique_ptr m_audioOutput; +#endif std::unique_ptr m_device; + size_t m_samples = 1024; unsigned m_sampleRate = 44100; }; diff --git a/src/platform/qt/AudioProcessorSDL.cpp b/src/platform/qt/AudioProcessorSDL.cpp index bf0a5dbdd..bfa9782d1 100644 --- a/src/platform/qt/AudioProcessorSDL.cpp +++ b/src/platform/qt/AudioProcessorSDL.cpp @@ -17,7 +17,7 @@ AudioProcessorSDL::AudioProcessorSDL(QObject* parent) } void AudioProcessorSDL::setInput(std::shared_ptr controller) { - AudioProcessor::setInput(controller); + AudioProcessor::setInput(std::move(controller)); if (m_audio.core && input()->core != m_audio.core) { mSDLDeinitAudio(&m_audio); mSDLInitAudio(&m_audio, input()); diff --git a/src/platform/qt/AudioProcessorSDL.h b/src/platform/qt/AudioProcessorSDL.h index c2d5d0ee1..2f86c0e16 100644 --- a/src/platform/qt/AudioProcessorSDL.h +++ b/src/platform/qt/AudioProcessorSDL.h @@ -9,6 +9,7 @@ #ifdef BUILD_SDL +#define SDL_MAIN_HANDLED #include "platform/sdl/sdl-audio.h" namespace QGBA { diff --git a/src/platform/qt/BattleChipModel.cpp b/src/platform/qt/BattleChipModel.cpp index 2acbd9b7f..941b3f547 100644 --- a/src/platform/qt/BattleChipModel.cpp +++ b/src/platform/qt/BattleChipModel.cpp @@ -118,8 +118,7 @@ void BattleChipModel::setFlavor(int flavor) { if (line.trimmed().isEmpty()) { continue; } - QString name = QString::fromUtf8(line).trimmed(); - m_chipIdToName[id] = name; + m_chipIdToName[id] = QString::fromUtf8(line).trimmed(); } } diff --git a/src/platform/qt/BattleChipView.cpp b/src/platform/qt/BattleChipView.cpp index 93f239b7e..46b24e927 100644 --- a/src/platform/qt/BattleChipView.cpp +++ b/src/platform/qt/BattleChipView.cpp @@ -24,18 +24,17 @@ using namespace QGBA; BattleChipView::BattleChipView(std::shared_ptr controller, Window* window, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) - , m_controller(controller) + , m_controller(std::move(controller)) , m_window(window) { m_ui.setupUi(this); m_ui.chipList->setModel(&m_model); - char title[9]; CoreController::Interrupter interrupter(m_controller); mCore* core = m_controller->thread()->core; - title[8] = '\0'; - core->getGameCode(core, title); - QString qtitle(title); + mGameInfo info; + core->getGameInfo(core, &info); + QString qtitle(info.title); #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) int size = QFontMetrics(QFont()).height() / ((int) ceil(devicePixelRatioF()) * 12); @@ -101,11 +100,11 @@ BattleChipView::BattleChipView(std::shared_ptr controller, Windo m_controller->attachBattleChipGate(); setFlavor(4); - if (qtitle.startsWith("AGB-B4B") || qtitle.startsWith("AGB-B4W") || qtitle.startsWith("AGB-BR4") || qtitle.startsWith("AGB-BZ3")) { + if (qtitle.startsWith("B4B") || qtitle.startsWith("B4W") || qtitle.startsWith("BR4") || qtitle.startsWith("BZ3")) { m_ui.gateBattleChip->setChecked(true); - } else if (qtitle.startsWith("AGB-BRB") || qtitle.startsWith("AGB-BRK")) { + } else if (qtitle.startsWith("BRB") || qtitle.startsWith("BRK")) { m_ui.gateProgress->setChecked(true); - } else if (qtitle.startsWith("AGB-BR5") || qtitle.startsWith("AGB-BR6")) { + } else if (qtitle.startsWith("BR5") || qtitle.startsWith("BR6")) { m_ui.gateBeastLink->setChecked(true); } @@ -217,7 +216,7 @@ void BattleChipView::loadDeck() { error->show(); return; } - + QList newDeck; QStringList deck = ini.value("deck").toString().split(','); for (const auto& item : deck) { diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 5b8ba3fa8..51aa22401 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -12,8 +12,8 @@ if(BUILD_SDL) link_directories(${SDL2_LIBDIR}) endif() list(APPEND PLATFORM_LIBRARY ${SDL_LIBRARY}) - list(APPEND PLATFORM_SRC ${PLATFORM_SRC} ${CMAKE_SOURCE_DIR}/src/platform/sdl/sdl-events.c ${CMAKE_SOURCE_DIR}/src/platform/sdl/sdl-audio.c) - include_directories(${SDL_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/src/platform/sdl) + list(APPEND PLATFORM_SRC ${PLATFORM_SRC} ${PROJECT_SOURCE_DIR}/src/platform/sdl/sdl-events.c ${PROJECT_SOURCE_DIR}/src/platform/sdl/sdl-audio.c) + include_directories(${SDL_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/src/platform/sdl) endif() if(POLICY CMP0071) @@ -25,12 +25,24 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(QT_LIBRARIES) -set(QT_V 5) -find_package(Qt${QT_V} COMPONENTS Core Widgets Network OPTIONAL_COMPONENTS Multimedia) -if(QT_V GREATER_EQUAL 6) - find_package(Qt${QT_V} COMPONENTS OpenGL OpenGLWidgets) +option(FORCE_QT_VERSION "Force the used Qt version" OFF) + +if(FORCE_QT_VERSION EQUAL 5 OR FORCE_QT_VERSION EQUAL 6) + set(QT_VERSIONS ${FORCE_QT_VERSION}) +else() + set(QT_VERSIONS 6 5) endif() -set(QT Qt${QT_V}) +foreach(V ${QT_VERSIONS}) + set(QT Qt${V}) + set(QT_V ${V}) + find_package(${QT} COMPONENTS Core Widgets Network OPTIONAL_COMPONENTS Multimedia) + if(QT_V GREATER_EQUAL 6) + find_package(${QT} COMPONENTS OpenGL OpenGLWidgets) + endif() + if(${${QT}Widgets_FOUND}) + break() + endif() +endforeach() if(NOT BUILD_GL AND NOT BUILD_GLES2 AND NOT BUILD_GLES3) message(WARNING "OpenGL is recommended to build the Qt port") @@ -48,20 +60,22 @@ if(APPLE) endif() if(Qt6Widgets_VERSION) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.14") + set(MIN_VER 10.14) elseif(Qt5Widgets_VERSION MATCHES "^5.15") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.13") + set(MIN_VER 10.13) elseif(Qt5Widgets_VERSION MATCHES "^5.1[234]") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.12") + set(MIN_VER 10.12) elseif(Qt5Widgets_VERSION MATCHES "^5.11") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.11") + set(MIN_VER 10.11) elseif(Qt5Widgets_VERSION MATCHES "^5.(9|10)") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.10") + set(MIN_VER 10.10) elseif(Qt5Widgets_VERSION MATCHES "^5.8") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.9") + set(MIN_VER 10.9) else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.8") + set(MIN_VER 10.8) endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${MIN_VER}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${MIN_VER}") if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() @@ -223,11 +237,8 @@ endif() if(${QT}Multimedia_FOUND) list(APPEND AUDIO_SRC AudioProcessorQt.cpp - AudioDevice.cpp) - if(QT_V LESS 6) - list(APPEND SOURCE_FILES - VideoDumper.cpp) - endif() + AudioDevice.cpp + VideoDumper.cpp) if (WIN32 AND QT_STATIC) list(APPEND QT_LIBRARIES ${QT}::QWindowsAudioPlugin ${QT}::DSServicePlugin ${QT}::QWindowsVistaStylePlugin ${QT}::QJpegPlugin strmiids mfuuid mfplat mf ksguid dxva2 evr d3d9) @@ -243,7 +254,7 @@ if(NOT AUDIO_SRC) return() endif() -if(USE_DEBUGGERS) +if(ENABLE_DEBUGGERS) list(APPEND SOURCE_FILES DebuggerController.cpp DebuggerConsole.cpp @@ -251,7 +262,7 @@ if(USE_DEBUGGERS) MemoryAccessLogView.cpp) endif() -if(USE_GDB_STUB) +if(ENABLE_GDB_STUB) list(APPEND SOURCE_FILES GDBController.cpp GDBWindow.cpp) endif() @@ -307,7 +318,7 @@ if(APPLE) set(MACOSX_BUNDLE_BUNDLE_VERSION ${LIB_VERSION_STRING}) set(MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}) set(MACOSX_BUNDLE_GUI_IDENTIFIER com.endrift.${BINARY_NAME}-qt) - set_source_files_properties(${CMAKE_SOURCE_DIR}/res/mgba.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + set_source_files_properties(${PROJECT_SOURCE_DIR}/res/mgba.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) if(DISTBUILD) set(APPDIR ".") else() @@ -315,13 +326,13 @@ if(APPLE) endif() endif() if(WIN32) - configure_file(${CMAKE_SOURCE_DIR}/res/mgba.rc.in ${CMAKE_BINARY_DIR}/res/mgba.rc) + configure_file(${PROJECT_SOURCE_DIR}/res/mgba.rc.in ${CMAKE_BINARY_DIR}/res/mgba.rc) list(APPEND RESOURCES ${CMAKE_BINARY_DIR}/res/mgba.rc) - set_source_files_properties(${CMAKE_BINARY_DIR}/res/mgba.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_SOURCE_DIR}/res/mgba.ico) + set_source_files_properties(${CMAKE_BINARY_DIR}/res/mgba.rc PROPERTIES OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/res/mgba.ico) endif() if(NOT DEFINED DATADIR) if(APPLE) - set(DATADIR ${APPDIR}/${PROJECT_NAME}.app/Contents/Resources) + set(DATADIR ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.app/Contents/Resources) elseif(WIN32 AND NOT WIN32_UNIX_PATHS) set(DATADIR ".") else() @@ -330,10 +341,9 @@ if(NOT DEFINED DATADIR) endif() if(BUILD_GL OR BUILD_GLES2 OR BUILD_EPOXY) if(NOT USE_LIBZIP AND NOT USE_MINIZIP) - install(DIRECTORY ${CMAKE_SOURCE_DIR}/res/shaders DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) + install(DIRECTORY ${PROJECT_SOURCE_DIR}/res/shaders DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) else() - file(GLOB SHADERS ${CMAKE_SOURCE_DIR}/res/shaders/*.shader) - message(STATUS ${SHADERS}) + file(GLOB SHADERS ${PROJECT_SOURCE_DIR}/res/shaders/*.shader) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/shaders) foreach(SHADER_DIR ${SHADERS}) get_filename_component(SHADER ${SHADER_DIR} NAME) @@ -344,9 +354,9 @@ if(BUILD_GL OR BUILD_GLES2 OR BUILD_EPOXY) endif() endif() if(ENABLE_SCRIPTING AND USE_LUA) - install(DIRECTORY ${CMAKE_SOURCE_DIR}/res/scripts DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) + install(DIRECTORY ${PROJECT_SOURCE_DIR}/res/scripts DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) endif() -install(FILES ${CMAKE_SOURCE_DIR}/res/nointro.dat DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) +install(FILES ${PROJECT_SOURCE_DIR}/res/nointro.dat DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) if(NOT WIN32 AND NOT APPLE) if(DATADIR MATCHES "^\\.[.\\]") list(APPEND QT_DEFINES DATADIR="${DATADIR}") @@ -412,11 +422,12 @@ else() qt5_wrap_ui(UI_SRC ${UI_FILES}) endif() -add_executable(${BINARY_NAME}-qt WIN32 MACOSX_BUNDLE main.cpp ${CMAKE_SOURCE_DIR}/res/mgba.icns ${SOURCE_FILES} ${PLATFORM_SRC} ${UI_SRC} ${AUDIO_SRC} ${RESOURCES}) -set_target_properties(${BINARY_NAME}-qt PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/res/info.plist.in COMPILE_DEFINITIONS "${FEATURE_DEFINES};${FUNCTION_DEFINES};${OS_DEFINES};${QT_DEFINES}" COMPILE_OPTIONS "${FEATURE_FLAGS}") +add_executable(${BINARY_NAME}-qt WIN32 MACOSX_BUNDLE main.cpp ${PROJECT_SOURCE_DIR}/res/mgba.icns ${SOURCE_FILES} ${PLATFORM_SRC} ${UI_SRC} ${AUDIO_SRC} ${RESOURCES}) +set_target_properties(${BINARY_NAME}-qt PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/res/info.plist.in COMPILE_DEFINITIONS "${FEATURE_DEFINES};${FUNCTION_DEFINES};${OS_DEFINES};${QT_DEFINES}" COMPILE_OPTIONS "${FEATURE_FLAGS}") if(WIN32) set_target_properties(${BINARY_NAME}-qt PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") + target_link_libraries(${BINARY_NAME}-qt dwmapi) if(NOT MSVC) target_link_libraries(${BINARY_NAME}-qt -municode) endif() @@ -435,7 +446,7 @@ if(QT_STATIC) if(CMAKE_CROSSCOMPILING) set(QWINDOWS_DEPS ${QT}EventDispatcherSupport ${QT}FontDatabaseSupport ${QT}ThemeSupport ${QT}WindowsUIAutomationSupport) endif() - list(APPEND QT_LIBRARIES ${QT}::QWindowsIntegrationPlugin ${QWINDOWS_DEPS} amstrmid dwmapi uxtheme imm32 -static-libgcc -static-libstdc++) + list(APPEND QT_LIBRARIES ${QT}::QWindowsIntegrationPlugin ${QWINDOWS_DEPS} amstrmid uxtheme imm32 -static-libgcc -static-libstdc++) set_target_properties(${QT}::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE};version;winmm;ssl;crypto;ws2_32;iphlpapi;crypt32;userenv;netapi32;wtsapi32") set_target_properties(${QT}::Gui PROPERTIES INTERFACE_LINK_LIBRARIES ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) elseif(APPLE) @@ -455,14 +466,11 @@ endif() target_link_libraries(${BINARY_NAME}-qt ${PLATFORM_LIBRARY} ${BINARY_NAME} ${QT_LIBRARIES}) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}" PARENT_SCOPE) -install(TARGETS ${BINARY_NAME}-qt - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-qt - BUNDLE DESTINATION ${APPDIR} COMPONENT ${BINARY_NAME}-qt) if(UNIX AND NOT APPLE) - install(FILES ${CMAKE_SOURCE_DIR}/res/mgba-qt.desktop DESTINATION share/applications RENAME io.mgba.${PROJECT_NAME}.desktop COMPONENT ${BINARY_NAME}-qt) + install(FILES ${PROJECT_SOURCE_DIR}/res/mgba-qt.desktop DESTINATION share/applications RENAME io.mgba.${PROJECT_NAME}.desktop COMPONENT ${BINARY_NAME}-qt) endif() if(UNIX AND NOT (APPLE AND DISTBUILD)) - install(FILES ${CMAKE_SOURCE_DIR}/doc/mgba-qt.6 DESTINATION ${MANDIR}/man6 COMPONENT ${BINARY_NAME}-qt) + install(FILES ${PROJECT_SOURCE_DIR}/doc/mgba-qt.6 DESTINATION ${MANDIR}/man6 COMPONENT ${BINARY_NAME}-qt) endif() if(APPLE OR WIN32) set_target_properties(${BINARY_NAME}-qt PROPERTIES OUTPUT_NAME ${PROJECT_NAME}) @@ -483,6 +491,10 @@ if(APPLE) file(GLOB_RECURSE PLUGINS \"${BUNDLE_PATH}/Contents/PlugIns/*${CMAKE_SHARED_LIBRARY_SUFFIX}\") fixup_bundle(\"${BUNDLE_PATH}\" \"${PLUGINS}\" \"\") " COMPONENT ${BINARY_NAME}-qt) + if(CODESIGN_IDENTITY) + install(CODE "execute_process(COMMAND codesign -s \"${CODESIGN_IDENTITY}\" -vf -o runtime --timestamp --entitlements \"${PROJECT_SOURCE_DIR}/res/entitlements.plist\" \"${BUNDLE_PATH}\")" + COMPONENT ${BINARY_NAME}-qt) + endif() else() set(DEPLOY_OPTIONS -p platforms/libqcocoa.dylib,audio/libqtaudio_coreaudio.dylib,mediaservice/libqavfcamera.dylib) if(NOT CMAKE_INSTALL_NAME_TOOL EQUAL "install_name_tool") @@ -494,7 +506,10 @@ if(APPLE) if(DEFINED CROSS_ROOT) set(DEPLOY_OPTIONS ${DEPLOY_OPTIONS} -R "${CROSS_ROOT}") endif() - install(CODE "execute_process(COMMAND \"${CMAKE_SOURCE_DIR}/tools/deploy-mac.py\" -v ${DEPLOY_OPTIONS} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${APPDIR}/${PROJECT_NAME}.app\")") + if($ENV{CODESIGN_IDENTITY}) + set(DEPLOY_OPTIONS ${DEPLOY_OPTIONS} -s "$ENV{CODESIGN_IDENTITY}" -E "${PROJECT_SOURCE_DIR}/res/entitlements.xml") + endif() + install(CODE "execute_process(COMMAND \"${PROJECT_SOURCE_DIR}/tools/deploy-mac.py\" -v ${DEPLOY_OPTIONS} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${APPDIR}/${PROJECT_NAME}.app\")") endif() elseif(WIN32) if(CMAKE_MAJOR_VERSION EQUAL 3 AND CMAKE_MINOR_VERSION EQUAL 8) @@ -503,7 +518,7 @@ elseif(WIN32) endif() if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") find_program(BASH bash) - install(CODE "execute_process(COMMAND \"${BASH}\" \"${CMAKE_SOURCE_DIR}/tools/deploy-win.sh\" \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.exe\" \"\${CMAKE_INSTALL_PREFIX}\" \"\$ENV{PWD}\" WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}\")" COMPONENT ${BINARY_NAME}-qt) + install(CODE "execute_process(COMMAND \"${BASH}\" \"${PROJECT_SOURCE_DIR}/tools/deploy-win.sh\" \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.exe\" \"\${CMAKE_INSTALL_PREFIX}\" \"\$ENV{PWD}\" WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}\")" COMPONENT ${BINARY_NAME}-qt) endif() if(DISTBUILD) file(WRITE "${CMAKE_BINARY_DIR}/portable.ini" "") @@ -521,3 +536,7 @@ if(DISTBUILD AND NOT APPLE) add_custom_command(TARGET ${BINARY_NAME}-qt POST_BUILD COMMAND "${STRIP}" "$") endif() endif() + +install(TARGETS ${BINARY_NAME}-qt + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-qt + BUNDLE DESTINATION ${APPDIR} COMPONENT ${BINARY_NAME}-qt) diff --git a/src/platform/qt/ColorPicker.cpp b/src/platform/qt/ColorPicker.cpp index 22d995c0f..8cebab520 100644 --- a/src/platform/qt/ColorPicker.cpp +++ b/src/platform/qt/ColorPicker.cpp @@ -44,13 +44,11 @@ bool ColorPicker::eventFilter(QObject* obj, QEvent* event) { return false; } - QWidget* swatch = static_cast(obj); - QColorDialog* colorPicker = new QColorDialog; colorPicker->setAttribute(Qt::WA_DeleteOnClose); colorPicker->setCurrentColor(m_defaultColor); colorPicker->open(); - connect(colorPicker, &QColorDialog::colorSelected, [this, swatch](const QColor& color) { + connect(colorPicker, &QColorDialog::colorSelected, [this](const QColor& color) { setColor(color); emit colorChanged(color); }); diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index 7a26ea844..819b2479d 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -13,12 +13,15 @@ #include #ifdef M_CORE_GB -#include +#include #endif static const mOption s_frontendOptions[] = { { "ecard", true, '\0' }, { "mb", true, '\0' }, +#ifdef ENABLE_SCRIPTING + { "script", true, '\0' }, +#endif { 0 } }; @@ -31,7 +34,7 @@ ConfigOption::ConfigOption(const QString& name, QObject* parent) } void ConfigOption::connect(std::function slot, QObject* parent) { - m_slots[parent] = slot; + m_slots[parent] = std::move(slot); QObject::connect(parent, &QObject::destroyed, this, [this, parent]() { m_slots.remove(parent); }); @@ -49,7 +52,12 @@ std::shared_ptr ConfigOption::addValue(const QString& text, const QVaria action = std::make_shared(function, name, text, this); } action->setExclusive(); - QObject::connect(action.get(), &QObject::destroyed, this, [this, action, value]() { + std::weak_ptr weakAction(action); + QObject::connect(action.get(), &QObject::destroyed, this, [this, weakAction = std::move(weakAction), value]() { + if (weakAction.expired()) { + return; + } + std::shared_ptr action(weakAction.lock()); m_actions.removeAll(std::make_pair(action, value)); }); m_actions.append(std::make_pair(action, value)); @@ -71,7 +79,12 @@ std::shared_ptr ConfigOption::addBoolean(const QString& text, ActionMapp action = std::make_shared(function, m_name, text, this); } - QObject::connect(action.get(), &QObject::destroyed, this, [this, action]() { + std::weak_ptr weakAction(action); + QObject::connect(action.get(), &QObject::destroyed, this, [this, weakAction]() { + if (weakAction.expired()) { + return; + } + std::shared_ptr action(weakAction.lock()); m_actions.removeAll(std::make_pair(action, QVariant(1))); }); m_actions.append(std::make_pair(action, QVariant(1))); @@ -141,9 +154,15 @@ ConfigController::ConfigController(QObject* parent) mSubParserGraphicsInit(&m_subparsers[0], &m_graphicsOpts); m_subparsers[1].usage = "Frontend options:\n" - " --ecard FILE Scan an e-Reader card in the first loaded game\n" - " Can be passed multiple times for multiple cards\n" - " --mb FILE Boot a multiboot image with FILE inserted into the ROM slot"; + " --ecard FILE Scan an e-Reader card in the first loaded game\n" + " Can be passed multiple times for multiple cards\n" + " --mb FILE Boot a multiboot image with FILE inserted into the ROM slot" +#ifdef ENABLE_SCRIPTING + "\n --script FILE Script file to load on start\n" + " Can be passed multiple times\n" +#endif + ; + m_subparsers[1].parse = nullptr; m_subparsers[1].parseLong = [](struct mSubParser* parser, const char* option, const char* arg) { ConfigController* self = static_cast(parser->opts); @@ -161,6 +180,17 @@ ConfigController::ConfigController(QObject* parent) self->m_argvOptions[optionName] = QString::fromUtf8(arg); return true; } +#ifdef ENABLE_SCRIPTING + if (optionName == QLatin1String("script")) { + QStringList scripts; + if (self->m_argvOptions.contains(optionName)) { + scripts = self->m_argvOptions[optionName].toStringList(); + } + scripts.append(QString::fromUtf8(arg)); + self->m_argvOptions[optionName] = scripts; + return true; + } +#endif return false; }; m_subparsers[1].apply = nullptr; @@ -289,7 +319,11 @@ void ConfigController::setOption(const char* key, const char* value) { } void ConfigController::setOption(const char* key, const QVariant& value) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (value.type() == QVariant::Bool) { +#else + if (value.typeId() == QMetaType::Type::Bool) { +#endif setOption(key, value.toBool()); return; } @@ -356,7 +390,7 @@ void ConfigController::write() { } void ConfigController::makePortable() { - mCoreConfigMakePortable(&m_config); + mCoreConfigMakePortable(&m_config, nullptr); QString fileName(configDir()); fileName.append(QDir::separator()); diff --git a/src/platform/qt/ConfigController.h b/src/platform/qt/ConfigController.h index 4c71c3943..4325a46ba 100644 --- a/src/platform/qt/ConfigController.h +++ b/src/platform/qt/ConfigController.h @@ -130,7 +130,7 @@ private: mGraphicsOpts m_graphicsOpts{}; std::array m_subparsers; bool m_parsed = false; - + QHash m_argvOptions; QHash m_optionSet; std::unique_ptr m_settings; diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 6b21f2c8e..2496f8039 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -49,7 +49,7 @@ CoreController::CoreController(mCore* core, QObject* parent) GBASIODolphinCreate(&m_dolphin); #endif -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS mDebuggerInit(&m_debugger); #endif @@ -97,7 +97,7 @@ CoreController::CoreController(mCore* core, QObject* parent) controller->m_frameCounter = -1; if (!controller->m_hwaccel) { - context->core->setVideoBuffer(context->core, reinterpret_cast(controller->m_activeBuffer.data()), controller->screenDimensions().width()); + context->core->setVideoBuffer(context->core, reinterpret_cast(controller->m_activeBuffer.data()), controller->screenDimensions().width()); } QString message(tr("Reset r%1-%2 %3").arg(gitRevision).arg(QLatin1String(gitCommitShort)).arg(controller->m_crc32, 8, 16, QLatin1Char('0'))); @@ -218,7 +218,7 @@ CoreController::~CoreController() { mCoreThreadJoin(&m_threadContext); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS mDebuggerDeinit(&m_debugger); #endif @@ -236,12 +236,12 @@ void CoreController::setPath(const QString& path, const QString& base) { m_baseDirectory = base; } -const color_t* CoreController::drawContext() { +const mColor* CoreController::drawContext() { if (m_hwaccel) { return nullptr; } QMutexLocker locker(&m_bufferMutex); - return reinterpret_cast(m_completeBuffer.constData()); + return reinterpret_cast(m_completeBuffer.constData()); } QImage CoreController::getPixels() { @@ -307,14 +307,14 @@ void CoreController::loadConfig(ConfigController* config) { m_preload = config->getOption("preload").toInt(); QSize sizeBefore = screenDimensions(); - m_activeBuffer.resize(256 * 224 * sizeof(color_t)); - m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), sizeBefore.width()); + m_activeBuffer.resize(256 * 224 * sizeof(mColor)); + m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), sizeBefore.width()); mCoreLoadForeignConfig(m_threadContext.core, config->config()); QSize sizeAfter = screenDimensions(); - m_activeBuffer.resize(sizeAfter.width() * sizeAfter.height() * sizeof(color_t)); - m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), sizeAfter.width()); + m_activeBuffer.resize(sizeAfter.width() * sizeAfter.height() * sizeof(mColor)); + m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), sizeAfter.width()); if (hasStarted()) { updateFastForward(); @@ -331,7 +331,7 @@ void CoreController::loadConfig(ConfigController* config) { #endif } -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS void CoreController::attachDebugger(bool interrupt) { Interrupter interrupter(this); if (!m_threadContext.core->debugger) { @@ -423,8 +423,8 @@ bool CoreController::attachDolphin(const Address& address) { return false; } if (GBASIODolphinConnect(&m_dolphin, &address, 0, 0)) { - GBA* gba = static_cast(m_threadContext.core->board); - GBASIOSetDriver(&gba->sio, &m_dolphin.d, SIO_JOYBUS); + clearMultiplayerController(); + m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_GBA_LINK_PORT, &m_dolphin.d); return true; } return false; @@ -432,8 +432,8 @@ bool CoreController::attachDolphin(const Address& address) { void CoreController::detachDolphin() { if (platform() == mPLATFORM_GBA) { - GBA* gba = static_cast(m_threadContext.core->board); - GBASIOSetDriver(&gba->sio, nullptr, SIO_JOYBUS); + // TODO: Reattach to multiplayer controller + m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_GBA_LINK_PORT, NULL); } GBASIODolphinDestroy(&m_dolphin); } @@ -461,11 +461,11 @@ void CoreController::setLogger(LogController* logger) { void CoreController::start() { QSize size(screenDimensions()); - m_activeBuffer.resize(size.width() * size.height() * sizeof(color_t)); + m_activeBuffer.resize(size.width() * size.height() * sizeof(mColor)); m_activeBuffer.fill(0xFF); m_completeBuffer = m_activeBuffer; - m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), size.width()); + m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), size.width()); if (!m_patched) { mCoreAutoloadPatch(m_threadContext.core); @@ -478,7 +478,7 @@ void CoreController::start() { void CoreController::stop() { setSync(false); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS detachDebugger(); #endif setPaused(false); @@ -556,11 +556,7 @@ void CoreController::rewind(int states) { if (!states) { states = INT_MAX; } - for (int i = 0; i < states; ++i) { - if (!mCoreRewindRestore(&m_threadContext.impl->rewind, m_threadContext.core)) { - break; - } - } + mCoreRewindRestore(&m_threadContext.impl->rewind, m_threadContext.core, states); interrupter.resume(); emit frameAvailable(); emit rewound(); @@ -740,7 +736,7 @@ void CoreController::saveState(const QString& path, int flags) { vf->read(vf, controller->m_backupSaveState.data(), controller->m_backupSaveState.size()); vf->close(vf); } - vf = VFileDevice::open(controller->m_statePath, O_WRONLY | O_CREAT | O_TRUNC); + vf = VFileDevice::open(controller->m_statePath, O_RDWR | O_CREAT | O_TRUNC); if (!vf) { return; } @@ -980,7 +976,7 @@ void CoreController::scanCard(const QString& path) { } } scanCards(lines); - m_eReaderData = eReaderData; + m_eReaderData = std::move(eReaderData); } else if (image.size() == QSize(989, 44) || image.size() == QSize(639, 44)) { const uchar* bits = image.constBits(); size_t size; @@ -1055,7 +1051,7 @@ void CoreController::attachPrinter() { colors.append(qRgb(0xA8, 0xA8, 0xA8)); colors.append(qRgb(0x50, 0x50, 0x50)); colors.append(qRgb(0x00, 0x00, 0x00)); - image.setColorTable(colors); + image.setColorTable(std::move(colors)); for (int y = 0; y < height; ++y) { for (int x = 0; x < GB_VIDEO_HORIZONTAL_PIXELS; x += 4) { uint8_t byte = data[(x + y * GB_VIDEO_HORIZONTAL_PIXELS) / 4]; @@ -1098,7 +1094,7 @@ void CoreController::attachBattleChipGate() { Interrupter interrupter(this); clearMultiplayerController(); GBASIOBattlechipGateCreate(&m_battlechip); - m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_GBA_BATTLECHIP_GATE, &m_battlechip); + m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_GBA_LINK_PORT, &m_battlechip); } void CoreController::detachBattleChipGate() { @@ -1106,7 +1102,7 @@ void CoreController::detachBattleChipGate() { return; } Interrupter interrupter(this); - m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_GBA_BATTLECHIP_GATE, nullptr); + m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_GBA_LINK_PORT, nullptr); } void CoreController::setBattleChipId(uint16_t id) { @@ -1198,7 +1194,7 @@ void CoreController::setFramebufferHandle(int fb) { if (hasStarted()) { m_threadContext.core->reloadConfigOption(m_threadContext.core, "hwaccelVideo", NULL); if (!m_hwaccel) { - m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), screenDimensions().width()); + m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer.data()), screenDimensions().width()); } } } @@ -1322,9 +1318,9 @@ void CoreController::updateROMInfo() { mCore* core = m_threadContext.core; core->checksum(core, &m_crc32, mCHECKSUM_CRC32); - char gameTitle[17] = { '\0' }; - core->getGameTitle(core, gameTitle); - m_internalTitle = QLatin1String(gameTitle); + mGameInfo info; + core->getGameInfo(core, &info); + m_internalTitle = QLatin1String(info.title); #ifdef USE_SQLITE3 if (db && m_crc32 && NoIntroDBLookupGameByCRC(db, m_crc32, &game)) { diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index c46b4d6e9..57eb9ffe0 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -87,7 +87,7 @@ public: QString baseDirectory() const { return m_baseDirectory; } QString savePath() const { return m_savePath; } - const color_t* drawContext(); + const mColor* drawContext(); QImage getPixels(); bool isPaused(); @@ -107,7 +107,7 @@ public: mCheatDevice* cheatDevice() { return m_threadContext.core->cheatDevice(m_threadContext.core); } -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS mDebugger* debugger() { return &m_debugger; } void attachDebugger(bool interrupt = true); void detachDebugger(); @@ -305,7 +305,7 @@ private: bool m_autoload; int m_autosaveCounter = 0; -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS struct mDebugger m_debugger; #endif diff --git a/src/platform/qt/DebuggerConsole.h b/src/platform/qt/DebuggerConsole.h index f98635a68..fd2d4e952 100644 --- a/src/platform/qt/DebuggerConsole.h +++ b/src/platform/qt/DebuggerConsole.h @@ -25,7 +25,7 @@ protected: private: Ui::DebuggerConsole m_ui; - int m_historyOffset; + int m_historyOffset = 0; DebuggerConsoleController* m_consoleController; }; diff --git a/src/platform/qt/DebuggerConsoleController.cpp b/src/platform/qt/DebuggerConsoleController.cpp index 7d6624d77..716c31639 100644 --- a/src/platform/qt/DebuggerConsoleController.cpp +++ b/src/platform/qt/DebuggerConsoleController.cpp @@ -162,12 +162,12 @@ void DebuggerConsoleController::historyLoad() { if (line.endsWith("\r\n")) { line.chop(2); } else if (line.endsWith("\n")) { - line.chop(1); + line.chop(1); } history.append(QString::fromUtf8(line)); } QMutexLocker lock(&m_mutex); - m_history = history; + m_history = std::move(history); } void DebuggerConsoleController::historySave() { diff --git a/src/platform/qt/Display.cpp b/src/platform/qt/Display.cpp index b9bb77c1f..2cc7df66e 100644 --- a/src/platform/qt/Display.cpp +++ b/src/platform/qt/Display.cpp @@ -33,49 +33,33 @@ QGBA::Display* QGBA::Display::create(QWidget* parent) { switch (s_driver) { #if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) case Driver::OPENGL: -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) { - format.setVersion(2, 0); - } else { - format.setVersion(3, 3); + default: + if (DisplayGL::highestCompatible(format)) { + return new DisplayGL(format, parent); } - format.setProfile(QSurfaceFormat::CoreProfile); - if (DisplayGL::supportsFormat(format)) { - QSurfaceFormat::setDefaultFormat(format); - } else { -#ifdef BUILD_GL - LOG(QT, WARN) << ("Failed to create an OpenGL Core context, trying old-style..."); - format.setVersion(1, 4); - format.setOption(QSurfaceFormat::DeprecatedFunctions); - if (!DisplayGL::supportsFormat(format)) { - return nullptr; - } -#else - return nullptr; -#endif - } - return new DisplayGL(format, parent); -#endif + break; #endif #ifdef BUILD_GL case Driver::OPENGL1: - format.setVersion(1, 4); - if (!DisplayGL::supportsFormat(format)) { - return nullptr; + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + format.setVersion(1, 4); + } else { + format.setVersion(1, 1); } - return new DisplayGL(format, parent); + if (DisplayGL::supportsFormat(format)) { + return new DisplayGL(format, parent); + } + break; #endif case Driver::QT: +#if !defined(BUILD_GL) && !defined(BUILD_GLES2) && !defined(BUILD_GLES3) && !defined(USE_EPOXY) + default: +#endif return new DisplayQt(parent); - default: -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) - return new DisplayGL(format, parent); -#else - return new DisplayQt(parent); -#endif } + return nullptr; } QGBA::Display::Display(QWidget* parent) @@ -116,7 +100,10 @@ void QGBA::Display::configure(ConfigController* config) { config->updateOption("videoSync"); #if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) if (opts->shader && supportsShaders()) { - struct VDir* shader = VDirOpen(opts->shader); + struct VDir* shader = VDirOpenArchive(opts->shader); + if (!shader) { + shader = VDirOpen(opts->shader); + } if (shader) { setShaders(shader); shader->close(shader); diff --git a/src/platform/qt/Display.h b/src/platform/qt/Display.h index 3c723ba91..3cc2fc61f 100644 --- a/src/platform/qt/Display.h +++ b/src/platform/qt/Display.h @@ -57,11 +57,12 @@ public: virtual void setVideoScale(int) {} virtual void setBackgroundImage(const QImage&) = 0; virtual QSize contentSize() const = 0; + virtual void setMaximumSize(const QSize& size) = 0; - virtual void setVideoProxy(std::shared_ptr proxy) { m_videoProxy = proxy; } + virtual void setVideoProxy(std::shared_ptr proxy) { m_videoProxy = std::move(proxy); } std::shared_ptr videoProxy() { return m_videoProxy; } virtual VideoBackend* videoBackend(); - + signals: void drawingStarted(); void showCursor(); @@ -105,6 +106,7 @@ private: bool m_filter = false; QTimer m_mouseTimer; std::shared_ptr m_videoProxy; + QSize m_maxSize; }; } diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index eaae3f63c..e62e9685e 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -53,6 +53,12 @@ typedef struct _XDisplay Display; #define OVERHEAD_NSEC 300000 #endif +// Legacy define from X11/X.h +#ifdef Unsorted +#undef Unsorted +#endif + +#include "LogController.h" #include "OpenGLBug.h" #include "utils.h" @@ -186,6 +192,7 @@ DisplayGL::DisplayGL(const QSurfaceFormat& format, QWidget* parent) setAttribute(Qt::WA_NativeWindow); window()->windowHandle()->setFormat(format); windowHandle()->setSurfaceType(QSurface::OpenGLSurface); + windowHandle()->destroy(); windowHandle()->create(); #ifdef USE_SHARE_WIDGET @@ -245,7 +252,7 @@ void DisplayGL::startDrawing(std::shared_ptr controller) { m_isDrawing = true; m_painter->setContext(controller); m_painter->setMessagePainter(messagePainter()); - m_context = controller; + m_context = std::move(controller); if (videoProxy()) { videoProxy()->moveToThread(&m_drawThread); } @@ -277,6 +284,47 @@ void DisplayGL::startDrawing(std::shared_ptr controller) { QTimer::singleShot(8, this, &DisplayGL::updateContentSize); } +bool DisplayGL::highestCompatible(QSurfaceFormat& format) { +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + format.setVersion(3, 3); + format.setProfile(QSurfaceFormat::CoreProfile); + if (DisplayGL::supportsFormat(format)) { + return true; + } + } else { +#if defined(BUILD_GLES3) || defined(USE_EPOXY) + format.setVersion(3, 1); + if (DisplayGL::supportsFormat(format)) { + return true; + } +#endif +#if defined(BUILD_GLES2) || defined(USE_EPOXY) + format.setVersion(2, 0); + if (DisplayGL::supportsFormat(format)) { + return true; + } +#endif + } +#endif + +#ifdef BUILD_GL +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) + LOG(QT, WARN) << tr("Failed to create an OpenGL 3 context, trying old-style..."); +#endif + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + format.setVersion(1, 4); + } else { + format.setVersion(1, 1); + } + format.setOption(QSurfaceFormat::DeprecatedFunctions); + if (DisplayGL::supportsFormat(format)) { + return true; + } +#endif + return false; +} + bool DisplayGL::supportsFormat(const QSurfaceFormat& format) { if (!s_supports.contains(format)) { QOpenGLContext context; @@ -466,7 +514,7 @@ void DisplayGL::setVideoProxy(std::shared_ptr proxy) { if (proxy) { proxy->moveToThread(&m_drawThread); } - m_painter->setVideoProxy(proxy); + m_painter->setVideoProxy(std::move(proxy)); } void DisplayGL::updateContentSize() { @@ -477,6 +525,10 @@ int DisplayGL::framebufferHandle() { return m_painter->glTex(); } +void DisplayGL::setMaximumSize(const QSize& size) { + QMetaObject::invokeMethod(m_painter.get(), "setMaximumSize", Q_ARG(const QSize&, size)); +} + PainterGL::PainterGL(QWindow* window, mGLWidget* widget, const QSurfaceFormat& format) : m_window(window) , m_format(format) @@ -624,7 +676,7 @@ void PainterGL::destroy() { } void PainterGL::setContext(std::shared_ptr context) { - m_context = context; + m_context = std::move(context); } void PainterGL::resizeContext() { @@ -647,6 +699,7 @@ void PainterGL::resizeContext() { mRectangle dims = {0, 0, size.width(), size.height()}; m_backend->setLayerDimensions(m_backend, VIDEO_LAYER_IMAGE, &dims); recenterLayers(); + m_dims = size; } void PainterGL::setMessagePainter(MessagePainter* messagePainter) { @@ -657,22 +710,7 @@ void PainterGL::recenterLayers() { if (!m_context) { return; } - const static std::initializer_list centeredLayers{VIDEO_LAYER_BACKGROUND}; - int width, height; - mRectangle frame = {0}; - m_backend->imageSize(m_backend, VIDEO_LAYER_IMAGE, &width, &height); - frame.width = width; - frame.height = height; - unsigned scale = std::max(1U, m_context->videoScale()); - - for (VideoLayer l : centeredLayers) { - mRectangle dims{}; - m_backend->imageSize(m_backend, l, &width, &height); - dims.width = width * scale; - dims.height = height * scale; - mRectangleCenter(&frame, &dims); - m_backend->setLayerDimensions(m_backend, l, &dims); - } + VideoBackendRecenter(m_backend, std::max(1U, m_context->videoScale())); } void PainterGL::resize(const QSize& size) { @@ -687,6 +725,11 @@ void PainterGL::resize(const QSize& size) { } } +void PainterGL::setMaximumSize(const QSize& size) { + m_maxSize = size; + resizeContext(); +} + void PainterGL::lockAspectRatio(bool lock) { m_backend->lockAspectRatio = lock; resize(m_size); @@ -878,7 +921,11 @@ void PainterGL::unpause() { void PainterGL::performDraw() { float r = m_window->devicePixelRatio(); - m_backend->contextResized(m_backend, m_size.width() * r, m_size.height() * r); + QSize maxSize = m_maxSize; + if (!maxSize.isValid()) { + maxSize = QSize(0, 0); + } + m_backend->contextResized(m_backend, m_size.width() * r, m_size.height() * r, maxSize.width() * r, maxSize.height() * r); if (m_buffer) { m_backend->setImage(m_backend, VIDEO_LAYER_IMAGE, m_buffer); } diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index d94a68621..5b0aab2cd 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -95,7 +95,9 @@ public: void setVideoProxy(std::shared_ptr) override; int framebufferHandle() override; QSize contentSize() const override { return m_cachedContentSize; } + void setMaximumSize(const QSize& size) override; + static bool highestCompatible(QSurfaceFormat&); static bool supportsFormat(const QSurfaceFormat&); public slots: @@ -171,6 +173,7 @@ public slots: void pause(); void unpause(); void resize(const QSize& size); + void setMaximumSize(const QSize& size); void lockAspectRatio(bool lock); void lockIntegerScaling(bool lock); void interframeBlending(bool enable); @@ -229,6 +232,7 @@ private: VideoBackend* m_backend = nullptr; QSize m_size; QSize m_dims; + QSize m_maxSize; MessagePainter* m_messagePainter = nullptr; QElapsedTimer m_delayTimer; std::shared_ptr m_videoProxy; diff --git a/src/platform/qt/DisplayQt.cpp b/src/platform/qt/DisplayQt.cpp index 51874cb40..b71147c43 100644 --- a/src/platform/qt/DisplayQt.cpp +++ b/src/platform/qt/DisplayQt.cpp @@ -43,7 +43,7 @@ void DisplayQt::startDrawing(std::shared_ptr controller) { m_height = size.height(); m_oldBacking = QImage(); m_isDrawing = true; - m_context = controller; + m_context = std::move(controller); emit drawingStarted(); } @@ -78,7 +78,7 @@ void DisplayQt::filter(bool filter) { void DisplayQt::framePosted() { update(); - const color_t* buffer = m_context->drawContext(); + const mColor* buffer = m_context->drawContext(); if (const_cast(m_layers[VIDEO_LAYER_IMAGE]).bits() == reinterpret_cast(buffer)) { return; } @@ -130,7 +130,24 @@ void DisplayQt::paintEvent(QPaintEvent*) { struct mRectangle frame; VideoBackendGetFrame(&m_backend, &frame); QPoint origin(-frame.x, -frame.y); - QRect full(clampSize(contentSize(), size(), isAspectRatioLocked(), isIntegerScalingLocked())); + QSize drawSize(contentSize()); + if (!drawSize.isValid() || drawSize.width() < 1 || drawSize.height() < 1) { + return; + } + QSize usedSize = size(); + QPoint screenOrigin(0, 0); + if (m_maxSize.isValid()) { + if (m_maxSize.width() < usedSize.width()) { + screenOrigin.setX((usedSize.width() - m_maxSize.width()) / 2); + usedSize.setWidth(m_maxSize.width()); + } + if (m_maxSize.height() < usedSize.height()) { + screenOrigin.setY((usedSize.height() - m_maxSize.height()) / 2); + usedSize.setHeight(m_maxSize.height()); + } + } + QRect full(clampSize(contentSize(), usedSize, isAspectRatioLocked(), isIntegerScalingLocked())); + full.translate(screenOrigin); painter.save(); painter.translate(full.topLeft()); painter.scale(full.width() / static_cast(frame.width), full.height() / static_cast(frame.height)); @@ -216,7 +233,7 @@ void DisplayQt::swap(struct VideoBackend*) { void DisplayQt::clear(struct VideoBackend*) { } -void DisplayQt::contextResized(struct VideoBackend*, unsigned, unsigned) { +void DisplayQt::contextResized(struct VideoBackend*, unsigned, unsigned, unsigned, unsigned) { } void DisplayQt::setImageSize(struct VideoBackend* v, enum VideoLayer layer, int w, int h) { @@ -241,9 +258,8 @@ void DisplayQt::setImage(struct VideoBackend* v, enum VideoLayer layer, const vo if (layer > self->m_layers.size()) { return; } - QImage image = self->m_layers[layer]; - image = QImage(static_cast(frame), image.width(), image.height(), QImage::Format_ARGB32).rgbSwapped(); - self->m_layers[layer] = image; + QImage& image = self->m_layers[layer]; + self->m_layers[layer] = QImage(static_cast(frame), image.width(), image.height(), QImage::Format_ARGB32).rgbSwapped(); } void DisplayQt::drawFrame(struct VideoBackend* v) { diff --git a/src/platform/qt/DisplayQt.h b/src/platform/qt/DisplayQt.h index c1363dede..a6816a18b 100644 --- a/src/platform/qt/DisplayQt.h +++ b/src/platform/qt/DisplayQt.h @@ -27,6 +27,8 @@ public: VideoShader* shaders() override { return nullptr; } QSize contentSize() const override; VideoBackend* videoBackend() override { return &m_backend; } + void setMaximumSize(const QSize& size) override { m_maxSize = size; } + public slots: void stopDrawing() override; @@ -56,7 +58,7 @@ private: static void layerDimensions(const struct VideoBackend*, enum VideoLayer, struct mRectangle*); static void swap(struct VideoBackend*); static void clear(struct VideoBackend*); - static void contextResized(struct VideoBackend*, unsigned w, unsigned h); + static void contextResized(struct VideoBackend*, unsigned w, unsigned h, unsigned maxW, unsigned maxH); static void setImageSize(struct VideoBackend*, enum VideoLayer, int w, int h); static void imageSize(struct VideoBackend*, enum VideoLayer, int* w, int* h); static void setImage(struct VideoBackend*, enum VideoLayer, const void* frame); @@ -69,6 +71,7 @@ private: int m_width = -1; int m_height = -1; QImage m_oldBacking{nullptr}; + QSize m_maxSize; std::shared_ptr m_context = nullptr; }; diff --git a/src/platform/qt/ForwarderController.cpp b/src/platform/qt/ForwarderController.cpp index 56e202019..abf2d27d0 100644 --- a/src/platform/qt/ForwarderController.cpp +++ b/src/platform/qt/ForwarderController.cpp @@ -160,7 +160,7 @@ void ForwarderController::gotManifest(QNetworkReply* reply) { mUpdaterGetUpdateForChannel(&context, platform.toUtf8().constData(), m_channel.toUtf8().constData(), &update); downloadBuild({bucket + update.path}); - mUpdaterDeinit(&context); + mUpdaterDeinit(&context); } void ForwarderController::downloadBuild(const QUrl& url) { @@ -174,7 +174,7 @@ void ForwarderController::downloadBuild(const QUrl& url) { .arg(extension)); if (!m_sourceFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { emit buildFailed(); - return; + return; } QNetworkReply* reply = GBAApp::app()->httpGet(url); @@ -232,9 +232,9 @@ bool ForwarderController::toolInstalled(const QString& tool) { void ForwarderController::connectReply(QNetworkReply* reply, Download download, void (ForwarderController::*next)(QNetworkReply*)) { #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) - connect(reply, &QNetworkReply::errorOccurred, this, [this, reply]() { + connect(reply, &QNetworkReply::errorOccurred, this, [this]() { #else - connect(reply, qOverload<>(&QNetworkReply::error), this, [this, reply]() { + connect(reply, qOverload<>(&QNetworkReply::error), this, [this]() { #endif emit buildFailed(); }); diff --git a/src/platform/qt/ForwarderGenerator3DS.h b/src/platform/qt/ForwarderGenerator3DS.h index b22585063..8713be1bf 100644 --- a/src/platform/qt/ForwarderGenerator3DS.h +++ b/src/platform/qt/ForwarderGenerator3DS.h @@ -23,7 +23,7 @@ public: System system() const override { return System::N3DS; } QString extension() const override { return QLatin1String("cia"); } - virtual QStringList externalTools() const { return {"bannertool", "3dstool", "ctrtool", "makerom"}; } + virtual QStringList externalTools() const override { return {"bannertool", "3dstool", "ctrtool", "makerom"}; } void rebuild(const QString& source, const QString& target) override; diff --git a/src/platform/qt/ForwarderView.cpp b/src/platform/qt/ForwarderView.cpp index 922ef7c16..7261c0941 100644 --- a/src/platform/qt/ForwarderView.cpp +++ b/src/platform/qt/ForwarderView.cpp @@ -97,7 +97,7 @@ void ForwarderView::build() { if (m_ui.baseType->currentIndex() == 2) { m_controller.setBaseFilename(m_ui.baseFilename->text()); } else { - m_controller.clearBaseFilename(); + m_controller.clearBaseFilename(); } m_controller.startBuild(m_ui.outputFilename->text()); m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); @@ -235,14 +235,14 @@ void ForwarderView::updateProgress() { if (m_needsForwarderKit) { m_ui.progressBar->setValue(450 + m_downloadProgress * 50); } else { - m_ui.progressBar->setValue(m_downloadProgress * 100); + m_ui.progressBar->setValue(m_downloadProgress * 100); } break; case ForwarderController::BASE: if (m_needsForwarderKit) { m_ui.progressBar->setValue(500 + m_downloadProgress * 500); } else { - m_ui.progressBar->setValue(100 + m_downloadProgress * 900); + m_ui.progressBar->setValue(100 + m_downloadProgress * 900); } break; } diff --git a/src/platform/qt/FrameView.cpp b/src/platform/qt/FrameView.cpp index 76b56be3a..245ebf4bb 100644 --- a/src/platform/qt/FrameView.cpp +++ b/src/platform/qt/FrameView.cpp @@ -31,7 +31,7 @@ using namespace QGBA; FrameView::FrameView(std::shared_ptr controller, QWidget* parent) - : AssetView(controller, parent) + : AssetView(std::move(controller), parent) { m_ui.setupUi(this); @@ -505,12 +505,20 @@ bool FrameView::eventFilter(QObject*, QEvent* event) { QPointF pos; switch (event->type()) { case QEvent::MouseButtonPress: +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) pos = static_cast(event)->localPos(); +#else + pos = static_cast(event)->position(); +#endif pos /= m_ui.magnification->value(); selectLayer(pos); return true; case QEvent::MouseButtonDblClick: +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) pos = static_cast(event)->localPos(); +#else + pos = static_cast(event)->position(); +#endif pos /= m_ui.magnification->value(); disableLayer(pos); return true; @@ -566,7 +574,7 @@ void FrameView::newVl() { unsigned width, height; m_vl->baseVideoSize(m_vl, &width, &height); m_framebuffer = QImage(width, height, QImage::Format_RGBX8888); - m_vl->setVideoBuffer(m_vl, reinterpret_cast(m_framebuffer.bits()), width); + m_vl->setVideoBuffer(m_vl, reinterpret_cast(m_framebuffer.bits()), width); m_vl->reset(m_vl); } diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index e21dbef05..fdc710c0c 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -274,17 +274,17 @@ QNetworkReply* GBAApp::httpGet(const QUrl& url) { return m_netman.get(req); } -qint64 GBAApp::submitWorkerJob(std::function job, std::function callback) { - return submitWorkerJob(job, nullptr, callback); +qint64 GBAApp::submitWorkerJob(std::function&& job, std::function&& callback) { + return submitWorkerJob(std::move(job), nullptr, std::move(callback)); } -qint64 GBAApp::submitWorkerJob(std::function job, QObject* context, std::function callback) { +qint64 GBAApp::submitWorkerJob(std::function&& job, QObject* context, std::function&& callback) { qint64 jobId = m_nextJob; ++m_nextJob; - WorkerJob* jobRunnable = new WorkerJob(jobId, job, this); + WorkerJob* jobRunnable = new WorkerJob(jobId, std::move(job), this); m_workerJobs.insert(jobId, jobRunnable); if (callback) { - waitOnJob(jobId, context, callback); + waitOnJob(jobId, context, std::move(callback)); } m_workerThreads.start(jobRunnable); return jobId; @@ -308,14 +308,15 @@ bool GBAApp::removeWorkerJob(qint64 jobId) { return success; } -bool GBAApp::waitOnJob(qint64 jobId, QObject* context, std::function callback) { +bool GBAApp::waitOnJob(qint64 jobId, QObject* context, std::function&& callback) { if (!m_workerJobs.contains(jobId)) { return false; } if (!context) { context = this; } - QMetaObject::Connection connection = connect(this, &GBAApp::jobFinished, context, [jobId, callback](qint64 testedJobId) { + QMetaObject::Connection connection = connect(this, &GBAApp::jobFinished, context, + [jobId, callback = std::move(callback)](qint64 testedJobId) { if (jobId != testedJobId) { return; } @@ -381,7 +382,7 @@ void GBAApp::restartForUpdate() { #ifndef Q_OS_WIN QFile(extractedPath).setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner); #endif - m_invokeOnExit = extractedPath; + m_invokeOnExit = std::move(extractedPath); } for (auto& window : m_windows) { @@ -396,9 +397,9 @@ void GBAApp::finishJob(qint64 jobId) { m_workerJobCallbacks.remove(jobId); } -GBAApp::WorkerJob::WorkerJob(qint64 id, std::function job, GBAApp* owner) +GBAApp::WorkerJob::WorkerJob(qint64 id, std::function&& job, GBAApp* owner) : m_id(id) - , m_job(job) + , m_job(std::move(job)) , m_owner(owner) { setAutoDelete(true); diff --git a/src/platform/qt/GBAApp.h b/src/platform/qt/GBAApp.h index e9907685f..2388bc297 100644 --- a/src/platform/qt/GBAApp.h +++ b/src/platform/qt/GBAApp.h @@ -74,10 +74,10 @@ public: QNetworkAccessManager* netman(); QNetworkReply* httpGet(const QUrl&); - qint64 submitWorkerJob(std::function job, std::function callback = {}); - qint64 submitWorkerJob(std::function job, QObject* context, std::function callback); + qint64 submitWorkerJob(std::function&& job, std::function&& callback = {}); + qint64 submitWorkerJob(std::function&& job, QObject* context, std::function&& callback); bool removeWorkerJob(qint64 jobId); - bool waitOnJob(qint64 jobId, QObject* context, std::function callback); + bool waitOnJob(qint64 jobId, QObject* context, std::function&& callback); ApplicationUpdater* updater() { return &m_updater; } QString invokeOnExit() { return m_invokeOnExit; } @@ -103,7 +103,7 @@ private slots: private: class WorkerJob : public QRunnable { public: - WorkerJob(qint64 id, std::function job, GBAApp* owner); + WorkerJob(qint64 id, std::function&& job, GBAApp* owner); public: void run() override; diff --git a/src/platform/qt/GBAKeyEditor.cpp b/src/platform/qt/GBAKeyEditor.cpp index 88963afa2..8a8427973 100644 --- a/src/platform/qt/GBAKeyEditor.cpp +++ b/src/platform/qt/GBAKeyEditor.cpp @@ -18,6 +18,7 @@ #include "KeyEditor.h" #ifdef BUILD_SDL +#define SDL_MAIN_HANDLED #include "platform/sdl/sdl-events.h" #endif @@ -53,7 +54,7 @@ GBAKeyEditor::GBAKeyEditor(InputController* controller, int type, const QString& refresh(); #ifdef BUILD_SDL - if (type == SDL_BINDING_BUTTON) { + if (type == SDL_BINDING_BUTTON || type == SDL_BINDING_CONTROLLER) { m_profileSelect = new QComboBox(this); connect(m_profileSelect, static_cast(&QComboBox::currentIndexChanged), this, &GBAKeyEditor::selectGamepad); @@ -121,6 +122,7 @@ GBAKeyEditor::GBAKeyEditor(InputController* controller, int type, const QString& connect(key, &KeyEditor::valueChanged, this, &GBAKeyEditor::setNext); connect(key, &KeyEditor::axisChanged, this, &GBAKeyEditor::setNext); connect(key, &KeyEditor::hatChanged, this, &GBAKeyEditor::setNext); + key->setInputController(m_controller); key->installEventFilter(this); } @@ -264,7 +266,7 @@ void GBAKeyEditor::refresh() { void GBAKeyEditor::lookupBinding(const mInputMap* map, KeyEditor* keyEditor, int key) { #ifdef BUILD_SDL - if (m_type == SDL_BINDING_BUTTON) { + if (m_type == SDL_BINDING_BUTTON || m_type == SDL_BINDING_CONTROLLER) { int value = mInputQueryBinding(map, m_type, key); keyEditor->setValueButton(value); return; @@ -328,7 +330,7 @@ void GBAKeyEditor::lookupHats(const mInputMap* map) { void GBAKeyEditor::bindKey(const KeyEditor* keyEditor, int key) { InputMapper mapper = m_controller->mapper(m_type); #ifdef BUILD_SDL - if (m_type == SDL_BINDING_BUTTON && keyEditor->axis() >= 0) { + if ((m_type == SDL_BINDING_BUTTON || m_type == SDL_BINDING_CONTROLLER) && keyEditor->axis() >= 0) { mapper.bindAxis(keyEditor->axis(), keyEditor->direction(), key); } if (m_type == SDL_BINDING_BUTTON && keyEditor->hat() >= 0) { diff --git a/src/platform/qt/GBAOverride.cpp b/src/platform/qt/GBAOverride.cpp index 57fb2048e..dbf627268 100644 --- a/src/platform/qt/GBAOverride.cpp +++ b/src/platform/qt/GBAOverride.cpp @@ -14,9 +14,9 @@ void GBAOverride::identify(const struct mCore* core) { if (core->platform(core) != mPLATFORM_GBA) { return; } - char gameId[8]; - core->getGameCode(core, gameId); - memcpy(override.id, &gameId[4], 4); + mGameInfo info; + core->getGameInfo(core, &info); + memcpy(override.id, info.code, 4); } void GBAOverride::save(struct Configuration* config) const { diff --git a/src/platform/qt/GBAOverride.h b/src/platform/qt/GBAOverride.h index 477af0014..b93cb1953 100644 --- a/src/platform/qt/GBAOverride.h +++ b/src/platform/qt/GBAOverride.h @@ -7,7 +7,7 @@ #include "Override.h" -#include +#include namespace QGBA { diff --git a/src/platform/qt/GBOverride.h b/src/platform/qt/GBOverride.h index e967211de..fc1a7d2c9 100644 --- a/src/platform/qt/GBOverride.h +++ b/src/platform/qt/GBOverride.h @@ -7,7 +7,7 @@ #include "Override.h" -#include +#include namespace QGBA { diff --git a/src/platform/qt/GDBController.h b/src/platform/qt/GDBController.h index 6bf0a7132..50c0fb927 100644 --- a/src/platform/qt/GDBController.h +++ b/src/platform/qt/GDBController.h @@ -7,7 +7,7 @@ #include "DebuggerController.h" -#ifdef USE_GDB_STUB +#ifdef ENABLE_GDB_STUB #include diff --git a/src/platform/qt/GDBWindow.cpp b/src/platform/qt/GDBWindow.cpp index 3f1f86efb..8c4738387 100644 --- a/src/platform/qt/GDBWindow.cpp +++ b/src/platform/qt/GDBWindow.cpp @@ -44,7 +44,7 @@ GDBWindow::GDBWindow(GDBController* controller, QWidget* parent) connect(m_portEdit, &QLineEdit::textChanged, this, &GDBWindow::portChanged); settingsGrid->addWidget(m_portEdit, 0, 1, Qt::AlignLeft); - m_bindAddressEdit = new QLineEdit("0.0.0.0"); + m_bindAddressEdit = new QLineEdit("127.0.0.1"); m_bindAddressEdit->setMaxLength(15); connect(m_bindAddressEdit, &QLineEdit::textChanged, this, &GDBWindow::bindAddressChanged); settingsGrid->addWidget(m_bindAddressEdit, 1, 1, Qt::AlignLeft); diff --git a/src/platform/qt/IOViewer.cpp b/src/platform/qt/IOViewer.cpp index b354ff415..9b44af04f 100644 --- a/src/platform/qt/IOViewer.cpp +++ b/src/platform/qt/IOViewer.cpp @@ -1025,7 +1025,7 @@ const QList& IOViewer::registerDescriptions(mPlat regGBA.append({ { tr("Enable IRQs"), 0 }, }); - s_registers[mPLATFORM_GBA] = regGBA; + s_registers[mPLATFORM_GBA] = std::move(regGBA); #endif #ifdef M_CORE_GB QList regGB; @@ -1323,7 +1323,7 @@ const QList& IOViewer::registerDescriptions(mPlat }); // 0xFF40: LCDC regGB.append({ - { tr("Background enable/priority"), 1 }, + { tr("Background enable/priority"), 0 }, { tr("Enable sprites"), 1 }, { tr("Double-height sprites"), 2 }, { tr("Background tile map"), 3, 1, { @@ -1555,7 +1555,7 @@ const QList& IOViewer::registerDescriptions(mPlat { tr("Serial"), 3 }, { tr("Joypad"), 4 }, }); - s_registers[mPLATFORM_GB] = regGB; + s_registers[mPLATFORM_GB] = std::move(regGB); #endif return s_registers[platform]; } @@ -1687,7 +1687,15 @@ void IOViewer::bitFlipped() { void IOViewer::writeback() { { CoreController::Interrupter interrupter(m_controller); - GBAIOWrite(static_cast(m_controller->thread()->core->board), m_register, m_value); + mCore* core = m_controller->thread()->core; + switch (m_width) { + case 0: + core->busWrite8(core, m_base + m_register, m_value); + break; + case 1: + core->busWrite16(core, m_base + m_register, m_value); + break; + } } updateRegister(); } diff --git a/src/platform/qt/IOViewer.h b/src/platform/qt/IOViewer.h index 120f201e0..fabe478ac 100644 --- a/src/platform/qt/IOViewer.h +++ b/src/platform/qt/IOViewer.h @@ -28,7 +28,7 @@ public: , size(size) , readonly(readonly) , description(description) {} - RegisterItem(const QString& description, uint start, int size, QStringList items, bool readonly = false) + RegisterItem(const QString& description, uint start, int size, const QStringList& items, bool readonly = false) : start(start) , size(size) , readonly(readonly) diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 5e8634497..3deca07f3 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -16,8 +16,13 @@ #include #include #ifdef BUILD_QT_MULTIMEDIA +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #include #include +#else +#include +#include +#endif #endif #include @@ -50,6 +55,10 @@ InputController::InputController(QWidget* topLevel, QObject* parent) m_gamepadTimer.start(); #ifdef BUILD_QT_MULTIMEDIA +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + m_captureSession.setVideoSink(&m_videoSink); + connect(&m_videoSink, &QVideoSink::videoFrameChanged, &m_videoDumper, &VideoDumper::present); +#endif connect(&m_videoDumper, &VideoDumper::imageAvailable, this, &InputController::setCamImage); #endif @@ -90,18 +99,30 @@ InputController::InputController(QWidget* topLevel, QObject* parent) #ifdef BUILD_QT_MULTIMEDIA image->p->m_cameraActive = true; QByteArray camera = image->p->m_config->getQtOption("camera").toByteArray(); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (!camera.isNull()) { image->p->m_cameraDevice = camera; } +#else + if (!camera.isNull()) { + for (const auto& cam : QMediaDevices::videoInputs()) { + if (cam.id() == camera) { + image->p->m_cameraDevice = cam; + } + } + } +#endif QMetaObject::invokeMethod(image->p, "setupCam"); #endif }; m_image.stopRequestImage = [](mImageSource* context) { - InputControllerImage* image = static_cast(context); #ifdef BUILD_QT_MULTIMEDIA + InputControllerImage* image = static_cast(context); image->p->m_cameraActive = false; QMetaObject::invokeMethod(image->p, "teardownCam"); +#else + UNUSED(context); #endif }; @@ -151,15 +172,16 @@ void InputController::setConfiguration(ConfigController* config) { } bool InputController::loadConfiguration(uint32_t type) { - if (!mInputMapLoad(&m_inputMap, type, m_config->input())) { - return false; - } + bool loaded = mInputMapLoad(&m_inputMap, type, m_config->input()); auto driver = m_inputDrivers.value(type); if (!driver) { return false; } + if (!loaded) { + driver->bindDefaults(this); + } driver->loadConfiguration(m_config); - return true; + return loaded; } bool InputController::loadProfile(uint32_t type, const QString& profile) { @@ -345,11 +367,12 @@ void InputController::update() { int InputController::pollEvents() { int activeButtons = 0; for (auto& pad : gamepads()) { - InputMapper im(mapper(pad)); + InputMapper im(mapper(pad.get())); activeButtons |= im.mapKeys(pad->currentButtons()); activeButtons |= im.mapAxes(pad->currentAxes()); activeButtons |= im.mapHats(pad->currentHats()); } + QReadLocker l(&m_eventsLock); for (int i = 0; i < GBA_KEY_MAX; ++i) { if ((activeButtons & (1 << i)) && hasPendingEvent(i)) { activeButtons ^= 1 << i; @@ -358,7 +381,7 @@ int InputController::pollEvents() { return activeButtons; } -Gamepad* InputController::gamepad(uint32_t type) { +std::shared_ptr InputController::gamepad(uint32_t type) { auto driver = m_inputDrivers.value(type); if (!driver) { return nullptr; @@ -370,13 +393,13 @@ Gamepad* InputController::gamepad(uint32_t type) { return driver->activeGamepad(); } -QList InputController::gamepads() { - QList pads; +QList> InputController::gamepads() { + QList> pads; for (auto& driver : m_inputDrivers) { if (!driver->supportsGamepads()) { continue; } - Gamepad* pad = driver->activeGamepad(); + std::shared_ptr pad = driver->activeGamepad(); if (pad) { pads.append(pad); } @@ -386,7 +409,7 @@ QList InputController::gamepads() { QSet InputController::activeGamepadButtons(uint32_t type) { QSet activeButtons; - Gamepad* pad = gamepad(type); + std::shared_ptr pad = gamepad(type); if (!pad) { return {}; } @@ -401,7 +424,7 @@ QSet InputController::activeGamepadButtons(uint32_t type) { QSet> InputController::activeGamepadAxes(uint32_t type) { QSet> activeAxes; - Gamepad* pad = gamepad(type); + std::shared_ptr pad = gamepad(type); if (!pad) { return {}; } @@ -422,7 +445,7 @@ QSet> InputController::activeGamepadAxes QSet> InputController::activeGamepadHats(uint32_t type) { QSet> activeHats; - Gamepad* pad = gamepad(type); + std::shared_ptr pad = gamepad(type); if (!pad) { return {}; } @@ -594,9 +617,13 @@ void InputController::setCamImage(const QImage& image) { QList> InputController::listCameras() const { QList> out; #ifdef BUILD_QT_MULTIMEDIA - QList cams = QCameraInfo::availableCameras(); - for (const auto& cam : cams) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + for (const auto& cam : QCameraInfo::availableCameras()) { out.append(qMakePair(cam.deviceName().toLatin1(), cam.description())); +#else + for (const auto& cam : QMediaDevices::videoInputs()) { + out.append(qMakePair(cam.id(), cam.description())); +#endif } #endif return out; @@ -638,6 +665,7 @@ void InputController::setupCam() { return; } +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (!m_camera) { m_camera = std::make_unique(m_cameraDevice); connect(m_camera.get(), &QCamera::statusChanged, this, &InputController::prepareCamSettings, Qt::QueuedConnection); @@ -649,17 +677,31 @@ void InputController::setupCam() { m_camera->setCaptureMode(QCamera::CaptureVideo); m_camera->setViewfinder(&m_videoDumper); m_camera->load(); +#else + if (!m_camera) { + m_camera = std::make_unique(m_cameraDevice); + m_captureSession.setCamera(m_camera.get()); + } + prepareCamFormat(); +#endif #endif } #ifdef BUILD_QT_MULTIMEDIA +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) void InputController::prepareCamSettings(QCamera::Status status) { if (status != QCamera::LoadedStatus || m_camera->state() == QCamera::ActiveState) { return; } + prepareCamFormat(); +} +#endif + +void InputController::prepareCamFormat() { #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) - QCameraViewfinderSettings settings; QSize size(1280, 720); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + QCameraViewfinderSettings settings; auto cameraRes = m_camera->supportedViewfinderResolutions(settings); for (auto& cameraSize : cameraRes) { if (cameraSize.width() < m_image.w || cameraSize.height() < m_image.h) { @@ -688,6 +730,25 @@ void InputController::prepareCamSettings(QCamera::Status status) { } } m_camera->setViewfinderSettings(settings); +#else + bool goodFormatFound = false; + auto goodFormats = m_videoDumper.supportedPixelFormats(); + QCameraFormat bestFormat; + for (const auto& format : m_cameraDevice.videoFormats()) { + if (!goodFormats.contains(format.pixelFormat())) { + continue; + } + if (format.resolution().width() <= size.width() && format.resolution().height() <= size.height()) { + size = format.resolution(); + bestFormat = format; + goodFormatFound = true; + } + } + if (!goodFormatFound) { + LOG(QT, WARN) << "Could not find a valid camera format!"; + } + m_camera->setCameraFormat(bestFormat); +#endif #endif m_camera->start(); } @@ -696,7 +757,11 @@ void InputController::prepareCamSettings(QCamera::Status status) { void InputController::teardownCam() { #ifdef BUILD_QT_MULTIMEDIA if (m_camera) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) m_camera->unload(); +#else + m_captureSession.setCamera(nullptr); +#endif m_camera.reset(); } #endif @@ -704,6 +769,7 @@ void InputController::teardownCam() { void InputController::setCamera(const QByteArray& name) { #ifdef BUILD_QT_MULTIMEDIA +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (m_cameraDevice == name) { return; } @@ -711,8 +777,20 @@ void InputController::setCamera(const QByteArray& name) { if (m_camera && m_camera->state() == QCamera::ActiveState) { teardownCam(); } +#else + if (m_cameraDevice.id() == name) { + return; + } + for (const auto& cam : QMediaDevices::videoInputs()) { + if (cam.id() == name) { + m_cameraDevice = cam; + } + } +#endif if (m_cameraActive) { setupCam(); } +#else + UNUSED(name); #endif } diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h index 6f2326cbd..07e752fd7 100644 --- a/src/platform/qt/InputController.h +++ b/src/platform/qt/InputController.h @@ -25,10 +25,13 @@ #include #ifdef BUILD_QT_MULTIMEDIA -#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #include "VideoDumper.h" -#endif + #include +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +#include +#include +#endif #endif struct mRotationSource; @@ -126,7 +129,7 @@ public slots: void setCamera(const QByteArray& id); private slots: -#ifdef BUILD_QT_MULTIMEDIA +#if defined(BUILD_QT_MULTIMEDIA) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) void prepareCamSettings(QCamera::Status); #endif void setupCam(); @@ -143,13 +146,17 @@ private: static int claimPlayer(); static void freePlayer(int); - Gamepad* gamepad(uint32_t type); - QList gamepads(); + std::shared_ptr gamepad(uint32_t type); + QList> gamepads(); QSet activeGamepadButtons(uint32_t type); QSet> activeGamepadAxes(uint32_t type); QSet> activeGamepadHats(uint32_t type); +#if defined(BUILD_QT_MULTIMEDIA) + void prepareCamFormat(); +#endif + struct InputControllerLux : GBALuminanceSource { InputController* p; uint8_t value; @@ -168,10 +175,14 @@ private: #ifdef BUILD_QT_MULTIMEDIA bool m_cameraActive = false; - QByteArray m_cameraDevice; std::unique_ptr m_camera; -#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) VideoDumper m_videoDumper; +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + QByteArray m_cameraDevice; +#else + QCameraDevice m_cameraDevice; + QMediaCaptureSession m_captureSession; + QVideoSink m_videoSink; #endif #endif diff --git a/src/platform/qt/KeyEditor.cpp b/src/platform/qt/KeyEditor.cpp index 7d3ba1990..6ce94fc55 100644 --- a/src/platform/qt/KeyEditor.cpp +++ b/src/platform/qt/KeyEditor.cpp @@ -5,6 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "KeyEditor.h" +#include "InputController.h" +#include "input/Gamepad.h" #include "input/GamepadAxisEvent.h" #include "input/GamepadButtonEvent.h" #include "ShortcutController.h" @@ -18,6 +20,7 @@ using namespace QGBA; KeyEditor::KeyEditor(QWidget* parent) : QLineEdit(parent) + , m_controller(nullptr) , m_direction(GamepadAxisEvent::NEUTRAL) , m_hatDirection(GamepadHatEvent::CENTER) { @@ -26,12 +29,19 @@ KeyEditor::KeyEditor(QWidget* parent) m_lastKey.setSingleShot(true); } +void KeyEditor::setInputController(InputController* controller) { + m_controller = controller; + if (m_button) { + updateButtonText(); + } +} + void KeyEditor::setValue(int key) { m_key = key; if (m_button) { updateButtonText(); } else { - if (key < 0) { + if (key == Qt::Key_unknown) { setText(tr("---")); } else { setText(keyName(key)); @@ -68,7 +78,7 @@ void KeyEditor::setValueHat(int hat, GamepadHatEvent::Direction direction) { void KeyEditor::clearButton() { m_button = true; - setValue(-1); + setValue(Qt::Key_unknown); } void KeyEditor::clearAxis() { @@ -96,48 +106,13 @@ QSize KeyEditor::sizeHint() const { void KeyEditor::keyPressEvent(QKeyEvent* event) { if (!m_button) { - if (m_key < 0 || !m_lastKey.isActive()) { - m_key = 0; + if (!m_lastKey.isActive()) { + m_key = Qt::Key_unknown; } m_lastKey.start(KEY_TIME); - if (m_key) { - if (ShortcutController::isModifierKey(m_key)) { - switch (event->key()) { - case Qt::Key_Shift: - setValue(Qt::ShiftModifier); - break; - case Qt::Key_Control: - setValue(Qt::ControlModifier); - break; - case Qt::Key_Alt: - setValue(Qt::AltModifier); - break; - case Qt::Key_Meta: - setValue(Qt::MetaModifier); - break; - } - } - if (ShortcutController::isModifierKey(event->key())) { - switch (event->key()) { - case Qt::Key_Shift: - setValue(m_key | Qt::ShiftModifier); - break; - case Qt::Key_Control: - setValue(m_key | Qt::ControlModifier); - break; - case Qt::Key_Alt: - setValue(m_key | Qt::AltModifier); - break; - case Qt::Key_Meta: - setValue(m_key | Qt::MetaModifier); - break; - } - } else { - setValue(event->key() | (m_key & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))); - } - } else { - setValue(event->key()); - } + setValue(ShortcutController::isModifierKey(event->key()) ? + event->key() : + event->key() | (event->modifiers() & ~Qt::KeypadModifier)); } event->accept(); } @@ -203,11 +178,29 @@ void KeyEditor::updateButtonText() { break; } } - if (m_key >= 0) { - text.append(QString::number(m_key)); + if (m_key != Qt::Key_unknown) { + std::shared_ptr gamepad; + if (m_controller && m_controller->gamepadDriver()) { + gamepad = m_controller->gamepadDriver()->activeGamepad(); + } + if (!gamepad) { + text.append(QString::number(m_key)); + } else { + text.append(gamepad->buttonHumanName(m_key)); + } } if (m_direction != GamepadAxisEvent::NEUTRAL) { - text.append((m_direction == GamepadAxisEvent::NEGATIVE ? "-" : "+") + QString::number(m_axis)); + QString name; + std::shared_ptr gamepad; + if (m_controller && m_controller->gamepadDriver()) { + gamepad = m_controller->gamepadDriver()->activeGamepad(); + } + if (!gamepad) { + name = QString::number(m_axis); + } else { + name = gamepad->axisHumanName(m_axis); + } + text.append((m_direction == GamepadAxisEvent::NEGATIVE ? "-" : "+") + name); } if (text.isEmpty()) { setText(tr("---")); diff --git a/src/platform/qt/KeyEditor.h b/src/platform/qt/KeyEditor.h index c1bb56fae..66599ad60 100644 --- a/src/platform/qt/KeyEditor.h +++ b/src/platform/qt/KeyEditor.h @@ -13,12 +13,16 @@ namespace QGBA { +class InputController; + class KeyEditor : public QLineEdit { Q_OBJECT public: KeyEditor(QWidget* parent = nullptr); + void setInputController(InputController* controller); + int value() const { return m_key; } GamepadAxisEvent::Direction direction() const { return m_direction; } @@ -53,10 +57,11 @@ private: void updateButtonText(); - int m_key = -1; + int m_key = Qt::Key_unknown; int m_axis = -1; int m_hat = -1; bool m_button = false; + InputController* m_controller; GamepadAxisEvent::Direction m_direction; GamepadHatEvent::Direction m_hatDirection; QTimer m_lastKey; diff --git a/src/platform/qt/MapView.cpp b/src/platform/qt/MapView.cpp index a00c63c0e..aef8c58b7 100644 --- a/src/platform/qt/MapView.cpp +++ b/src/platform/qt/MapView.cpp @@ -161,8 +161,13 @@ bool MapView::eventFilter(QObject*, QEvent* event) { if (event->type() != QEvent::MouseButtonPress) { return false; } +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) int x = static_cast(event)->x(); int y = static_cast(event)->y(); +#else + int x = static_cast(event)->position().x(); + int y = static_cast(event)->position().y(); +#endif x /= 8 * m_ui.magnification->value(); y /= 8 * m_ui.magnification->value(); selectTile(x, y); diff --git a/src/platform/qt/MemoryAccessLogView.cpp b/src/platform/qt/MemoryAccessLogView.cpp index 0c9325ed3..3c846b440 100644 --- a/src/platform/qt/MemoryAccessLogView.cpp +++ b/src/platform/qt/MemoryAccessLogView.cpp @@ -8,6 +8,7 @@ #include #include "GBAApp.h" +#include "LogController.h" #include "utils.h" #include "VFileDevice.h" @@ -15,7 +16,7 @@ using namespace QGBA; MemoryAccessLogView::MemoryAccessLogView(std::shared_ptr controller, QWidget* parent) : QWidget(parent) - , m_controller(controller) + , m_controller(std::move(controller)) { m_ui.setupUi(this); @@ -78,7 +79,7 @@ void MemoryAccessLogView::start() { m_controller->attachDebuggerModule(&m_logger.d); if (!mDebuggerAccessLoggerOpen(&m_logger, vf, flags)) { mDebuggerAccessLoggerDeinit(&m_logger); - // log error + LOG(QT, ERROR) << tr("Failed to open memory log file"); return; } diff --git a/src/platform/qt/MemoryAccessLogView.h b/src/platform/qt/MemoryAccessLogView.h index 896ba5a07..ffe31cc43 100644 --- a/src/platform/qt/MemoryAccessLogView.h +++ b/src/platform/qt/MemoryAccessLogView.h @@ -44,7 +44,7 @@ private: QSet m_watchedRegions; QHash m_regionBoxes; QHash m_regionMapping; - struct mDebuggerAccessLogger m_logger; + struct mDebuggerAccessLogger m_logger{}; bool m_active = false; mDebuggerAccessLogRegionFlags activeFlags() const; diff --git a/src/platform/qt/MemoryDump.cpp b/src/platform/qt/MemoryDump.cpp index 982353ee2..59cef31be 100644 --- a/src/platform/qt/MemoryDump.cpp +++ b/src/platform/qt/MemoryDump.cpp @@ -13,7 +13,7 @@ using namespace QGBA; MemoryDump::MemoryDump(std::shared_ptr controller, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) - , m_controller(controller) + , m_controller(std::move(controller)) { m_ui.setupUi(this); @@ -117,4 +117,4 @@ QByteArray MemoryDump::serialize() { } return mem; -} \ No newline at end of file +} diff --git a/src/platform/qt/MemoryModel.cpp b/src/platform/qt/MemoryModel.cpp index 538ce2c51..9bcf54223 100644 --- a/src/platform/qt/MemoryModel.cpp +++ b/src/platform/qt/MemoryModel.cpp @@ -511,8 +511,13 @@ void MemoryModel::wheelEvent(QWheelEvent* event) { } void MemoryModel::mousePressEvent(QMouseEvent* event) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (event->x() < m_margins.left() || event->y() < m_margins.top() || event->x() > size().width() - m_margins.right()) { +#else + if (event->position().x() < m_margins.left() || event->position().y() < m_margins.top() || + event->position().x() > size().width() - m_margins.right()) { +#endif m_selection = qMakePair(0, 0); return; } @@ -540,8 +545,13 @@ void MemoryModel::mousePressEvent(QMouseEvent* event) { } void MemoryModel::mouseMoveEvent(QMouseEvent* event) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (event->x() < m_margins.left() || event->y() < m_margins.top() || event->x() > size().width() - m_margins.right()) { +#else + if (event->position().x() < m_margins.left() || event->position().y() < m_margins.top() || + event->position().x() > size().width() - m_margins.right()) { +#endif return; } diff --git a/src/platform/qt/MemorySearch.cpp b/src/platform/qt/MemorySearch.cpp index 34f87fe14..7a8446887 100644 --- a/src/platform/qt/MemorySearch.cpp +++ b/src/platform/qt/MemorySearch.cpp @@ -21,7 +21,7 @@ MemorySearch::MemorySearch(std::shared_ptr controller, QWidget* mCoreMemorySearchResultsInit(&m_results, 0); connect(m_ui.search, &QPushButton::clicked, this, &MemorySearch::search); - connect(m_ui.value, &QLineEdit::returnPressed, this, &MemorySearch::search); + connect(m_ui.value, &QLineEdit::returnPressed, this, &MemorySearch::search); connect(m_ui.searchWithin, &QPushButton::clicked, this, &MemorySearch::searchWithin); connect(m_ui.refresh, &QPushButton::clicked, this, &MemorySearch::refresh); connect(m_ui.numHex, &QPushButton::clicked, this, &MemorySearch::refresh); diff --git a/src/platform/qt/MultiplayerController.cpp b/src/platform/qt/MultiplayerController.cpp index 7ded956a4..e95498fad 100644 --- a/src/platform/qt/MultiplayerController.cpp +++ b/src/platform/qt/MultiplayerController.cpp @@ -7,6 +7,7 @@ #include "CoreController.h" #include "LogController.h" +#include "utils.h" #ifdef M_CORE_GBA #include @@ -27,8 +28,14 @@ MultiplayerController::Player::Player(CoreController* coreController) int MultiplayerController::Player::id() const { switch (controller->platform()) { #ifdef M_CORE_GBA - case mPLATFORM_GBA: - return node.gba->id; + case mPLATFORM_GBA: { + int id = node.gba->d.deviceId(&node.gba->d); + if (id >= 0) { + return id; + } else { + return preferredId; + } + } #endif #ifdef M_CORE_GB case mPLATFORM_GB: @@ -89,25 +96,7 @@ MultiplayerController::MultiplayerController() { switch (player->controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - if (!id) { - for (int i = 1; i < controller->m_players.count(); ++i) { - player = controller->player(i); - if (player->node.gba->d.p->mode > SIO_MULTI) { - player->controller->setSync(true); - continue; - } - player->controller->setSync(false); - player->cyclesPosted += cycles; - if (player->awake < 1) { - player->node.gba->nextEvent += player->cyclesPosted; - } - mCoreThreadStopWaiting(player->controller->thread()); - player->awake = 1; - } - } else { - player->controller->setSync(true); - player->cyclesPosted += cycles; - } + abort(); break; #endif #ifdef M_CORE_GB @@ -169,7 +158,6 @@ MultiplayerController::MultiplayerController() { switch (player->controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - player->cyclesPosted += reinterpret_cast(lockstep)->players[0]->eventDiff; break; #endif #ifdef M_CORE_GB @@ -184,7 +172,6 @@ MultiplayerController::MultiplayerController() { switch (player->controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - player->node.gba->nextEvent += player->cyclesPosted; break; #endif #ifdef M_CORE_GB @@ -205,6 +192,9 @@ MultiplayerController::MultiplayerController() { MultiplayerController::~MultiplayerController() { mLockstepDeinit(&m_lockstep); + if (m_platform == mPLATFORM_GBA) { + GBASIOLockstepCoordinatorDeinit(&m_gbaCoordinator); + } } bool MultiplayerController::attachGame(CoreController* controller) { @@ -214,11 +204,12 @@ bool MultiplayerController::attachGame(CoreController* controller) { interrupters.append(p.controller); } - if (m_lockstep.attached == 0) { + bool doDelayedAttach = false; + if (m_platform == mPLATFORM_NONE) { switch (controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - GBASIOLockstepInit(&m_gbaLockstep); + GBASIOLockstepCoordinatorInit(&m_gbaCoordinator); break; #endif #ifdef M_CORE_GB @@ -240,28 +231,50 @@ bool MultiplayerController::attachGame(CoreController* controller) { } Player player{controller}; + for (int i = 0; i < MAX_GBAS; ++i) { + if (m_claimedIds & (1 << i)) { + continue; + } + player.preferredId = i; + m_claimedIds |= 1 << i; + break; + } switch (controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: { - if (m_lockstep.attached >= MAX_GBAS) { + if (attached() >= MAX_GBAS) { return false; } - GBA* gba = static_cast(thread->core->board); + GBASIOLockstepDriver* node = new GBASIOLockstepDriver; + LockstepUser* user = new LockstepUser; + mLockstepThreadUserInit(user, thread); + user->controller = this; + user->pid = m_nextPid; + user->d.requestedId = [](mLockstepUser* ctx) { + mLockstepThreadUser* tctx = reinterpret_cast(ctx); + LockstepUser* user = static_cast(tctx); + MultiplayerController* controller = user->controller; + const auto iter = controller->m_pids.find(user->pid); + if (iter == controller->m_pids.end()) { + return -1; + } + const Player& p = iter.value(); + return p.preferredId; + }; - GBASIOLockstepNode* node = new GBASIOLockstepNode; - GBASIOLockstepNodeCreate(node); - GBASIOLockstepAttachNode(&m_gbaLockstep, node); + GBASIOLockstepDriverCreate(node, &user->d); player.node.gba = node; - GBASIOSetDriver(&gba->sio, &node->d, SIO_MULTI); - GBASIOSetDriver(&gba->sio, &node->d, SIO_NORMAL_32); + if (m_pids.size()) { + doDelayedAttach = true; + } break; } #endif #ifdef M_CORE_GB case mPLATFORM_GB: { - if (m_lockstep.attached >= 2) { + if (attached() >= 2) { return false; } @@ -271,6 +284,7 @@ bool MultiplayerController::attachGame(CoreController* controller) { GBSIOLockstepNodeCreate(node); GBSIOLockstepAttachNode(&m_gbLockstep, node); player.node.gb = node; + player.attached = true; GBSIOSetDriver(&gb->sio, &node->d); break; @@ -281,7 +295,7 @@ bool MultiplayerController::attachGame(CoreController* controller) { } QPair path(controller->path(), controller->baseDirectory()); - int claimed = m_claimed[path]; + int claimed = m_claimedSaves[path]; int saveId = 0; mCoreConfigGetIntValue(&controller->thread()->core->config, "savePlayerId", &saveId); @@ -304,12 +318,25 @@ bool MultiplayerController::attachGame(CoreController* controller) { } else { player.saveId = 1; } - m_claimed[path] |= 1 << (player.saveId - 1); + m_claimedSaves[path] |= 1 << (player.saveId - 1); m_pids.insert(m_nextPid, player); ++m_nextPid; fixOrder(); + if (doDelayedAttach) { + for (auto pid: m_players) { + Player& player = m_pids.find(pid).value(); + if (player.attached) { + continue; + } + struct mCore* core = player.controller->thread()->core; + GBASIOLockstepCoordinatorAttach(&m_gbaCoordinator, player.node.gba); + core->setPeripheral(core, mPERIPH_GBA_LINK_PORT, &player.node.gba->d); + player.attached = true; + } + } + emit gameAttached(); return true; } @@ -328,8 +355,7 @@ void MultiplayerController::detachGame(CoreController* controller) { for (int i = 0; i < m_players.count(); ++i) { Player* p = player(i); if (!p) { - LOG(QT, ERROR) << tr("Trying to detach a multiplayer player that's not attached"); - return; + continue; } CoreController* playerController = p->controller; if (playerController == controller) { @@ -337,17 +363,24 @@ void MultiplayerController::detachGame(CoreController* controller) { } interrupters.append(playerController); } + if (pid < 0) { + LOG(QT, WARN) << tr("Trying to detach a multiplayer player that's not attached"); + return; + } switch (controller->platform()) { #ifdef M_CORE_GBA case mPLATFORM_GBA: { GBA* gba = static_cast(thread->core->board); - GBASIOLockstepNode* node = reinterpret_cast(gba->sio.drivers.multiplayer); - GBASIOSetDriver(&gba->sio, nullptr, SIO_MULTI); - GBASIOSetDriver(&gba->sio, nullptr, SIO_NORMAL_32); - if (node) { - GBASIOLockstepDetachNode(&m_gbaLockstep, node); - delete node; + Player& p = m_pids.find(pid).value(); + GBASIODriver* node = gba->sio.driver; + if (node == &p.node.gba->d) { + thread->core->setPeripheral(thread->core, mPERIPH_GBA_LINK_PORT, NULL); } + if (p.attached) { + GBASIOLockstepCoordinatorDetach(&m_gbaCoordinator, p.node.gba); + } + delete reinterpret_cast(p.node.gba->user); + delete p.node.gba; break; } #endif @@ -371,16 +404,25 @@ void MultiplayerController::detachGame(CoreController* controller) { QPair path(controller->path(), controller->baseDirectory()); Player& p = m_pids.find(pid).value(); if (!p.saveId) { - LOG(QT, ERROR) << "Clearing invalid save ID"; + LOG(QT, WARN) << tr("Clearing invalid save ID"); } else { - m_claimed[path] &= ~(1 << (p.saveId - 1)); - if (!m_claimed[path]) { - m_claimed.remove(path); + m_claimedSaves[path] &= ~(1 << (p.saveId - 1)); + if (!m_claimedSaves[path]) { + m_claimedSaves.remove(path); } } + if (p.preferredId < 0) { + LOG(QT, WARN) << tr("Clearing invalid preferred ID"); + } else { + m_claimedIds &= ~(1 << p.preferredId); + } + m_pids.remove(pid); if (m_pids.size() == 0) { + if (m_platform == mPLATFORM_GBA) { + GBASIOLockstepCoordinatorDeinit(&m_gbaCoordinator); + } m_platform = mPLATFORM_NONE; } else { fixOrder(); @@ -417,8 +459,17 @@ int MultiplayerController::saveId(CoreController* controller) const { } int MultiplayerController::attached() { - int num; - num = m_lockstep.attached; + int num = 0; + switch (m_platform) { + case mPLATFORM_GB: + num = m_lockstep.attached; + break; + case mPLATFORM_GBA: + num = saturateCast(GBASIOLockstepCoordinatorAttached(&m_gbaCoordinator)); + break; + default: + break; + } return num; } @@ -453,12 +504,13 @@ void MultiplayerController::fixOrder() { switch (m_platform) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - for (int pid : m_pids.keys()) { + // TODO: fix + /*for (int pid : m_pids.keys()) { Player& p = m_pids.find(pid).value(); GBA* gba = static_cast(p.controller->thread()->core->board); - GBASIOLockstepNode* node = reinterpret_cast(gba->sio.drivers.multiplayer); - m_players[node->id] = pid; - } + GBASIOLockstepDriver* node = reinterpret_cast(gba->sio.driver); + m_players[node->d.deviceId(&node->d)] = pid; + }*/ break; #endif #ifdef M_CORE_GB diff --git a/src/platform/qt/MultiplayerController.h b/src/platform/qt/MultiplayerController.h index b5582319f..666cb390b 100644 --- a/src/platform/qt/MultiplayerController.h +++ b/src/platform/qt/MultiplayerController.h @@ -49,7 +49,7 @@ signals: private: union Node { GBSIOLockstepNode* gb; - GBASIOLockstepNode* gba; + GBASIOLockstepDriver* gba; }; struct Player { Player(CoreController* controller); @@ -63,6 +63,12 @@ private: int32_t cyclesPosted = 0; unsigned waitMask = 0; int saveId = 1; + int preferredId = 0; + bool attached = false; + }; + struct LockstepUser : mLockstepThreadUser { + MultiplayerController* controller; + int pid; }; Player* player(int id); @@ -73,18 +79,20 @@ private: mLockstep m_lockstep; #ifdef M_CORE_GB GBSIOLockstep m_gbLockstep; -#endif -#ifdef M_CORE_GBA - GBASIOLockstep m_gbaLockstep; #endif }; +#ifdef M_CORE_GBA + GBASIOLockstepCoordinator m_gbaCoordinator; +#endif + mPlatform m_platform = mPLATFORM_NONE; int m_nextPid = 0; + int m_claimedIds = 0; QHash m_pids; QList m_players; QMutex m_lock; - QHash, int> m_claimed; + QHash, int> m_claimedSaves; }; } diff --git a/src/platform/qt/ObjView.cpp b/src/platform/qt/ObjView.cpp index f4482aba6..a29c621fb 100644 --- a/src/platform/qt/ObjView.cpp +++ b/src/platform/qt/ObjView.cpp @@ -138,7 +138,7 @@ void ObjView::updateTilesGBA(bool force) { for (unsigned y = 0; y < newInfo.height; ++y) { for (unsigned x = 0; x < newInfo.width; ++x, ++i, ++tile, ++tileBase) { if (tile < maxTiles) { - const color_t* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[16 * tileBase], tile, newInfo.paletteId); + const mColor* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[16 * tileBase], tile, newInfo.paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { @@ -233,7 +233,7 @@ void ObjView::updateTilesGB(bool force) { m_ui.tile->setPalette(newInfo.paletteId); for (unsigned y = 0; y < newInfo.height; ++y, ++i) { unsigned t = tile + i; - const color_t* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[8 * t], t, newInfo.paletteId); + const mColor* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[8 * t], t, newInfo.paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { diff --git a/src/platform/qt/OverrideView.cpp b/src/platform/qt/OverrideView.cpp index 07e114c1c..bec404a00 100644 --- a/src/platform/qt/OverrideView.cpp +++ b/src/platform/qt/OverrideView.cpp @@ -153,14 +153,13 @@ void OverrideView::updateOverrides() { if (m_ui.tabWidget->currentWidget() == m_ui.tabGBA) { auto gba = std::make_unique(); memset(gba->override.id, 0, 4); - gba->override.savetype = static_cast(m_ui.savetype->currentIndex() - 1); + gba->override.savetype = static_cast(m_ui.savetype->currentIndex() - 1); gba->override.hardware = HW_NO_OVERRIDE; - gba->override.idleLoop = IDLE_LOOP_NONE; - gba->override.mirroring = false; + gba->override.idleLoop = GBA_IDLE_LOOP_NONE; gba->override.vbaBugCompat = false; gba->vbaBugCompatSet = false; - if (gba->override.savetype != SAVEDATA_AUTODETECT) { + if (gba->override.savetype != GBA_SAVEDATA_AUTODETECT) { hasOverride = true; } if (!m_ui.hwAutodetect->isChecked()) { @@ -246,7 +245,7 @@ void OverrideView::gameStarted() { m_ui.hwGBPlayer->setChecked(gba->memory.hw.devices & HW_GB_PLAYER_DETECTION); m_ui.vbaBugCompat->setChecked(gba->vbaBugCompat); - if (gba->idleLoop != IDLE_LOOP_NONE) { + if (gba->idleLoop != GBA_IDLE_LOOP_NONE) { m_ui.idleLoop->setText(QString::number(gba->idleLoop, 16)); } else { m_ui.idleLoop->clear(); diff --git a/src/platform/qt/PlacementControl.cpp b/src/platform/qt/PlacementControl.cpp index fc031d019..0011dff5f 100644 --- a/src/platform/qt/PlacementControl.cpp +++ b/src/platform/qt/PlacementControl.cpp @@ -15,7 +15,7 @@ using namespace QGBA; PlacementControl::PlacementControl(std::shared_ptr controller, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) - , m_controller(controller) + , m_controller(std::move(controller)) { m_ui.setupUi(this); diff --git a/src/platform/qt/ROMInfo.cpp b/src/platform/qt/ROMInfo.cpp index 473918f26..25aafeda8 100644 --- a/src/platform/qt/ROMInfo.cpp +++ b/src/platform/qt/ROMInfo.cpp @@ -24,21 +24,23 @@ ROMInfo::ROMInfo(std::shared_ptr controller, QWidget* parent) const NoIntroDB* db = GBAApp::app()->gameDB(); #endif uint32_t crc32 = 0; + uint8_t md5[16]{}; CoreController::Interrupter interrupter(controller); mCore* core = controller->thread()->core; - char title[17] = {}; - core->getGameTitle(core, title); - m_ui.title->setText(QLatin1String(title)); - title[8] = '\0'; - core->getGameCode(core, title); - if (title[0]) { - m_ui.id->setText(QLatin1String(title)); + mGameInfo info; + core->getGameInfo(core, &info); + m_ui.title->setText(QLatin1String(info.title)); + if (info.code[0]) { + m_ui.id->setText(QLatin1String(info.code)); } else { m_ui.id->setText(tr("(unknown)")); } + m_ui.maker->setText(QLatin1String(info.maker)); + m_ui.version->setText(QString::number(info.version)); core->checksum(core, &crc32, mCHECKSUM_CRC32); + core->checksum(core, &md5, mCHECKSUM_MD5); m_ui.size->setText(QString::number(core->romSize(core)) + tr(" bytes")); @@ -63,6 +65,10 @@ ROMInfo::ROMInfo(std::shared_ptr controller, QWidget* parent) m_ui.name->setText(tr("(unknown)")); } + m_ui.md5->setText(QString::asprintf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + md5[0x0], md5[0x1], md5[0x2], md5[0x3], md5[0x4], md5[0x5], md5[0x6], md5[0x7], + md5[0x8], md5[0x9], md5[0xA], md5[0xB], md5[0xC], md5[0xD], md5[0xE], md5[0xF])); + QString savePath = controller->savePath(); if (!savePath.isEmpty()) { m_ui.savefile->setText(savePath); diff --git a/src/platform/qt/ROMInfo.ui b/src/platform/qt/ROMInfo.ui index 727cff032..a4a179ca8 100644 --- a/src/platform/qt/ROMInfo.ui +++ b/src/platform/qt/ROMInfo.ui @@ -6,120 +6,186 @@ 0 0 - 236 - 146 + 180 + 298 ROM Info - + QLayout::SetFixedSize - - QFormLayout::FieldsStayAtSizeHint - - - - Game name: - - - - - - - {NAME} - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + File information + + + + + Game name: + + + + + + + {NAME} + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + File size: + + + + + + + {SIZE} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + CRC32: + + + + + + + {CRC} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + MD5 + + + + + + + {MD5} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Save file: + + + + + + + {SAVEFILE} + + + + - - - Internal name: - - - - - - - {TITLE} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Game ID: - - - - - - - {ID} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - File size: - - - - - - - {SIZE} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - CRC32: - - - - - - - {CRC} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Save file: - - - - - - - {SAVEFILE} + + + ROM header + + + + + Internal name: + + + + + + + {TITLE} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Game ID: + + + + + + + {ID} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Maker Code: + + + + + + + {MAKER} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Revision: + + + + + + + {VERSION} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + diff --git a/src/platform/qt/ReportView.cpp b/src/platform/qt/ReportView.cpp index 04944ef5c..9843cae76 100644 --- a/src/platform/qt/ReportView.cpp +++ b/src/platform/qt/ReportView.cpp @@ -497,17 +497,16 @@ void ReportView::addROMInfo(QStringList& report, CoreController* controller) { report << QString("Currently paused: %1").arg(yesNo[controller->isPaused()]); mCore* core = controller->thread()->core; - char title[17] = {}; - core->getGameTitle(core, title); - report << QString("Internal title: %1").arg(QLatin1String(title)); - - title[8] = '\0'; - core->getGameCode(core, title); - if (title[0]) { - report << QString("Game code: %1").arg(QLatin1String(title)); + struct mGameInfo info; + core->getGameInfo(core, &info); + report << QString("Internal title: %1").arg(QLatin1String(info.title)); + if (info.code[0]) { + report << QString("Game code: %1").arg(QLatin1String(info.code)); } else { report << QString("Invalid game code"); } + report << QString("Game maker: %1").arg(QLatin1String(info.maker)); + report << QString("Game version: %1").arg(info.version); uint32_t crc32 = 0; core->checksum(core, &crc32, mCHECKSUM_CRC32); diff --git a/src/platform/qt/SaveConverter.cpp b/src/platform/qt/SaveConverter.cpp index 44e061c8f..205a7563d 100644 --- a/src/platform/qt/SaveConverter.cpp +++ b/src/platform/qt/SaveConverter.cpp @@ -86,18 +86,18 @@ void SaveConverter::refreshInputTypes() { m_validSaves.clear(); m_ui.inputType->clear(); if (m_ui.inputFile->text().isEmpty()) { - m_ui.inputType->addItem(tr("No file selected")); + m_ui.inputType->addItem(tr("No file selected")); m_ui.inputType->setEnabled(false); return; } std::shared_ptr vf = std::make_shared(m_ui.inputFile->text(), QIODevice::ReadOnly); if (!vf->isOpen()) { - m_ui.inputType->addItem(tr("Could not open file")); + m_ui.inputType->addItem(tr("Could not open file")); m_ui.inputType->setEnabled(false); return; } - + detectFromSavestate(*vf); detectFromSize(vf); detectFromHeaders(vf); @@ -108,7 +108,7 @@ void SaveConverter::refreshInputTypes() { if (m_validSaves.count()) { m_ui.inputType->setEnabled(true); } else { - m_ui.inputType->addItem(tr("No valid formats found")); + m_ui.inputType->addItem(tr("No valid formats found")); m_ui.inputType->setEnabled(false); } } @@ -127,7 +127,7 @@ void SaveConverter::refreshOutputTypes() { if (m_validOutputs.count()) { m_ui.outputType->setEnabled(true); } else { - m_ui.outputType->addItem(tr("No valid conversions found")); + m_ui.outputType->addItem(tr("No valid conversions found")); m_ui.outputType->setEnabled(false); } checkCanConvert(); @@ -170,8 +170,8 @@ void SaveConverter::detectFromSavestate(VFile* vf) { switch (platform) { #ifdef M_CORE_GBA case mPLATFORM_GBA: - save.gba.type = static_cast(state.at(offsetof(GBASerializedState, savedata.type))); - if (save.gba.type == SAVEDATA_EEPROM || save.gba.type == SAVEDATA_EEPROM512) { + save.gba.type = static_cast(state.at(offsetof(GBASerializedState, savedata.type))); + if (save.gba.type == GBA_SAVEDATA_EEPROM || save.gba.type == GBA_SAVEDATA_EEPROM512) { save.endianness = Endian::LITTLE; } break; @@ -198,25 +198,25 @@ void SaveConverter::detectFromSize(std::shared_ptr vf) { switch (vf->size()) { case GBA_SIZE_SRAM: case GBA_SIZE_SRAM + 16: - m_validSaves.append(AnnotatedSave{SAVEDATA_SRAM, vf}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_SRAM, vf}); break; case GBA_SIZE_FLASH512: case GBA_SIZE_FLASH512 + 16: - m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH512, vf}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_FLASH512, vf}); break; case GBA_SIZE_FLASH1M: case GBA_SIZE_FLASH1M + 16: - m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH1M, vf}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_FLASH1M, vf}); break; case GBA_SIZE_EEPROM: case GBA_SIZE_EEPROM + 16: - m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, vf, Endian::LITTLE}); - m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, vf, Endian::BIG}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_EEPROM, vf, Endian::LITTLE}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_EEPROM, vf, Endian::BIG}); break; case GBA_SIZE_EEPROM512: case GBA_SIZE_EEPROM512 + 16: - m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, vf, Endian::LITTLE}); - m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, vf, Endian::BIG}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_EEPROM512, vf, Endian::LITTLE}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_EEPROM512, vf, Endian::BIG}); break; } #endif @@ -272,16 +272,16 @@ void SaveConverter::detectFromHeaders(std::shared_ptr vf) { QByteArray bytes = QByteArray::fromRawData(static_cast(data), size); bytes.data(); // Trigger a deep copy before we delete the backing if (size == GBA_SIZE_FLASH1M) { - m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH1M, std::make_shared(bytes), Endian::NONE, Container::SHARKPORT}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_FLASH1M, std::make_shared(bytes), Endian::NONE, Container::SHARKPORT}); } else { - m_validSaves.append(AnnotatedSave{SAVEDATA_SRAM, std::make_shared(bytes.left(GBA_SIZE_SRAM)), Endian::NONE, Container::SHARKPORT}); - m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH512, std::make_shared(bytes.left(GBA_SIZE_FLASH512)), Endian::NONE, Container::SHARKPORT}); - m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, std::make_shared(bytes.left(GBA_SIZE_EEPROM)), Endian::BIG, Container::SHARKPORT}); - m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, std::make_shared(bytes.left(GBA_SIZE_EEPROM512)), Endian::BIG, Container::SHARKPORT}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_SRAM, std::make_shared(bytes.left(GBA_SIZE_SRAM)), Endian::NONE, Container::SHARKPORT}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_FLASH512, std::make_shared(bytes.left(GBA_SIZE_FLASH512)), Endian::NONE, Container::SHARKPORT}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_EEPROM, std::make_shared(bytes.left(GBA_SIZE_EEPROM)), Endian::BIG, Container::SHARKPORT}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_EEPROM512, std::make_shared(bytes.left(GBA_SIZE_EEPROM512)), Endian::BIG, Container::SHARKPORT}); } free(data); } - } else if (buffer.left(gsv.count()) == gsv) { + } else if (buffer.left(gsv.size()) == gsv) { size_t size; void* data = GBASavedataGSVGetPayload(*vf, &size, nullptr, false); if (data) { @@ -289,20 +289,20 @@ void SaveConverter::detectFromHeaders(std::shared_ptr vf) { bytes.data(); // Trigger a deep copy before we delete the backing switch (size) { case GBA_SIZE_FLASH1M: - m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH1M, std::make_shared(bytes), Endian::NONE, Container::GSV}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_FLASH1M, std::make_shared(bytes), Endian::NONE, Container::GSV}); break; case GBA_SIZE_FLASH512: - m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH512, std::make_shared(bytes), Endian::NONE, Container::GSV}); - m_validSaves.append(AnnotatedSave{SAVEDATA_FLASH1M, std::make_shared(bytes), Endian::NONE, Container::GSV}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_FLASH512, std::make_shared(bytes), Endian::NONE, Container::GSV}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_FLASH1M, std::make_shared(bytes), Endian::NONE, Container::GSV}); break; case GBA_SIZE_SRAM: - m_validSaves.append(AnnotatedSave{SAVEDATA_SRAM, std::make_shared(bytes.left(GBA_SIZE_SRAM)), Endian::NONE, Container::GSV}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_SRAM, std::make_shared(bytes.left(GBA_SIZE_SRAM)), Endian::NONE, Container::GSV}); break; case GBA_SIZE_EEPROM: - m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM, std::make_shared(bytes.left(GBA_SIZE_EEPROM)), Endian::BIG, Container::GSV}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_EEPROM, std::make_shared(bytes.left(GBA_SIZE_EEPROM)), Endian::BIG, Container::GSV}); break; case GBA_SIZE_EEPROM512: - m_validSaves.append(AnnotatedSave{SAVEDATA_EEPROM512, std::make_shared(bytes.left(GBA_SIZE_EEPROM512)), Endian::BIG, Container::GSV}); + m_validSaves.append(AnnotatedSave{GBA_SAVEDATA_EEPROM512, std::make_shared(bytes.left(GBA_SIZE_EEPROM512)), Endian::BIG, Container::GSV}); break; } free(data); @@ -401,7 +401,7 @@ SaveConverter::AnnotatedSave::AnnotatedSave(mPlatform platform, std::shared_ptr< } #ifdef M_CORE_GBA -SaveConverter::AnnotatedSave::AnnotatedSave(SavedataType type, std::shared_ptr vf, Endian endianness, Container container) +SaveConverter::AnnotatedSave::AnnotatedSave(GBASavedataType type, std::shared_ptr vf, Endian endianness, Container container) : container(container) , platform(mPLATFORM_GBA) , size(vf->size()) @@ -468,15 +468,15 @@ SaveConverter::AnnotatedSave::operator QString() const { #ifdef M_CORE_GBA case mPLATFORM_GBA: switch (gba.type) { - case SAVEDATA_SRAM: + case GBA_SAVEDATA_SRAM: typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "SRAM"); break; - case SAVEDATA_FLASH512: - case SAVEDATA_FLASH1M: + case GBA_SAVEDATA_FLASH512: + case GBA_SAVEDATA_FLASH1M: typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 flash"); break; - case SAVEDATA_EEPROM: - case SAVEDATA_EEPROM512: + case GBA_SAVEDATA_EEPROM: + case GBA_SAVEDATA_EEPROM512: typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 EEPROM"); break; default: @@ -494,21 +494,21 @@ SaveConverter::AnnotatedSave::operator QString() const { if (size & 0xFF) { typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 SRAM + RTC"); } else { - typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 SRAM"); + typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "%1 SRAM"); } break; case GB_MBC2: if (size == 0x100) { typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "packed MBC2"); } else { - typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "unpacked MBC2"); + typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "unpacked MBC2"); } break; case GB_MBC6: if (size == GB_SIZE_MBC6_FLASH) { typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "MBC6 flash"); } else if (size > GB_SIZE_MBC6_FLASH) { - typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "MBC6 combined SRAM + flash"); + typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "MBC6 combined SRAM + flash"); } else { typeFormat = QCoreApplication::translate("QGBA::SaveConverter", "MBC6 SRAM"); } @@ -664,8 +664,8 @@ QByteArray SaveConverter::AnnotatedSave::convertTo(const SaveConverter::Annotate #ifdef M_CORE_GBA case mPLATFORM_GBA: switch (gba.type) { - case SAVEDATA_EEPROM: - case SAVEDATA_EEPROM512: + case GBA_SAVEDATA_EEPROM: + case GBA_SAVEDATA_EEPROM512: if (endianness == target.endianness) { break; } diff --git a/src/platform/qt/SaveConverter.h b/src/platform/qt/SaveConverter.h index 2fa133071..764e13d9c 100644 --- a/src/platform/qt/SaveConverter.h +++ b/src/platform/qt/SaveConverter.h @@ -48,7 +48,7 @@ private slots: private: #ifdef M_CORE_GBA struct GBASave { - SavedataType type; + GBASavedataType type; }; #endif #ifdef M_CORE_GB @@ -66,7 +66,7 @@ private: AnnotatedSave(); AnnotatedSave(mPlatform, std::shared_ptr, Endian = Endian::NONE, Container = Container::NONE); #ifdef M_CORE_GBA - AnnotatedSave(SavedataType, std::shared_ptr, Endian = Endian::NONE, Container = Container::NONE); + AnnotatedSave(GBASavedataType, std::shared_ptr, Endian = Endian::NONE, Container = Container::NONE); #endif #ifdef M_CORE_GB AnnotatedSave(GBMemoryBankControllerType, std::shared_ptr, Endian = Endian::NONE, Container = Container::NONE); diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 7f0fef53f..c86dcf06e 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -18,7 +18,7 @@ #ifdef M_CORE_GB #include "GameBoy.h" -#include +#include #endif #include @@ -26,6 +26,7 @@ #include #ifdef BUILD_SDL +#define SDL_MAIN_HANDLED #include "platform/sdl/sdl-events.h" #endif @@ -333,8 +334,13 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC GBAKeyEditor* buttonEditor = nullptr; #ifdef BUILD_SDL +#if SDL_VERSION_ATLEAST(2, 0, 0) + QString profile = inputController->profileForType(SDL_BINDING_CONTROLLER); + buttonEditor = new GBAKeyEditor(inputController, SDL_BINDING_CONTROLLER, profile); +#else QString profile = inputController->profileForType(SDL_BINDING_BUTTON); buttonEditor = new GBAKeyEditor(inputController, SDL_BINDING_BUTTON, profile); +#endif addPage(tr("Controllers"), buttonEditor, Page::CONTROLLERS); connect(m_ui.buttonBox, &QDialogButtonBox::accepted, buttonEditor, &GBAKeyEditor::save); #endif @@ -391,29 +397,38 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC shortcutView->setController(shortcutController); shortcutView->setInputController(inputController); addPage(tr("Shortcuts"), shortcutView, Page::SHORTCUTS); + +#if defined(BUILD_GLES2) || defined(USE_EPOXY) + m_dummyShader = new QLabel(tr("Shaders are not supported when the display driver is not OpenGL.\n\n" + "If it is set to OpenGL and you still see this, your graphics card or drivers may be too old.")); + m_dummyShader->setWordWrap(true); + m_dummyShader->setAlignment(Qt::AlignCenter); + addPage(tr("Shaders"), m_dummyShader, Page::SHADERS); +#endif } SettingsView::~SettingsView() { -#if defined(BUILD_GL) || defined(BUILD_GLES2) - setShaderSelector(nullptr); +#if defined(BUILD_GLES2) || defined(USE_EPOXY) + if (m_shader) { + m_shader->setParent(nullptr); + } #endif } void SettingsView::setShaderSelector(ShaderSelector* shaderSelector) { -#if defined(BUILD_GL) || defined(BUILD_GLES2) - if (m_shader) { - auto items = m_ui.tabs->findItems(tr("Shaders"), Qt::MatchFixedString); - for (const auto& item : items) { - m_ui.tabs->removeItemWidget(item); - } - m_ui.stackedWidget->removeWidget(m_shader); - m_shader->setParent(nullptr); +#if defined(BUILD_GLES2) || defined(USE_EPOXY) + auto items = m_ui.tabs->findItems(tr("Shaders"), Qt::MatchFixedString); + for (QListWidgetItem* item : items) { + delete item; + } + if (!m_shader) { + m_ui.stackedWidget->removeWidget(m_dummyShader); } m_shader = shaderSelector; if (shaderSelector) { - m_ui.stackedWidget->addWidget(m_shader); - m_ui.tabs->addItem(tr("Shaders")); - connect(m_ui.buttonBox, &QDialogButtonBox::accepted, m_shader, &ShaderSelector::saved); + addPage(tr("Shaders"), m_shader, Page::SHADERS); + } else { + addPage(tr("Shaders"), m_dummyShader, Page::SHADERS); } #endif } @@ -573,7 +588,6 @@ void SettingsView::updateConfig() { if (displayDriver != m_controller->getQtOption("displayDriver")) { m_controller->setQtOption("displayDriver", displayDriver); Display::setDriver(static_cast(displayDriver.toInt())); - setShaderSelector(nullptr); emit displayDriverChanged(); } @@ -601,12 +615,6 @@ void SettingsView::updateConfig() { emit languageChanged(); } - bool oldAudioHle = m_controller->getOption("gba.audioHle", "0") != "0"; - if (oldAudioHle != m_ui.audioHle->isChecked()) { - saveSetting("gba.audioHle", m_ui.audioHle); - emit audioHleChanged(); - } - if (m_ui.multiplayerAudioAll->isChecked()) { m_controller->setQtOption("multiplayerAudio", "all"); } else if (m_ui.multiplayerAudio1->isChecked()) { @@ -734,7 +742,6 @@ void SettingsView::reloadConfig() { loadSetting("logToStdout", m_ui.logToStdout); loadSetting("logFile", m_ui.logFile); loadSetting("useDiscordPresence", m_ui.useDiscordPresence); - loadSetting("gba.audioHle", m_ui.audioHle); loadSetting("dynamicTitle", m_ui.dynamicTitle, true); loadSetting("gba.forceGbp", m_ui.forceGbp); loadSetting("vbaBugCompat", m_ui.vbaBugCompat, true); diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h index 3543419fc..85cf35a99 100644 --- a/src/platform/qt/SettingsView.h +++ b/src/platform/qt/SettingsView.h @@ -51,8 +51,6 @@ public: SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, LogController* logController, QWidget* parent = nullptr); ~SettingsView(); - void setShaderSelector(ShaderSelector* shaderSelector); - signals: void biosLoaded(int platform, const QString&); void audioDriverChanged(); @@ -63,10 +61,10 @@ signals: void pathsChanged(); void languageChanged(); void libraryCleared(); - void audioHleChanged(); public slots: void selectPage(Page); + void setShaderSelector(ShaderSelector* shaderSelector); private slots: void selectBios(QLineEdit*); @@ -82,6 +80,7 @@ private: ConfigController* m_controller; InputController* m_input; ShaderSelector* m_shader = nullptr; + QLabel* m_dummyShader; LogConfigModel m_logModel; QTimer m_checkTimer; diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 42e4af5a0..8539e6bdb 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -1307,14 +1307,7 @@ - - - - XQ GBA audio (experimental) - - - - + OpenGL enhancements diff --git a/src/platform/qt/ShortcutController.cpp b/src/platform/qt/ShortcutController.cpp index 0ed445cd2..db7f27e6a 100644 --- a/src/platform/qt/ShortcutController.cpp +++ b/src/platform/qt/ShortcutController.cpp @@ -143,7 +143,7 @@ bool ShortcutController::eventFilter(QObject* obj, QEvent* event) { QKeyEvent* keyEvent = static_cast(event); #ifdef ENABLE_SCRIPTING if (m_scripting) { - m_scripting->event(obj, event); + m_scripting->scriptingEvent(obj, event); } #endif if (keyEvent->isAutoRepeat()) { @@ -165,7 +165,7 @@ bool ShortcutController::eventFilter(QObject* obj, QEvent* event) { if (event->type() == GamepadButtonEvent::Down()) { #ifdef ENABLE_SCRIPTING if (m_scripting) { - m_scripting->event(obj, event); + m_scripting->scriptingEvent(obj, event); } #endif auto item = m_buttons.find(static_cast(event)->value()); @@ -186,7 +186,7 @@ bool ShortcutController::eventFilter(QObject* obj, QEvent* event) { if (event->type() == GamepadButtonEvent::Up()) { #ifdef ENABLE_SCRIPTING if (m_scripting) { - m_scripting->event(obj, event); + m_scripting->scriptingEvent(obj, event); } #endif auto item = m_buttons.find(static_cast(event)->value()); @@ -224,7 +224,7 @@ bool ShortcutController::eventFilter(QObject* obj, QEvent* event) { #ifdef ENABLE_SCRIPTING if (event->type() == GamepadHatEvent::Type()) { if (m_scripting) { - m_scripting->event(obj, event); + m_scripting->scriptingEvent(obj, event); } } #endif @@ -326,7 +326,7 @@ void ShortcutController::loadProfile(const QString& profile) { m_profileName = profile; m_profile = InputProfile::findProfile(profile); onSubitems({}, [this](std::shared_ptr item) { - loadGamepadShortcuts(item); + loadGamepadShortcuts(std::move(item)); }); } diff --git a/src/platform/qt/ShortcutModel.cpp b/src/platform/qt/ShortcutModel.cpp index b73982cad..f90667935 100644 --- a/src/platform/qt/ShortcutModel.cpp +++ b/src/platform/qt/ShortcutModel.cpp @@ -28,11 +28,11 @@ QVariant ShortcutModel::data(const QModelIndex& index, int role) const { if (role != Qt::DisplayRole || !index.isValid()) { return QVariant(); } - const Item* item = static_cast(index.internalPointer()); - const Shortcut* shortcut = item->shortcut; + const Item& item = m_cache[index.internalId()]; + const Shortcut* shortcut = item.shortcut; switch (index.column()) { case 0: - return m_controller->visibleName(item->name); + return m_controller->visibleName(item.name); case 1: return shortcut ? keyName(shortcut->shortcut()) : QVariant(); case 2: @@ -77,28 +77,31 @@ QVariant ShortcutModel::headerData(int section, Qt::Orientation orientation, int QModelIndex ShortcutModel::index(int row, int column, const QModelIndex& parent) const { QString pmenu; if (parent.isValid()) { - pmenu = static_cast(parent.internalPointer())->name; + const Item& item = m_cache[parent.internalId()]; + pmenu = item.name; } QString name = m_controller->name(row, pmenu); - Item* item = &m_cache[name]; - item->name = name; - item->shortcut = m_controller->shortcut(name); - return createIndex(row, column, item); + size_t hash = qHash(name); + Item& item = m_cache[hash]; + item.name = name; + item.shortcut = m_controller->shortcut(name); + return createIndex(row, column, hash); } QModelIndex ShortcutModel::parent(const QModelIndex& index) const { if (!index.isValid() || !index.internalPointer()) { return QModelIndex(); } - Item* item = static_cast(index.internalPointer()); - QString parent = m_controller->parent(item->name); + const Item& item = m_cache[index.internalId()]; + QString parent = m_controller->parent(item.name); if (parent.isNull()) { return QModelIndex(); } - Item* pitem = &m_cache[parent]; - pitem->name = parent; - pitem->shortcut = m_controller->shortcut(parent); - return createIndex(m_controller->indexIn(parent), 0, pitem); + size_t hash = qHash(parent); + Item& pitem = m_cache[hash]; + pitem.name = parent; + pitem.shortcut = m_controller->shortcut(parent); + return createIndex(m_controller->indexIn(parent), 0, hash); } int ShortcutModel::columnCount(const QModelIndex&) const { @@ -109,25 +112,26 @@ int ShortcutModel::rowCount(const QModelIndex& index) const { if (!index.isValid()) { return m_controller->count(); } - Item* item = static_cast(index.internalPointer()); - return m_controller->count(item->name); + const Item& item = m_cache[index.internalId()]; + return m_controller->count(item.name); } QString ShortcutModel::name(const QModelIndex& index) const { if (!index.isValid()) { return {}; } - Item* item = static_cast(index.internalPointer()); - return item->name; + const Item& item = m_cache[index.internalId()]; + return item.name; } void ShortcutModel::addRowNamed(const QString& name) { QString parent = m_controller->parent(name); - Item* item = &m_cache[parent]; - item->name = parent; - item->shortcut = m_controller->shortcut(parent); + size_t hash = qHash(name); + Item& item = m_cache[hash]; + item.name = parent; + item.shortcut = m_controller->shortcut(parent); int index = m_controller->indexIn(name); - beginInsertRows(createIndex(m_controller->indexIn(parent), 0, item), index, index + 1); + beginInsertRows(createIndex(m_controller->indexIn(parent), 0, hash), index, index + 1); endInsertRows(); } diff --git a/src/platform/qt/ShortcutModel.h b/src/platform/qt/ShortcutModel.h index 3eb3b1178..64a1d3301 100644 --- a/src/platform/qt/ShortcutModel.h +++ b/src/platform/qt/ShortcutModel.h @@ -44,7 +44,7 @@ private: const Shortcut* shortcut = nullptr; }; - mutable QHash m_cache; + mutable QHash m_cache; }; -} \ No newline at end of file +} diff --git a/src/platform/qt/ShortcutView.cpp b/src/platform/qt/ShortcutView.cpp index 5efbc4d62..f457263c5 100644 --- a/src/platform/qt/ShortcutView.cpp +++ b/src/platform/qt/ShortcutView.cpp @@ -54,6 +54,7 @@ void ShortcutView::setInputController(InputController* controller) { } m_input = controller; m_input->stealFocus(this); + m_ui.keyEdit->setInputController(controller); } void ShortcutView::load(const QModelIndex& index) { diff --git a/src/platform/qt/Swatch.cpp b/src/platform/qt/Swatch.cpp index 3eb85d780..f4a9ad7c3 100644 --- a/src/platform/qt/Swatch.cpp +++ b/src/platform/qt/Swatch.cpp @@ -56,8 +56,13 @@ void Swatch::paintEvent(QPaintEvent*) { } void Swatch::mousePressEvent(QMouseEvent* event) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) int x = event->x() / (m_size + 1); int y = event->y() / (m_size + 1); +#else + int x = event->position().x() / (m_size + 1); + int y = event->position().y() / (m_size + 1); +#endif emit indexPressed(y * m_dims.width() + x); } diff --git a/src/platform/qt/TilePainter.cpp b/src/platform/qt/TilePainter.cpp index c27ade72e..88f7b51b1 100644 --- a/src/platform/qt/TilePainter.cpp +++ b/src/platform/qt/TilePainter.cpp @@ -39,8 +39,13 @@ void TilePainter::resizeEvent(QResizeEvent*) { } void TilePainter::mousePressEvent(QMouseEvent* event) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) int x = event->x() / m_size; int y = event->y() / m_size; +#else + int x = event->position().x() / m_size; + int y = event->position().y() / m_size; +#endif int index = y * (width() / m_size) + x; if (index < m_tileCount) { emit indexPressed(index); @@ -57,7 +62,7 @@ void TilePainter::clearTile(int index) { update(r); } -void TilePainter::setTile(int index, const color_t* data) { +void TilePainter::setTile(int index, const mColor* data) { QPainter painter(&m_backing); int w = width() / m_size; int x = index % w; @@ -76,7 +81,7 @@ void TilePainter::setTileCount(int tiles) { int w = width() / m_size; int h = (tiles + w - 1) * m_size / w; setMinimumSize(m_size, h - (h % m_size)); - } else { + } else { int w = minimumSize().width() / m_size; if (!w) { w = 1; diff --git a/src/platform/qt/TilePainter.h b/src/platform/qt/TilePainter.h index 5ef4b0555..f1f4a86e0 100644 --- a/src/platform/qt/TilePainter.h +++ b/src/platform/qt/TilePainter.h @@ -23,7 +23,7 @@ public: public slots: void clearTile(int index); - void setTile(int index, const color_t*); + void setTile(int index, const mColor*); void setTileCount(int tiles); void setTileMagnification(int mag); diff --git a/src/platform/qt/TileView.cpp b/src/platform/qt/TileView.cpp index 7d8d1a71e..6ba409a0a 100644 --- a/src/platform/qt/TileView.cpp +++ b/src/platform/qt/TileView.cpp @@ -132,7 +132,7 @@ void TileView::updateTilesGBA(bool force) { if (m_ui.tilesBg->isChecked()) { m_ui.tiles->setTileCount(1024); } else if (m_ui.tilesObj->isChecked()) { - m_ui.tiles->setTileCount(512); + m_ui.tiles->setTileCount(512); } else { m_ui.tiles->setTileCount(1536); } @@ -142,7 +142,7 @@ void TileView::updateTilesGBA(bool force) { objOffset = 0; cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 1); for (int i = 0; i < 1024; ++i) { - const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, 0); + const mColor* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, 0); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { @@ -153,7 +153,7 @@ void TileView::updateTilesGBA(bool force) { if (!m_ui.tilesBg->isChecked()) { cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 3); for (int i = 1024; i < 1536; ++i) { - const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 1024, 0); + const mColor* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 1024, 0); if (data) { m_ui.tiles->setTile(i - objOffset, data); } else if (force) { @@ -165,7 +165,7 @@ void TileView::updateTilesGBA(bool force) { if (m_ui.tilesBg->isChecked()) { m_ui.tiles->setTileCount(2048); } else if (m_ui.tilesObj->isChecked()) { - m_ui.tiles->setTileCount(1024); + m_ui.tiles->setTileCount(1024); } else { m_ui.tiles->setTileCount(3072); } @@ -175,7 +175,7 @@ void TileView::updateTilesGBA(bool force) { objOffset = 0; cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0); for (int i = 0; i < 2048; ++i) { - const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, m_paletteId); + const mColor* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, m_paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { @@ -186,7 +186,7 @@ void TileView::updateTilesGBA(bool force) { if (!m_ui.tilesBg->isChecked()) { cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 2); for (int i = 2048; i < 3072; ++i) { - const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 2048, m_paletteId); + const mColor* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 2048, m_paletteId); if (data) { m_ui.tiles->setTile(i - objOffset, data); } else if (force) { @@ -205,7 +205,7 @@ void TileView::updateTilesGB(bool force) { m_ui.tiles->setTileCount(count); mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0); for (int i = 0; i < count; ++i) { - const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[8 * i], i, m_paletteId); + const mColor* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[8 * i], i, m_paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { diff --git a/src/platform/qt/VideoDumper.cpp b/src/platform/qt/VideoDumper.cpp index 7fdb433bb..913406a70 100644 --- a/src/platform/qt/VideoDumper.cpp +++ b/src/platform/qt/VideoDumper.cpp @@ -6,58 +6,66 @@ #include "VideoDumper.h" #include -#include using namespace QGBA; VideoDumper::VideoDumper(QObject* parent) +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) : QAbstractVideoSurface(parent) +#else + : QObject(parent) +#endif { } bool VideoDumper::present(const QVideoFrame& frame) { QVideoFrame mappedFrame(frame); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (!mappedFrame.map(QAbstractVideoBuffer::ReadOnly)) { return false; } - QVideoFrame::PixelFormat vFormat = mappedFrame.pixelFormat(); - QImage::Format format = QVideoFrame::imageFormatFromPixelFormat(vFormat); +#else + if (!mappedFrame.map(QVideoFrame::ReadOnly)) { + return false; + } +#endif + PixelFormat vFormat = mappedFrame.pixelFormat(); + QImage::Format format = imageFormatFromPixelFormat(vFormat); bool swap = false; #ifdef USE_FFMPEG bool useScaler = false; #endif if (format == QImage::Format_Invalid) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (vFormat < QVideoFrame::Format_BGRA5658_Premultiplied) { vFormat = static_cast(vFormat - QVideoFrame::Format_BGRA32 + QVideoFrame::Format_ARGB32); - format = QVideoFrame::imageFormatFromPixelFormat(vFormat); - if (format == QImage::Format_ARGB32) { - format = QImage::Format_RGBA8888; - } else if (format == QImage::Format_ARGB32_Premultiplied) { - format = QImage::Format_RGBA8888_Premultiplied; - } +#else + if (vFormat < PixelFormat::Format_AYUV) { +#endif + format = imageFormatFromPixelFormat(vFormat); swap = true; } else { #ifdef USE_FFMPEG enum AVPixelFormat pixelFormat; switch (vFormat) { - case QVideoFrame::Format_YUV420P: + case VideoDumper::PixelFormat::Format_YUV420P: pixelFormat = AV_PIX_FMT_YUV420P; break; #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - case QVideoFrame::Format_YUV422P: + case VideoDumper::PixelFormat::Format_YUV422P: pixelFormat = AV_PIX_FMT_YUV422P; break; #endif - case QVideoFrame::Format_YUYV: + case VideoDumper::PixelFormat::Format_YUYV: pixelFormat = AV_PIX_FMT_YUYV422; break; - case QVideoFrame::Format_UYVY: + case VideoDumper::PixelFormat::Format_UYVY: pixelFormat = AV_PIX_FMT_UYVY422; break; - case QVideoFrame::Format_NV12: + case VideoDumper::PixelFormat::Format_NV12: pixelFormat = AV_PIX_FMT_NV12; break; - case QVideoFrame::Format_NV21: + case VideoDumper::PixelFormat::Format_NV21: pixelFormat = AV_PIX_FMT_NV12; break; default: @@ -80,11 +88,15 @@ bool VideoDumper::present(const QVideoFrame& frame) { #endif } } - uchar* bits = mappedFrame.bits(); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + Direction direction = surfaceFormat().scanLineDirection(); +#else + Direction direction = mappedFrame.surfaceFormat().scanLineDirection(); +#endif #ifdef USE_FFMPEG QImage image; if (!useScaler) { - image = QImage(bits, mappedFrame.width(), mappedFrame.height(), mappedFrame.bytesPerLine(), format); + image = QImage(mappedFrame.bits(0), mappedFrame.width(), mappedFrame.height(), mappedFrame.bytesPerLine(0), format); } if (useScaler) { image = QImage(mappedFrame.width(), mappedFrame.height(), format); @@ -99,14 +111,14 @@ bool VideoDumper::present(const QVideoFrame& frame) { sws_scale(m_scaler, planes, strides, 0, mappedFrame.height(), &outBits, &outStride); } else #else - QImage image(bits, mappedFrame.width(), mappedFrame.height(), mappedFrame.bytesPerLine(), format); + QImage image(mappedFrame.bits(0), mappedFrame.width(), mappedFrame.height(), mappedFrame.bytesPerLine(0), format); #endif if (swap) { image = image.rgbSwapped(); - } else if (surfaceFormat().scanLineDirection() != QVideoSurfaceFormat::BottomToTop) { + } else if (direction != Direction::BottomToTop) { image = image.copy(); // Create a deep copy of the bits } - if (surfaceFormat().scanLineDirection() == QVideoSurfaceFormat::BottomToTop) { + if (direction == Direction::BottomToTop) { image = image.mirrored(); } mappedFrame.unmap(); @@ -114,29 +126,63 @@ bool VideoDumper::present(const QVideoFrame& frame) { return true; } +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) QList VideoDumper::supportedPixelFormats(QAbstractVideoBuffer::HandleType) const { - QList list; - list.append(QVideoFrame::Format_RGB32); - list.append(QVideoFrame::Format_ARGB32); - list.append(QVideoFrame::Format_RGB24); - list.append(QVideoFrame::Format_ARGB32_Premultiplied); - list.append(QVideoFrame::Format_RGB565); - list.append(QVideoFrame::Format_RGB555); - list.append(QVideoFrame::Format_BGR32); - list.append(QVideoFrame::Format_BGRA32); - list.append(QVideoFrame::Format_BGR24); - list.append(QVideoFrame::Format_BGRA32_Premultiplied); - list.append(QVideoFrame::Format_BGR565); - list.append(QVideoFrame::Format_BGR555); + return VideoDumper::supportedPixelFormats(); +} +#endif + +QList VideoDumper::supportedPixelFormats() { + QList list{{ +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + VideoDumper::PixelFormat::Format_RGB32, + VideoDumper::PixelFormat::Format_ARGB32, + VideoDumper::PixelFormat::Format_RGB24, + VideoDumper::PixelFormat::Format_ARGB32_Premultiplied, + VideoDumper::PixelFormat::Format_RGB565, + VideoDumper::PixelFormat::Format_RGB555, + VideoDumper::PixelFormat::Format_BGR32, + VideoDumper::PixelFormat::Format_BGRA32, + VideoDumper::PixelFormat::Format_BGR24, + VideoDumper::PixelFormat::Format_BGRA32_Premultiplied, + VideoDumper::PixelFormat::Format_BGR565, + VideoDumper::PixelFormat::Format_BGR555, +#else + VideoDumper::PixelFormat::Format_XRGB8888, + VideoDumper::PixelFormat::Format_ARGB8888, + VideoDumper::PixelFormat::Format_ARGB8888_Premultiplied, + VideoDumper::PixelFormat::Format_RGBX8888, + VideoDumper::PixelFormat::Format_RGBA8888, + VideoDumper::PixelFormat::Format_XBGR8888, + VideoDumper::PixelFormat::Format_ABGR8888, + VideoDumper::PixelFormat::Format_BGRX8888, + VideoDumper::PixelFormat::Format_BGRA8888, + VideoDumper::PixelFormat::Format_BGRA8888_Premultiplied, +#endif #ifdef USE_FFMPEG - list.append(QVideoFrame::Format_YUYV); - list.append(QVideoFrame::Format_UYVY); + VideoDumper::PixelFormat::Format_YUYV, + VideoDumper::PixelFormat::Format_UYVY, #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - list.append(QVideoFrame::Format_YUV422P); + VideoDumper::PixelFormat::Format_YUV422P, #endif - list.append(QVideoFrame::Format_YUV420P); - list.append(QVideoFrame::Format_NV12); - list.append(QVideoFrame::Format_NV21); + VideoDumper::PixelFormat::Format_YUV420P, + VideoDumper::PixelFormat::Format_NV12, + VideoDumper::PixelFormat::Format_NV21, #endif + }}; return list; } + +QImage::Format VideoDumper::imageFormatFromPixelFormat(VideoDumper::PixelFormat vFormat) { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + QImage::Format format = QVideoFrame::imageFormatFromPixelFormat(vFormat); +#else + QImage::Format format = QVideoFrameFormat::imageFormatFromPixelFormat(vFormat); +#endif + if (format == QImage::Format_ARGB32) { + format = QImage::Format_RGBA8888; + } else if (format == QImage::Format_ARGB32_Premultiplied) { + format = QImage::Format_RGBA8888_Premultiplied; + } + return format; +} diff --git a/src/platform/qt/VideoDumper.h b/src/platform/qt/VideoDumper.h index c22688c2b..2dcceac0f 100644 --- a/src/platform/qt/VideoDumper.h +++ b/src/platform/qt/VideoDumper.h @@ -5,7 +5,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once +#include +#include +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #include +#include +#else +#include +#endif #ifdef USE_FFMPEG extern "C" { @@ -15,14 +22,38 @@ extern "C" { namespace QGBA { -class VideoDumper : public QAbstractVideoSurface { +class VideoDumper : public +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) +QAbstractVideoSurface +#else +QObject +#endif +{ Q_OBJECT public: +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + using PixelFormat = QVideoFrame::PixelFormat; + using Direction = QVideoSurfaceFormat::Direction; +#else + using PixelFormat = QVideoFrameFormat::PixelFormat; + using Direction = QVideoFrameFormat::Direction; +#endif + VideoDumper(QObject* parent = nullptr); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + QList supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const override; +#endif + static QList supportedPixelFormats(); + static QImage::Format imageFormatFromPixelFormat(PixelFormat); + +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) bool present(const QVideoFrame& frame) override; - QList supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override; +#else +public slots: + bool present(const QVideoFrame& frame); +#endif signals: void imageAvailable(const QImage& image); diff --git a/src/platform/qt/VideoProxy.cpp b/src/platform/qt/VideoProxy.cpp index 17168da0e..2b24e7121 100644 --- a/src/platform/qt/VideoProxy.cpp +++ b/src/platform/qt/VideoProxy.cpp @@ -48,12 +48,14 @@ VideoProxy::~VideoProxy() { void VideoProxy::attach(CoreController* controller) { CoreController::Interrupter interrupter(controller); + m_logContext = &controller->thread()->logger.d; controller->thread()->core->videoLogger = &m_logger; } void VideoProxy::detach(CoreController* controller) { CoreController::Interrupter interrupter(controller); if (controller->thread()->core->videoLogger == &m_logger) { + m_logContext = nullptr; controller->thread()->core->videoLogger = nullptr; } } @@ -64,11 +66,13 @@ void VideoProxy::setProxiedBackend(VideoBackend* backend) { } void VideoProxy::processData() { + mLogSetThreadLogger(m_logContext); mVideoLoggerRendererRun(&m_logger, false); m_fromThreadCond.wakeAll(); } void VideoProxy::processCommands() { + mLogSetThreadLogger(m_logContext); mVideoProxyBackendRun(&m_backend, false); } @@ -76,10 +80,9 @@ void VideoProxy::init() { } void VideoProxy::reset() { - m_mutex.lock(); + QMutexLocker locker(&m_mutex); RingFIFOClear(&m_dirtyQueue); m_toThreadCond.wakeAll(); - m_mutex.unlock(); } void VideoProxy::deinit() { @@ -89,13 +92,13 @@ bool VideoProxy::writeData(const void* data, size_t length) { while (!RingFIFOWrite(&m_dirtyQueue, data, length)) { if (QThread::currentThread() == thread()) { // We're on the main thread + mLogSetThreadLogger(m_logContext); mVideoLoggerRendererRun(&m_logger, false); } else { emit dataAvailable(); - m_mutex.lock(); + QMutexLocker locker(&m_mutex); m_toThreadCond.wakeAll(); m_fromThreadCond.wait(&m_mutex); - m_mutex.unlock(); } } return true; @@ -108,10 +111,9 @@ bool VideoProxy::readData(void* data, size_t length, bool block) { if (!block || read) { break; } - m_mutex.lock(); + QMutexLocker locker(&m_mutex); m_fromThreadCond.wakeAll(); m_toThreadCond.wait(&m_mutex); - m_mutex.unlock(); } return read; } @@ -126,9 +128,9 @@ void VideoProxy::postEvent(enum mVideoLoggerEvent event) { } void VideoProxy::handleEvent(int event) { - m_mutex.lock(); + QMutexLocker locker(&m_mutex); + mLogSetThreadLogger(m_logContext); m_logger.handleEvent(&m_logger, static_cast(event)); - m_mutex.unlock(); } void VideoProxy::lock() { @@ -140,10 +142,11 @@ void VideoProxy::unlock() { } void VideoProxy::wait() { - m_mutex.lock(); + QMutexLocker locker(&m_mutex); while (RingFIFOSize(&m_dirtyQueue)) { if (QThread::currentThread() == thread()) { // We're on the main thread + mLogSetThreadLogger(m_logContext); mVideoLoggerRendererRun(&m_logger, false); } else { emit dataAvailable(); @@ -151,7 +154,6 @@ void VideoProxy::wait() { m_fromThreadCond.wait(&m_mutex, 1); } } - m_mutex.unlock(); } void VideoProxy::wake(int y) { diff --git a/src/platform/qt/VideoProxy.h b/src/platform/qt/VideoProxy.h index 43bb280c3..8cb1020cd 100644 --- a/src/platform/qt/VideoProxy.h +++ b/src/platform/qt/VideoProxy.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -72,6 +73,7 @@ private: } m_logger; struct mVideoProxyBackend m_backend; + struct mLogger* m_logContext = nullptr; RingFIFO m_dirtyQueue; QMutex m_mutex; diff --git a/src/platform/qt/VideoView.h b/src/platform/qt/VideoView.h index 23b5ef034..9e3ab5ca2 100644 --- a/src/platform/qt/VideoView.h +++ b/src/platform/qt/VideoView.h @@ -75,7 +75,7 @@ private: QSize dims; Preset() {} - Preset(QString container, QString vcodec, QString acodec, int vbr, int abr, QSize dims = QSize()) + Preset(const QString& container, const QString& vcodec, const QString& acodec, int vbr, int abr, QSize dims = QSize()) : container(container) , vcodec(vcodec) , acodec(acodec) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 746f44aff..8dca02078 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -14,6 +14,10 @@ #include #include +#ifdef Q_OS_WIN +#include +#endif + #ifdef USE_SQLITE3 #include "ArchiveInspector.h" #include "library/LibraryController.h" @@ -123,7 +127,7 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi if (value.toBool()) { attachWidget(m_libraryView); } else { - attachWidget(m_screenWidget); + attachWidget(m_screenWidget); } } }, this); @@ -132,8 +136,8 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi ConfigOption* showFilenameInLibrary = m_config->addOption("showFilenameInLibrary"); showFilenameInLibrary->connect([this](const QVariant& value) { m_libraryView->setShowFilename(value.toBool()); - }, this); - m_config->updateOption("showFilenameInLibrary"); + }, this); + m_config->updateOption("showFilenameInLibrary"); ConfigOption* libraryStyle = m_config->addOption("libraryStyle"); libraryStyle->connect([this](const QVariant& value) { m_libraryView->setViewStyle(static_cast(value.toInt())); @@ -177,8 +181,13 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi #ifdef BUILD_SDL m_inputController.addInputDriver(std::make_shared(&m_inputController)); +#if SDL_VERSION_ATLEAST(2, 0, 0) + m_inputController.setGamepadDriver(SDL_BINDING_CONTROLLER); + m_inputController.setSensorDriver(SDL_BINDING_CONTROLLER); +#else m_inputController.setGamepadDriver(SDL_BINDING_BUTTON); m_inputController.setSensorDriver(SDL_BINDING_BUTTON); +#endif #endif m_shortcutController->setConfigController(m_config); @@ -206,7 +215,7 @@ void Window::argumentsPassed() { m_pendingState = args->savestate; } -#ifdef USE_GDB_STUB +#ifdef ENABLE_GDB_STUB if (args->debugGdb) { if (!m_gdbController) { m_gdbController = new GDBController(this); @@ -219,7 +228,7 @@ void Window::argumentsPassed() { } #endif -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS if (args->debugCli) { consoleOpen(); } @@ -247,6 +256,9 @@ void Window::argumentsPassed() { void Window::resizeFrame(const QSize& size) { QSize newSize(size); + if (!m_config->getOption("lockFrameSize").toInt()) { + m_savedSize = size; + } if (windowHandle()) { QRect geom = windowHandle()->screen()->availableGeometry(); if (newSize.width() > geom.width()) { @@ -535,18 +547,10 @@ void Window::openSettingsWindow(SettingsView::Page page) { connect(settingsWindow, &SettingsView::videoRendererChanged, this, &Window::changeRenderer); connect(settingsWindow, &SettingsView::languageChanged, this, &Window::mustRestart); connect(settingsWindow, &SettingsView::pathsChanged, this, &Window::reloadConfig); - connect(settingsWindow, &SettingsView::audioHleChanged, this, [this]() { - if (!m_controller) { - return; - } - if (m_controller->platform() != mPLATFORM_GBA) { - return; - } - mustReset(); - }); #ifdef USE_SQLITE3 connect(settingsWindow, &SettingsView::libraryCleared, m_libraryView, &LibraryController::clear); #endif + connect(this, &Window::shaderSelectorAdded, settingsWindow, &SettingsView::setShaderSelector); openView(settingsWindow); settingsWindow->selectPage(page); } @@ -602,7 +606,7 @@ std::function Window::openNamedControllerTView(std::unique_ptr* name, }; } -#ifdef USE_GDB_STUB +#ifdef ENABLE_GDB_STUB void Window::gdbOpen() { if (!m_gdbController) { m_gdbController = new GDBController(this); @@ -614,7 +618,7 @@ void Window::gdbOpen() { } #endif -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS void Window::consoleOpen() { if (!m_console) { m_console = new DebuggerConsoleController(this); @@ -718,6 +722,11 @@ void Window::showEvent(QShowEvent* event) { return; } m_wasOpened = true; +#ifdef Q_OS_WIN + HWND hwnd = reinterpret_cast(winId()); + DWM_WINDOW_CORNER_PREFERENCE cornerPref = DWMWCP_DONOTROUND; + DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, sizeof(cornerPref)); +#endif if (m_initialSize.isValid()) { resizeFrame(m_initialSize); } @@ -919,7 +928,11 @@ void Window::gameStarted() { #ifdef M_CORE_GBA if (m_controller->platform() == mPLATFORM_GBA) { QVariant eCardList = m_config->takeArgvOption(QString("ecard")); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (eCardList.canConvert(QMetaType::QStringList)) { +#else + if (QMetaType::canConvert(eCardList.metaType(), QMetaType(QMetaType::QStringList))) { +#endif m_controller->scanCards(eCardList.toStringList()); } } @@ -1038,7 +1051,12 @@ void Window::reloadDisplayDriver() { } #if defined(BUILD_GL) || defined(BUILD_GLES2) m_shaderView.reset(); - m_shaderView = std::make_unique(m_display.get(), m_config); + if (m_display->supportsShaders()) { + m_shaderView = std::make_unique(m_display.get(), m_config); + emit shaderSelectorAdded(m_shaderView.get()); + } else { + emit shaderSelectorAdded(nullptr); + } #endif connect(m_display.get(), &QGBA::Display::hideCursor, [this]() { @@ -1068,7 +1086,12 @@ void Window::reloadDisplayDriver() { m_display->setMinimumSize(GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS); #endif - m_display->setBackgroundImage(QImage{m_config->getOption("backgroundImage")}); + QString backgroundImage = m_config->getOption("backgroundImage"); + if (backgroundImage.isEmpty()) { + m_display->setBackgroundImage(QImage{}); + } else { + m_display->setBackgroundImage(QImage{backgroundImage}); + } if (!proxy) { proxy = std::make_shared(); @@ -1093,7 +1116,9 @@ void Window::reloadAudioDriver() { m_audioProcessor = std::unique_ptr(AudioProcessor::create()); m_audioProcessor->setInput(m_controller); m_audioProcessor->configure(m_config); - m_audioProcessor->start(); + if (!m_audioProcessor->start()) { + LOG(QT, WARN) << "Failed to start audio processor"; + } } void Window::changeRenderer() { @@ -1459,6 +1484,11 @@ void Window::setupMenu(QMenuBar* menubar) { }, "emu"); auto rewindHeld = m_actions.addHeldAction(tr("Rewind (held)"), "holdRewind", [this](bool held) { + // Prevent rewinding while the load/save state window is active + if (held && this->m_stateWindow != nullptr) { + return; + } + if (m_controller) { m_controller->setRewinding(held); } @@ -1515,15 +1545,30 @@ void Window::setupMenu(QMenuBar* menubar) { for (int i = 1; i <= 8; ++i) { auto setSize = m_actions.addAction(tr("%1×").arg(QString::number(i)), QString("frame.%1x").arg(QString::number(i)), [this, i]() { auto setSize = m_frameSizes[i]; - showNormal(); - QSize size(GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS); + bool lockFrameSize = m_config->getOption("lockFrameSize").toInt(); + if (!lockFrameSize) { + showNormal(); + } +#if defined(M_CORE_GBA) + QSize minimumSize = QSize(GBA_VIDEO_HORIZONTAL_PIXELS, GBA_VIDEO_VERTICAL_PIXELS); +#elif defined(M_CORE_GB) + QSize minimumSize = QSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); +#endif + QSize size; if (m_display) { size = m_display->contentSize(); } + if (size.isNull()) { + size = minimumSize; + } size *= i; m_savedScale = i; m_config->setOption("scaleMultiplier", i); // TODO: Port to other + m_savedSize = size; resizeFrame(size); + if (lockFrameSize) { + m_display->setMaximumSize(size); + } setSize->setActive(true); }, "frame"); setSize->setExclusive(true); @@ -1538,8 +1583,22 @@ void Window::setupMenu(QMenuBar* menubar) { #else fullscreenKeys = QKeySequence("Ctrl+F"); #endif + m_actions.addSeparator("frame"); m_actions.addAction(tr("Toggle fullscreen"), "fullscreen", this, &Window::toggleFullScreen, "frame", fullscreenKeys); + ConfigOption* lockFrameSize = m_config->addOption("lockFrameSize"); + lockFrameSize->addBoolean(tr("&Lock frame size"), &m_actions, "frame"); + lockFrameSize->connect([this](const QVariant& value) { + if (m_display) { + if (value.toBool()) { + m_display->setMaximumSize(m_display->size()); + } else { + m_display->setMaximumSize({}); + } + } + }, this); + m_config->updateOption("lockFrameSize"); + ConfigOption* lockAspectRatio = m_config->addOption("lockAspectRatio"); lockAspectRatio->addBoolean(tr("Lock aspect ratio"), &m_actions, "av"); lockAspectRatio->connect([this](const QVariant& value) { @@ -1612,7 +1671,7 @@ void Window::setupMenu(QMenuBar* menubar) { double nativeGB = double(GBA_ARM7TDMI_FREQUENCY) / double(VIDEO_TOTAL_LENGTH); fpsTargets[nativeGB] = fpsTargetOption->addValue(tr("Native (59.7275)"), nativeGB, &m_actions, "target"); - fpsTargetOption->connect([this, fpsTargets](const QVariant& value) { + fpsTargetOption->connect([this, fpsTargets = std::move(fpsTargets)](const QVariant& value) { reloadConfig(); for (auto iter = fpsTargets.begin(); iter != fpsTargets.end(); ++iter) { bool enableSignals = iter.value()->blockSignals(true); @@ -1670,14 +1729,14 @@ void Window::setupMenu(QMenuBar* menubar) { m_actions.addAction(tr("Make portable"), "makePortable", this, &Window::tryMakePortable, "tools"); m_actions.addSeparator("tools"); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS m_actions.addAction(tr("Open debugger console..."), "debuggerWindow", this, &Window::consoleOpen, "tools"); -#ifdef USE_GDB_STUB +#ifdef ENABLE_GDB_STUB auto gdbWindow = addGameAction(tr("Start &GDB server..."), "gdbWindow", this, &Window::gdbOpen, "tools"); m_platformActions.insert(mPLATFORM_GBA, gdbWindow); #endif #endif -#if defined(USE_DEBUGGERS) || defined(ENABLE_SCRIPTING) +#if defined(ENABLE_DEBUGGERS) || defined(ENABLE_SCRIPTING) m_actions.addSeparator("tools"); #endif @@ -1707,7 +1766,7 @@ void Window::setupMenu(QMenuBar* menubar) { addGameAction(tr("Search memory..."), "memorySearch", openControllerTView(), "stateViews"); addGameAction(tr("View &I/O registers..."), "ioViewer", openControllerTView(), "stateViews"); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS addGameAction(tr("Log memory &accesses..."), "memoryAccessView", openControllerTView(), "tools"); #endif @@ -1924,15 +1983,27 @@ void Window::setupOptions() { ConfigOption* backgroundImage = m_config->addOption("backgroundImage"); backgroundImage->connect([this](const QVariant& value) { if (m_display) { - m_display->setBackgroundImage(QImage{value.toString()}); + QString backgroundImage = value.toString(); + if (backgroundImage.isEmpty()) { + m_display->setBackgroundImage(QImage{}); + } else { + m_display->setBackgroundImage(QImage{backgroundImage}); + } } }, this); m_config->updateOption("backgroundImage"); } void Window::attachWidget(QWidget* widget) { + // Fix https://mgba.io/i/2885 -- seems like a Qt bug + if (m_display && widget != m_display.get()) { + m_display->hide(); + } takeCentralWidget(); setCentralWidget(widget); + if (m_display && widget == m_display.get()) { + m_display->show(); + } } void Window::detachWidget() { @@ -1975,7 +2046,7 @@ void Window::updateMRU() { } std::shared_ptr Window::addGameAction(const QString& visibleName, const QString& name, Action::Function function, const QString& menu, const QKeySequence& shortcut) { - auto action = m_actions.addAction(visibleName, name, [this, function]() { + auto action = m_actions.addAction(visibleName, name, [this, function = std::move(function)]() { if (m_controller) { function(); } @@ -1999,7 +2070,7 @@ std::shared_ptr Window::addGameAction(const QString& visibleName, const } std::shared_ptr Window::addGameAction(const QString& visibleName, const QString& name, Action::BooleanFunction function, const QString& menu, const QKeySequence& shortcut) { - auto action = m_actions.addBooleanAction(visibleName, name, [this, function](bool value) { + auto action = m_actions.addBooleanAction(visibleName, name, [this, function = std::move(function)](bool value) { if (m_controller) { function(value); } @@ -2112,19 +2183,23 @@ void Window::setController(CoreController* controller, const QString& fname) { #ifdef M_CORE_GBA if (m_controller->platform() == mPLATFORM_GBA) { QVariant mb = m_config->takeArgvOption(QString("mb")); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) if (mb.canConvert(QMetaType::QString)) { +#else + if (QMetaType::canConvert(mb.metaType(), QMetaType(QMetaType::QString))) { +#endif m_controller->replaceGame(mb.toString()); } } #endif -#ifdef USE_GDB_STUB +#ifdef ENABLE_GDB_STUB if (m_gdbController) { m_gdbController->setController(m_controller); } #endif -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS if (m_console) { m_console->setController(m_controller); } @@ -2177,11 +2252,28 @@ void Window::setController(CoreController* controller, const QString& fname) { m_controller->setPaused(true); m_pendingPause = false; } + +#ifdef ENABLE_SCRIPTING + if (!m_scripting) { + QStringList scripts = m_config->getArgvOption("script").toStringList(); + if (!scripts.isEmpty()) { + scriptingOpen(); + for (const auto& scriptPath : scripts) { + m_scripting->loadFile(scriptPath); + } + } + } +#endif } void Window::attachDisplay() { m_display->attach(m_controller); connect(m_display.get(), &QGBA::Display::drawingStarted, this, &Window::changeRenderer); + if (m_config->getOption("lockFrameSize").toInt()) { + m_display->setMaximumSize(m_savedSize); + } else { + m_display->setMaximumSize({}); + } m_display->startDrawing(m_controller); #ifdef ENABLE_SCRIPTING diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index b2e8de82b..cb467f89d 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -73,6 +73,7 @@ signals: void startDrawing(); void shutdown(); void paused(bool); + void shaderSelectorAdded(ShaderSelector*); public slots: void setController(CoreController* controller, const QString& fname); @@ -108,11 +109,11 @@ public slots: void startVideoLog(); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS void consoleOpen(); #endif -#ifdef USE_GDB_STUB +#ifdef ENABLE_GDB_STUB void gdbOpen(); #endif @@ -194,6 +195,7 @@ private: std::unique_ptr m_display; QSize m_initialSize; + QSize m_savedSize; int m_savedScale; // TODO: Move these to a new class @@ -206,7 +208,7 @@ private: LogController m_log{0}; LogView* m_logView; -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS DebuggerConsoleController* m_console = nullptr; #endif LoadSaveState* m_stateWindow = nullptr; @@ -249,7 +251,7 @@ private: std::unique_ptr m_gifView; #endif -#ifdef USE_GDB_STUB +#ifdef ENABLE_GDB_STUB GDBController* m_gdbController = nullptr; #endif diff --git a/src/platform/qt/input/Gamepad.h b/src/platform/qt/input/Gamepad.h index 1781885cd..9a1cf19ec 100644 --- a/src/platform/qt/input/Gamepad.h +++ b/src/platform/qt/input/Gamepad.h @@ -22,6 +22,9 @@ public: virtual QList currentAxes() = 0; virtual QList currentHats() = 0; + virtual QString buttonHumanName(int) const = 0; + virtual QString axisHumanName(int) const = 0; + virtual int buttonCount() const = 0; virtual int axisCount() const = 0; virtual int hatCount() const = 0; diff --git a/src/platform/qt/input/InputDriver.cpp b/src/platform/qt/input/InputDriver.cpp index f76649bd8..3f805f411 100644 --- a/src/platform/qt/input/InputDriver.cpp +++ b/src/platform/qt/input/InputDriver.cpp @@ -36,7 +36,7 @@ QList InputDriver::connectedKeySources() const { return {}; } -QList InputDriver::connectedGamepads() const { +QList> InputDriver::connectedGamepads() const { return {}; } @@ -57,8 +57,8 @@ KeySource* InputDriver::activeKeySource() { return ks[activeKeySource]; } -Gamepad* InputDriver::activeGamepad() { - QList pads(connectedGamepads()); +std::shared_ptr InputDriver::activeGamepad() { + QList> pads(connectedGamepads()); int activeGamepad = activeGamepadIndex(); if (activeGamepad < 0 || activeGamepad >= pads.count()) { return nullptr; diff --git a/src/platform/qt/input/InputDriver.h b/src/platform/qt/input/InputDriver.h index cc0a6e0cd..4b0513f2e 100644 --- a/src/platform/qt/input/InputDriver.h +++ b/src/platform/qt/input/InputDriver.h @@ -9,6 +9,8 @@ #include #include +#include + struct mRotationSource; struct mRumble; @@ -42,13 +44,13 @@ public: virtual bool update() = 0; virtual QList connectedKeySources() const; - virtual QList connectedGamepads() const; + virtual QList> connectedGamepads() const; virtual int activeKeySourceIndex() const; virtual int activeGamepadIndex() const; KeySource* activeKeySource(); - Gamepad* activeGamepad(); + std::shared_ptr activeGamepad(); virtual void setActiveKeySource(int); virtual void setActiveGamepad(int); diff --git a/src/platform/qt/input/SDLInputDriver.cpp b/src/platform/qt/input/SDLInputDriver.cpp index 5b68462d1..792c84834 100644 --- a/src/platform/qt/input/SDLInputDriver.cpp +++ b/src/platform/qt/input/SDLInputDriver.cpp @@ -112,7 +112,7 @@ void SDLInputDriver::bindDefaults(InputController* controller) { mRumble* SDLInputDriver::rumble() { #if SDL_VERSION_ATLEAST(2, 0, 0) if (m_playerAttached) { - return &m_sdlPlayer.rumble.d; + return &m_sdlPlayer.rumble.d.d; } #endif return nullptr; @@ -139,10 +139,10 @@ bool SDLInputDriver::update() { return true; } -QList SDLInputDriver::connectedGamepads() const { - QList pads; +QList> SDLInputDriver::connectedGamepads() const { + QList> pads; for (auto& pad : m_gamepads) { - pads.append(pad.get()); + pads.append(pad); } return pads; } @@ -159,7 +159,7 @@ void SDLInputDriver::updateGamepads() { m_gamepads.removeAt(i); --i; } - std::sort(m_gamepads.begin(), m_gamepads.end(), [](const auto& a, const auto b) { + std::sort(m_gamepads.begin(), m_gamepads.end(), [](const auto& a, const auto& b) { return a->m_index < b->m_index; }); @@ -173,7 +173,7 @@ void SDLInputDriver::updateGamepads() { } m_gamepads.append(std::make_shared(this, i)); } - std::sort(m_gamepads.begin(), m_gamepads.end(), [](const auto& a, const auto b) { + std::sort(m_gamepads.begin(), m_gamepads.end(), [](const auto& a, const auto& b) { return a->m_index < b->m_index; }); } @@ -249,6 +249,7 @@ SDLGamepad::SDLGamepad(SDLInputDriver* driver, int index, QObject* parent) #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), m_guid, sizeof(m_guid)); + m_id = SDL_JoystickInstanceID(joystick); #endif } @@ -257,13 +258,20 @@ QList SDLGamepad::currentButtons() { return {}; } - SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; QList buttons; +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_GameController* controller = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->controller; + for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) { + buttons.append(SDL_GameControllerGetButton(controller, static_cast(i))); + } +#else + SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; int numButtons = SDL_JoystickNumButtons(joystick); for (int i = 0; i < numButtons; ++i) { buttons.append(SDL_JoystickGetButton(joystick, i)); } +#endif return buttons; } @@ -273,13 +281,20 @@ QList SDLGamepad::currentAxes() { return {}; } - SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; QList axes; +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_GameController* controller = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->controller; + for (int i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) { + axes.append(SDL_GameControllerGetAxis(controller, static_cast(i))); + } +#else + SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; int numAxes = SDL_JoystickNumAxes(joystick); for (int i = 0; i < numAxes; ++i) { axes.append(SDL_JoystickGetAxis(joystick, i)); } +#endif return axes; } @@ -289,24 +304,52 @@ QList SDLGamepad::currentHats() { return {}; } - SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; QList hats; +#if !SDL_VERSION_ATLEAST(2, 0, 0) + SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; int numHats = SDL_JoystickNumHats(joystick); for (int i = 0; i < numHats; ++i) { hats.append(static_cast(SDL_JoystickGetHat(joystick, i))); } +#endif return hats; } +QString SDLGamepad::buttonHumanName(int button) const { +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_GameController* controller = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->controller; + const char* name = mSDLButtonName(controller, static_cast(button)); + if (name) { + return QString::fromUtf8(name); + } +#endif + return QString::number(button); +} + +QString SDLGamepad::axisHumanName(int axis) const { +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_GameController* controller = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->controller; + const char* name = mSDLAxisName(controller, static_cast(axis)); + if (name) { + return QString::fromUtf8(name); + } +#endif + return QString::number(axis); +} + int SDLGamepad::buttonCount() const { if (!verify()) { return -1; } +#if SDL_VERSION_ATLEAST(2, 0, 0) + return SDL_CONTROLLER_BUTTON_MAX; +#else SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; return SDL_JoystickNumButtons(joystick); +#endif } int SDLGamepad::axisCount() const { @@ -314,8 +357,12 @@ int SDLGamepad::axisCount() const { return -1; } +#if SDL_VERSION_ATLEAST(2, 0, 0) + return SDL_CONTROLLER_AXIS_MAX; +#else SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; return SDL_JoystickNumAxes(joystick); +#endif } int SDLGamepad::hatCount() const { @@ -323,8 +370,12 @@ int SDLGamepad::hatCount() const { return -1; } +#if SDL_VERSION_ATLEAST(2, 0, 0) + return 0; +#else SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, m_index)->joystick; return SDL_JoystickNumHats(joystick); +#endif } QString SDLGamepad::name() const { @@ -345,11 +396,10 @@ QString SDLGamepad::visibleName() const { #if SDL_VERSION_ATLEAST(2, 0, 0) bool SDLGamepad::updateIndex() { - char guid[34]; for (size_t i = 0; i < SDL_JoystickListSize(&s_sdlEvents.joysticks); ++i) { SDL_Joystick* joystick = SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, i)->joystick; - SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), guid, sizeof(guid)); - if (memcmp(guid, m_guid, 33) == 0) { + SDL_JoystickID id = SDL_JoystickInstanceID(joystick); + if (id == m_id) { m_index = i; return true; } diff --git a/src/platform/qt/input/SDLInputDriver.h b/src/platform/qt/input/SDLInputDriver.h index 0ca2f4030..70c7eed17 100644 --- a/src/platform/qt/input/SDLInputDriver.h +++ b/src/platform/qt/input/SDLInputDriver.h @@ -8,6 +8,8 @@ #include "input/Gamepad.h" #include "input/InputDriver.h" +#define SDL_MAIN_HANDLED + #include "platform/sdl/sdl-events.h" #include @@ -29,7 +31,11 @@ public: SDLInputDriver(InputController*, QObject* parent = nullptr); ~SDLInputDriver(); +#if SDL_VERSION_ATLEAST(2, 0, 0) + uint32_t type() const override { return SDL_BINDING_CONTROLLER; } +#else uint32_t type() const override { return SDL_BINDING_BUTTON; } +#endif QString visibleName() const override { return QLatin1String("SDL"); } QString currentProfile() const override; @@ -44,7 +50,7 @@ public: bool update() override; - QList connectedGamepads() const override; + QList> connectedGamepads() const override; int activeGamepadIndex() const override; void setActiveGamepad(int) override; @@ -87,6 +93,9 @@ public: int axisCount() const override; int hatCount() const override; + QString buttonHumanName(int) const override; + QString axisHumanName(int) const override; + QString name() const override; QString visibleName() const override; @@ -100,6 +109,7 @@ private: size_t m_index; #if SDL_VERSION_ATLEAST(2, 0, 0) char m_guid[34]{}; + SDL_JoystickID m_id; #endif bool verify() const; diff --git a/src/platform/qt/library/LibraryTree.cpp b/src/platform/qt/library/LibraryTree.cpp index 37d07e3e7..c9029e963 100644 --- a/src/platform/qt/library/LibraryTree.cpp +++ b/src/platform/qt/library/LibraryTree.cpp @@ -181,7 +181,7 @@ void LibraryTree::rebuildTree() { QHash pathNodes; if (m_currentStyle == LibraryStyle::STYLE_TREE) { - for (const QString& folder : m_pathNodes.keys()) { + for (const QString& folder : m_pathNodes.keys()) { QTreeWidgetItem* i = new LibraryTreeItem; pathNodes.insert(folder, i); i->setText(0, folder.section("/", -1)); diff --git a/src/platform/qt/main.cpp b/src/platform/qt/main.cpp index 4343168a7..f98d2cd88 100644 --- a/src/platform/qt/main.cpp +++ b/src/platform/qt/main.cpp @@ -90,7 +90,9 @@ int main(int argc, char* argv[]) { QApplication::setApplicationName(projectName); QApplication::setApplicationVersion(projectVersion); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); +#endif #ifdef BUILD_GLES2 QSurfaceFormat format; @@ -104,9 +106,18 @@ int main(int argc, char* argv[]) { QApplication::setWindowIcon(QIcon(":/res/mgba-256.png")); #endif +#ifdef Q_OS_UNIX + QApplication::setDesktopFileName(QString("io.mgba.mGBA")); +#endif + QTranslator qtTranslator; - qtTranslator.load(locale, "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath)); - application.installTranslator(&qtTranslator); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) + if (qtTranslator.load(locale, "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { +#else + if (qtTranslator.load(locale, "qt", "_", QLibraryInfo::path(QLibraryInfo::TranslationsPath))) { +#endif + application.installTranslator(&qtTranslator); + } #ifdef QT_STATIC QTranslator qtStaticTranslator; @@ -115,8 +126,9 @@ int main(int argc, char* argv[]) { #endif QTranslator langTranslator; - langTranslator.load(locale, binaryName, "-", ":/translations/"); - application.installTranslator(&langTranslator); + if (langTranslator.load(locale, binaryName, "-", ":/translations/")) { + application.installTranslator(&langTranslator); + } Window* w = application.newWindow(); w->loadConfig(); diff --git a/src/platform/qt/scripting/ScriptingController.cpp b/src/platform/qt/scripting/ScriptingController.cpp index f4c5092c1..b1d68e22a 100644 --- a/src/platform/qt/scripting/ScriptingController.cpp +++ b/src/platform/qt/scripting/ScriptingController.cpp @@ -73,7 +73,7 @@ void ScriptingController::setController(std::shared_ptr controll if (!controller) { return; } - m_controller = controller; + m_controller = std::move(controller); CoreController::Interrupter interrupter(m_controller); m_controller->thread()->scriptContext = &m_scriptContext; if (m_controller->hasStarted()) { @@ -92,6 +92,7 @@ void ScriptingController::setInputController(InputController* input) { } void ScriptingController::setVideoBackend(VideoBackend* backend) { + m_videoBackend = backend; mScriptCanvasUpdateBackend(&m_scriptContext, backend); } @@ -170,11 +171,11 @@ void ScriptingController::flushStorage() { } bool ScriptingController::eventFilter(QObject* obj, QEvent* ev) { - event(obj, ev); + scriptingEvent(obj, ev); return false; } -void ScriptingController::event(QObject* obj, QEvent* event) { +void ScriptingController::scriptingEvent(QObject* obj, QEvent* event) { if (!m_controller) { return; } @@ -188,7 +189,7 @@ void ScriptingController::event(QObject* obj, QEvent* event) { return; case QEvent::KeyPress: case QEvent::KeyRelease: { - struct mScriptKeyEvent ev{mSCRIPT_EV_TYPE_KEY}; + struct mScriptKeyEvent ev{{mSCRIPT_EV_TYPE_KEY}}; auto keyEvent = static_cast(event); ev.state = event->type() == QEvent::KeyRelease ? mSCRIPT_INPUT_STATE_UP : static_cast(event)->isAutoRepeat() ? mSCRIPT_INPUT_STATE_HELD : mSCRIPT_INPUT_STATE_DOWN; @@ -199,7 +200,7 @@ void ScriptingController::event(QObject* obj, QEvent* event) { } case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: { - struct mScriptMouseButtonEvent ev{mSCRIPT_EV_TYPE_MOUSE_BUTTON}; + struct mScriptMouseButtonEvent ev{{mSCRIPT_EV_TYPE_MOUSE_BUTTON}}; auto mouseEvent = static_cast(event); ev.mouse = 0; ev.state = event->type() == QEvent::MouseButtonPress ? mSCRIPT_INPUT_STATE_DOWN : mSCRIPT_INPUT_STATE_UP; @@ -208,7 +209,7 @@ void ScriptingController::event(QObject* obj, QEvent* event) { return; } case QEvent::MouseMove: { - struct mScriptMouseMoveEvent ev{mSCRIPT_EV_TYPE_MOUSE_MOVE}; + struct mScriptMouseMoveEvent ev{{mSCRIPT_EV_TYPE_MOUSE_MOVE}}; auto mouseEvent = static_cast(event); QPoint pos = mouseEvent->pos(); pos = static_cast(obj)->normalizedPoint(m_controller.get(), pos); @@ -219,7 +220,7 @@ void ScriptingController::event(QObject* obj, QEvent* event) { return; } case QEvent::Wheel: { - struct mScriptMouseWheelEvent ev{mSCRIPT_EV_TYPE_MOUSE_WHEEL}; + struct mScriptMouseWheelEvent ev{{mSCRIPT_EV_TYPE_MOUSE_WHEEL}}; auto wheelEvent = static_cast(event); QPoint adelta = wheelEvent->angleDelta(); QPoint pdelta = wheelEvent->pixelDelta(); @@ -240,7 +241,7 @@ void ScriptingController::event(QObject* obj, QEvent* event) { auto type = event->type(); if (type == GamepadButtonEvent::Down() || type == GamepadButtonEvent::Up()) { - struct mScriptGamepadButtonEvent ev{mSCRIPT_EV_TYPE_GAMEPAD_BUTTON}; + struct mScriptGamepadButtonEvent ev{{mSCRIPT_EV_TYPE_GAMEPAD_BUTTON}}; auto gamepadEvent = static_cast(event); ev.pad = 0; ev.state = event->type() == GamepadButtonEvent::Down() ? mSCRIPT_INPUT_STATE_DOWN : mSCRIPT_INPUT_STATE_UP; @@ -248,7 +249,7 @@ void ScriptingController::event(QObject* obj, QEvent* event) { mScriptContextFireEvent(&m_scriptContext, &ev.d); } if (type == GamepadHatEvent::Type()) { - struct mScriptGamepadHatEvent ev{mSCRIPT_EV_TYPE_GAMEPAD_HAT}; + struct mScriptGamepadHatEvent ev{{mSCRIPT_EV_TYPE_GAMEPAD_HAT}}; updateGamepad(); auto gamepadEvent = static_cast(event); ev.pad = 0; @@ -264,7 +265,7 @@ void ScriptingController::updateGamepad() { detachGamepad(); return; } - Gamepad* gamepad = driver->activeGamepad(); + std::shared_ptr gamepad = driver->activeGamepad(); if (!gamepad) { detachGamepad(); return; @@ -301,7 +302,7 @@ void ScriptingController::updateGamepad() { void ScriptingController::attach() { CoreController::Interrupter interrupter(m_controller); mScriptContextAttachCore(&m_scriptContext, m_controller->thread()->core); -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS m_controller->attachDebugger(false); #endif } @@ -339,6 +340,7 @@ void ScriptingController::init() { mScriptContextAttachLogger(&m_scriptContext, &m_logger); m_bufferModel->attachToContext(&m_scriptContext); + mScriptCanvasUpdateBackend(&m_scriptContext, m_videoBackend); HashTableEnumerate(&m_scriptContext.engines, [](const char* key, void* engine, void* context) { ScriptingController* self = static_cast(context); diff --git a/src/platform/qt/scripting/ScriptingController.h b/src/platform/qt/scripting/ScriptingController.h index a44e52b2e..5c579a768 100644 --- a/src/platform/qt/scripting/ScriptingController.h +++ b/src/platform/qt/scripting/ScriptingController.h @@ -43,7 +43,7 @@ public: bool loadFile(const QString& path); bool load(VFileDevice& vf, const QString& name); - void event(QObject* obj, QEvent* ev); + void scriptingEvent(QObject* obj, QEvent* ev); mScriptContext* context() { return &m_scriptContext; } ScriptingTextBufferModel* textBufferModel() const { return m_bufferModel; } @@ -87,6 +87,7 @@ private: mScriptEngineContext* m_activeEngine = nullptr; QHash m_engines; ScriptingTextBufferModel* m_bufferModel; + VideoBackend* m_videoBackend = nullptr; mScriptGamepad m_gamepad; diff --git a/src/platform/qt/scripting/ScriptingTextBuffer.cpp b/src/platform/qt/scripting/ScriptingTextBuffer.cpp index fe85eda0e..9a5de818d 100644 --- a/src/platform/qt/scripting/ScriptingTextBuffer.cpp +++ b/src/platform/qt/scripting/ScriptingTextBuffer.cpp @@ -107,7 +107,7 @@ void ScriptingTextBuffer::moveCursor(const QPoint& pos) { m_shim.cursor.insertBlock(); } } else { - m_shim.cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, y); + m_shim.cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, y); } int x = pos.x(); diff --git a/src/platform/qt/scripting/ScriptingTextBuffer.h b/src/platform/qt/scripting/ScriptingTextBuffer.h index b70e9f82a..b4a9c5b83 100644 --- a/src/platform/qt/scripting/ScriptingTextBuffer.h +++ b/src/platform/qt/scripting/ScriptingTextBuffer.h @@ -10,6 +10,7 @@ #include #include +#include #include namespace QGBA { diff --git a/src/platform/qt/scripting/ScriptingView.cpp b/src/platform/qt/scripting/ScriptingView.cpp index 3878b668a..d31a9c738 100644 --- a/src/platform/qt/scripting/ScriptingView.cpp +++ b/src/platform/qt/scripting/ScriptingView.cpp @@ -39,6 +39,7 @@ ScriptingView::ScriptingView(ScriptingController* controller, ConfigController* connect(m_ui.buffers->selectionModel(), &QItemSelectionModel::currentChanged, this, &ScriptingView::selectBuffer); connect(m_ui.load, &QAction::triggered, this, &ScriptingView::load); + connect(m_ui.loadMostRecent, &QAction::triggered, this, &ScriptingView::loadMostRecent); connect(m_ui.reset, &QAction::triggered, controller, &ScriptingController::reset); m_mruFiles = m_config->getMRU(ConfigController::MRU::Script); @@ -66,6 +67,10 @@ void ScriptingView::load() { } } +void ScriptingView::loadMostRecent() { + m_controller->loadFile(m_mruFiles.at(0)); +} + void ScriptingView::controllerReset() { selectBuffer(QModelIndex()); } @@ -105,7 +110,15 @@ void ScriptingView::updateMRU() { m_ui.mru->clear(); for (const auto& fname : m_mruFiles) { m_ui.mru->addAction(fname, [this, fname]() { - m_controller->loadFile(fname); + if (m_controller->loadFile(fname)) { + appendMRU(fname); + } }); } + checkEmptyMRU(); } + + +void ScriptingView::checkEmptyMRU() { + m_ui.loadMostRecent->setEnabled(!m_mruFiles.isEmpty()); +} \ No newline at end of file diff --git a/src/platform/qt/scripting/ScriptingView.h b/src/platform/qt/scripting/ScriptingView.h index 1f90a3f19..a62bd2314 100644 --- a/src/platform/qt/scripting/ScriptingView.h +++ b/src/platform/qt/scripting/ScriptingView.h @@ -22,6 +22,7 @@ public: private slots: void submitRepl(); void load(); + void loadMostRecent(); void controllerReset(); void selectBuffer(const QModelIndex& current, const QModelIndex& = QModelIndex()); @@ -31,6 +32,7 @@ private: void appendMRU(const QString&); void updateMRU(); + void checkEmptyMRU(); Ui::ScriptingView m_ui; diff --git a/src/platform/qt/scripting/ScriptingView.ui b/src/platform/qt/scripting/ScriptingView.ui index 8b97449b0..4d55a8707 100644 --- a/src/platform/qt/scripting/ScriptingView.ui +++ b/src/platform/qt/scripting/ScriptingView.ui @@ -98,6 +98,7 @@ + @@ -108,6 +109,11 @@ Load script... + + + + &Load most recent + diff --git a/src/platform/qt/ts/mgba-de.ts b/src/platform/qt/ts/mgba-de.ts index a1d1b2e15..4e65105da 100644 --- a/src/platform/qt/ts/mgba-de.ts +++ b/src/platform/qt/ts/mgba-de.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) Game Boy Advance-ROMs (%1) - + Game Boy ROMs (%1) Game Boy-ROMs (%1) - + All ROMs (%1) Alle ROMs (%1) - + %1 Video Logs (*.mvl) %1 Video-Logs (*.mvl) @@ -70,7 +70,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd. An update to %1 is available. - Ein Update für %1 ist verfügbar. + Ein Update auf %1 ist verfügbar. @@ -132,7 +132,7 @@ Download-Größe: %3 (None) - (keiner) + (Nichts) @@ -145,7 +145,7 @@ Download-Größe: %3 Loading... - Laden … + Lädt … @@ -191,17 +191,17 @@ Download-Größe: %3 QGBA::AudioDevice - + Can't set format of context-less audio device Format des kontextlosen Audio-Gerätes konnte nicht gesetzt werden - + Audio device is missing its core - Dem Audio-Gerät fehlt ein Core + Dem Audio-Gerät fehlt sein Core - + Writing data to read-only audio device Schreibe Daten an ein schreibgeschütztes Audio-Gerät @@ -209,7 +209,7 @@ Download-Größe: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input Ohne Eingabe kann ein Audio-Prozessor nicht gestartet werden @@ -285,28 +285,28 @@ Download-Größe: %3 Erweiterte Optionen anzeigen - + BattleChip data missing BattleChip-Daten fehlen - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? BattleChip-Daten fehlen. BattleChip Gates wird weiterhin funktionieren, einige Grafiken werden jedoch fehlen. Möchtest Du die Daten jetzt herunterladen? - - + + Select deck file Deck-Datei auswählen - + Incompatible deck Inkompatibles Deck - + The selected deck is not compatible with this Chip Gate Das gewählte Deck ist nicht mit diesem Chip Gate kompatibel @@ -367,19 +367,19 @@ Download-Größe: %3 Codes hier eingeben... - - + + Autodetect (recommended) Automatisch erkennen (empfohlen) - - + + Select cheats file Cheat-Datei auswählen - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. Einige Cheats konnten nicht hinzugefügt werden. Bitte stelle sicher, dass sie korrekt formatiert sind und/oder probiere es mit anderen Cheat-Typen. @@ -395,40 +395,40 @@ Download-Größe: %3 Rewinding not currently enabled - Rücklauf ist derzeit nicht aktiviert + Zurückspulen ist derzeit nicht aktiviert - + Reset the game? Spiel zurücksetzen? - + Most games will require a reset to load the new save. Do you want to reset now? Die meisten Spiele müssen zurückgesetzt werden, um einen neuen Spielstand zu laden. Möchtest Du das Spiel jetzt zurücksetzen? - + Failed to open save file: %1 Fehler beim Öffnen der Speicherdatei: %1 - + Failed to open game file: %1 Fehler beim Öffnen der Spieldatei: %1 - + Can't yank pack in unexpected platform! Das GamePak kann nur auf unterstützten Plattformen herausgezogen werden! - + Failed to open snapshot file for reading: %1 Konnte Snapshot-Datei %1 nicht zum Lesen öffnen - + Failed to open snapshot file for writing: %1 Konnte Snapshot-Datei %1 nicht zum Schreiben öffnen @@ -477,6 +477,14 @@ Download-Größe: %3 CLI-Verlauf kann nicht gespeichert werden + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -716,7 +724,7 @@ Download-Größe: %3 Image files (*.png *.jpg *.bmp) - + Bilddateien (*.png *.jpg *.bmp) @@ -724,7 +732,7 @@ Download-Größe: %3 Inspect frame - Bild beobachten + Frame untersuchen @@ -734,7 +742,7 @@ Download-Größe: %3 Freeze frame - Bild einfrieren + Frame einfrieren @@ -757,52 +765,52 @@ Download-Größe: %3 Zurücksetzen - + Export frame Bild exportieren - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Keine - + Background Hintergrund - + Window Fenster - + Objwin Objwin - + Sprite Sprite - + Backdrop Hintergrund - + Frame Frame - + %1 %2 %1 %2 @@ -818,22 +826,22 @@ Download-Größe: %3 QGBA::GBAKeyEditor - + Clear Button Button löschen - + Clear Analog Analog löschen - + Refresh Aktualisieren - + Set all Alle belegen @@ -3006,8 +3014,8 @@ Download-Größe: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Download-Größe: %3 Vertikal - - - + + + N/A Nicht verfügbar - + Export map Map exportieren - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Durchsuchen + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + Start + + + + Stop + Stopp + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Download-Größe: %3 Aktualisieren - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 byte%2 @@ -3750,19 +3822,19 @@ Download-Größe: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Versuch Multiplayer-Spieler zu trennen der nicht verbunden ist - + Trying to get player ID for a multiplayer player that's not attached - + Versuch Spieler-ID festzustellen von einem Multiplayer-Spieler der nicht verbunden ist - + Trying to get save ID for a multiplayer player that's not attached - + Versuch Speicherstand-ID festzustellen von einem Multiplayer-Spieler der nicht verbunden ist @@ -4157,35 +4229,35 @@ Download-Größe: %3 OBJ exportieren - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette Palette exportieren - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 Fehler beim Öffnen der Ausgabe-Palettendatei: %1 @@ -4259,7 +4331,7 @@ Download-Größe: %3 QGBA::ROMInfo - + @@ -4299,18 +4371,28 @@ Download-Größe: %3 + Maker Code: + + + + + Revision: + + + + File size: Dateigröße: - + CRC32: CRC32: - + Save file: - + Speicherstand: @@ -4364,62 +4446,62 @@ Download-Größe: %3 QGBA::SaveConverter - + Save games and save states (%1) Spielstände und Savestates (%1) - + Select save game or save state Spielstand oder Savestate auswählen - + Save games (%1) Spielstände (%1) - + Select save game Spielstand auswählen - + Conversion failed Konvertierung fehlgeschlagen - + Failed to convert the save game. This is probably a bug. Fehler beim Konvertieren des Spielstands. Es handelt sich möglicherweise um einen Programmfehler. - + No file selected Keine Datei ausgewählt - + Could not open file Datei konnte nicht geöffnet werden - + No valid formats found Keine gültigen Formate gefunden - + Please select a valid input file Bitte wähle eine gültige Eingabedatei - + No valid conversions found Keine gültigen Konvertierungen gefunden - + Cannot convert save games between platforms Der Spielstand konnte nicht zwischen verschiedenen Plattformen konvertiert werden @@ -4445,97 +4527,97 @@ Download-Größe: %3 Ausgabedatei - + %1 %2 save game Spielstand %1 %2 - + little endian little-endian - + big endian big-endian - + SRAM SRAM - + %1 flash %1 Flash - + %1 EEPROM %1 EEPROM - + + RTC - + + RTC - + %1 SRAM + RTC %1 SRAM + RTC - + %1 SRAM %1 SRAM - + packed MBC2 MBC2, komprimiert - + unpacked MBC2 MBC2, entpackt - + MBC6 flash MBC6 Flash-Speicher - + MBC6 combined SRAM + flash MBC6 SRAM + Flash-Speicher - + MBC6 SRAM MBC6 SRAM - + TAMA5 TAMA5 - + %1 (%2) %1 (%2) - + %1 save state with embedded %2 save game Savestate %1 mit eingebettetem Spielstand %2 - + %1 SharkPort %2 save game SharkPort %1 Spielstand %2 - + %1 GameShark Advance SP %2 save game %1 GameShark Advance SP %2 Spielstand @@ -4571,32 +4653,37 @@ Download-Größe: %3 Kürzlich geöffnetes Skript laden - + Load script... Skript laden... - + + &Load most recent + + + + &Reset Zu&rücksetzen - + 0 0 - + Select script to load Skript auswählen, welches geladen werden soll - + Lua scripts (*.lua) Lua-Skripte (*.lua) - + All files (*.*) Alle Dateien (*.*) @@ -4689,105 +4776,105 @@ Download-Größe: %3 QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (erzwinge Version 1.x) - + None Keiner - + None (Still Image) Keiner (Standbild) - + Keyboard Tastatur - + Controllers Gamepads - + Shortcuts Tastenkürzel - - + + Shaders Shader - + Select BIOS BIOS auswählen - + Select directory Verzeichnis auswählen - + Select image - Bild auswählen + Bild auswählen - + Image file (*.png *.jpg *.jpeg) - Bilddatei (*.png *.jpg *.jpeg) + Bilddatei (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never Nie - + Just now Gerade eben - + Less than an hour ago Vor weniger als einer Stunde - + %n hour(s) ago Vor %n Stunde @@ -4795,7 +4882,7 @@ Download-Größe: %3 - + %n day(s) ago Vor %n Tag @@ -5074,7 +5161,7 @@ Download-Größe: %3 Custom border: - + Benutzerdefinierter Rand: @@ -5119,40 +5206,40 @@ Download-Größe: %3 Rewind speed: - + Zurückspulgeschwindigkeit: - + Default color palette only Nur Standard-Farbpalette - + SGB color palette if available SGB-Farbpalette, sofern verfügbar - + GBC color palette if available GBC-Farbpalette, sofern verfügbar - + SGB (preferred) or GBC color palette if available SGB (bevorzugt) oder GBC-Farbpalette, sofern verfügbar - + Game Boy Camera Game Boy Camera - + Driver: Treiber: - + Source: Quelle: @@ -5223,42 +5310,42 @@ Download-Größe: %3 Zusätzliche Savestate-Daten laden: - + Models Modelle - + GB only: Nur GB: - + SGB compatible: SGB-kompatibel: - + GBC only: Nur GBC: - + GBC compatible: GBC-kompatibel: - + SGB and GBC compatible: SGB- und GBC-kompatibel: - + Game Boy palette Game Boy-Palette - + Preset: Voreinstellungen: @@ -5303,57 +5390,52 @@ Download-Größe: %3 Software - + OpenGL enhancements OpenGL-Verbesserungen - + High-resolution scale: Hochauflösende Skalierung: - - XQ GBA audio (experimental) - XQ GBA-Audio (experimentell) - - - + Cheats Cheats - + Log to file In Datei protokollieren - + Log to console Auf die Konsole protokollieren - + Select Log File Protokoll-Datei auswählen - + Default BG colors: Standard-Hintergrundfarben: - + Default sprite colors 1: Standard-Sprite-Farben 1: - + Default sprite colors 2: Standard-Sprite-Farben 2: - + Super Game Boy borders Super Game Boy-Rahmen @@ -5384,25 +5466,25 @@ Download-Größe: %3 - - - - - - - - - + + + + + + + + + Browse Durchsuchen - + Use BIOS file if found BIOS-Datei verwenden, wenn vorhanden - + Skip BIOS intro BIOS-Intro überspringen @@ -5457,7 +5539,7 @@ Download-Größe: %3 Enable rewind - Rücklauf aktivieren + Zurückspulen aktivieren @@ -5467,7 +5549,7 @@ Download-Größe: %3 Rewind history: - Rücklauf-Verlauf: + Zurückspulverlauf: @@ -5480,56 +5562,56 @@ Download-Größe: %3 Autofeuer-Intervall: - + (240×160) (240×160) - + GB BIOS file: Datei mit GB-BIOS: - + GBA BIOS file: Datei mit GBA-BIOS: - + GBC BIOS file: Datei mit GBC-BIOS: - + SGB BIOS file: Datei mit SGB-BIOS: - + Save games Spielstände - - - - - + + + + + Same directory as the ROM Verzeichnis der ROM-Datei - + Save states Savestates - + Screenshots Bildschirmfotos - + Patches Korrekturen @@ -5777,7 +5859,6 @@ Download-Größe: %3 - WebM WebM @@ -5786,19 +5867,8 @@ Download-Größe: %3 Format Format - - - MKV - MKV - - - - AVI - AVI - - MP4 MP4 @@ -5842,72 +5912,6 @@ Download-Größe: %3 &Native &Nativ - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - Leer - - - - FLAC - FLAC - - - - WavPack - WavPack - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - Unkomprimiert - Bitrate (kbps) @@ -5918,16 +5922,6 @@ Download-Größe: %3 ABR ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5957,85 +5951,85 @@ Download-Größe: %3 QGBA::Window - + Archives (%1) Archive (%1) - - + + Select ROM ROM auswählen - - + + Select save Speicherdatei wählen - + Select patch Patch wählen - + Patches (*.ips *.ups *.bps) Korrekturen (*.ips *.ups *.bps) - + Select e-Reader card images Bilder der Lesegerät-Karte auswählen - + Image file (*.png *.jpg *.jpeg) Bilddatei (*.png *.jpg *.jpeg) - + Conversion finished Konvertierung abgeschlossen - + %1 of %2 e-Reader cards converted successfully. %1 von %2 Lesegerät-Karten erfolgreich konvertiert. - + Select image Bild auswählen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Bild-Datei (*.png *.gif *.jpg *.jpeg);;Alle Dateien (*) - + GameShark saves (*.sps *.xps) GameShark-Speicherdaten (*.sps *.xps) - + Select video log Video-Log auswählen - + Video logs (*.mvl) Video-Logs (*.mvl) - + Crash Absturz - + The game has crashed with the following error: %1 @@ -6044,694 +6038,704 @@ Download-Größe: %3 %1 - + Unimplemented BIOS call Nicht implementierter BIOS-Aufruf - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Dieses Spiel verwendet einen BIOS-Aufruf, der nicht implementiert ist. Bitte verwenden Sie für die beste Spielerfahrung das offizielle BIOS. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Es konnte kein geeignetes Ausgabegerät erstellt werden, stattdessen wird Software-Rendering als Rückfalloption genutzt. Spiele laufen möglicherweise langsamer, besonders innerhalb großer Fenster. - + Really make portable? Portablen Modus wirklich aktivieren? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Diese Einstellung wird den Emulator so konfigurieren, dass er seine Konfiguration aus dem gleichen Verzeichnis wie die Programmdatei lädt. Möchten Sie fortfahren? - + Restart needed Neustart benötigt - + Some changes will not take effect until the emulator is restarted. Einige Änderungen werden erst übernommen, wenn der Emulator neu gestartet wurde. - + - Player %1 of %2 - Spieler %1 von %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 Bilder/Sekunde) - %4 - + &File &Datei - + Load &ROM... &ROM laden... - + Load ROM in archive... ROM aus Archiv laden... - + Save games Spielstände - + Automatically determine Automatisch erkennen - + Use player %0 save game Verwende Spielstand von Spieler %0 - + Load &patch... &Patch laden... - + Boot BIOS BIOS booten - + Replace ROM... ROM ersetzen... - + Convert e-Reader card image to raw... Lesegerät-Kartenbild in Rohdaten umwandeln … - + ROM &info... ROM-&Informationen... - + Recent Zuletzt verwendet - + Make portable Portablen Modus aktivieren - + &Load state Savestate (aktueller Zustand) &laden - + Load state file... Savestate-Datei laden... - + &Save state Savestate (aktueller Zustand) &speichern - + Save state file... Savestate-Datei speichern... - + Quick load Schnell laden - + Quick save Schnell speichern - + Load recent Lade zuletzt gespeicherten Savestate - + Save recent Speichere aktuellen Zustand - + Undo load state Laden des Savestate rückgängig machen - + Undo save state Speichern des Savestate rückgängig machen - - + + State &%1 Savestate &%1 - + Load camera image... Lade Kamerabild... - + Convert save game... Spielstand konvertieren... - + Reset needed Zurücksetzen erforderlich - + Some changes will not take effect until the game is reset. Einige Änderungen werden erst dann wirksam, wenn das Spiel zurückgesetzt wird. - + New multiplayer window Neues Multiplayer-Fenster - + Connect to Dolphin... Mit Dolphin verbinden... - + Report bug... Fehler melden... - + E&xit &Beenden - + &Emulation &Emulation - + &Reset Zu&rücksetzen - + Sh&utdown Schli&eßen - + Yank game pak Spielmodul herausziehen - + &Pause &Pause - + &Next frame &Nächstes Bild - + Fast forward (held) Schneller Vorlauf (gehalten) - + &Fast forward Schneller &Vorlauf - + Fast forward speed Vorlauf-Geschwindigkeit - + Unbounded Unbegrenzt - + %0x %0x - - - Increase fast forward speed - - - Decrease fast forward speed - + Increase fast forward speed + Vorspulgeschwindigkeit erhöhen + Decrease fast forward speed + Vorspulgeschwindigkeit senken + + + Rewind (held) Zurückspulen (gehalten) - + Re&wind Zur&ückspulen - + Step backwards Schrittweiser Rücklauf - + Solar sensor Sonnen-Sensor - + Increase solar level Sonnen-Level erhöhen - + Decrease solar level Sonnen-Level verringern - + Brightest solar level Hellster Sonnen-Level - + Darkest solar level Dunkelster Sonnen-Level - + Brightness %1 Helligkeit %1 - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Audio/&Video - + Frame size Bildgröße - + Toggle fullscreen Vollbildmodus umschalten - + + &Lock frame size + + + + Lock aspect ratio Seitenverhältnis korrigieren - + Force integer scaling Pixelgenaue Skalierung (Integer scaling) - + Interframe blending Interframe-Überblendung - + Frame&skip Frame&skip - + Mute Stummschalten - + FPS target Bildwiederholrate - + Take &screenshot &Screenshot erstellen - + F12 F12 - + Scripting... Scripting... - + Create forwarder... Forwarder erzeugen... - + Game state views Spiel-Zustände ansehen - + + Log memory &accesses... + + + + Clear Leeren - + Game Boy Printer... Game Boy Printer... - + Video layers Video-Ebenen - + Audio channels Audio-Kanäle - + Adjust layer placement... Lage der Bildebenen anpassen... - + &Tools &Werkzeuge - + View &logs... &Logs ansehen... - + Game &overrides... Spiel-&Überschreibungen... - + &Cheats... &Cheats... - + Open debugger console... Debugger-Konsole öffnen... - + Start &GDB server... &GDB-Server starten... - + Settings... Einstellungen... - + Select folder Ordner auswählen - + Save games (%1) Spielstände (%1) - + Select save game Spielstand auswählen - + mGBA save state files (%1) mGBA-Savestates (%1) - - + + Select save state Savestate auswählen - + Select e-Reader dotcode e-Reader-Code auswählen - + e-Reader card (*.raw *.bin *.bmp) e-Reader-Karte (*.raw *.bin *.bmp) - + GameShark saves (*.gsv *.sps *.xps) GameShark-Spielstände (*.gsv *.sps *.xps) - + Couldn't Start Konnte nicht gestartet werden - + Could not start game. Spiel konnte nicht gestartet werden. - + Add folder to library... Ordner zur Bibliothek hinzufügen... - + Load alternate save game... Alternativen Spielstand laden... - + Load temporary save game... Temporären Spielstand laden... - + Scan e-Reader dotcodes... e-Reader-Code einlesen... - + Import GameShark Save... GameShare-Speicherstand importieren... - + Export GameShark Save... GameShark-Speicherstand exportieren... - + About... Über... - + %1× %1x - + Bilinear filtering Bilineare Filterung - + Native (59.7275) Nativ (59.7275) - + Record A/V... Audio/Video aufzeichnen... - + Record GIF/WebP/APNG... GIF/WebP/APNG aufzeichnen... - + Game Pak sensors... Spielmodul-Sensoren... - + View &palette... &Palette betrachten... - + View &sprites... &Sprites betrachten... - + View &tiles... &Tiles betrachten... - + View &map... &Map betrachten... - + &Frame inspector... &Bildbetrachter... - + View memory... Speicher betrachten... - + Search memory... Speicher durchsuchen... - + View &I/O registers... &I/O-Register betrachten... - + Record debug video log... Video-Protokoll aufzeichnen... - + Stop debug video log Aufzeichnen des Video-Protokolls beenden - + Exit fullscreen Vollbildmodus beenden - + GameShark Button (held) GameShark-Taste (gehalten) - + Autofire Autofeuer - + Autofire A Autofeuer A - + Autofire B Autofeuer B - + Autofire L Autofeuer L - + Autofire R Autofeuer R - + Autofire Start Autofeuer Start - + Autofire Select Autofeuer Select - + Autofire Up Autofeuer nach oben - + Autofire Right Autofeuer rechts - + Autofire Down Autofeuer nach unten - + Autofire Left Autofeuer links @@ -6769,40 +6773,40 @@ Download-Größe: %3 ? - + Super (L) - Super (L) + Super (L) - + Super (R) - Super (R) + Super (R) - + Menu - Menü + Menü QShortcut - + Shift Shift - + Control Strg - + Alt Alt - + Meta AltGr diff --git a/src/platform/qt/ts/mgba-en.ts b/src/platform/qt/ts/mgba-en.ts index 4b67efd50..cdb0f81b4 100644 --- a/src/platform/qt/ts/mgba-en.ts +++ b/src/platform/qt/ts/mgba-en.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) @@ -185,17 +185,17 @@ Download size: %3 QGBA::AudioDevice - + Can't set format of context-less audio device - + Audio device is missing its core - + Writing data to read-only audio device @@ -203,7 +203,7 @@ Download size: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input @@ -279,28 +279,28 @@ Download size: %3 - + BattleChip data missing - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? - - + + Select deck file - + Incompatible deck - + The selected deck is not compatible with this Chip Gate @@ -361,19 +361,19 @@ Download size: %3 - - + + Autodetect (recommended) - - + + Select cheats file - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. @@ -392,37 +392,37 @@ Download size: %3 - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -471,6 +471,14 @@ Download size: %3 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -751,52 +759,52 @@ Download size: %3 - + Export frame - + Portable Network Graphics (*.png) - + None - + Background - + Window - + Objwin - + Sprite - + Backdrop - + Frame - + %1 %2 @@ -812,22 +820,22 @@ Download size: %3 QGBA::GBAKeyEditor - + Clear Button - + Clear Analog - + Refresh - + Set all @@ -3000,8 +3008,8 @@ Download size: %3 QGBA::KeyEditor - - + + --- @@ -3372,23 +3380,87 @@ Download size: %3 - - - + + + N/A - + Export map - + Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3635,22 +3707,22 @@ Download size: %3 - + (%0/%1×) - + (⅟%0×) - + (%0×) - + %1 byte%2 @@ -3744,17 +3816,17 @@ Download size: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -4151,35 +4223,35 @@ Download size: %3 - + #%0 - + 0x%0 + + - - 0x%0 (%1) - + Export palette - + Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 @@ -4253,7 +4325,7 @@ Download size: %3 QGBA::ROMInfo - + @@ -4293,16 +4365,26 @@ Download size: %3 - File size: + Maker Code: - CRC32: + Revision: + File size: + + + + + CRC32: + + + + Save file: @@ -4358,62 +4440,62 @@ Download size: %3 QGBA::SaveConverter - + Save games and save states (%1) - + Select save game or save state - + Save games (%1) - + Select save game - + Conversion failed - + Failed to convert the save game. This is probably a bug. - + No file selected - + Could not open file - + No valid formats found - + Please select a valid input file - + No valid conversions found - + Cannot convert save games between platforms @@ -4439,97 +4521,97 @@ Download size: %3 - + %1 %2 save game - + little endian - + big endian - + SRAM - + %1 flash - + %1 EEPROM - + + RTC - + %1 SRAM + RTC - + %1 SRAM - + packed MBC2 - + unpacked MBC2 - + MBC6 flash - + MBC6 combined SRAM + flash - + MBC6 SRAM - + TAMA5 - + %1 (%2) - + %1 save state with embedded %2 save game - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4565,32 +4647,37 @@ Download size: %3 - + Load script... - + + &Load most recent + + + + &Reset - + 0 - + Select script to load - + Lua scripts (*.lua) - + All files (*.*) @@ -4683,105 +4770,105 @@ Download size: %3 QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None - + None (Still Image) - + Keyboard - + Controllers - + Shortcuts - - + + Shaders - + Select BIOS - + Select directory - + Select image - + Image file (*.png *.jpg *.jpeg) - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago @@ -4789,7 +4876,7 @@ Download size: %3 - + %n day(s) ago @@ -5116,37 +5203,37 @@ Download size: %3 - + Default color palette only - + SGB color palette if available - + GBC color palette if available - + SGB (preferred) or GBC color palette if available - + Game Boy Camera - + Driver: - + Source: @@ -5323,42 +5410,42 @@ Download size: %3 - + Models - + GB only: - + SGB compatible: - + GBC only: - + GBC compatible: - + SGB and GBC compatible: - + Game Boy palette - + Preset: @@ -5395,135 +5482,130 @@ Download size: %3 - + OpenGL enhancements - + High-resolution scale: - + (240×160) - - XQ GBA audio (experimental) - - - - + GB BIOS file: - - - - - - - - - + + + + + + + + + Browse - + Use BIOS file if found - + Skip BIOS intro - + GBA BIOS file: - + GBC BIOS file: - + SGB BIOS file: - + Save games - - - - - + + + + + Same directory as the ROM - + Save states - + Screenshots - + Patches - + Cheats - + Log to file - + Log to console - + Select Log File - + Default BG colors: - + Default sprite colors 1: - + Default sprite colors 2: - + Super Game Boy borders @@ -5781,13 +5863,11 @@ Download size: %3 - WebM - MP4 @@ -5826,82 +5906,6 @@ Download size: %3 Format - - - MKV - - - - - AVI - - - - - HEVC - - - - - HEVC (NVENC) - - - - - VP8 - - - - - VP9 - - - - - FFV1 - - - - - - None - - - - - FLAC - - - - - WavPack - - - - - Opus - - - - - Vorbis - - - - - MP3 - - - - - AAC - - - - - Uncompressed - - Bitrate (kbps) @@ -5912,16 +5916,6 @@ Download size: %3 ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5951,779 +5945,789 @@ Download size: %3 QGBA::Window - + Archives (%1) - - + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Increase fast forward speed - + Decrease fast forward speed - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - - Lock aspect ratio - - - - - Force integer scaling - - - - - Interframe blending - - - - - Bilinear filtering + + &Lock frame size + Lock aspect ratio + + + + + Force integer scaling + + + + + Interframe blending + + + + + Bilinear filtering + + + + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Create forwarder... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + Game state views - + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + + Log memory &accesses... + + + + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -6761,17 +6765,17 @@ Download size: %3 - + Super (L) - + Super (R) - + Menu @@ -6779,22 +6783,22 @@ Download size: %3 QShortcut - + Shift - + Control - + Alt - + Meta diff --git a/src/platform/qt/ts/mgba-es.ts b/src/platform/qt/ts/mgba-es_419.ts similarity index 91% rename from src/platform/qt/ts/mgba-es.ts rename to src/platform/qt/ts/mgba-es_419.ts index 83c4d5d98..cc40f84f7 100644 --- a/src/platform/qt/ts/mgba-es.ts +++ b/src/platform/qt/ts/mgba-es_419.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) ROMs para Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs para Game Boy Advance (%1) - + All ROMs (%1) Todas las ROMs (%1) - + %1 Video Logs (*.mvl) %1 Registros de vídeo (*.mvl) @@ -191,17 +191,17 @@ Tamaño de descarga: %3 QGBA::AudioDevice - + Can't set format of context-less audio device No se puede establecer el formato de un dispositivo de audio sin contexto - + Audio device is missing its core No se encuentra el sistema del dispositivo de audio - + Writing data to read-only audio device Escribiendo datos a dispositivo de audio de sólo lectura @@ -209,7 +209,7 @@ Tamaño de descarga: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input No se puede iniciar el procesador de audio sin entrada @@ -285,28 +285,28 @@ Tamaño de descarga: %3 Mostrar configuración avanzada - + BattleChip data missing Faltan los datos del BattleChip - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? Faltan los datos de BattleChip. Los BattleChip Gates seguirán funcionando pero faltarán algunos gráficos. ¿Quieres descargar los datos ahora? - - + + Select deck file Seleccionar fichero de baraja - + Incompatible deck Baraja no compatible - + The selected deck is not compatible with this Chip Gate La baraja seleccionada no es compatible con este Chip Gate @@ -367,19 +367,19 @@ Tamaño de descarga: %3 Ingresa los códigos aquí... - - + + Autodetect (recommended) Autodetectar (recomendado) - - + + Select cheats file Seleccionar archivo de trucos - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. Algunos trucos no se pudieron añadir. Asegúrate de que están en el formato correcto y/o prueba otro tipo de trucos. @@ -398,37 +398,37 @@ Tamaño de descarga: %3 Rebobinado desactivado actualmente - + Reset the game? ¿Reiniciar el juego? - + Most games will require a reset to load the new save. Do you want to reset now? La mayoría de juegos requieren reiniciar para cargar la nueva partida guardada. ¿Quieres reiniciar ahora? - + Failed to open save file: %1 Error al abrir el archivo de guardado: %1 - + Failed to open game file: %1 Error al abrir el archivo del juego: %1 - + Can't yank pack in unexpected platform! ¡No se puede quitar el cartucho en esta plataforma! - + Failed to open snapshot file for reading: %1 Error al leer del archivo de captura: %1 - + Failed to open snapshot file for writing: %1 Error al escribir al archivo de captura: %1 @@ -477,6 +477,14 @@ Tamaño de descarga: %3 No se ha podido abrir el historial de la línea de comandos para escritura + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -656,7 +664,7 @@ Tamaño de descarga: %3 Use default image - Utilizar la imagen por defecto + Utilizar imagen por defecto @@ -686,17 +694,17 @@ Tamaño de descarga: %3 Build finished - Construcción finalizada + Compilación finalizada Forwarder finished building - Transmisor terminado de construir + Transmisor terminado de compilar Build failed - Falló la construcción + Falló la compilación @@ -716,7 +724,7 @@ Tamaño de descarga: %3 Image files (*.png *.jpg *.bmp) - + Archivos de imagen (*.png *.jpg *.bmp) @@ -757,52 +765,52 @@ Tamaño de descarga: %3 Reiniciar - + Export frame Exportar cuadro - + Portable Network Graphics (*.png) Gráficos de red portátiles (*.png) - + None Ninguno - + Background Fondo - + Window Ventana - + Objwin Objwin - + Sprite Sprite - + Backdrop Telón de fondo (backdrop) - + Frame Cuadro - + %1 %2 %1× {1 %2?} @@ -818,22 +826,22 @@ Tamaño de descarga: %3 QGBA::GBAKeyEditor - + Clear Button Reestablecer botones - + Clear Analog Reestablecer sticks analógicos - + Refresh Actualizar - + Set all Configurar todo @@ -3006,8 +3014,8 @@ Tamaño de descarga: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Tamaño de descarga: %3 Vertical - - - + + + N/A n/d - + Export map Exportar mapa - + Portable Network Graphics (*.png) Gráficos de red portátiles (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + Detener + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Tamaño de descarga: %3 Actualizar - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 byte%2 @@ -3750,19 +3822,19 @@ Tamaño de descarga: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Intentando desvincular a un multijugador que no está conectado - + Trying to get player ID for a multiplayer player that's not attached - + Intentando obtener el ID de un multijugador que no está conectado - + Trying to get save ID for a multiplayer player that's not attached - + Intentando obtener ID de guardado para un jugador multijugador que no está conectado @@ -3780,7 +3852,7 @@ Tamaño de descarga: %3 Export - Esportar + Exportar @@ -4157,35 +4229,35 @@ Tamaño de descarga: %3 Exportar OBJ - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette Exportar paleta - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 Error al abrir el archivo de paleta de salida: %1 @@ -4228,7 +4300,7 @@ Tamaño de descarga: %3 Hurry up! - ¡Apúrate! + ¡Apresúrate! @@ -4259,7 +4331,7 @@ Tamaño de descarga: %3 QGBA::ROMInfo - + @@ -4299,18 +4371,28 @@ Tamaño de descarga: %3 + Maker Code: + + + + + Revision: + + + + File size: Tamaño del archivo: - + CRC32: CRC32: - + Save file: - + Guardar: @@ -4364,62 +4446,62 @@ Tamaño de descarga: %3 QGBA::SaveConverter - + Save games and save states (%1) Juegos y estados guardados (%1) - + Select save game or save state Seleccionar juego o estado guardado - + Save games (%1) Datos de guardado (%1) - + Select save game Seleccionar juego guardado - + Conversion failed Conversión fallada - + Failed to convert the save game. This is probably a bug. No se pudo convertir el estado guardado. Esto probablemente es un error. - + No file selected Archivo no seleccionado - + Could not open file Error al abrir el archivo - + No valid formats found No se encontraron formatos válidos - + Please select a valid input file Seleccione un archivo de entrada válido - + No valid conversions found No se encontraron conversiones validas - + Cannot convert save games between platforms No se pueden convertir los estados guardados entre plataformas distintas @@ -4445,97 +4527,97 @@ Tamaño de descarga: %3 Archivo de salida - + %1 %2 save game %1 %2 juego guardado - + little endian little-endian - + big endian big-endian - + SRAM SRAM - + %1 flash %1 flash - + %1 EEPROM %1 EEPROM - + + RTC - + + RTC - + %1 SRAM + RTC %1 SRAM + RTC - + %1 SRAM %1 SRAM - + packed MBC2 MBC2 empacado - + unpacked MBC2 MBC2 desempacado - + MBC6 flash flash MBC6 - + MBC6 combined SRAM + flash SRAM + flash combinados MBC6 - + MBC6 SRAM SRAM MBC6 - + TAMA5 TAMA5 - + %1 (%2) %1 (%2) - + %1 save state with embedded %2 save game %1 estado guardado con juego guardado %2 integrado - + %1 SharkPort %2 save game %1 SharkPort %2 partida guardada - + %1 GameShark Advance SP %2 save game %1 GameShark Advance SP %2 partida guardada @@ -4571,32 +4653,37 @@ Tamaño de descarga: %3 Cargar script reciente - + Load script... Cargar script... - + + &Load most recent + + + + &Reset &Reiniciar - + 0 0 - + Select script to load Elegir script - + Lua scripts (*.lua) Scripts de Lua (*.lua) - + All files (*.*) Todos los archivos (*.*) @@ -4689,105 +4776,105 @@ Tamaño de descarga: %3 QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forzar versión 1.x) - + None Ninguno - + None (Still Image) Nada (imagen estática) - + Keyboard Teclado - + Controllers Mandos - + Shortcuts Atajos de teclado - - + + Shaders Shaders - + Select BIOS Seleccionar BIOS - + Select directory Elegir carpeta - + Select image - Seleccionar imagen + Seleccionar imagen - + Image file (*.png *.jpg *.jpeg) - Archivo de imagen (*.png *.jpg *.jpeg) + Archivo de imagen (*.png *.jpg *.jpeg) - + (%1×%2) - + Never Nunca - + Just now Ahora mismo - + Less than an hour ago Hace menos de una hora - + %n hour(s) ago Hace %n hora @@ -4795,11 +4882,11 @@ Tamaño de descarga: %3 - + %n day(s) ago - Hace %n dia - Hace %n dias + Hace %n día + Hace %n días @@ -5089,7 +5176,7 @@ Tamaño de descarga: %3 Custom border: - + Borde personalizado: @@ -5134,40 +5221,40 @@ Tamaño de descarga: %3 Rewind speed: - + Velocidad de rebobinado: - + Default color palette only Sólo paleta de colores predeterminada - + SGB color palette if available Paleta de color SGB si está disponible - + GBC color palette if available Paleta de color GBC si está disponible - + SGB (preferred) or GBC color palette if available Paleta de colores SGB (preferida) o GBC si está disponible - + Game Boy Camera Cámara Game Boy - + Driver: Controlador: - + Source: Fuente: @@ -5213,7 +5300,7 @@ Tamaño de descarga: %3 Activar modo de compatibilidad VBA en ROM hacks - + Preset: Ajustes: @@ -5228,22 +5315,22 @@ Tamaño de descarga: %3 Avance rápido (mantenido): - + (240×160) (240×160) - + Log to file Guardar en archivo - + Log to console Escribir en consola - + Select Log File Seleccionar @@ -5381,61 +5468,56 @@ Tamaño de descarga: %3 Software - + OpenGL enhancements Mejoras para OpenGL - + High-resolution scale: Escala de alta resolución: - - XQ GBA audio (experimental) - Mejorar audio GBA (experimental) - - - + GB BIOS file: Archivo BIOS GB: - - - - - - - - - + + + + + + + + + Browse Examinar - + Use BIOS file if found Usar archivo BIOS si está disponible - + Skip BIOS intro Saltar animación de entrada de la BIOS - + GBA BIOS file: Archivo BIOS GBA: - + GBC BIOS file: Archivo BIOS GBC: - + SGB BIOS file: Archivo BIOS SGB: @@ -5445,91 +5527,91 @@ Tamaño de descarga: %3 Guardar estado automáticamente - + Save games Datos de guardado - - - - - + + + + + Same directory as the ROM En el mismo directorio que la ROM - + Save states Estados de guardado - + Screenshots Capturas de pantalla - + Patches Parches - + Cheats Trucos - + Models Modelos - + GB only: Sólo GB: - + SGB compatible: Compatible con SGB: - + GBC only: Sólo GBC: - + GBC compatible: Compatible con GBC: - + SGB and GBC compatible: Compatible con SGB y GBC: - + Game Boy palette Paleta de Game Boy - + Default BG colors: Colores de fondo por defecto: - + Super Game Boy borders Bordes de Super Game Boy - + Default sprite colors 1: Colores de sprite 1 por defecto: - + Default sprite colors 2: Colores de sprite 2 por defecto: @@ -5777,7 +5859,6 @@ Tamaño de descarga: %3 - WebM WebM @@ -5786,19 +5867,8 @@ Tamaño de descarga: %3 Format Formato - - - MKV - MKV - - - - AVI - AVI - - MP4 MP4 @@ -5842,72 +5912,6 @@ Tamaño de descarga: %3 &Native &Nativo - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - Ninguno - - - - FLAC - FLAC - - - - WavPack - WavPack - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - Sin comprimir - Bitrate (kbps) @@ -5918,16 +5922,6 @@ Tamaño de descarga: %3 ABR ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5957,80 +5951,80 @@ Tamaño de descarga: %3 QGBA::Window - + Archives (%1) Contenedores (%1) - - + + Select ROM Seleccionar ROM - + Select folder Seleccionar carpeta - - + + Select save Seleccionar guardado - + Select patch Seleccionar parche - + Patches (*.ips *.ups *.bps) Parches (*.ips *.ups *.bps) - + Select e-Reader dotcode Seleccionar dotcode del e-Reader - + e-Reader card (*.raw *.bin *.bmp) Tarjeta e-Reader (*.raw *.bin *.bmp) - + Select image Seleccionar imagen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Archivo de imagen (*.png *.gif *.jpg *.jpeg);;Todos los archivos (*) - + GameShark saves (*.sps *.xps) Guardados de GameShark (*.sps *.xps) - + Select video log Seleccionar registro de vídeo - + Video logs (*.mvl) Registros de vídeo (*.mvl) - + Crash Cierre inesperado - + The game has crashed with the following error: %1 @@ -6039,699 +6033,709 @@ Tamaño de descarga: %3 %1 - + Unimplemented BIOS call Llamada a BIOS no implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este juego utiliza una llamada al BIOS que no se ha implementado. Utiliza el BIOS oficial para obtener la mejor experiencia. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. No se pudo crear un dispositivo de pantalla apropiado, recurriendo a software. Los juegos pueden funcionar lentamente, especialmente con ventanas grandes. - + Really make portable? ¿Hacer "portable"? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Esto hará que el emulador cargue su configuración desde el mismo directorio que el ejecutable. ¿Quieres continuar? - + Restart needed Reinicio necesario - + Some changes will not take effect until the emulator is restarted. Algunos cambios no surtirán efecto hasta que se reinicie el emulador. - + - Player %1 of %2 - Jugador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Archivo - + Load &ROM... Cargar &ROM... - + Load ROM in archive... - Cargar ROM desde contenedor... + Cargar ROM desde archivo comprimido... - + Add folder to library... Agregar carpeta a la biblioteca... - + Save games Datos de guardado - + Automatically determine Determinar automáticamente - + Use player %0 save game Usar la partida guardada del jugador %0 - + Load &patch... Cargar &parche... - + Boot BIOS Arrancar BIOS - + Replace ROM... Reemplazar ROM... - + ROM &info... &Información de la ROM... - + Recent - Cargar reciente + Reciente - + Make portable Crear instalación portable - + &Load state Ca&rgar estado - + Report bug... Reportar error... - + About... Acerca de... - + Game Pak sensors... Sensores del cartucho... - + Clear Limpiar - + Load state file... Cargar archivo de estado... - + Save games (%1) Juegos guardados (%1) - + Select save game Elegir juego guardado - + mGBA save state files (%1) Archivos estados guardados mGBA (%1) - - + + Select save state Elegir estado guardado - + Select e-Reader card images Elegir imágenes de tarjeta e-Reader - + Image file (*.png *.jpg *.jpeg) Archivo de imagen (*.png *.jpg *.jpeg) - + Conversion finished Conversión terminada - + %1 of %2 e-Reader cards converted successfully. %1 de %2 tarjetas e-Reader convertidas con éxito. - + Load alternate save game... Cargar partida guardada alternativa... - + Load temporary save game... Cargar partida guardada temporal... - + Convert e-Reader card image to raw... Convertir imagen de tarjeta e-Reader a archivo en bruto... - + &Save state Guardar e&stado - + Save state file... Guardar archivo de estado... - + Quick load Cargado rápido - + Quick save Guardado rápido - + Load recent Cargar reciente - + Save recent Guardar reciente - + Undo load state Deshacer cargar estado - + Undo save state Deshacer guardar estado - - + + State &%1 Estado &%1 - + Load camera image... Cargar imagen para cámara... - + Convert save game... Convertir juego guardado... - + GameShark saves (*.gsv *.sps *.xps) Partidas guardadas de GameShark (*.gsv *.sps *.xps) - + Reset needed Reinicio necesario - + Some changes will not take effect until the game is reset. Algunos cambios no tendrán efecto hasta que se reinicie el juego. - + New multiplayer window Nueva ventana multijugador - + Connect to Dolphin... Conectar a Dolphin... - + E&xit Salir (&X) - + &Emulation &Emulación - + &Reset &Reiniciar - + Sh&utdown Apagar (&U) - + Yank game pak Sacar cartucho - + &Pause &Pausar - + &Next frame Cuadro siguie&nte - + Fast forward (held) Avance rápido (mantener) - + &Fast forward &Avance rápido - + Fast forward speed Velocidad de avance rápido - + Unbounded Sin límite - + %0x %0x - - - Increase fast forward speed - - - Decrease fast forward speed - + Increase fast forward speed + Aumentar la velocidad de avance rápido + Decrease fast forward speed + Disminuir velocidad de avance rápido + + + Rewind (held) Rebobinar (mantener) - + Re&wind Re&bobinar - + Step backwards Paso hacia atrás - + Solar sensor Sensor solar - + Increase solar level Subir nivel - + Decrease solar level Bajar nivel - + Brightest solar level Más claro - + Darkest solar level Más oscuro - + Brightness %1 Brillo %1 - + Audio/&Video Audio/&vídeo - + Frame size Tamaño del cuadro - + Toggle fullscreen Pantalla completa - + + &Lock frame size + + + + Lock aspect ratio Bloquear proporción de aspecto - + Force integer scaling Forzar escala a enteros - + Bilinear filtering Filtro bilineal - + Frame&skip &Salto de cuadros - + Mute Silenciar - + FPS target Objetivo de FPS - + Native (59.7275) Nativo (59,7275) - + Take &screenshot Tomar pan&tallazo - + F12 F12 - + Game Boy Printer... Game Boy Printer... - + BattleChip Gate... BattleChip Gate... - + %1× %1× - + Interframe blending Mezcla entre cuadros - + Record A/V... Grabar A/V... - + Video layers Capas de vídeo - + Audio channels Canales de audio - + Adjust layer placement... Ajustar ubicación de capas... - + &Tools Herramien&tas - + View &logs... Ver re&gistros... - + Game &overrides... Ajustes específic&os por juego... - + Couldn't Start No se pudo iniciar - + Could not start game. No se pudo iniciar el juego. - + Scan e-Reader dotcodes... Escanear dotcodes del e-Reader... - + Import GameShark Save... Importar desde GameShark... - + Export GameShark Save... Exportar a GameShark... - + Record GIF/WebP/APNG... Grabar GIF/WebP/APNG... - + &Cheats... Tru&cos... - + Settings... Ajustes... - + Open debugger console... Abrir consola de depuración... - + Start &GDB server... Iniciar servidor &GDB... - + Scripting... Scripts... - + Create forwarder... Crear autocargador... - + Game state views Estado del juego - + View &palette... Ver &paleta... - + View &sprites... Ver &sprites... - + View &tiles... Ver m&osaicos... - + View &map... Ver &mapa... - + &Frame inspector... Inspec&tor de cuadros... - + View memory... Ver memoria... - + Search memory... Buscar memoria... - + View &I/O registers... Ver registros &I/O... - + + Log memory &accesses... + + + + Record debug video log... Grabar registro de depuración de vídeo... - + Stop debug video log Detener registro de depuración de vídeo - + Exit fullscreen Salir de pantalla completa - + GameShark Button (held) Botón GameShark (mantener) - + Autofire Disparo automático - + Autofire A Disparo automático A - + Autofire B Disparo automático B - + Autofire L Disparo automático L - + Autofire R Disparo automático R - + Autofire Start Disparo automático Start - + Autofire Select Disparo automático Select - + Autofire Up Disparo automático arriba - + Autofire Right Disparo automático derecha - + Autofire Down Disparo automático abajo - + Autofire Left Disparo automático izquierda @@ -6769,40 +6773,40 @@ Tamaño de descarga: %3 ? - + Super (L) - Super (L) + Súper (L) - + Super (R) - Super (R) + Súper (R) - + Menu - Menú + Menú QShortcut - + Shift Mayús - + Control Ctrl - + Alt Alt - + Meta Meta diff --git a/src/platform/qt/ts/mgba-fr.ts b/src/platform/qt/ts/mgba-fr.ts index 7efbfef1c..27eb207a9 100644 --- a/src/platform/qt/ts/mgba-fr.ts +++ b/src/platform/qt/ts/mgba-fr.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) ROMs de Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs de Game Boy (%1) - + All ROMs (%1) Toutes les ROM (%1) - + %1 Video Logs (*.mvl) %1 Journaux vidéo (*.mvl) @@ -191,17 +191,17 @@ Taille du téléchargement : %3 QGBA::AudioDevice - + Can't set format of context-less audio device - + Audio device is missing its core - + Writing data to read-only audio device @@ -209,7 +209,7 @@ Taille du téléchargement : %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input @@ -285,28 +285,28 @@ Taille du téléchargement : %3 Paramètres avancés - + BattleChip data missing - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? - - + + Select deck file - + Incompatible deck - + The selected deck is not compatible with this Chip Gate @@ -368,19 +368,19 @@ Taille du téléchargement : %3 Entrez les codes ici… - - + + Autodetect (recommended) Détecter automatiquement (recommandé) - - + + Select cheats file Choisir un fichier de cheats - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. @@ -399,37 +399,37 @@ Taille du téléchargement : %3 Le rembobinage n'est pas actuellement activé - + Reset the game? Réinitialiser le jeu ? - + Most games will require a reset to load the new save. Do you want to reset now? La plupart des jeux nécessitent une réinitialisation pour charger la nouvelle sauvegarde. Voulez-vous réinitialiser maintenant ? - + Failed to open save file: %1 Échec de l'ouverture du fichier de sauvegarde : %1 - + Failed to open game file: %1 Échec de l'ouverture du fichier de jeu : %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 Échec de l'ouverture de l'instantané pour lire : %1 - + Failed to open snapshot file for writing: %1 Échec de l'ouverture de l'instantané pour écrire : %1 @@ -478,6 +478,14 @@ Taille du téléchargement : %3 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -758,52 +766,52 @@ Taille du téléchargement : %3 Réinitialiser - + Export frame Exporter l'image - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Aucun - + Background Arrière plan - + Window Fenêtre - + Objwin Objwin - + Sprite Sprite - + Backdrop Toile de fond - + Frame Cadre - + %1 %2 %1 %2 @@ -819,22 +827,22 @@ Taille du téléchargement : %3 QGBA::GBAKeyEditor - + Clear Button Bouton d'effacement - + Clear Analog Effacer l'analogique - + Refresh Rafraîchir - + Set all Tout définir @@ -3017,8 +3025,8 @@ Taille du téléchargement : %3 QGBA::KeyEditor - - + + --- --- @@ -3396,23 +3404,87 @@ Taille du téléchargement : %3 Vertical - - - + + + N/A s.o. - + Export map Exporter la map - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Parcourir + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + Arrêter + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3659,22 +3731,22 @@ Taille du téléchargement : %3 Rafraîchir - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 octet%2 @@ -3768,17 +3840,17 @@ Taille du téléchargement : %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -4175,35 +4247,35 @@ Taille du téléchargement : %3 Exporter l'OBJ - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette Exporter la palette - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 Impossible d'ouvrir le fichier de la palette de sortie : %1 @@ -4277,7 +4349,7 @@ Taille du téléchargement : %3 QGBA::ROMInfo - + @@ -4317,16 +4389,26 @@ Taille du téléchargement : %3 + Maker Code: + + + + + Revision: + + + + File size: Taille du fichier : - + CRC32: CRC32 : - + Save file: @@ -4382,62 +4464,62 @@ Taille du téléchargement : %3 QGBA::SaveConverter - + Save games and save states (%1) - + Select save game or save state - + Save games (%1) - + Select save game - + Conversion failed - + Failed to convert the save game. This is probably a bug. - + No file selected - + Could not open file - + No valid formats found - + Please select a valid input file - + No valid conversions found - + Cannot convert save games between platforms @@ -4463,97 +4545,97 @@ Taille du téléchargement : %3 - + %1 %2 save game - + little endian - + big endian - + SRAM SRAM - + %1 flash - + %1 EEPROM - + + RTC - + %1 SRAM + RTC - + %1 SRAM - + packed MBC2 - + unpacked MBC2 - + MBC6 flash - + MBC6 combined SRAM + flash - + MBC6 SRAM - + TAMA5 - + %1 (%2) - + %1 save state with embedded %2 save game - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4589,32 +4671,37 @@ Taille du téléchargement : %3 - + Load script... - + + &Load most recent + + + + &Reset &Réinitialiser - + 0 0 - + Select script to load - + Lua scripts (*.lua) - + All files (*.*) @@ -4708,105 +4795,105 @@ Taille du téléchargement : %3 QGBA::SettingsView - - + + Qt Multimedia Qt Multimédia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (version forcée 1.x) - + None Aucun - + None (Still Image) Aucun (Image fixe) - + Keyboard Clavier - + Controllers Contrôleurs - + Shortcuts Raccourcis - - + + Shaders Shaders - + Select BIOS Choisir le BIOS - + Select directory - + Select image Choisir une image - + Image file (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago @@ -4814,7 +4901,7 @@ Taille du téléchargement : %3 - + %n day(s) ago @@ -5182,77 +5269,77 @@ Taille du téléchargement : %3 - + Models - + GB only: - + SGB compatible: - + GBC only: - + GBC compatible: - + SGB and GBC compatible: - + Game Boy palette - + Preset: - + Default color palette only - + SGB color palette if available - + GBC color palette if available - + SGB (preferred) or GBC color palette if available - + Game Boy Camera - + Driver: - + Source: @@ -5262,17 +5349,17 @@ Taille du téléchargement : %3 - + Log to file Journalisation vers le fichier - + Log to console Journalisation vers la console - + Select Log File Sélectionner le fichier de journalisation @@ -5435,120 +5522,115 @@ Taille du téléchargement : %3 Logiciel(s) - + OpenGL enhancements Améliorations OpenGL - + High-resolution scale: Échelle haute résolution : - + (240×160) (240×160) - - XQ GBA audio (experimental) - XQ GBA audio (expérimental) - - - + GB BIOS file: GB BIOS : - - - - - - - - - + + + + + + + + + Browse Parcourir - + Use BIOS file if found Utiliser le fichier BIOS si trouvé - + Skip BIOS intro Passer l'intro du BIOS - + GBA BIOS file: GBA BIOS : - + GBC BIOS file: GBC BIOS : - + SGB BIOS file: SGB BIOS : - + Save games Sauvegarder les jeux - - - - - + + + + + Same directory as the ROM Même répertoire que la ROM - + Save states Sauvegarder les états - + Screenshots Captures d'écran - + Patches Correctifs - + Cheats Cheats - + Default BG colors: Couleurs par défaut de l'arrière plan : - + Super Game Boy borders Bordures Super Game Boy - + Default sprite colors 1: Couleurs par défaut de la sprite nº 1 : - + Default sprite colors 2: Couleurs par défaut de la sprite n°2 : @@ -5796,7 +5878,6 @@ Taille du téléchargement : %3 - WebM WebM @@ -5805,19 +5886,8 @@ Taille du téléchargement : %3 Format Format - - - MKV - MKV - - - - AVI - AVI - - MP4 MP4 @@ -5861,72 +5931,6 @@ Taille du téléchargement : %3 &Native &Natif - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - Aucun - - - - FLAC - FLAC - - - - WavPack - - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - Non compressé - Bitrate (kbps) @@ -5937,16 +5941,6 @@ Taille du téléchargement : %3 ABR ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5976,100 +5970,100 @@ Taille du téléchargement : %3 QGBA::Window - + Archives (%1) Archives (%1) - - + + Select ROM Choisir une ROM - + Select folder Choisir un dossier - - + + Select save Choisir une sauvegarde - + Select patch Sélectionner un correctif - + Patches (*.ips *.ups *.bps) Correctifs/Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Sélectionnez le numéro de point du e-Reader - + e-Reader card (*.raw *.bin *.bmp) e-Reader carte (*.raw *.bin *.bmp) - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Select image Choisir une image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Image (*.png *.gif *.jpg *.jpeg);;Tous les fichiers (*) - + GameShark saves (*.sps *.xps) Sauvegardes GameShark (*.sps *.xps) - + Select video log Sélectionner un journal vidéo - + Video logs (*.mvl) Journaux vidéo (*.mvl) - + Crash Plantage - + The game has crashed with the following error: %1 @@ -6078,679 +6072,689 @@ Taille du téléchargement : %3 %1 - + Unimplemented BIOS call Requête au BIOS non supporté - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Ce jeu utilise un appel BIOS qui n'est pas implémenté. Veuillez utiliser le BIOS officiel pour une meilleure expérience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Échec de la création d'un périphérique d'affichage approprié, retour à l'affichage du logiciel. Les jeux peuvent fonctionner lentement, en particulier avec des fenêtres plus grandes. - + Really make portable? Vraiment rendre portable ? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Cela amènera l'émulateur à charger sa configuration depuis le même répertoire que l'exécutable. Souhaitez vous continuer ? - + Restart needed Un redémarrage est nécessaire - + Some changes will not take effect until the emulator is restarted. Certains changements ne prendront effet qu'après le redémarrage de l'émulateur. - + - Player %1 of %2 - Joueur %1 of %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Fichier - + Load &ROM... Charger une &ROM… - + Load ROM in archive... Charger la ROM d'une archive… - + Add folder to library... Ajouter un dossier à la bibliothèque… - + Load &patch... Charger un c&orrectif… - + Boot BIOS Démarrer le BIOS - + Replace ROM... Remplacer la ROM… - + Increase fast forward speed - + Decrease fast forward speed - + + &Lock frame size + + + + Create forwarder... - + Game state views - + + Log memory &accesses... + + + + Convert e-Reader card image to raw... - + ROM &info... &Infos sur la ROM… - + Recent Récent - + Make portable Rendre portable - + &Load state &Charger un état - + &Save state &Sauvegarder un état - + Quick load Chargement rapide - + Quick save Sauvegarde rapide - + Load recent Charger un fichier récent - + Save recent Sauvegarder un fichier récent - + Undo load state Annuler le chargement de l'état - + Undo save state Annuler la sauvegarde de l'état - - + + State &%1 État &%1 - + Load camera image... Charger une image de la caméra… - + Convert save game... - + New multiplayer window Nouvelle fenêtre multijoueur - + Connect to Dolphin... - + Report bug... Signalement de l'erreur… - + E&xit &Quitter - + &Emulation &Émulation - + &Reset &Réinitialiser - + Sh&utdown Extin&ction - + Yank game pak Yank game pak - + &Pause &Pause - + &Next frame &Image suivante - + Fast forward (held) Avance rapide (maintenir) - + &Fast forward A&vance rapide - + Fast forward speed Vitesse de l'avance rapide - + Unbounded Sans limites - + %0x %0x - + Rewind (held) Rembobiner (maintenir) - + Re&wind Rem&bobiner - + Step backwards Retour en arrière - + Solar sensor Capteur solaire - + Increase solar level Augmenter le niveau solaire - + Decrease solar level Diminuer le niveau solaire - + Brightest solar level Tester le niveau solaire - + Darkest solar level Assombrir le niveau solaire - + Brightness %1 Luminosité %1 - + Audio/&Video Audio/&Vidéo - + Frame size Taille de l'image - + Toggle fullscreen Basculer en plein écran - + Lock aspect ratio Bloquer les proportions - + Force integer scaling Forcer la mise à l'échelle par des nombres entiers - + Bilinear filtering Filtrage bilinèaire - + Frame&skip &Saut d'image - + Mute Muet - + FPS target FPS ciblé - + Take &screenshot Prendre une ca&pture d'écran - + F12 F12 - + Game Boy Printer... Imprimante GameBoy… - + Video layers Couches vidéo - + Audio channels Canaux audio - + Adjust layer placement... Ajuster la disposition… - + &Tools Ou&tils - + View &logs... Voir les &journaux… - + Game &overrides... - + Couldn't Start N'a pas pu démarrer - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + GameShark saves (*.gsv *.sps *.xps) - + Could not start game. Impossible de démarrer le jeu. - + Load alternate save game... - + Load temporary save game... - + Scan e-Reader dotcodes... Scanner les dotcodes e-Reader... - + Load state file... Charger le fichier d'état... - + Save state file... Enregistrer le fichier d'état... - + Import GameShark Save... Importer la sauvegarde de GameShark... - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games Sauvegarder les jeux - + Export GameShark Save... Exporter la sauvegarde de GameShark... - + Automatically determine - + Use player %0 save game - + About... À propos de… - + BattleChip Gate... - + %1× %1× - + Interframe blending Mélange d'images - + Native (59.7275) Natif (59.7275) - + Record A/V... Enregistrer A/V... - + Record GIF/WebP/APNG... Enregistrer GIF/WebP/APNG... - + Game Pak sensors... Capteurs de la Game Pak... - + &Cheats... &Cheats… - + Settings... Paramètres… - + Open debugger console... Ouvrir la console de débug… - + Start &GDB server... Démarrer le serveur &GDB… - + Scripting... - + View &palette... Voir la &palette… - + View &sprites... Voir les &sprites… - + View &tiles... Voir les &tiles… - + View &map... Voir la &map… - + &Frame inspector... Inspecteur de &frame... - + View memory... Voir la mémoire… - + Search memory... Recherche dans la mémoire… - + View &I/O registers... Voir les registres d'&E/S... - + Record debug video log... Enregistrer le journal vidéo de débogage... - + Stop debug video log Arrêter le journal vidéo de débogage - + Exit fullscreen Quitter le plein écran - + GameShark Button (held) Bouton GameShark (maintenir) - + Autofire Tir automatique - + Autofire A Tir automatique A - + Autofire B Tir automatique B - + Autofire L Tir automatique L - + Autofire R Tir automatique R - + Autofire Start Tir automatique Start - + Autofire Select Tir automatique Select - + Autofire Up Tir automatique Up - + Autofire Right Tir automatique Right - + Autofire Down Tir automatique Down - + Autofire Left Tir automatique Gauche - + Clear Vider @@ -6788,17 +6792,17 @@ Taille du téléchargement : %3 ? - + Super (L) Super (L) - + Super (R) Super (R) - + Menu Menu @@ -6806,22 +6810,22 @@ Taille du téléchargement : %3 QShortcut - + Shift Shift - + Control Control - + Alt Alt - + Meta Méta/Super diff --git a/src/platform/qt/ts/mgba-hu.ts b/src/platform/qt/ts/mgba-hu.ts index 4e5f7e1f0..a51655410 100644 --- a/src/platform/qt/ts/mgba-hu.ts +++ b/src/platform/qt/ts/mgba-hu.ts @@ -4,24 +4,24 @@ QGBA - + Game Boy Advance ROMs (%1) Game Boy Advance ROMok (%1) - + Game Boy ROMs (%1) Game Boy ROMok (%1) - + All ROMs (%1) Összes ROM (%1) - + %1 Video Logs (*.mvl) - + %1 Videonaplók (*.mvl) @@ -50,8 +50,9 @@ © 2013 – {year} Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 – {year} Jeffrey Pfau, a Mozilla Public License 2.0 alatt licencelve -A Game Boy Advance a Nintendo Co., Ltd. bejegyzett védjegye + © 2013 – {year} Jeffrey Pfau, a Mozilla Public License 2.0 alatt licencelve. + +A Game Boy Advance a Nintendo Co., Ltd. bejegyzett védjegye. @@ -64,47 +65,52 @@ A Game Boy Advance a Nintendo Co., Ltd. bejegyzett védjegye An update is available - + Egy frissítés érhető el An update to %1 is available. - + Egy frissítés elérhető %1 verzióra. + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + +Szeretné most letöleni és telepíteni? Az emulátor újraindítására lesz szükség a letöltés befejezésekor. Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + +Az automatikus frisítés ezen platformon nem elérhető, a frissítéseket manuálisan telepíthetők. Current version: %1 New version: %2 Download size: %3 - + Jelenlegi verzió: %1 +Új verzió: %2 +Letöltendő adat: %3 Downloading update... - + Frissítés letöltése... Downloading failed. Please update manually. - + A letöltés meghiúsult. Próbálja meg manuálisan frissíteni aprogramot. Downloading done. Press OK to restart %1 and install the update. - + A letöltés kész. Nyomja meg az OK gombot %1 újraindításához és a frissítés telepítéséhez. @@ -112,22 +118,22 @@ Download size: %3 Stable - + Stabil Development - + Fejlesztési Unknown - + Nem ismert (None) - + (nincs) @@ -148,7 +154,7 @@ Download size: %3 Tile # - + Cím # @@ -186,17 +192,17 @@ Download size: %3 QGBA::AudioDevice - + Can't set format of context-less audio device - + Audio device is missing its core - + Writing data to read-only audio device @@ -204,7 +210,7 @@ Download size: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input @@ -232,7 +238,7 @@ Download size: %3 Insert - + Beszúrás @@ -280,28 +286,28 @@ Download size: %3 - + BattleChip data missing - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? - - + + Select deck file - + Incompatible deck - + The selected deck is not compatible with this Chip Gate @@ -329,7 +335,7 @@ Download size: %3 Add New Code - + Új kód hozzáadása @@ -339,12 +345,12 @@ Download size: %3 Add Lines - + Sorok hozzáadása Code type - + Kód típusa @@ -362,21 +368,21 @@ Download size: %3 Írd ide a kódokat... - - + + Autodetect (recommended) - + Automatikus felisnerés (javasolt) - - + + Select cheats file Csalásfájl kiválasztása - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. - + Néhány csalást nem sikerült betölteni. Ellenőrizze, hogy helyesen formázottak-e és/vagy próbáljon ki más csalástípust! @@ -390,40 +396,40 @@ Download size: %3 Rewinding not currently enabled - + Visszatekerés jelenleg nem engedélyezett - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Nem sikerült a mentésfájl megnyitása: %1 - + Failed to open game file: %1 Nem sikerült a játékfájl megnyitása: %1 - + Can't yank pack in unexpected platform! A játékkazettát nem lehet kirántani ismeretlen platformon! - + Failed to open snapshot file for reading: %1 A pillanatkép fájljának olvasásra való megnyitása sikertelen: %1 - + Failed to open snapshot file for writing: %1 A pillanatkép fájljának írásra való megnyitása sikertelen: %1 @@ -451,7 +457,7 @@ Download size: %3 Debugger - Hibakereső + Hibakereső @@ -472,12 +478,20 @@ Download size: %3 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector Connect to Dolphin - Csatlakozás Dolphin emulátorhoz + Csatlakozás Dolphin emulátorhoz @@ -512,12 +526,12 @@ Download size: %3 Couldn't Connect - + Nem sikerült csatlakozni Could not connect to Dolphin. - + Nem sikerült csatlakozni Dolphin emulátorhoz. @@ -719,7 +733,7 @@ Download size: %3 Inspect frame - Képkocka vizsgáló + Képkocka vizsgálata @@ -752,52 +766,52 @@ Download size: %3 Visszaállítás - + Export frame Képkocka exportálása - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Nincs - + Background Háttér - + Window Ablak - + Objwin Objektumablak - + Sprite Sprite - + Backdrop Háttérréteg - + Frame Képkocka - + %1 %2 %1 %2 @@ -813,22 +827,22 @@ Download size: %3 QGBA::GBAKeyEditor - + Clear Button Gombhozzárendelés törlése - + Clear Analog Analóg hozzárendelések törlése - + Refresh Frissítés - + Set all Mind beállítása @@ -965,22 +979,22 @@ Download size: %3 Autodetect - Automatikus észlelés + Automatikus észlelés Game Boy (DMG) - + Game Boy (DMG) Game Boy Pocket (MGB) - + Game Boy Pocket (MGB) Super Game Boy (SGB) - + Super Game Boy (SGB) @@ -1138,7 +1152,7 @@ Download size: %3 0x0000 - + 0x0000 @@ -2951,7 +2965,7 @@ Download size: %3 Unknown - + Nem ismert @@ -3001,8 +3015,8 @@ Download size: %3 QGBA::KeyEditor - - + + --- @@ -3373,23 +3387,87 @@ Download size: %3 - - - + + + N/A - + Export map - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3636,22 +3714,22 @@ Download size: %3 Frissítés - + (%0/%1×) - + (⅟%0×) - + (%0×) - + %1 byte%2 @@ -3745,17 +3823,17 @@ Download size: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -4152,35 +4230,35 @@ Download size: %3 Objektumpaletta exportálása - + #%0 - + 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette - + Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 @@ -4254,7 +4332,7 @@ Download size: %3 QGBA::ROMInfo - + @@ -4294,16 +4372,26 @@ Download size: %3 - File size: + Maker Code: - CRC32: + Revision: + File size: + + + + + CRC32: + + + + Save file: @@ -4359,62 +4447,62 @@ Download size: %3 QGBA::SaveConverter - + Save games and save states (%1) - + Select save game or save state - + Save games (%1) - + Select save game - + Conversion failed - + Failed to convert the save game. This is probably a bug. - + No file selected - + Could not open file - + No valid formats found - + Please select a valid input file - + No valid conversions found - + Cannot convert save games between platforms @@ -4440,97 +4528,97 @@ Download size: %3 - + %1 %2 save game - + little endian - + big endian - + SRAM SRAM - + %1 flash - + %1 EEPROM - + + RTC - + %1 SRAM + RTC - + %1 SRAM - + packed MBC2 - + unpacked MBC2 - + MBC6 flash - + MBC6 combined SRAM + flash - + MBC6 SRAM - + TAMA5 - + %1 (%2) - + %1 save state with embedded %2 save game - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4566,32 +4654,37 @@ Download size: %3 - + Load script... - + + &Load most recent + + + + &Reset - + 0 0 - + Select script to load - + Lua scripts (*.lua) - + All files (*.*) @@ -4684,112 +4777,112 @@ Download size: %3 QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None Nincs - + None (Still Image) - + Keyboard - + Controllers - + Shortcuts - - + + Shaders - + Select BIOS - + Select directory - + Select image - + Image file (*.png *.jpg *.jpeg) - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -5054,37 +5147,37 @@ Download size: %3 - + Default color palette only - + SGB color palette if available - + GBC color palette if available - + SGB (preferred) or GBC color palette if available - + Game Boy Camera - + Driver: - + Source: @@ -5322,42 +5415,42 @@ Download size: %3 - + Models - + GB only: - + SGB compatible: - + GBC only: - + GBC compatible: - + SGB and GBC compatible: - + Game Boy palette - + Preset: @@ -5394,135 +5487,130 @@ Download size: %3 - + OpenGL enhancements - + High-resolution scale: - + (240×160) - - XQ GBA audio (experimental) - - - - + GB BIOS file: - - - - - - - - - + + + + + + + + + Browse - + Use BIOS file if found - + Skip BIOS intro - + GBA BIOS file: - + GBC BIOS file: - + SGB BIOS file: - + Save games - - - - - + + + + + Same directory as the ROM - + Save states - + Screenshots - + Patches - + Cheats Csalások - + Log to file - + Log to console - + Select Log File - + Default BG colors: - + Default sprite colors 1: - + Default sprite colors 2: - + Super Game Boy borders @@ -5780,13 +5868,11 @@ Download size: %3 - WebM - MP4 @@ -5825,82 +5911,6 @@ Download size: %3 Format - - - MKV - - - - - AVI - - - - - HEVC - - - - - HEVC (NVENC) - - - - - VP8 - - - - - VP9 - - - - - FFV1 - - - - - - None - Nincs - - - - FLAC - - - - - WavPack - - - - - Opus - - - - - Vorbis - - - - - MP3 - - - - - AAC - - - - - Uncompressed - - Bitrate (kbps) @@ -5911,16 +5921,6 @@ Download size: %3 ABR - - - H.264 - - - - - H.264 (NVENC) - - VBR @@ -5950,779 +5950,789 @@ Download size: %3 QGBA::Window - + Archives (%1) - - + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x %0x - + Increase fast forward speed - + Decrease fast forward speed - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× %1× - + Toggle fullscreen - - Lock aspect ratio - - - - - Force integer scaling - - - - - Interframe blending - - - - - Bilinear filtering + + &Lock frame size + Lock aspect ratio + + + + + Force integer scaling + + + + + Interframe blending + + + + + Bilinear filtering + + + + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Create forwarder... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + Game state views - + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + + Log memory &accesses... + + + + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Napló törlése @@ -6760,17 +6770,17 @@ Download size: %3 - + Super (L) - + Super (R) - + Menu @@ -6778,22 +6788,22 @@ Download size: %3 QShortcut - + Shift - + Control - + Alt - + Meta diff --git a/src/platform/qt/ts/mgba-it.ts b/src/platform/qt/ts/mgba-it.ts index a0a0deb5e..7338f41f6 100644 --- a/src/platform/qt/ts/mgba-it.ts +++ b/src/platform/qt/ts/mgba-it.ts @@ -4,24 +4,24 @@ QGBA - + Game Boy Advance ROMs (%1) - ROM per Game Boy Advance (%1) + ROM per Game Boy Advance (%1) - + Game Boy ROMs (%1) - ROM per Game Boy (%1) + ROM per Game Boy (%1) - + All ROMs (%1) - Tutte le ROM (%1) + Tutte le ROM (%1) - + %1 Video Logs (*.mvl) - %1 log Video (*.mvl) + %1 log Video (*.mvl) @@ -191,17 +191,17 @@ Dimensione del download: %3 QGBA::AudioDevice - + Can't set format of context-less audio device Non è stato possibile impostare il formato per il dispositivo audio - + Audio device is missing its core Il dispositivo audio è mancante di un core - + Writing data to read-only audio device Scrittura dati sul dispositivo in modalità sola lettura @@ -209,7 +209,7 @@ Dimensione del download: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input Impossibile avviare un processore audio senza input @@ -285,28 +285,28 @@ Dimensione del download: %3 Mostra avanzate - + BattleChip data missing Dati Battlechip mancanti - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? Dati Battlechip mancanti. I Battlechip Gates continueranno a funzionare ma alcuni elementi grafici mancheranno. Sei sicuro di voler scaricare questi dati adesso? - - + + Select deck file Selezione file mazzo - + Incompatible deck Mazzo non compatibile - + The selected deck is not compatible with this Chip Gate Il mazzo selezionato non è compatibile con questo Chip Gate @@ -367,19 +367,19 @@ Dimensione del download: %3 Inserisci i codici qui.. - - + + Autodetect (recommended) Rilevamento automatico (consigliato) - - + + Select cheats file Seleziona il file cheats - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. Non è stato possibile aggiungere alcuni trucchi. Assicurati che siano formattati correttamente e / o prova altri tipi di trucchi. @@ -398,37 +398,37 @@ Dimensione del download: %3 La funzione 'riavvolgi' non è attualmente abilitata - + Reset the game? Riavviare il gioco? - + Most games will require a reset to load the new save. Do you want to reset now? La maggior parte dei giochi richiede un riavvio per caricare il nuovo salvataggio. Vuoi riavviare ora? - + Failed to open save file: %1 Impossibile aprire il file di salvataggio: %1 - + Failed to open game file: %1 Impossibile aprire il file di gioco: %1 - + Can't yank pack in unexpected platform! Non riesco a strappare il pacchetto in una piattaforma inaspettata! - + Failed to open snapshot file for reading: %1 Impossibile aprire il file snapshot per la lettura: %1 - + Failed to open snapshot file for writing: %1 Impossibile aprire il file snapshot per la scrittura: %1 @@ -477,6 +477,14 @@ Dimensione del download: %3 Impossibile aprire lo storico della riga di comando in scrittura + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -530,12 +538,12 @@ Dimensione del download: %3 3DS - + 3DS Vita - + Vita @@ -543,12 +551,12 @@ Dimensione del download: %3 Icon - + Icona Banner - + Striscia @@ -556,17 +564,17 @@ Dimensione del download: %3 Bubble - + Bolla Background - Sfondo + Sfondo Startup - + Avvio @@ -574,149 +582,149 @@ Dimensione del download: %3 Create forwarder - + Crea Icona di avvio Files - + File ROM file: - + File ROM: Browse - Sfoglia + Sfoglia Output filename: - + Nome file in uscita: Forwarder base: - + Base dell'Icona di avvio: Latest stable version - + Ultima versione stabile Latest development build - + Ultima development build Specific file - + File specifico Base file: - + File base: System - + Sistema 3DS - + 3DS Vita - + Vita Presentation - + Presentazione Title: - + Titolo: Images: - + Immagini: Use default image - + Usa immagine predefinita Preferred size: - + Dimensione preferita: Select image file - + Seleziona file immagine Select ROM file - + Seleziona file ROM Select output filename - + Selezione nome file in uscita Select base file - + Selezione file base Build finished - + Build completata Forwarder finished building - + Icona di avvio compilazione completata Build failed - + Build fallita Failed to build forwarder - + Impossibile compilare Icona di avvio %1 installable package (*.%2) - + %1 pacchetto installabile (*.%2) Select an image - + Seleziona una immagine Image files (*.png *.jpg *.bmp) - + File immagine (*.png *.jpg *.bmp) @@ -757,52 +765,52 @@ Dimensione del download: %3 Reset - + Export frame Esporta Frame - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Nessuno - + Background Sfondo - + Window Finestra - + Objwin Objwin - + Sprite Sprite - + Backdrop Sfondo - + Frame Inquadratura - + %1 %2 %1x {1 %2?} @@ -818,22 +826,22 @@ Dimensione del download: %3 QGBA::GBAKeyEditor - + Clear Button Svuota i pulsanti - + Clear Analog Svuota Analogici - + Refresh Aggiorna - + Set all Imposta tutti @@ -1085,12 +1093,12 @@ Dimensione del download: %3 NT (old 1) - + NT (vec. 1) NT (old 2) - + NT (vec. 2) @@ -1115,12 +1123,12 @@ Dimensione del download: %3 GGB-81 - + GGB-81 Li Cheng - + Li Cheng @@ -3006,8 +3014,8 @@ Dimensione del download: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Dimensione del download: %3 Verticale - - - + + + N/A N/D - + Export map Esporta Mappa - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Sfoglia + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + Ferma + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Dimensione del download: %3 Aggiorna - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 byte%2 @@ -3750,19 +3822,19 @@ Dimensione del download: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Tentativo di scollegare un giocatore in multi che non è collegato - + Trying to get player ID for a multiplayer player that's not attached - + Cerco di ottenere l'ID giocatore per un giocatore in multi non collegato - + Trying to get save ID for a multiplayer player that's not attached - + Cerco di ottenere l'ID di salvataggio per un giocatore in multi non collegato @@ -4157,35 +4229,35 @@ Dimensione del download: %3 Esporta OBJ - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette Esporta palette - + Windows PAL (*.pal);;Adobe Color Table (*.act) WIndows PAL (*.pal);;Tabella dei colori Adobe (*.act) - + Failed to open output palette file: %1 Errore nell'aprire il file palette di output: %1 @@ -4259,7 +4331,7 @@ Dimensione del download: %3 QGBA::ROMInfo - + @@ -4299,18 +4371,28 @@ Dimensione del download: %3 + Maker Code: + + + + + Revision: + + + + File size: Dimensioni del file: - + CRC32: CRC32: - + Save file: - + Salva file: @@ -4364,62 +4446,62 @@ Dimensione del download: %3 QGBA::SaveConverter - + Save games and save states (%1) Salvataggi e stati di salvataggio dei giochi (%1) - + Select save game or save state Seleziona salvataggio o stato di salvataggio - + Save games (%1) Salvataggi (%1) - + Select save game Seleziona salvataggio - + Conversion failed Conversione fallita - + Failed to convert the save game. This is probably a bug. Impossibile convertire il salvataggio. Molto probabilmente è dovuto ad un bug. - + No file selected Nessun file selezionato - + Could not open file Non è stato possibile aprire il file - + No valid formats found Nessun formato valido trovato - + Please select a valid input file Si prega di selezionare un file di input valido - + No valid conversions found Nessune conversioni valide trovate - + Cannot convert save games between platforms Impossibile convertire salvataggi tra piattaforme @@ -4445,97 +4527,97 @@ Dimensione del download: %3 File output - + %1 %2 save game %1 %2 salvataggio - + little endian little endian - + big endian big endian - + SRAM SRAM - + %1 flash %1 flash - + %1 EEPROM %1 EEPROM - + + RTC - + + RTC - + %1 SRAM + RTC %1 SRAM + OTR - + %1 SRAM %1 SRAM - + packed MBC2 MBC2 compresso - + unpacked MBC2 MBC2 non compresso - + MBC6 flash MBC6 flash - + MBC6 combined SRAM + flash MBC6 combinato con la SRAM + flash - + MBC6 SRAM SRAM MBC6 - + TAMA5 TAMA5 - + %1 (%2) %1 (%2) - + %1 save state with embedded %2 save game %1 stato di salvataggio incorporato con il salvataggio %2 - + %1 SharkPort %2 save game %1 SharkPort %2 salvataggio gioco - + %1 GameShark Advance SP %2 save game %1 GameShark Advance SP %2 salvataggio gioco @@ -4571,32 +4653,37 @@ Dimensione del download: %3 Carica script recente - + Load script... Carica script... - + + &Load most recent + + + + &Reset &Ripristina - + 0 0 - + Select script to load Selezionare lo script da caricare - + Lua scripts (*.lua) Script Lua (*.lua) - + All files (*.*) Tutti i file (*.*) @@ -4689,105 +4776,105 @@ Dimensione del download: %3 QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forza la versione 1.x) - + None Nessuno - + None (Still Image) nessuno (immagine fissa) - + Keyboard Tastiera - + Controllers Controller - + Shortcuts Scorciatoie - - + + Shaders Shader - + Select BIOS Seleziona BIOS - + Select directory Seleziona directory - + Select image - Seleziona immagine + Seleziona immagine - + Image file (*.png *.jpg *.jpeg) - File immagine (*.png *.jpg *.jpeg) + File immagine (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never Mai - + Just now - Solo adesso + Proprio adesso - + Less than an hour ago - Meno di un ora fa + Meno di un'ora fa - + %n hour(s) ago %n ora fa @@ -4795,7 +4882,7 @@ Dimensione del download: %3 - + %n day(s) ago %n giorno fa @@ -4815,7 +4902,7 @@ Dimensione del download: %3 Gameplay - Gameplay + In gioco @@ -5079,7 +5166,7 @@ Dimensione del download: %3 Custom border: - + Bordo personalizzato: @@ -5109,7 +5196,7 @@ Dimensione del download: %3 Last checked: - Vista l'ultima volta: + Ultimo controllo: @@ -5124,75 +5211,75 @@ Dimensione del download: %3 Rewind speed: - + Velocità riavvolgimento: - + Models Modelli - + GB only: Solo GB: - + SGB compatible: Compatibile SGB: - + GBC only: Solo GBC: - + GBC compatible: Compatibile BGC: - + SGB and GBC compatible: Compatibile SGB e GBC: - + Game Boy palette Tavolozza Game Boy - + Default color palette only Solo tavolozza colori predefinita - + SGB color palette if available Tavolozza colori SGB se disponibile - + GBC color palette if available Tavolozza colori GBC se disponibile - + SGB (preferred) or GBC color palette if available Tavolozza colori SGB (preferita) o GBC se disponibile - + Game Boy Camera Videocamera Game Boy - + Driver: Driver: - + Source: Sorgente: @@ -5238,7 +5325,7 @@ Dimensione del download: %3 Abilita compatibilità con i bug di VBA nelle hack delle ROM - + Preset: Profilo: @@ -5278,62 +5365,57 @@ Dimensione del download: %3 Software - + OpenGL enhancements Miglioramenti OpenGL - + High-resolution scale: Rapporto alta risoluzione: - + (240×160) (240×160) - - XQ GBA audio (experimental) - audio XQ GBA (sperimentale) - - - + Cheats Trucchi - + Log to file Registro log in file - + Log to console Registro log in console - + Select Log File Seleziona file log - + Default BG colors: Colori predefiniti sfondo: - + Super Game Boy borders Bordi Super Game Boy - + Default sprite colors 1: Colori predefiniti sprite 1: - + Default sprite colors 2: Colori predefiniti sprite 2: @@ -5359,25 +5441,25 @@ Dimensione del download: %3 - - - - - - - - - + + + + + + + + + Browse Sfoglia - + Use BIOS file if found Usa il file del BIOS se è presente - + Skip BIOS intro Salta intro del BIOS @@ -5485,51 +5567,51 @@ Dimensione del download: %3 Intervallo Autofire: - + GB BIOS file: File BIOS del GB: - + GBA BIOS file: File BIOS del GBA: - + GBC BIOS file: File BIOS del GBC: - + SGB BIOS file: File BIOS del SGB: - + Save games Salva le partite - - - - - + + + + + Same directory as the ROM Stessa cartella della ROM - + Save states Salvataggio Stati - + Screenshots Schermate - + Patches Patch @@ -5555,7 +5637,7 @@ Dimensione del download: %3 by %1 - per %1 + di %1 @@ -5777,7 +5859,6 @@ Dimensione del download: %3 - WebM WebM @@ -5786,32 +5867,11 @@ Dimensione del download: %3 Format Formato - - - MKV - MKV - - - - AVI - AVI - - MP4 MP4 - - - HEVC - HEVC - - - - VP8 - VP8 - High &Quality @@ -5852,72 +5912,6 @@ Dimensione del download: %3 &Native &Nativa - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - Nessuno - - - - FLAC - FLAC - - - - WavPack - - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - Senza compressione - Bitrate (kbps) @@ -5957,95 +5951,95 @@ Dimensione del download: %3 QGBA::Window - + Archives (%1) Archivi (%1) - - + + Select ROM Seleziona ROM - - + + Select save Seleziona salvataggio - + Select patch Seleziona patch - + Patches (*.ips *.ups *.bps) Patch (*.ips *.ups *.bps) - + Select e-Reader dotcode Selezione e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) Scheda e-Reader (*.raw *.bin *.bmp) - + Select e-Reader card images Seleziona immagini carte e-Reader - + Image file (*.png *.jpg *.jpeg) File immagine (*.png *.jpg *.jpeg) - + Conversion finished Conversione terminata - + %1 of %2 e-Reader cards converted successfully. %1 di %2 carte e-Reader convertite con successo. - + Select image Seleziona immagine - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) File immagine (*.png *.gif *.jpg *.jpeg);;Tutti i file (*) - + GameShark saves (*.sps *.xps) Salvataggi GameShark (*.sps *.xps) - + Select video log Seleziona log video - + Video logs (*.mvl) Log video (*.mvl) - + Crash Errore fatale - + The game has crashed with the following error: %1 @@ -6054,684 +6048,694 @@ Dimensione del download: %3 %1 - + Unimplemented BIOS call BIOS non implementato - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Questo gioco utilizza una chiamata BIOS non implementata. Utilizza il BIOS ufficiale per una migliore esperienza. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Impossibile creare un dispositivo di visualizzazione appropriato, tornando alla visualizzazione software. I giochi possono funzionare lentamente, specialmente con finestre più grandi. - + Really make portable? Vuoi davvero rendere portatile l'applicazione? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? In questo modo l'emulatore carica la propria configurazione dalla stessa cartella dell'eseguibile. Vuoi continuare? - + Restart needed È necessario riavviare - + Some changes will not take effect until the emulator is restarted. Alcune modifiche non avranno effetto finché l'emulatore non verrà riavviato. - + - Player %1 of %2 - Giocatore %1 di %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File File - + Load &ROM... Carica ROM... - + Load ROM in archive... Carica la ROM in archivio... - + Load &patch... Carica patch... - + Boot BIOS Avvia BIOS - + Replace ROM... Sostituisci la ROM... - + Scan e-Reader dotcodes... Scansiona e-Reader dotcode... - + Convert e-Reader card image to raw... Converti immagini carte e-Reader in raw... - + ROM &info... Informazioni ROM... - + Recent Recenti - + Make portable Rendi portatile - + &Load state Carica stato - + &Save state Salva stato - + Quick load Caricamento rapido - + Quick save Salvataggio rapido - + Load recent Carica recente - + Save recent Salva recente - + Undo load state Annulla il caricamento dello stato - + Undo save state Annulla salvataggio stato - - + + State &%1 Stato %1 - + Load camera image... Carica immagine fotocamera... - + Convert save game... Converti salvataggi... - + GameShark saves (*.gsv *.sps *.xps) Salvataggi GameShark (*.gsv *.sps *.xps) - + Reset needed Reset necessario - + Some changes will not take effect until the game is reset. Alcune modifiche non si applicheranno finché il gioco non viene resettato. - + New multiplayer window Nuova finestra multigiocatore - + Connect to Dolphin... Connessione a Dolphin... - + Report bug... Segnala bug... - + E&xit Esci (&X) - + &Emulation Emulazione - + &Reset Reset - + Sh&utdown Spegni (&U) - + Yank game pak Stacca game pak - + &Pause Pausa - + &Next frame Salta il prossimo frame (&N) - + Fast forward (held) Avanzamento rapido (tieni premuto) - + &Fast forward Avanzamento rapido (&F) - + Fast forward speed Velocità di avanzamento rapido - + Unbounded Illimitata - + %0x %0x - - - Increase fast forward speed - - - Decrease fast forward speed - + Increase fast forward speed + Aumenta la velocità di avvolgimento veloce + Decrease fast forward speed + Diminuisci la velocità di avvolgimento veloce + + + Rewind (held) Riavvolgimento (tieni premuto) - + Re&wind Riavvolgimento (&W) - + Step backwards Torna indietro - + Solar sensor Sensore solare - + Increase solar level Incrementa il livello solare - + Decrease solar level Riduci il livello solare - + Brightest solar level Livello solare massimo - + Darkest solar level Livello solare minimo - + Brightness %1 Luminosità %1 - + Audio/&Video Audio/Video - + Frame size Dimensione frame - + Toggle fullscreen Abilita schermo Intero - + + &Lock frame size + + + + Lock aspect ratio Blocca rapporti aspetto - + Frame&skip Salto frame - + Mute Muto - + FPS target FPS finali - + Take &screenshot Acquisisci schermata - + F12 F12 - + Record GIF/WebP/APNG... Registra GIF / WebP / APNG ... - + Video layers Layers video - + Audio channels Canali audio - + &Tools Strumenti - + View &logs... Visualizza registri (&log)... - + Game &overrides... Valore specifico per il gioco... - + &Cheats... Trucchi... - + Create forwarder... - + Crea Icona di avvio... - + Open debugger console... Apri console debugger... - + Start &GDB server... Avvia server GDB... - + Settings... Impostazioni... - + Select folder Seleziona cartella - + Couldn't Start Non è stato possibile avviare - + Could not start game. Non è stato possibile avviare il gioco. - + Add folder to library... Aggiungi cartella alla libreria... - + Load state file... Carica stato di salvataggio... - + Save state file... Salva stato di salvataggio... - + Import GameShark Save... Importa Salvataggio GameShark... - + Export GameShark Save... Esporta Salvataggio GameShark... - + About... Informazioni… - + Force integer scaling Forza ridimensionamento a interi - + Bilinear filtering Filtro bilineare - + Game Boy Printer... Stampante Game Boy... - + Save games (%1) Salvataggi (%1) - + Select save game Seleziona salvataggio - + mGBA save state files (%1) file di stati di salvataggio mGBA (%1) - - + + Select save state Seleziona stato di salvataggio - + Save games Salvataggi - + Load alternate save game... Carica stato di salvataggio alternativo... - + Load temporary save game... Carica salvataggio temporaneo... - + Automatically determine Determina automaticamente - + Use player %0 save game Usa il salvataggio del giocatore %0 - + BattleChip Gate... BattleChip Gate... - + %1× %1x - + Interframe blending Miscelazione dei frame - + Native (59.7275) Nativo (59.7) - + Record A/V... Registra A/V... - + Adjust layer placement... Regola posizionamento layer... - + Game Pak sensors... Sensori Game Pak... - + Scripting... Scripting... - + Game state views Viste degli stati del gioco - + View &palette... Mostra palette... - + View &sprites... Mostra sprites... - + View &tiles... Mostra tiles... - + View &map... Mostra mappa... - + &Frame inspector... &Frame inspector... - + View memory... Mostra memoria... - + Search memory... Ricerca memoria... - + View &I/O registers... Mostra registri I/O... - + + Log memory &accesses... + + + + Record debug video log... Registra video log di debug... - + Stop debug video log Ferma video log di debug - + Exit fullscreen Esci da Schermo Intero - + GameShark Button (held) Pulsante GameShark (tieni premuto) - + Autofire Pulsanti Autofire - + Autofire A Autofire A - + Autofire B Autofire B - + Autofire L Autofire L - + Autofire R Autofire R - + Autofire Start Autofire Start - + Autofire Select Autofire Select - + Autofire Up Autofire Su - + Autofire Right AAutofire Destra - + Autofire Down Autofire Giù - + Autofire Left Autofire Sinistra - + Clear Pulisci @@ -6769,40 +6773,40 @@ Dimensione del download: %3 ? - + Super (L) - Super (L) + Super (L) - + Super (R) - Super (R) + Super (R) - + Menu - Menu + Menu QShortcut - + Shift Shift - + Control Control - + Alt Alt - + Meta Meta diff --git a/src/platform/qt/ts/mgba-ja.ts b/src/platform/qt/ts/mgba-ja.ts index 29e56717f..dfb056123 100644 --- a/src/platform/qt/ts/mgba-ja.ts +++ b/src/platform/qt/ts/mgba-ja.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) ゲームボーイアドバンスファイル (%1) - + Game Boy ROMs (%1) ゲームボーイファイル (%1) - + All ROMs (%1) すべてのROM (%1) - + %1 Video Logs (*.mvl) %1ビデオログ (*.mvl) @@ -191,17 +191,17 @@ Download size: %3 QGBA::AudioDevice - + Can't set format of context-less audio device - + Audio device is missing its core オーディオ デバイスにコアがありません - + Writing data to read-only audio device @@ -209,7 +209,7 @@ Download size: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input @@ -285,28 +285,28 @@ Download size: %3 詳細表示 - + BattleChip data missing バトルチップのデータが見つかりません - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? バトルチップの画像データが見つかりません。このままでもチップゲートは動作しますが、チップの画像が表示されないまま使う事になります。今すぐダウンロードしますか? - - + + Select deck file デッキファイルを選択 - + Incompatible deck 互換性のないデッキ - + The selected deck is not compatible with this Chip Gate 選択したデッキはこのチップゲートでは使用できません @@ -367,19 +367,19 @@ Download size: %3 ここにコードを入力してください... - - + + Autodetect (recommended) 自動検出 (推奨) - - + + Select cheats file チートファイルを選択 - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. 一部のコードが追加できませんでした。フォーマットが正常かどうかを確認してください。もしくは、違う形式に変換して試してみてください。 @@ -398,37 +398,37 @@ Download size: %3 - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 セーブファイルを開けませんでした: %1 - + Failed to open game file: %1 ゲームファイルを開けませんでした: %1 - + Can't yank pack in unexpected platform! 予期しないプラットフォームでパックをヤンクすることはできません! - + Failed to open snapshot file for reading: %1 読み取り用のスナップショットファイルを開けませんでした: %1 - + Failed to open snapshot file for writing: %1 書き込み用のスナップショットファイルを開けませんでした: %1 @@ -477,6 +477,14 @@ Download size: %3 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -757,52 +765,52 @@ Download size: %3 リセット - + Export frame フレームを書き出す - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None なし - + Background バックグラウンド - + Window ウインドウ - + Objwin Objwin - + Sprite スプライト - + Backdrop 背景 - + Frame フレーム - + %1 %2 %1 %2 @@ -818,22 +826,22 @@ Download size: %3 QGBA::GBAKeyEditor - + Clear Button ボタンクリア - + Clear Analog アナログクリア - + Refresh 更新 - + Set all すべて設定 @@ -3006,8 +3014,8 @@ Download size: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Download size: %3 - - - + + + N/A N/A - + Export map マップを書き出す - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + 参照 + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + 停止 + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Download size: %3 更新 - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 byte%2 @@ -3750,17 +3822,17 @@ Download size: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -4157,35 +4229,35 @@ Download size: %3 OBJを書き出す - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette パレットを書き出す - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 出力パレットファイルを開けませんでした: %1 @@ -4259,7 +4331,7 @@ Download size: %3 QGBA::ROMInfo - + @@ -4299,16 +4371,26 @@ Download size: %3 + Maker Code: + + + + + Revision: + + + + File size: ファイルサイズ: - + CRC32: CRC32: - + Save file: @@ -4364,62 +4446,62 @@ Download size: %3 QGBA::SaveConverter - + Save games and save states (%1) セーブデータ または ステートセーブ (%1) - + Select save game or save state セーブゲームまたはステートセーブを選択 - + Save games (%1) セーブデータ (%1) - + Select save game セーブデータを選択 - + Conversion failed 変換に失敗しました - + Failed to convert the save game. This is probably a bug. セーブデータの変換に失敗しました。バグによるものである可能性があります。 - + No file selected ファイルが選択されていません - + Could not open file - + No valid formats found - + Please select a valid input file 有効な入力ファイルを選択してください - + No valid conversions found 利用可能な変換先がありません - + Cannot convert save games between platforms @@ -4445,97 +4527,97 @@ Download size: %3 出力 - + %1 %2 save game - + little endian リトルエンディアン - + big endian ビッグエンディアン - + SRAM SRAM - + %1 flash - + %1 EEPROM - + + RTC - + %1 SRAM + RTC - + %1 SRAM - + packed MBC2 - + unpacked MBC2 - + MBC6 flash - + MBC6 combined SRAM + flash - + MBC6 SRAM - + TAMA5 - + %1 (%2) - + %1 save state with embedded %2 save game %2 形式のセーブデータが埋め込まれた %1 のステートセーブ - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4571,32 +4653,37 @@ Download size: %3 - + Load script... - + + &Load most recent + + + + &Reset リセット (&R) - + 0 0 - + Select script to load - + Lua scripts (*.lua) - + All files (*.*) @@ -4689,112 +4776,112 @@ Download size: %3 QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) ソフト(Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL(バージョン1.xを強制) - + None なし - + None (Still Image) なし(静止画) - + Keyboard キーボード - + Controllers コントローラー - + Shortcuts ショートカット - - + + Shaders シェーダー - + Select BIOS BIOSを選択 - + Select directory フォルダを選択 - + Select image 画像を開く - + Image file (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never 一度もしていない - + Just now たった今 - + Less than an hour ago 1時間以内 - + %n hour(s) ago %n 時間前 - + %n day(s) ago %n 日前 @@ -5135,37 +5222,37 @@ Download size: %3 - + Default color palette only - + SGB color palette if available - + GBC color palette if available - + SGB (preferred) or GBC color palette if available - + Game Boy Camera - + Driver: - + Source: @@ -5216,42 +5303,42 @@ Download size: %3 ステートロード時に読み込む: - + Models - + GB only: - + SGB compatible: - + GBC only: - + GBC compatible: - + SGB and GBC compatible: - + Game Boy palette - + Preset: @@ -5261,22 +5348,22 @@ Download size: %3 ゲームボーイプレーヤーの機能をデフォルトで有効化 - + (240×160) (240×160) - + Log to file ファイルに出力する - + Log to console コンソールに出力する - + Select Log File ログファイルを選択 @@ -5419,115 +5506,110 @@ Download size: %3 ソフト - + OpenGL enhancements OpenGL機能強化 - + High-resolution scale: 高解像度スケール: - - XQ GBA audio (experimental) - XQ GBA オーディオ機能(実験的) - - - + GB BIOS file: ゲームボーイ: - - - - - - - - - + + + + + + + + + Browse 参照 - + Use BIOS file if found 存在する場合にBIOSファイルを使用 - + Skip BIOS intro BIOSイントロをスキップ - + GBA BIOS file: ゲームボーイアドバンス: - + GBC BIOS file: ゲームボーイカラー: - + SGB BIOS file: スーパーゲームボーイ: - + Save games セーブデータ - - - - - + + + + + Same directory as the ROM ROMファイルと同じディレクトリ - + Save states セーブステート - + Screenshots スクリーンショット - + Patches パッチ - + Cheats チート - + Default BG colors: デフォルト背景色: - + Super Game Boy borders スーパーゲームボーイのボーダー - + Default sprite colors 1: デフォルトスプライト1: - + Default sprite colors 2: デフォルトスプライト2: @@ -5775,7 +5857,6 @@ Download size: %3 - WebM WebM @@ -5784,19 +5865,8 @@ Download size: %3 Format フォーマット - - - MKV - MKV - - - - AVI - AVI - - MP4 MP4 @@ -5840,72 +5910,6 @@ Download size: %3 &Native ネイティブ (&N) - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC(NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - なし - - - - FLAC - FLAC - - - - WavPack - - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - 圧縮なし - Bitrate (kbps) @@ -5916,16 +5920,6 @@ Download size: %3 ABR ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5955,80 +5949,80 @@ Download size: %3 QGBA::Window - + Archives (%1) アーカイブファイル (%1) - - + + Select ROM ROMを開く - + Select folder フォルダを開く - - + + Select save セーブを開く - + Select patch パッチを開く - + Patches (*.ips *.ups *.bps) パッチファイル (*.ips *.ups *.bps) - + Select e-Reader dotcode カードeを開く - + e-Reader card (*.raw *.bin *.bmp) カードe (*.raw *.bin *.bmp) - + Select image 画像を開く - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 画像ファイル (*.png *.gif *.jpg *.jpeg);;すべてのファイル (*) - + GameShark saves (*.sps *.xps) GameSharkセーブファイル (*.sps *.xps) - + Select video log ビデオログを開く - + Video logs (*.mvl) ビデオログ (*.mvl) - + Crash クラッシュ - + The game has crashed with the following error: %1 @@ -6037,699 +6031,709 @@ Download size: %3 %1 - + Couldn't Start 起動失敗 - + Could not start game. ゲームを起動できませんでした。 - + Unimplemented BIOS call 未実装のBIOS呼び出し - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. このゲームは実装されていないBIOS呼び出しを使用します。最高のエクスペリエンスを得るには公式のBIOSを使用してください。 - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. 適切なディスプレイデバイスの作成に失敗し、ソフトディスプレイにフォールバックしました。特に大きなウィンドウでは、ゲームの実行が遅い場合があります。 - + Really make portable? 本当にポータブル化しますか? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? ポータブル化すると、以降は実行ファイルと同じディレクトリに設定ファイルが置かれるようになります。続行しますか? - + Restart needed 再起動が必要 - + Some changes will not take effect until the emulator is restarted. 一部の変更は、エミュレータを再起動するまで有効になりません。 - + - Player %1 of %2 - プレーヤー %1 of %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &ファイル (&F) - + Load &ROM... ROMをロード... - + Load ROM in archive... アーカイブにROMをロード... - + Add folder to library... ライブラリーにフォルダを追加... - + Load &patch... パッチをロード... (&P) - + Boot BIOS BIOSを起動 - + Replace ROM... ROMを交換... - + Scan e-Reader dotcodes... カードeをスキャン... - + ROM &info... ROM情報... (&I) - + Recent 最近開いたROM - + Make portable ポータブル化 - + &Load state ステートをロード (&L) - + Report bug... バグ報告 - + About... バージョン情報... - + Record GIF/WebP/APNG... GIF/WebP/APNGを記録 - + Game Pak sensors... カートリッジセンサー... - + Clear 消去 - + Load state file... ステートファイルをロード... - + Save games (%1) セーブデータ (%1) - + Select save game セーブデータを選択 - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Convert e-Reader card image to raw... - + &Save state ステートをセーブ (&S) - + Save state file... ステートファイルをセーブ... - + Quick load クイックロード - + Quick save クイックセーブ - + Load recent 最後に使ったクイックスロットからロード - + Save recent 最後に使ったクイックスロットにセーブ - + Undo load state クイックロードを元に戻す - + Undo save state クイックセーブを元に戻す - - + + State &%1 クイックスロット &%1 - + Load camera image... カメラ画像をロード... - + Convert save game... セーブデータを変換... - + GameShark saves (*.gsv *.sps *.xps) - + Import GameShark Save... GameSharkスナップショットを読み込む - + Export GameShark Save... GameSharkスナップショットを書き出す - + New multiplayer window 新しいウィンドウ(マルチプレイ) - + Connect to Dolphin... Dolphinに接続... - + E&xit 終了 (&X) - + &Emulation エミュレーション (&E) - + &Reset リセット (&R) - + Sh&utdown 閉じる (&U) - + Yank game pak カートリッジを抜く - + &Pause 一時停止 (&P) - + &Next frame 次のフレーム (&N) - + Fast forward (held) 早送り(押し) - + &Fast forward 早送り (&F) - + Fast forward speed 早送り速度 - + Unbounded 制限なし - + %0x %0x - + Increase fast forward speed - + Decrease fast forward speed - + Rewind (held) 巻戻し(押し) - + Re&wind 巻戻し (&R) - + Step backwards 1フレーム巻き戻す - + Solar sensor 太陽センサー - + Increase solar level 明るさを上げる - + Decrease solar level 明るさを下げる - + Brightest solar level 明るさ最高 - + Darkest solar level 明るさ最低 - + Brightness %1 明るさ %1 - + Audio/&Video オーディオ/ビデオ (&V) - + Frame size 画面サイズ - + Toggle fullscreen 全画面表示 - + + &Lock frame size + + + + Lock aspect ratio 縦横比を固定 - + Force integer scaling 整数スケーリングを強制 - + Bilinear filtering バイリニアフィルタリング - + Frame&skip フレームスキップ (&S) - + Mute ミュート - + FPS target FPS - + Native (59.7275) ネイティブ(59.7275) - + Take &screenshot スクリーンショット (&S) - + F12 F12 - + Game Boy Printer... ポケットプリンタ... - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games セーブデータ - + Automatically determine - + Use player %0 save game - + BattleChip Gate... バトルチップゲート... - + %1× %1× - + Interframe blending フレーム間混合 - + Record A/V... ビデオ録画... - + Video layers ビデオレイヤー - + Audio channels オーディオチャンネル - + Adjust layer placement... レイヤーの配置を調整... - + &Tools ツール (&T) - + View &logs... ログビューアー... (&L) - + Game &overrides... ゲーム別設定... (&O) - + &Cheats... チート... (&C) - + Settings... 設定... - + Open debugger console... デバッガコンソールを開く... - + Start &GDB server... GDBサーバを起動... (&G) - + Scripting... - + Create forwarder... - + Game state views - + View &palette... パレットビューアー... (&P) - + View &sprites... スプライトビューアー... (&S) - + View &tiles... タイルビューアー... (&T) - + View &map... マップビューアー... (&M) - + &Frame inspector... フレームインスペクタ... (&F) - + View memory... メモリビューアー... - + Search memory... メモリ検索... - + View &I/O registers... IOビューアー... (&I) - + + Log memory &accesses... + + + + Record debug video log... デバッグビデオログ... - + Stop debug video log デバッグビデオログを停止 - + Exit fullscreen 全画面表示を終了 - + GameShark Button (held) GameSharkボタン(押し) - + Autofire 連打 - + Autofire A 連打 A - + Autofire B 連打 B - + Autofire L 連打 L - + Autofire R 連打 R - + Autofire Start 連打 Start - + Autofire Select 連打 Select - + Autofire Up 連打 上 - + Autofire Right 連打 右 - + Autofire Down 連打 下 - + Autofire Left 連打 左 @@ -6767,17 +6771,17 @@ Download size: %3 ? - + Super (L) Super (L) - + Super (R) Super (R) - + Menu メニュー @@ -6785,22 +6789,22 @@ Download size: %3 QShortcut - + Shift Shift - + Control Control - + Alt Alt - + Meta Meta diff --git a/src/platform/qt/ts/mgba-ko.ts b/src/platform/qt/ts/mgba-ko.ts index a0955e500..5eb684915 100644 --- a/src/platform/qt/ts/mgba-ko.ts +++ b/src/platform/qt/ts/mgba-ko.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) 게임보이 어드밴스 롬 (%1) - + Game Boy ROMs (%1) 게임보이 롬 (%1) - + All ROMs (%1) 모든 롬 (%1) - + %1 Video Logs (*.mvl) %1 비디오 로그 (*.mvl) @@ -191,17 +191,17 @@ Download size: %3 QGBA::AudioDevice - + Can't set format of context-less audio device 컨텍스트 없는 오디오 장치의 형식을 설정할 수 없음 - + Audio device is missing its core 오디오 장치에 코어가 없음 - + Writing data to read-only audio device 읽기 전용 오디오 장치에 데이터 쓰기 @@ -209,7 +209,7 @@ Download size: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input 입력 없이 오디오 프로세서를 시작할 수 없음 @@ -285,28 +285,28 @@ Download size: %3 고급 보기 - + BattleChip data missing 배틀칩 데이터 누락 - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? 배트칩 데이터가 없습니다. 배틀칩 게이트는 계속 작동하지만 일부 그래픽이 누락됩니다. 지금 데이터를 다운로드하겠습니까? - - + + Select deck file 덱 파일 선택 - + Incompatible deck 호환되지 않는 덱 - + The selected deck is not compatible with this Chip Gate 선택한 덱은 이 칩 게이트와 호환되지 않음 @@ -367,19 +367,19 @@ Download size: %3 여기에 코드를 입력하세요... - - + + Autodetect (recommended) 자동 감지 (권장) - - + + Select cheats file 치트 파일 선택 - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. 일부 치트를 추가할 수 없습니다. 형식이 올바른지 확인하고 다른 치트 유형을 시도하세요. @@ -398,37 +398,37 @@ Download size: %3 현재 활성화되지 않은 되감기 - + Reset the game? 게임을 재설정하겠습니까? - + Most games will require a reset to load the new save. Do you want to reset now? 대부분의 게임은 새로운 저장을 로드하려면 재설정이 필요합니다. 지금 재설정하겠습니까? - + Failed to open save file: %1 저장 파일을 열지 못했습니다: %1 - + Failed to open game file: %1 게임 파일을 열지 못했습니다: %1 - + Can't yank pack in unexpected platform! 예기치 않은 플랫폼에서 팩을 잡아당길 수 없습니다! - + Failed to open snapshot file for reading: %1 읽기 용 스냅샷 파일을 열지 못했습니다: %1 - + Failed to open snapshot file for writing: %1 쓰기 용 스냅샷 파일을 열지 못했습니다: %1 @@ -477,6 +477,14 @@ Download size: %3 쓰기 위해 CLI 기록을 열 수 없음 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -716,7 +724,7 @@ Download size: %3 Image files (*.png *.jpg *.bmp) - + 이미지 파일 (*.png *.jpg *.bmp) @@ -757,52 +765,52 @@ Download size: %3 재설정 - + Export frame 프레임 내보내기 - + Portable Network Graphics (*.png) 휴대용 네트워크 그래픽 (*.png) - + None 없음 - + Background 배경 - + Window - + Objwin Objwin - + Sprite 스프라이트 - + Backdrop 배경 - + Frame 프레임 - + %1 %2 %1 %2 @@ -818,22 +826,22 @@ Download size: %3 QGBA::GBAKeyEditor - + Clear Button 버튼 정리 - + Clear Analog 아날로그 정리 - + Refresh 새로 고침 - + Set all 모두 설정 @@ -3006,8 +3014,8 @@ Download size: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Download size: %3 수직 - - - + + + N/A 해당 없음 - + Export map 맵 내보내기 - + Portable Network Graphics (*.png) 휴대용 네트워크 그래픽 (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + 시작 + + + + Stop + 정지 + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Download size: %3 새로 고침 - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 바이트%2 @@ -3750,19 +3822,19 @@ Download size: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + 연결되지 않은 멀티플레이어 플레이어를 분리하려고 함 - + Trying to get player ID for a multiplayer player that's not attached - + 연결되지 않은 멀티플레이어 플레이어의 플레이어 ID를 가져오려고 함 - + Trying to get save ID for a multiplayer player that's not attached - + 연결되지 않은 멀티플레이어 플레이어의 저장 ID를 얻으려고 함 @@ -4157,35 +4229,35 @@ Download size: %3 보트 타기 내보내기 - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette 팔레트 내보내기 - + Windows PAL (*.pal);;Adobe Color Table (*.act) 창 PAL (*.pal);;어도비 컬러 테이블 (*.act) - + Failed to open output palette file: %1 출력 팔레트 파일을 열지 못했습니다: %1 @@ -4259,7 +4331,7 @@ Download size: %3 QGBA::ROMInfo - + @@ -4299,18 +4371,28 @@ Download size: %3 + Maker Code: + + + + + Revision: + + + + File size: 파일 크기: - + CRC32: CRC32: - + Save file: - + 저장 파일: @@ -4364,62 +4446,62 @@ Download size: %3 QGBA::SaveConverter - + Save games and save states (%1) 게임 저장 및 상태 저장 (%1) - + Select save game or save state 게임 저장 또는 상태 저장 선택 - + Save games (%1) 게임 (%1) 저장 - + Select save game 저장 게임 선택 - + Conversion failed 변환 실패 - + Failed to convert the save game. This is probably a bug. 저장 게임을 변환하지 못했습니다. 이것은 아마도 버그일 것입니다. - + No file selected 파일 선택되지 않았음 - + Could not open file 파일 열 수 없음 - + No valid formats found 유효한 형식 없음 - + Please select a valid input file 유효한 입력 파일 선택 - + No valid conversions found 유효한 전환 없음 - + Cannot convert save games between platforms 플랫폼 간에 저장 게임 변환할 수 없음 @@ -4445,97 +4527,97 @@ Download size: %3 출력 파일 - + %1 %2 save game %1 %2 저장 게임 - + little endian 리틀 엔디안 - + big endian 빅 엔디안 - + SRAM SRAM - + %1 flash %1 플래시 - + %1 EEPROM %1 EEPROM - + + RTC - + + RTC - + %1 SRAM + RTC %1 SRAM + RTC - + %1 SRAM %1 SRAM - + packed MBC2 팩킹된 MBC2 - + unpacked MBC2 언팩킹된 MBC2 - + MBC6 flash MBC6 플래시 - + MBC6 combined SRAM + flash MBC6 결합 SRAM + 플래시 - + MBC6 SRAM MBC6 SRAM - + TAMA5 TAMA5 - + %1 (%2) %1 (%2) - + %1 save state with embedded %2 save game 포함된 %2 저장 게임이 있는 %1 저장 상태 - + %1 SharkPort %2 save game %1 샤크포트 %2 게임 저장 - + %1 GameShark Advance SP %2 save game %1 게임샤크 어드밴스 SP %2 게임 저장 @@ -4571,32 +4653,37 @@ Download size: %3 최근 스크립트 로드 - + Load script... 스크립트 로드... - + + &Load most recent + + + + &Reset 재설정 (&R) - + 0 0 - + Select script to load 로드할 스크립트 선택 - + Lua scripts (*.lua) 루아 스크립트 (*.lua) - + All files (*.*) 모든 파일 (*.*) @@ -4689,112 +4776,112 @@ Download size: %3 QGBA::SettingsView - - + + Qt Multimedia Qt 멀티미디어 - + SDL SDL - + Software (Qt) 소프트웨어 (Qt) - + OpenGL 오픈GL - + OpenGL (force version 1.x) 오픈GL (버전 1.x 강제) - + None 없음 - + None (Still Image) 없음 (정지 이미지) - + Keyboard 키보드 - + Controllers 컨트롤러 - + Shortcuts 단축키 - - + + Shaders 쉐이더 - + Select BIOS 바이오스 선택 - + Select directory 디렉토리 선택 - + Select image - 이미지 선택 + 이미지 선택 - + Image file (*.png *.jpg *.jpeg) - 이미지 파일 (*.png *.jpg *.jpeg) + 이미지 파일 (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never 절대 - + Just now 방금 - + Less than an hour ago 1시간 미만 전 - + %n hour(s) ago %n 시간 전 - + %n day(s) ago %n 일 전 @@ -5067,7 +5154,7 @@ Download size: %3 Custom border: - + 커스텀 테두리: @@ -5112,40 +5199,40 @@ Download size: %3 Rewind speed: - + 되감기 속도: - + Default color palette only 기본 색상 팔레트만 - + SGB color palette if available 가능한 경우 SGB 색상 팔레트 - + GBC color palette if available 가능한 경우 GBC 색상 팔레트 - + SGB (preferred) or GBC color palette if available 사용 가능한 경우 SGB (선호) 또는 GBC 색상 팔레트 - + Game Boy Camera 게임 보이 카메라 - + Driver: 드라이버: - + Source: 소스: @@ -5216,42 +5303,42 @@ Download size: %3 상태 추가 데이터 로드: - + Models 모델 - + GB only: GB 전용: - + SGB compatible: SGB 호환: - + GBC only: GBC 전용: - + GBC compatible: GBC 호환: - + SGB and GBC compatible: SGB 와 GBC 호환: - + Game Boy palette 게임 보이 팔레트 - + Preset: 사전 설정: @@ -5276,62 +5363,57 @@ Download size: %3 소프트웨어 - + OpenGL enhancements OpenGL 개선 사항 - + High-resolution scale: 고해상도 스케일: - + (240×160) (240×160) - - XQ GBA audio (experimental) - XQ GBA 오디오 (시험용) - - - + Cheats 치트 - + Default BG colors: 기본 배경 색상: - + Super Game Boy borders 슈퍼 게임 보이 테두리 - + Default sprite colors 1: 기본 스프라이트 색상 1: - + Log to file 파일에 기록 - + Log to console 콘솔에 기록 - + Select Log File 로그 파일 선택 - + Default sprite colors 2: 기본 스프라이트 색상 2: @@ -5357,25 +5439,25 @@ Download size: %3 - - - - - - - - - + + + + + + + + + Browse 브라우저 - + Use BIOS file if found 발견되면 바이오스 파일 사용 - + Skip BIOS intro 바이오스 소개 건너 뛰기 @@ -5483,51 +5565,51 @@ Download size: %3 Intervallo Autofire: - + GB BIOS file: GB 바이오스 파일: - + GBA BIOS file: GBA 바이오스 파일: - + GBC BIOS file: GBC 바이오스 파일: - + SGB BIOS file: SGB 바이오스 파일: - + Save games 게임 저장 - - - - - + + + + + Same directory as the ROM 롬과 같은 디렉토리 - + Save states 저장 파일 상태 - + Screenshots 스크린샷 - + Patches 패치 @@ -5775,7 +5857,6 @@ Download size: %3 - WebM WebM @@ -5784,32 +5865,11 @@ Download size: %3 Format 형식 - - - MKV - MKV - - - - AVI - AVI - - MP4 MP4 - - - HEVC - HEVC - - - - VP8 - VP8 - High &Quality @@ -5850,72 +5910,6 @@ Download size: %3 &Native 실기 (&N) - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - 없음 - - - - FLAC - FLAC - - - - WavPack - Wav팩 - - - - Opus - 오푸스 - - - - Vorbis - 보비스 - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - 미압축 - Bitrate (kbps) @@ -5955,95 +5949,95 @@ Download size: %3 QGBA::Window - + Archives (%1) 아카이브 (%1) - - + + Select ROM 롬 선택 - - + + Select save 저장 파일 선택 - + Select patch 패치 선택 - + Patches (*.ips *.ups *.bps) 패치 (*.ips *.ups *.bps) - + Select e-Reader dotcode e-리더 도트코드 선택 - + e-Reader card (*.raw *.bin *.bmp) e-리더 카드 (*.raw *.bin *.bmp) - + Select e-Reader card images e-리더 카드 이미지 선택 - + Image file (*.png *.jpg *.jpeg) 이미지 파일 (*.png *.jpg *.jpeg) - + Conversion finished 변환 완료 - + %1 of %2 e-Reader cards converted successfully. %2 e-리더 카드 중 %1이(가) 성공적으로 변환되었습니다. - + Select image 이미지 선택 - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 이미지 파일 (*.png *.gif *.jpg *.jpeg);;모든 파일 (*) - + GameShark saves (*.sps *.xps) 게임샤크 저장 파일 (*.sps *.xps) - + Select video log 비디오 로그 선택 - + Video logs (*.mvl) 비디오 로그 (*.mvl) - + Crash 치명적인 오류 - + The game has crashed with the following error: %1 @@ -6052,684 +6046,694 @@ Download size: %3 %1 - + Unimplemented BIOS call 구현되지 않은 바이오스 호출 - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. 이 게임은 구현되지 않은 바이오스 호출을 사용합니다. 최상의 성능을 얻으려면 공식 바이오스를 사용하십시오. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. 적절한 디스플레이 장치를 생성하지 못했습니다. 소프트웨어 디스플레이로 돌아갑니다. 특히 큰 창에서는 게임이 느리게 실행될 수 있습니다. - + Really make portable? 정말로 휴대용을 만듭니까? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? 이렇게하면 에뮬레이터가 실행 파일과 동일한 디렉토리에서 구성을 로드하게됩니다. 계속 하시겠습니까? - + Restart needed 재시작 필요 - + Some changes will not take effect until the emulator is restarted. 일부 변경 사항은 에뮬레이터가 다시 시작될 때까지 적용되지 않습니다. - + Reset needed 재설정 필요 - + Some changes will not take effect until the game is reset. 일부 변경 사항은 게임이 재설정될 때까지 적용되지 않습니다. - + - Player %1 of %2 - 플레이어 %1 의 %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &파일 - + Load &ROM... 로드 &롬... - + Load ROM in archive... 롬을 아카이브에 로드... - + Save games 게임 저장 - + Automatically determine 자동으로 결정 - + Use player %0 save game 플레이어 %0 저장 게임 사용 - + Load &patch... 로드 &패치... - + Boot BIOS BIOS 부팅 - + Replace ROM... 롬 교체... - + Scan e-Reader dotcodes... e-리더 도트코드 스캔... - + Game state views 게임 상태 보기 - + Convert e-Reader card image to raw... e-리더 카드 이미지를 원시 데이터로 변환... - + ROM &info... 롬 &정보... - + Recent 최근 실행 - + Make portable 휴대용 만들기 - + &Load state &로드 파일 상태 - + &Save state &저장 파일 상태 - + Quick load 빠른 로드 - + Quick save 빠른 저장 - + Load recent 최근 실행 로드 - + Save recent 최근 실행 저장 - + Undo load state 로드 파일 상태 복원 - + Undo save state 저장 파일 상태 복원 - - + + State &%1 상태 &%1 - + Load camera image... 카메라 이미지 로드... - + Convert save game... 저장 게임 변환... - + GameShark saves (*.gsv *.sps *.xps) 게임샤크 저장 (*.gsv *.sps *.xps) - + New multiplayer window 새로운 멀티 플레이어 창 - + Connect to Dolphin... 돌핀에 연결... - + E&xit 종&료 - + &Emulation &에뮬레이션 - + &Reset &재설정 - + Sh&utdown 종&료 - + Yank game pak 양키 게임 팩 - + &Pause &정지 - + &Next frame &다음 프레임 - + Fast forward (held) 빨리 감기 (누름) - + &Fast forward &빨리 감기 - + Fast forward speed 빨리 감기 속도 - + Unbounded 무제한 - + %0x %0x - - - Increase fast forward speed - - - Decrease fast forward speed - + Increase fast forward speed + 빨리 감기 속도 향상 + Decrease fast forward speed + 빨리 감기 속도 줄이기 + + + Rewind (held) 되김기 (누름) - + Re&wind 리&와인드 - + Step backwards 돌아가기 - + Brightest solar level 가장 밝은 태양 수준 - + Darkest solar level 가장 어두운 태양 수준 - + Brightness %1 밝기 %1 - + Audio/&Video 오디오/&비디오 - + Frame size 프레임 크기 - + Toggle fullscreen 전체화면 전환 - + + &Lock frame size + + + + Lock aspect ratio 화면비 잠금 - + Frame&skip 프레임&건너뛰기 - + Mute 무음 - + FPS target FPS 대상 - + Take &screenshot 스크린샷 &찍기 - + F12 F12 - + Video layers 비디오 레이어 - + Audio channels 오디오 채널 - + &Tools &도구 - + View &logs... 로그 &보기... - + Game &overrides... 게임 &오버라이드... - + &Cheats... &치트.. - + Create forwarder... 전달자 생성... - + Open debugger console... 디버거 콘솔 열기... - + Start &GDB server... GDB 서버 &시작... - + Settings... 설정... - + Select folder 폴더 선택 - + Couldn't Start 시작할 수 없음 - + Could not start game. 게임을 시작할 수 없습니다. - + Add folder to library... 라이브러리에 폴더 추가... - + Load state file... 상태 파일 로드... - + Save state file... 상태 파일 저장... - + Import GameShark Save... 게임샤크 저장 가져오기... - + Export GameShark Save... 게임샤크 저장 내보내기... - + Report bug... 버그를 제보하기... - + About... 정보... - + Solar sensor 태양광 센서 - + Increase solar level 태양광 레벨 증가 - + Decrease solar level 태양광 레벨 감소 - + Force integer scaling 정수 스케일링 강제 수행 - + Bilinear filtering 이중선형 필터링 - + Game Boy Printer... 게임 보이 프린터... - + Save games (%1) 게임 (%1) 저장 - + Select save game 저장 게임 선택 - + mGBA save state files (%1) mGBA 저장 상태 파일 (%1) - - + + Select save state 저장 상태 선택 - + Load alternate save game... 대체 저장 게임 로드... - + Load temporary save game... 임시 저장 게임 로드... - + BattleChip Gate... 배틀칩 게이트... - + %1× %1× - + Interframe blending 프레임간 조합 - + Native (59.7275) 실기 (59.7275) - + Record A/V... A/V 녹화... - + Record GIF/WebP/APNG... GIF/WebP/APNG 녹화... - + Adjust layer placement... 레이어 배치 조정... - + Game Pak sensors... 게임 팩 센서... - + Scripting... 스크립팅... - + View &palette... 팔레트 &보기... - + View &sprites... 스프라이트 &보기... - + View &tiles... 타일 &보기... - + View &map... 지도 &보기... - + &Frame inspector... 프레임 검사기 (&F)... - + View memory... 메모리 보기... - + Search memory... 메모리 검색... - + View &I/O registers... I/O 레지스터 &보기... - + + Log memory &accesses... + + + + Record debug video log... 디버그 비디오 로그 녹화... - + Stop debug video log 디버그 비디오 로그 중지 - + Exit fullscreen 전체화면 종료 - + GameShark Button (held) 게임샤크 버튼 (누름) - + Autofire 연사 - + Autofire A 연사 A - + Autofire B 연사 B - + Autofire L 연사 L - + Autofire R 연사 R - + Autofire Start 연사 시작 - + Autofire Select 연사 선택 - + Clear 지움 - + Autofire Up 연사 위쪽 - + Autofire Right 연사 오른쪽 - + Autofire Down 연사 아래쪽 - + Autofire Left 연사 왼쪽 @@ -6767,40 +6771,40 @@ Download size: %3 ? - + Super (L) - 슈퍼 (L) + 슈퍼 (L) - + Super (R) - 슈퍼 (R) + 슈퍼 (R) - + Menu - 메뉴 + 메뉴 QShortcut - + Shift 시프트 키 - + Control 콘트롤 키 - + Alt 알트 키 - + Meta 메타 diff --git a/src/platform/qt/ts/mgba-ms.ts b/src/platform/qt/ts/mgba-ms.ts index cb327e334..e606a3a96 100644 --- a/src/platform/qt/ts/mgba-ms.ts +++ b/src/platform/qt/ts/mgba-ms.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) ROM Game Boy Advance (%1) - + Game Boy ROMs (%1) ROM Game Boy (%1) - + All ROMs (%1) Semua ROM (%1) - + %1 Video Logs (*.mvl) %1 Log Video (*.mvl) @@ -185,17 +185,17 @@ Download size: %3 QGBA::AudioDevice - + Can't set format of context-less audio device - + Audio device is missing its core - + Writing data to read-only audio device @@ -203,7 +203,7 @@ Download size: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input @@ -279,28 +279,28 @@ Download size: %3 Lanjutan - + BattleChip data missing - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? - - + + Select deck file - + Incompatible deck - + The selected deck is not compatible with this Chip Gate @@ -361,19 +361,19 @@ Download size: %3 Masuk kod di sini... - - + + Autodetect (recommended) - - + + Select cheats file Pilih fail tipu - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. @@ -392,37 +392,37 @@ Download size: %3 - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Gagal membuka fail tersimpan: %1 - + Failed to open game file: %1 Gagal membuka fail permainan: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 Gagal membuka fail snapshot untuk baca: %1 - + Failed to open snapshot file for writing: %1 Gagal membuka fail snapshot untuk menulis: %1 @@ -471,6 +471,14 @@ Download size: %3 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -751,52 +759,52 @@ Download size: %3 Tetap semula - + Export frame Eksport bingkai - + Portable Network Graphics (*.png) Grafik Rangkaian Mudah Alih (*.png) - + None Tiada - + Background Latar belakang - + Window Tetingkap - + Objwin Objwin - + Sprite - + Backdrop - + Frame Bingkai - + %1 %2 %1 %2 @@ -812,22 +820,22 @@ Download size: %3 QGBA::GBAKeyEditor - + Clear Button - + Clear Analog - + Refresh Segar Semula - + Set all @@ -3000,8 +3008,8 @@ Download size: %3 QGBA::KeyEditor - - + + --- --- @@ -3372,23 +3380,87 @@ Download size: %3 - - - + + + N/A - + Export map Eksport peta - + Portable Network Graphics (*.png) Grafik Rangkaian Mudah Alih (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Pilih fail + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + Mula + + + + Stop + Henti + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3635,22 +3707,22 @@ Download size: %3 Segar Semula - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 bait%2 @@ -3744,17 +3816,17 @@ Download size: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -4151,35 +4223,35 @@ Download size: %3 Eksport OBJ - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette Eksport palet - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Jadual Warna Adobe(*.act) - + Failed to open output palette file: %1 Gagal membuka fail palet output: %1 @@ -4253,7 +4325,7 @@ Download size: %3 QGBA::ROMInfo - + @@ -4293,16 +4365,26 @@ Download size: %3 + Maker Code: + + + + + Revision: + + + + File size: Saiz fail: - + CRC32: CRC32: - + Save file: @@ -4358,62 +4440,62 @@ Download size: %3 QGBA::SaveConverter - + Save games and save states (%1) Simpanan permainan dan keadaan tersimpan (%1) - + Select save game or save state Pilih simpanan permainan atau keadaan tersimpan - + Save games (%1) Simpanan permainan (%1) - + Select save game Pilih simpanan permainan - + Conversion failed Penukaran gagal - + Failed to convert the save game. This is probably a bug. Gagal menukar simpanan permainan. Mungkin ini suatu pepijat. - + No file selected Tiada pilihan - + Could not open file Tidak dapat membuka fail - + No valid formats found Tiada format yang sah ditemui - + Please select a valid input file Sila pilih fail input yang sah - + No valid conversions found Tiada penukaran yang sah ditemui - + Cannot convert save games between platforms Tidak boleh menukar simpanan permainan antara platform @@ -4439,97 +4521,97 @@ Download size: %3 Fail output - + %1 %2 save game Simpanan permainan %1 %2 - + little endian little-endian - + big endian big-endian - + SRAM SRAM - + %1 flash %1 kilat - + %1 EEPROM %1 EEPROM - + + RTC - + %1 SRAM + RTC %1 SRAM + RTC - + %1 SRAM %1 SRAM - + packed MBC2 - + unpacked MBC2 - + MBC6 flash Kilat MBC6 - + MBC6 combined SRAM + flash MBC6 bergabung SRAM + kilat - + MBC6 SRAM SRAM MBC6 - + TAMA5 TAMA5 - + %1 (%2) %1 (%2) - + %1 save state with embedded %2 save game Keadaan tersimpan %1 dgn simpanan permainan terbenam %2 - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4565,32 +4647,37 @@ Download size: %3 - + Load script... - + + &Load most recent + + + + &Reset - + 0 4K {0?} - + Select script to load - + Lua scripts (*.lua) - + All files (*.*) @@ -4683,112 +4770,112 @@ Download size: %3 QGBA::SettingsView - - + + Qt Multimedia Multimedia Qt - + SDL SDL - + Software (Qt) Perisian (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (paksa versi 1.x) - + None Tiada - + None (Still Image) Tiada (Gambar Tenang) - + Keyboard Papan Kekunci - + Controllers Pengawal - + Shortcuts Pintas - - + + Shaders - + Select BIOS Pilih BIOS - + Select directory Pilih direktori - + Select image Pilih gambar - + Image file (*.png *.jpg *.jpeg) Fail gambar (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -5114,37 +5201,37 @@ Download size: %3 - + Default color palette only Palet warna piawai sahaja - + SGB color palette if available Palet warna SGB jika ada - + GBC color palette if available Palet warna GBC jika ada - + SGB (preferred) or GBC color palette if available SGB (pilihan utama) atau palet warna GBC jika ada - + Game Boy Camera Game Boy Camera - + Driver: Pemacu: - + Source: Sumber: @@ -5321,42 +5408,42 @@ Download size: %3 Data ekstra keadaan muat: - + Models Model - + GB only: GB sahaja: - + SGB compatible: SGB serasi: - + GBC only: GBC sahaja: - + GBC compatible: GBC serasi: - + SGB and GBC compatible: SGB dan GBC serasi: - + Game Boy palette Palet Game Boy - + Preset: Praset: @@ -5393,135 +5480,130 @@ Download size: %3 Perisian - + OpenGL enhancements - + High-resolution scale: - + (240×160) (240×160) - - XQ GBA audio (experimental) - - - - + GB BIOS file: Fail BIOS GB: - - - - - - - - - + + + + + + + + + Browse Pilih fail - + Use BIOS file if found Guna fail BIOS jika ada - + Skip BIOS intro Langkau pendahuluan BIOS - + GBA BIOS file: Fail BIOS GBA: - + GBC BIOS file: Fail BIOS GBC: - + SGB BIOS file: Fail BIOS SGB: - + Save games Simpanan permainan - - - - - + + + + + Same directory as the ROM Direktori sama dengan ROM - + Save states Keadaan tersimpan - + Screenshots Cekupan skrin - + Patches - + Cheats Tipuan - + Log to file Log dalam fail - + Log to console Log dalam konsol - + Select Log File Pilih fail log - + Default BG colors: Warna LB piawai: - + Default sprite colors 1: - + Default sprite colors 2: - + Super Game Boy borders @@ -5779,13 +5861,11 @@ Download size: %3 - WebM WebM - MP4 MP4 @@ -5824,82 +5904,6 @@ Download size: %3 Format Format - - - MKV - MKV - - - - AVI - AVI - - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - Tiada - - - - FLAC - FLAC - - - - WavPack - - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - - Bitrate (kbps) @@ -5910,16 +5914,6 @@ Download size: %3 ABR ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5949,80 +5943,80 @@ Download size: %3 QGBA::Window - + Archives (%1) Arkib (%1) - - + + Select ROM Pilih ROM - + Select folder Pilih folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image Pilih gambar - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Fail gambar (*.png *.gif *.jpg *.jpeg);;Semua fail (*) - + GameShark saves (*.sps *.xps) Simpanan GameShark (*.sps *.xps) - + Select video log Pilih log video - + Video logs (*.mvl) Log video (*.mvl) - + Crash Nahas - + The game has crashed with the following error: %1 @@ -6031,699 +6025,709 @@ Download size: %3 %1 - + Couldn't Start Tidak dapat memula - + Could not start game. Permainan tidak dapat bermula. - + Unimplemented BIOS call Panggilan BIOS yg belum dilaksanakan - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Permainan ini menggunakan panggilan BIOS yang belum dilaksanakan. Sila pakai BIOS rasmi untuk pengalaman yang lebih baik. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Gagal mencipta peranti paparan yang sesuai, berbalik ke paparan perisian. Permainan mungkin menjadi lembap, terutamanya dengan tetingkap besar. - + Really make portable? Betulkah mahu buat jadi mudah alih? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Ini akan menetapkan pelagak untuk muat konfigurasi dari direktori yang sama dengan fail bolehlakunya. Teruskan? - + Restart needed Mula semula diperlukan - + Some changes will not take effect until the emulator is restarted. Beberapa perubahan tidak akan dilaksanakan sehingga pelagak dimula semula. - + - Player %1 of %2 - Pemain %1 dari %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &File - + Load &ROM... Muat %ROM... - + Load ROM in archive... Muat ROM daripada arkib... - + Add folder to library... Tambah folder ke perpustakaan... - + Save games (%1) Simpanan permainan (%1) - + Select save game Pilih simpanan permainan - + mGBA save state files (%1) mGBA fail keadaan tersimpan (%1) - - + + Select save state Pilih keadaan tersimpan - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) Fail gambar (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... Muat simpanan permainan alternatif... - + Load temporary save game... Muat simpanan permainan sementara... - + Load &patch... - + Boot BIOS But BIOS - + Replace ROM... Ganti ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... &Perihal ROM... - + Recent Terkini - + Make portable Buat jadi mudah alih - + &Load state &Muat keadaan - + Load state file... Muat fail keadaan... - + &Save state &Simpan keadaan - + Save state file... Simpan fail keadaan... - + Quick load - + Quick save - + Load recent Muat terkini - + Save recent Simpan terkini - + Undo load state Buat asal keadaan termuat - + Undo save state Buat asal keadaan tersimpan - - + + State &%1 Keadaan &%1 - + Load camera image... Muat gambar kamera... - + Convert save game... Tukar simpanan permainan... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games Simpanan permainan - + Import GameShark Save... Import Simpanan GameShark... - + Export GameShark Save... Eksport Simpanan GameShark... - + Automatically determine - + Use player %0 save game - + New multiplayer window Tetingkap multipemain baru - + Connect to Dolphin... Sambung ke Dolphin... - + Report bug... Laporkan pepijat... - + About... Perihal... - + E&xit &Keluar - + &Emulation Pe&lagak - + &Reset - + Sh&utdown &Matikan - + Yank game pak Alih keluar Game Pak - + &Pause &Jeda - + &Next frame Bingkai se&terusnya - + Fast forward (held) Mundar laju (pegang) - + &Fast forward Mundar &laju - + Fast forward speed Kelajuan mundar laju - + Unbounded Tidak terbatas - + %0x %0x - + Increase fast forward speed - + Decrease fast forward speed - + Rewind (held) Putar balik (pegang) - + Re&wind Ma&ndir - + Step backwards Langkah belakang - + Solar sensor Pengesan suria - + Increase solar level Meningkatkan aras suria - + Decrease solar level Mengurangkan aras suria - + Brightest solar level Aras suria paling terang - + Darkest solar level Aras suria paling gelap - + Brightness %1 Kecerahan %1 - + Game Boy Printer... Pencetak Game Boy... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Audio/&Video - + Frame size Saiz bingkai - + %1× %1× - + Toggle fullscreen Togol skrinpenuh - + + &Lock frame size + + + + Lock aspect ratio Kekalkan nisbah aspek - + Force integer scaling Paksa skala integer - + Interframe blending Persebatian antarabingkai - + Bilinear filtering Penapisan bilinear - + Frame&skip Langkauan &bingkai - + Mute Senyap - + FPS target Sasaran FPS - + Native (59.7275) Asal (59.7275) - + Take &screenshot Ambil &cekupan skrin - + F12 F12 - + Record A/V... Rakam A/V... - + Record GIF/WebP/APNG... Rakam GIF/WebP/APNG... - + Video layers Lapisan video - + Audio channels Saluran audio - + Adjust layer placement... Melaras peletakan lapisan... - + &Tools &Alat - + View &logs... Lihat &log... - + Game &overrides... - + Game Pak sensors... Pengesan Game Pak... - + &Cheats... &Tipu... - + Create forwarder... - + Settings... Tetapan... - + Open debugger console... Buka konsol penyahpepijat... - + Start &GDB server... Mula pelayan &GDB... - + Scripting... - + Game state views - + View &palette... Pelihat &palet... - + View &sprites... - + View &tiles... Pelihat &jubin... - + View &map... Pelihat pe&ta... - + &Frame inspector... Periksa &bingkai... - + View memory... Lihat ingatan... - + Search memory... Cari ingatan... - + View &I/O registers... Lihat daftar &I/O... - + + Log memory &accesses... + + + + Record debug video log... Rakam log video nyahpepijat... - + Stop debug video log Henti log video nyahpepijat - + Exit fullscreen Keluar skrinpenuh - + GameShark Button (held) Butang GameShark (pegang) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Kosongkan @@ -6761,17 +6765,17 @@ Download size: %3 ? - + Super (L) Super (L) - + Super (R) Super (R) - + Menu Menu @@ -6779,22 +6783,22 @@ Download size: %3 QShortcut - + Shift Shift - + Control Ctrl - + Alt Alt - + Meta Meta diff --git a/src/platform/qt/ts/mgba-nb_NO.ts b/src/platform/qt/ts/mgba-nb_NO.ts index 128bee3ac..789faa1f0 100644 --- a/src/platform/qt/ts/mgba-nb_NO.ts +++ b/src/platform/qt/ts/mgba-nb_NO.ts @@ -4,24 +4,24 @@ QGBA - + Game Boy Advance ROMs (%1) - + Game Boy Advance ROM-filer (%1) - + Game Boy ROMs (%1) - + Game Boy ROM-filer (%1) - + All ROMs (%1) - + Alle ROM-filer (%1) - + %1 Video Logs (*.mvl) - + %1-videologger (*.mvl) @@ -34,7 +34,7 @@ <a href="http://mgba.io/">Website</a> • <a href="https://forums.mgba.io/">Forums / Support</a> • <a href="https://patreon.com/mgba">Donate</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Source</a> - <a href="http://mgba.io/">Nettside</a> • <a href="https://forums.mgba.io/">Forum / støtte</a> • <a href="https://patreon.com/mgba">Doner</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Kildekode</a> + <a href="https://mgba.io/">Nettside</a> • <a href="https://forums.mgba.io/">Forum / støtte</a> • <a href="https://patreon.com/mgba">Doner</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Kildekode</a> @@ -64,13 +64,14 @@ Game Boy Advance er et registrert varemerke tilhørende Nintendo Co., Ltd. An update is available - + En oppdatering er tilgjengelig An update to %1 is available. - + En oppdatering til %1 er tilgjengelig. + @@ -96,17 +97,17 @@ Nedlastningsstørrelse: %3 Downloading update... - Laster ned ny versjon … + Laster ned oppdatering … Downloading failed. Please update manually. - + Nedlastingen mislyktes. Vennligst oppdater manuelt. Downloading done. Press OK to restart %1 and install the update. - + Nedlastingen er fullført. Trykk OK for å starte %1 på nytt og installere oppdateringen. @@ -114,22 +115,22 @@ Nedlastningsstørrelse: %3 Stable - + Stabil Development - + Utvikling Unknown - Ukjent + Ukjent (None) - + (Ingen) @@ -137,12 +138,12 @@ Nedlastningsstørrelse: %3 Open in archive... - Åpne i arkiv … + Åpne i arkiv … Loading... - Laster inn … + Laster inn ... @@ -188,17 +189,17 @@ Nedlastningsstørrelse: %3 QGBA::AudioDevice - + Can't set format of context-less audio device - + Audio device is missing its core - + Writing data to read-only audio device Skriver data til skrivebeskyttet lydenhet @@ -206,7 +207,7 @@ Nedlastningsstørrelse: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input @@ -244,7 +245,7 @@ Nedlastningsstørrelse: %3 Load - Last inn + Last inn @@ -264,7 +265,7 @@ Nedlastningsstørrelse: %3 Inserted - + Satt inn @@ -282,28 +283,28 @@ Nedlastningsstørrelse: %3 Vis avanserte innstillinger - + BattleChip data missing - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? - - + + Select deck file - + Incompatible deck - + The selected deck is not compatible with this Chip Gate @@ -313,7 +314,7 @@ Nedlastningsstørrelse: %3 (untitled) - + (uten tittel) @@ -331,7 +332,7 @@ Nedlastningsstørrelse: %3 Add New Code - + Legg til ny kode @@ -341,12 +342,12 @@ Nedlastningsstørrelse: %3 Add Lines - + Legg til linjer Code type - + Kodetype @@ -364,19 +365,19 @@ Nedlastningsstørrelse: %3 Skriv inn koder her … - - + + Autodetect (recommended) - + Auto-oppdag (anbefales) - - + + Select cheats file - Velg juksekodefil + Velg juksekodefil - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. @@ -395,37 +396,37 @@ Nedlastningsstørrelse: %3 - + Reset the game? - + Vil du starte spillet på nytt? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 Klarte ikke å åpne spillfil: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -463,7 +464,7 @@ Nedlastningsstørrelse: %3 Break - + Stopp @@ -474,6 +475,14 @@ Nedlastningsstørrelse: %3 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -514,12 +523,12 @@ Nedlastningsstørrelse: %3 Couldn't Connect - + Kunne ikke koble til Could not connect to Dolphin. - + Klarte ikke å koble til Dolphin. @@ -527,12 +536,12 @@ Nedlastningsstørrelse: %3 3DS - + 3DS Vita - + Vita @@ -540,12 +549,12 @@ Nedlastningsstørrelse: %3 Icon - + Ikon Banner - + Plakat @@ -553,17 +562,17 @@ Nedlastningsstørrelse: %3 Bubble - + Boble Background - Bakgrunn + Bakgrunn Startup - + Oppstart @@ -576,24 +585,24 @@ Nedlastningsstørrelse: %3 Files - + Filer ROM file: - + ROM-fil: Browse - + Bla Output filename: - + Utdata-filnavn: @@ -603,7 +612,7 @@ Nedlastningsstørrelse: %3 Latest stable version - + Nyeste stabile versjon @@ -613,42 +622,42 @@ Nedlastningsstørrelse: %3 Specific file - + Spesifikk fil Base file: - + Grunnfil: System - + System 3DS - + 3DS Vita - + Vita Presentation - + Presentasjon Title: - + Tittel: Images: - + Bilder: @@ -658,17 +667,17 @@ Nedlastningsstørrelse: %3 Preferred size: - + Ønsket størrelse: Select image file - + Velg bildefil Select ROM file - + Velg ROM-fil @@ -678,7 +687,7 @@ Nedlastningsstørrelse: %3 Select base file - + Velg grunnfil @@ -708,12 +717,12 @@ Nedlastningsstørrelse: %3 Select an image - + Velg et bilde Image files (*.png *.jpg *.bmp) - + Bildefiler (*.png *.jpg *.bmp) @@ -736,7 +745,7 @@ Nedlastningsstørrelse: %3 Backdrop color - + Bakgrunnsfarge @@ -754,52 +763,52 @@ Nedlastningsstørrelse: %3 Tilbakestill - + Export frame - + Portable Network Graphics (*.png) - + Portable Network Graphics (*.png) - + None Ingen - + Background Bakgrunn - + Window Vindu - + Objwin - + Objwin - + Sprite - + Backdrop - + Bakgrunn - + Frame - + Ramme - + %1 %2 %1 %2 @@ -815,24 +824,24 @@ Nedlastningsstørrelse: %3 QGBA::GBAKeyEditor - + Clear Button - + Tøm knapper - + Clear Analog - + Tøm analoge - + Refresh Gjenoppfrisk - + Set all - + Sett alle @@ -850,7 +859,7 @@ Nedlastningsstørrelse: %3 Bind address - + Bindingsadresse @@ -860,7 +869,7 @@ Nedlastningsstørrelse: %3 Standard GDB - + Standard GDB @@ -875,7 +884,7 @@ Nedlastningsstørrelse: %3 Break - + Stopp @@ -967,7 +976,7 @@ Nedlastningsstørrelse: %3 Autodetect - + Auto-oppdag @@ -1037,7 +1046,7 @@ Nedlastningsstørrelse: %3 MBC5 + Rumble - + MBC5 + risting @@ -1047,7 +1056,7 @@ Nedlastningsstørrelse: %3 MBC7 (Tilt) - + MBC7 (Tilt) @@ -1082,27 +1091,27 @@ Nedlastningsstørrelse: %3 NT (old 1) - + NT (gammel 1) NT (old 2) - + NT (gammel 2) NT (new) - + NT (ny) Pokémon Jade/Diamond - + Pokémon Jade/Diamond BBD - + BBD @@ -1112,22 +1121,22 @@ Nedlastningsstørrelse: %3 GGB-81 - + GGB-81 Li Cheng - + Li Cheng Sachen (MMC1) - + Sachen (MMC1) Sachen (MMC2) - + Sachen (MMC2) @@ -1135,12 +1144,12 @@ Nedlastningsstørrelse: %3 I/O Viewer - + I/O-visning 0x0000 - + 0x0000 @@ -1212,37 +1221,37 @@ Nedlastningsstørrelse: %3 Enable background 0 - + Skru på bakgrunn 0 Enable background 1 - + Skru på bakgrunn 1 Enable background 2 - + Skru på bakgrunn 2 Enable background 3 - + Skru på bakgrunn 3 Enable OBJ - + Skru på OBJ Enable Window 0 - + Skru på vindu 1 Enable Window 1 - + Skru på vindu 1 @@ -1252,17 +1261,17 @@ Nedlastningsstørrelse: %3 Currently in VBlank - + For øyeblikket i VBlank Currently in HBlank - + For øyeblikket i HBlank Currently in VCounter - + For øyeblikket i VCounter @@ -1311,7 +1320,7 @@ Nedlastningsstørrelse: %3 Enable mosaic - + Skru på flislegging @@ -1319,7 +1328,7 @@ Nedlastningsstørrelse: %3 Enable 256-color - + Skru på 256-fargemodus @@ -1609,7 +1618,7 @@ Nedlastningsstørrelse: %3 Blend mode - + Blendmodus @@ -1742,7 +1751,7 @@ Nedlastningsstørrelse: %3 Initial volume - + Volum ved begynnelse @@ -1801,28 +1810,28 @@ Nedlastningsstørrelse: %3 0% - 0% + 0 % 100% - 100% + 100% 50% - 50% + 50% 25% - 25% + 25% @@ -1830,7 +1839,7 @@ Nedlastningsstørrelse: %3 75% - 75% + 75% @@ -1848,13 +1857,13 @@ Nedlastningsstørrelse: %3 15 - 15 + 15 7 - 7 + 7 @@ -1876,49 +1885,49 @@ Nedlastningsstørrelse: %3 Enable channel 1 right - + Skru på kanal 1 høyre Enable channel 2 right - + Skru på kanal 2 høyre Enable channel 3 right - + Skru på kanal 3 høyre Enable channel 4 right - + Skru på kanal 4 høyre Enable channel 1 left - + Skru på kanal 1 venstre Enable channel 2 left - + Skru på kanal 2 venstre Enable channel 3 left - + Skru på kanal 3 venstre Enable channel 4 left - + Skru på kanal 4 venstre @@ -1954,7 +1963,7 @@ Nedlastningsstørrelse: %3 0 - 0 + 0 @@ -1967,7 +1976,7 @@ Nedlastningsstørrelse: %3 1 - 1 + 1 @@ -2137,22 +2146,22 @@ Nedlastningsstørrelse: %3 Right/A - + Høyre/A Left/B - + Venstre/B Up/Select - + Opp/Select Down/Start - + Ned/Start @@ -2162,7 +2171,7 @@ Nedlastningsstørrelse: %3 Active face buttons - + Skru på hovedknappene @@ -2182,12 +2191,12 @@ Nedlastningsstørrelse: %3 Divider - + Skillelinje 1/16 - 1/16 + 1/16 @@ -2211,7 +2220,7 @@ Nedlastningsstørrelse: %3 Joypad - + Kontroller @@ -2271,13 +2280,13 @@ Nedlastningsstørrelse: %3 0x9800 – 0x9BFF - + 0x9800 – 0x9BFF 0x9C00 – 0x9FFF - + 0x9C00 – 0x9FFF @@ -2287,12 +2296,12 @@ Nedlastningsstørrelse: %3 0x8800 – 0x87FF - + 0x8800 – 0x87FF 0x8000 – 0x8FFF - + 0x8000 – 0x8FFF @@ -2317,12 +2326,12 @@ Nedlastningsstørrelse: %3 0: HBlank - + 0: HBlank 1: VBlank - + 1: VBlank @@ -2479,7 +2488,7 @@ Nedlastningsstørrelse: %3 Red - Rød + Rød @@ -2517,7 +2526,7 @@ Nedlastningsstørrelse: %3 WRAM bank - + WRAM-bank @@ -2569,7 +2578,7 @@ Nedlastningsstørrelse: %3 Fixed - + Fastsatt @@ -2618,7 +2627,7 @@ Nedlastningsstørrelse: %3 Immediate - + Umiddelbart @@ -2654,7 +2663,7 @@ Nedlastningsstørrelse: %3 IRQ - + IRQ @@ -2681,7 +2690,7 @@ Nedlastningsstørrelse: %3 Video Capture - + Videoopptak @@ -2715,7 +2724,7 @@ Nedlastningsstørrelse: %3 1/64 - 1/64 + 1/64 @@ -2724,7 +2733,7 @@ Nedlastningsstørrelse: %3 1/256 - 1/256 + 1/256 @@ -2733,14 +2742,14 @@ Nedlastningsstørrelse: %3 1/1024 - 1/1024 + 1/1024 Cascade - + Cascade @@ -2804,22 +2813,22 @@ Nedlastningsstørrelse: %3 SC - + SC SD - + SD SI - + SI SO - + SO @@ -2855,43 +2864,43 @@ Nedlastningsstørrelse: %3 SIO - + SIO DMA 0 - + DMA 0 DMA 1 - + DMA 1 DMA 2 - + DMA 2 DMA 3 - + DMA 3 Keypad - + Talltastatur Gamepak - + Spillkassett @@ -2905,7 +2914,7 @@ Nedlastningsstørrelse: %3 4 - 4 + 4 @@ -2913,7 +2922,7 @@ Nedlastningsstørrelse: %3 3 - 3 + 3 @@ -2922,7 +2931,7 @@ Nedlastningsstørrelse: %3 2 - 2 + 2 @@ -2931,7 +2940,7 @@ Nedlastningsstørrelse: %3 8 - 8 + 8 @@ -2966,7 +2975,7 @@ Nedlastningsstørrelse: %3 PHI terminal - + PHI-terminal @@ -2977,17 +2986,17 @@ Nedlastningsstørrelse: %3 4.19MHz - + 4,19MHz 8.38MHz - + 8,38MHz 16.78MHz - + 16,78MHz @@ -3003,10 +3012,10 @@ Nedlastningsstørrelse: %3 QGBA::KeyEditor - - + + --- - + --- @@ -3019,7 +3028,7 @@ Nedlastningsstørrelse: %3 Location - + Sted @@ -3034,7 +3043,7 @@ Nedlastningsstørrelse: %3 CRC32 - + CRC32 @@ -3056,7 +3065,7 @@ Nedlastningsstørrelse: %3 No Save - + Ingen lagrefil @@ -3111,12 +3120,12 @@ Nedlastningsstørrelse: %3 Load State - + Last inn tilstand Save State - + Lagre tilstand @@ -3170,12 +3179,12 @@ Nedlastningsstørrelse: %3 Stub - + Stump Game Error - Spillfeil + Spillfeil @@ -3183,7 +3192,7 @@ Nedlastningsstørrelse: %3 [%1] %2: %3 - + [%1] %2: %3 @@ -3208,7 +3217,7 @@ Nedlastningsstørrelse: %3 WARN - + ADVARSEL @@ -3236,7 +3245,7 @@ Nedlastningsstørrelse: %3 Enabled Levels - + Påskrudde nivåer @@ -3246,7 +3255,7 @@ Nedlastningsstørrelse: %3 Stub - + Stump @@ -3266,7 +3275,7 @@ Nedlastningsstørrelse: %3 Fatal - Kritisk + Kritisk @@ -3286,7 +3295,7 @@ Nedlastningsstørrelse: %3 Max Lines - + Maks antall linjer @@ -3304,7 +3313,7 @@ Nedlastningsstørrelse: %3 Export - Eksporter + Eksporter @@ -3342,7 +3351,7 @@ Nedlastningsstørrelse: %3 Xform - + Xform @@ -3352,12 +3361,12 @@ Nedlastningsstørrelse: %3 Mirror - + Speilvend None - Ingen + Ingen @@ -3367,28 +3376,92 @@ Nedlastningsstørrelse: %3 Horizontal - + Horisontal Vertical - + Vertikal - - - + + + N/A I/T - + Export map - + Portable Network Graphics (*.png) + Portable Network Graphics (*.png) + + + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Bla + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + Stopp + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) @@ -3422,7 +3495,7 @@ Nedlastningsstørrelse: %3 Failed to open output file: %1 - Klarte ikke å åpne utdatafil: %1 + Klarte ikke å åpne utdatafil: %1 @@ -3440,22 +3513,22 @@ Nedlastningsstørrelse: %3 Paste - Lim inn + Lim inn Load - Last inn + Last inn All - + Alle Load TBL - + Last inn TBL @@ -3465,7 +3538,7 @@ Nedlastningsstørrelse: %3 Failed to open output file: %1 - Klarte ikke å åpne utdatafil: %1 + Klarte ikke å åpne utdatafil: %1 @@ -3480,12 +3553,12 @@ Nedlastningsstørrelse: %3 TBL - + TBL ISO-8859-1 - + ISO-8859-1 @@ -3519,7 +3592,7 @@ Nedlastningsstørrelse: %3 Numeric - + Numerisk @@ -3535,7 +3608,7 @@ Nedlastningsstørrelse: %3 Guess - + Gjett @@ -3555,17 +3628,17 @@ Nedlastningsstørrelse: %3 Number type - + Nummertype Decimal - + Desimal Hexadecimal - + Heksadesimal @@ -3638,22 +3711,22 @@ Nedlastningsstørrelse: %3 Gjenoppfrisk - + (%0/%1×) - + (%0/%1×) - + (⅟%0×) - + (⅟%0×) - + (%0×) - + (%0×) - + %1 byte%2 @@ -3708,7 +3781,7 @@ Nedlastningsstørrelse: %3 Load TBL - + Last inn TBL @@ -3733,7 +3806,7 @@ Nedlastningsstørrelse: %3 Load - Last inn + Last inn @@ -3741,23 +3814,23 @@ Nedlastningsstørrelse: %3 Frame %1 - + Bilde %1 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -3807,17 +3880,17 @@ Nedlastningsstørrelse: %3 Export - Eksporter + Eksporter Attributes - + Attributter Transform - + Transformer @@ -3851,13 +3924,13 @@ Nedlastningsstørrelse: %3 H Short for horizontal - + H V Short for vertical - + V @@ -3878,7 +3951,7 @@ Nedlastningsstørrelse: %3 Enabled - + Skrudd på @@ -3894,7 +3967,7 @@ Nedlastningsstørrelse: %3 0x%0 - + 0x%0 @@ -3906,7 +3979,7 @@ Nedlastningsstørrelse: %3 --- - + --- @@ -3916,12 +3989,12 @@ Nedlastningsstørrelse: %3 OBJWIN - + OBJWIN Invalid - + Ugyldig @@ -3937,7 +4010,7 @@ Nedlastningsstørrelse: %3 Portable Network Graphics (*.png) - + Portable Network Graphics (*.png) @@ -3945,7 +4018,7 @@ Nedlastningsstørrelse: %3 Game Overrides - + Overstyringer for spill @@ -3958,7 +4031,7 @@ Nedlastningsstørrelse: %3 Autodetect - + Auto-oppdag @@ -3973,7 +4046,7 @@ Nedlastningsstørrelse: %3 Tilt - + Tilt @@ -4013,7 +4086,7 @@ Nedlastningsstørrelse: %3 EEPROM 8kB - + EEPROM 8kB @@ -4033,7 +4106,7 @@ Nedlastningsstørrelse: %3 Game Boy Player features - + Game Boy Player-funksjoner @@ -4043,12 +4116,12 @@ Nedlastningsstørrelse: %3 Game Boy - + Game Boy Game Boy model - + Game Boy-modell @@ -4073,7 +4146,7 @@ Nedlastningsstørrelse: %3 Palette preset - + Forhåndsvalgt fargepalett @@ -4096,7 +4169,7 @@ Nedlastningsstørrelse: %3 Palette - Palett + Palett @@ -4151,38 +4224,38 @@ Nedlastningsstørrelse: %3 Export OBJ - + Eksporter OBJ + + + + #%0 + #%0 + + + + 0x%0 + 0x%0 - #%0 - - - - 0x%0 - - - - - 0x%0 (%1) - 0x%0 (%1) + 0x%0 (%1) - + Export palette Eksporter palett - + Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 @@ -4197,7 +4270,7 @@ Nedlastningsstørrelse: %3 All - + Alle @@ -4207,12 +4280,12 @@ Nedlastningsstørrelse: %3 X - + X Y - + Y @@ -4250,13 +4323,13 @@ Nedlastningsstørrelse: %3 Portable Network Graphics (*.png) - + Portable Network Graphics (*.png) QGBA::ROMInfo - + @@ -4277,35 +4350,45 @@ Nedlastningsstørrelse: %3 ROM Info - + ROM-info Game name: - + Spillets navn: Internal name: - + Internt navn: Game ID: - + Spill-ID: - File size: + Maker Code: - CRC32: + Revision: + File size: + Filstørrelse: + + + + CRC32: + CRC32: + + + Save file: @@ -4335,12 +4418,12 @@ Nedlastningsstørrelse: %3 Generate report - + Generer rapport Save - Lagre + Lagre @@ -4350,7 +4433,7 @@ Nedlastningsstørrelse: %3 Include save file - + Inkluder lagrefilen @@ -4361,62 +4444,62 @@ Nedlastningsstørrelse: %3 QGBA::SaveConverter - + Save games and save states (%1) - + Lagrefiler og lagringstilstander - + Select save game or save state - + Save games (%1) - + Lagrefiler (%1) - + Select save game - + Velg lagrefil - + Conversion failed Konvertering mislyktes - + Failed to convert the save game. This is probably a bug. - + No file selected Ingen fil valgt - + Could not open file Kunne ikke åpne fil - + No valid formats found - + Please select a valid input file Velg en gyldig inndatafil - + No valid conversions found - + Cannot convert save games between platforms @@ -4428,111 +4511,111 @@ Nedlastningsstørrelse: %3 Input file - + Inndatafil Browse - + Bla Output file - + Utdatafil - + %1 %2 save game - + little endian - + big endian - + SRAM - SRAM + SRAM - + %1 flash - + %1 EEPROM - + %1 EEPROM - + + RTC - + %1 SRAM + RTC - + %1 SRAM - + %1 SRAM - + packed MBC2 - + unpacked MBC2 - + MBC6 flash - + MBC6 combined SRAM + flash - + MBC6 SRAM - + MBC6-SRAM - + TAMA5 - TAMA5 + TAMA5 - + %1 (%2) - + %1 (%2) - + %1 save state with embedded %2 save game - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4555,12 +4638,12 @@ Nedlastningsstørrelse: %3 Run - + Kjør File - + Fil @@ -4568,34 +4651,39 @@ Nedlastningsstørrelse: %3 - + Load script... + Last inn skript... + + + + &Load most recent - + &Reset - + &Omstart - + 0 - 0 + 0 - + Select script to load - + Lua scripts (*.lua) - + All files (*.*) - + Alle filer (*.*) @@ -4603,188 +4691,188 @@ Nedlastningsstørrelse: %3 Sensors - + Sensorer Realtime clock - Sanntidsklokke + Sanntidsklokke Fixed time - + Fastsatt tid System time - + Systemtid Start time at - + Start tiden på Now - + Offset time - + Tidsavvik sec - + sek MM/dd/yy hh:mm:ss AP - + dd/mm/YYYY hh:mm:ss AP Light sensor - Lyssensor + Lyssensor Brightness - + Lysstyrke Tilt sensor - + Tiltsensor Set Y - + Sett Y Set X - + Sett X Gyroscope - Gyroskop + Gyroskop Sensitivity - + Følsomhet QGBA::SettingsView - - + + Qt Multimedia - + SDL SDL - + Software (Qt) Programvare (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) - + OpenGL (tving versjon 1.x) - + None - Ingen + Ingen - + None (Still Image) - + Ingen (stillbilde) - + Keyboard Tastatur - + Controllers Kontrollere - + Shortcuts Snarveier - - + + Shaders Skyggeleggere - + Select BIOS Velg BIOS - + Select directory Velg mappe - + Select image - Velg bilde + Velg bilde - + Image file (*.png *.jpg *.jpeg) - + Bildefil (*.png *.jpg *.jpeg) - + (%1×%2) - + (%1×%2) - + Never - + Aldri - + Just now - + Akkurat nå - + Less than an hour ago - + Mindre enn én time siden - + %n hour(s) ago @@ -4792,7 +4880,7 @@ Nedlastningsstørrelse: %3 - + %n day(s) ago @@ -4802,12 +4890,12 @@ Nedlastningsstørrelse: %3 Settings - + Innstillinger Audio/Video - + Lyd/Video @@ -4817,129 +4905,129 @@ Nedlastningsstørrelse: %3 Interface - + Grensesnitt Update - + Oppdater Emulation - + Emulering Enhancements - + Forbedringer BIOS - + BIOS Paths - + Filbaner Logging - + Loggføring Game Boy - + Game Boy Audio driver: - + Lyddriver: Audio buffer: - + Lydbuffer: 1536 - 1536 + 1536 512 - 512 + 512 768 - 768 + 768 1024 - 1024 + 1024 2048 - 2048 + 2048 3072 - 3072 + 3072 4096 - 4096 + 4096 samples - + datapunkter Sample rate: - + Datapunktfrekvens: 44100 - 44100 + 44100 22050 - 22050 + 22050 32000 - 32000 + 32000 48000 - 48000 + 48000 Hz - + Hz Volume: - + Volum: @@ -4947,7 +5035,7 @@ Nedlastningsstørrelse: %3 Mute - + Demp lyd @@ -4957,17 +5045,17 @@ Nedlastningsstørrelse: %3 Audio in multiplayer: - + Lyd i flerspiller: All windows - + Alle vinduer Player 1 window only - + Kun spiller 1 sitt vindu @@ -4977,7 +5065,7 @@ Nedlastningsstørrelse: %3 Display driver: - + Skjermdriver: @@ -4987,45 +5075,45 @@ Nedlastningsstørrelse: %3 Skip every - + Hopp over hver frames - + bilder FPS target: - + Siktemål for bildefrekvens: frames per second - + bilder per sekund Sync: - + Synkroniser: Video - + Video Audio - + Lyd Lock aspect ratio - + Lås visningsforhold @@ -5035,7 +5123,7 @@ Nedlastningsstørrelse: %3 Bilinear filtering - + Bilineær filtrering @@ -5046,7 +5134,7 @@ Nedlastningsstørrelse: %3 Pause - + Pause @@ -5056,7 +5144,7 @@ Nedlastningsstørrelse: %3 On loading a game: - + Når det lastes inn et spill: @@ -5081,32 +5169,32 @@ Nedlastningsstørrelse: %3 Current channel: - + Nåværende kanal: Current version: - + Nåværende versjon: Update channel: - + Oppdateringskanal: Available version: - + Tilgjengelig versjon: (Unknown) - + (Ukjent) Last checked: - + Sist sjekket: @@ -5116,47 +5204,47 @@ Nedlastningsstørrelse: %3 Check now - + Sjekk nå - + Default color palette only - + SGB color palette if available - + SGB-fargepalett hvis tilgjengelig + + + + GBC color palette if available + GBC-fargepalett hvis tilgjengelig - GBC color palette if available - - - - SGB (preferred) or GBC color palette if available - + SGB (foretrukket) eller GBC-fargepalett hvis tilgjengelig - + Game Boy Camera - + Game Boy Camera - + Driver: - + Driver: - + Source: - + Kilde: Native (59.7275) - + Systemstandard (59.7275) @@ -5166,32 +5254,32 @@ Nedlastningsstørrelse: %3 Language - + Språk Library: - + Bibliotek: List view - + Listevisning Tree view - + Tre-visning Show when no game open - + Vis når ingen spill er åpne Clear cache - + Tøm mellomlageret @@ -5231,7 +5319,7 @@ Nedlastningsstørrelse: %3 Show FPS in title bar - + Vis bildefrekvensen i tittellinjen @@ -5272,17 +5360,17 @@ Nedlastningsstørrelse: %3 Enable rewind - + Skru på tilbakespoling Rewind history: - + Tilbakestillingshistorikk: Rewind speed: - + Tilbakespolingsfart: @@ -5292,12 +5380,12 @@ Nedlastningsstørrelse: %3 Run all - + Kjør alle Remove known - + Fjern kjente @@ -5326,56 +5414,56 @@ Nedlastningsstørrelse: %3 - + Models - + Modeller - + GB only: - + Kun GB: - + SGB compatible: - + SGB-kompatibel: - + GBC only: - + Kun GBC: - + GBC compatible: - + GBC-kompatibel: - + SGB and GBC compatible: - + SGB- og GBC-kompatible: - + Game Boy palette - + Game Boy-fargepalett - + Preset: - + Forhåndsinnstilling: Screenshot - + Skjermbilde Cheat codes - + Juksekoder @@ -5395,140 +5483,135 @@ Nedlastningsstørrelse: %3 Software - + Programvare - + OpenGL enhancements - + High-resolution scale: - + (240×160) - + (240×160) - - XQ GBA audio (experimental) - - - - + GB BIOS file: - + GB BIOS-fil: - - - - - - - - - + + + + + + + + + Browse - + Bla - + Use BIOS file if found - + Bruk BIOS-filen hvis den blir funnet - + Skip BIOS intro - + Hopp over BIOS-introen - + GBA BIOS file: - + GBA-BIOS-fil: - + GBC BIOS file: - + GBC-BIOS-fil: - + SGB BIOS file: - + SGB-BIOS-fil: - + Save games - + Lagrefiler - - - - - + + + + + Same directory as the ROM - + Save states - + Screenshots - + Skjermklipp - + Patches - + Patcher - + Cheats - Juks + Juks + + + + Log to file + Loggfør til en fil - Log to file - - - - Log to console - + Select Log File - + Default BG colors: - + Default sprite colors 1: - + Default sprite colors 2: - + Super Game Boy borders - + Super Game Boy-kanter @@ -5567,27 +5650,27 @@ Nedlastningsstørrelse: %3 Shaders - Skyggeleggere + Skygger Active Shader: - + Aktiv skyggelegger: Name - Navn + Navn Author - + Skaper Description - + Beskrivelse @@ -5615,7 +5698,7 @@ Nedlastningsstørrelse: %3 Gamepad - + Kontroller @@ -5628,17 +5711,17 @@ Nedlastningsstørrelse: %3 Keyboard - Tastatur + Tastatur Gamepad - + Kontroller Clear - Tøm + Tøm @@ -5652,7 +5735,7 @@ Nedlastningsstørrelse: %3 Portable Network Graphics (*.png) - + Portable Network Graphics (*.png) @@ -5662,7 +5745,7 @@ Nedlastningsstørrelse: %3 Tiles - + Fliser @@ -5672,22 +5755,22 @@ Nedlastningsstørrelse: %3 Export All - + Eksporter alle 256 colors - + 256 farger Palette - Palett + Palett Magnification - Forstørrelse + Forstørrelse @@ -5697,7 +5780,7 @@ Nedlastningsstørrelse: %3 Fit to window - + Tilpass til vinduet @@ -5717,17 +5800,17 @@ Nedlastningsstørrelse: %3 Both - Begge + Begge Copy Selected - + Kopier valgte Copy All - + Kopier alle @@ -5745,7 +5828,7 @@ Nedlastningsstørrelse: %3 Select output file - Velg utdatafil + Velg utdatafil @@ -5755,44 +5838,42 @@ Nedlastningsstørrelse: %3 Start - Start + Begynn Stop - Stopp + Stopp Select File - Velg fil + Velg fil Presets - + Forhåndsinnstillinger High &Quality - + Høy &kvalitet &YouTube - + &YouTube - WebM - + WebM - MP4 - + MP4 @@ -5802,22 +5883,22 @@ Nedlastningsstørrelse: %3 4K - 4K + 4K &1080p - + &1080p &720p - + &720p &480p - + &480p @@ -5827,93 +5908,7 @@ Nedlastningsstørrelse: %3 Format - - - - - MKV - - - - - AVI - - - - - H.264 - - - - - H.264 (NVENC) - - - - - HEVC - - - - - HEVC (NVENC) - - - - - VP8 - - - - - VP9 - - - - - FFV1 - - - - - - None - Ingen - - - - FLAC - - - - - WavPack - - - - - Opus - - - - - Vorbis - - - - - MP3 - - - - - AAC - - - - - Uncompressed - + Format @@ -5923,812 +5918,822 @@ Nedlastningsstørrelse: %3 ABR - + ABR VBR - + VBR CRF - + CRF Dimensions - Dimensjoner + Dimensjoner Lock aspect ratio - + Lås visningsforhold Show advanced - Vis avanserte innstillinger + Vis avansert QGBA::Window - + Archives (%1) Arkiv (%1) - - + + Select ROM Velg ROM - + Select folder Velg mappe - - + + Select save - + Velg lagrefil - + Select patch Velg feilfiks - + Patches (*.ips *.ups *.bps) Feilfikser (*.ips *.ups *.bps) - + Select e-Reader dotcode - + Velg e-Reader-punktkode - + e-Reader card (*.raw *.bin *.bmp) - + e-Reader-kort (*.raw *.bin *.bmp) - + Select image Velg bilde - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Bildefil (*.png *.gif *.jpg *.jpeg);;All filer (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Videologgføringer (*.mvl) - + Crash - Krasj + Krasj - + The game has crashed with the following error: %1 - + Couldn't Start - + Klarte ikke å starte opp - + Could not start game. - + Klarte ikke å starte opp spillet. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Gjennomfør omstart - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + &Fil - + Load &ROM... - + Last inn &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Lagrefiler (%1) - + Select save game - + Velg lagrefil - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Velg e-Reader-kortavbildninger - + Image file (*.png *.jpg *.jpeg) - + Bildefil (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Oppstarts-BIOS - + Replace ROM... - + Bytt ROM.... - + Scan e-Reader dotcodes... - + Skann e-Reader-punktkoder... - + Convert e-Reader card image to raw... - + ROM &info... - + ROM-&info ... - + Recent - + Nylig - + Make portable - + &Load state - + &Last inn tilstand - + Load state file... - + &Save state - + &Lagre en tilstand - + Save state file... - + Quick load - + Hurtiginnlasting - + Quick save - + Hurtiglagring - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + GameShark-lagrefiler (*.gsv *.sps *.xps) - + Reset needed - + Tilbakestilling kreves - + Some changes will not take effect until the game is reset. - + Save games - + Lagrefiler - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Nytt flerspillervindu - + Connect to Dolphin... - - - - - Report bug... - - - - - About... - + Koble til Dolphin... + Report bug... + Rapporter inn feil... + + + + About... + Om … + + + E&xit - + A&vslutt - + &Emulation - + &Emulering - + &Reset - - - - - Sh&utdown - - - - - Yank game pak - + &Omstart - &Pause - + Sh&utdown + Skr&u av - + + Yank game pak + Dra ut spillkassetten + + + + &Pause + &Pause + + + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - %0x + %0x - + Increase fast forward speed - + Decrease fast forward speed - - - Rewind (held) - - - Re&wind - + Rewind (held) + Spol tilbake (holdt) - + + Re&wind + Spol ti&lbake + + + Step backwards - - - Solar sensor - - - - - Increase solar level - - - - - Decrease solar level - - - - - Brightest solar level - - - - - Darkest solar level - - + Solar sensor + Solsensor + + + + Increase solar level + Øke solnivået + + + + Decrease solar level + Reduser solnivået + + + + Brightest solar level + Lyseste solnivå + + + + Darkest solar level + Mørkeste solnivå + + + Brightness %1 - + Lysstyrke %1 - + Game Boy Printer... - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Lyd/&Video - + Frame size - + Rammestørrelse - + %1× - %1× + %1× - + Toggle fullscreen - + Skru på/av fullskjerm - - Lock aspect ratio - - - - - Force integer scaling - - - - - Interframe blending - - - - - Bilinear filtering + + &Lock frame size + Lock aspect ratio + Lås visningsforhold + + + + Force integer scaling + + + + + Interframe blending + + + + + Bilinear filtering + Bilineær filtrering + + + Frame&skip - + Mute - + Demp lyd - + FPS target - + Native (59.7275) - + Systemstandard (59.7275) - + Take &screenshot - + Ta &skjermbilde - + F12 - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Lydkanaler - + Adjust layer placement... - + &Tools - + Verk&tøy - + View &logs... - + Game &overrides... - + Spilloverstyringer ... - + Game Pak sensors... - + Game Pak-sensorer ... - + &Cheats... - + Create forwarder... - + Settings... - + Innstillinger… - + Open debugger console... - + Start &GDB server... - + Scripting... - + Game state views - + View &palette... - + Vis &palett ... - + View &sprites... - + View &tiles... - + View &map... - + Vis &kart … - + &Frame inspector... - + View memory... - + Vis minne ... - + Search memory... - + Søk i minne ... - + View &I/O registers... - + + Log memory &accesses... + + + + Record debug video log... - + Stop debug video log - + Exit fullscreen - + Gå ut av fullskjerm - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear - Tøm + Tøm @@ -6736,70 +6741,70 @@ Nedlastningsstørrelse: %3 %1 byte - + %1 byte %1 kiB - + %1 kiB %1 MiB - + %1 MiB GBA - + GBA GB - + GB ? - + ? - + Super (L) - + Super (L) - + Super (R) - + Super (R) - + Menu - Meny + Meny QShortcut - + Shift - + Shift - + Control - + Kontroll - + Alt - + Alt - + Meta - + Meta diff --git a/src/platform/qt/ts/mgba-pl.ts b/src/platform/qt/ts/mgba-pl.ts index 180b32630..12ce34462 100644 --- a/src/platform/qt/ts/mgba-pl.ts +++ b/src/platform/qt/ts/mgba-pl.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) ROMy Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMy Game Boy (%1) - + All ROMs (%1) Wszystkie ROMy (%1) - + %1 Video Logs (*.mvl) Dzienniki wideo %1 (*.mvl) @@ -191,17 +191,17 @@ Rozmiar pobierania: %3 QGBA::AudioDevice - + Can't set format of context-less audio device Nie można ustawić formatu bezkontekstowego urządzenia audio - + Audio device is missing its core Urządzenie audio nie ma rdzenia - + Writing data to read-only audio device Zapisywanie danych na urządzeniu audio tylko do odczytu @@ -209,7 +209,7 @@ Rozmiar pobierania: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input Nie można uruchomić procesora dźwięku bez wejścia @@ -285,28 +285,28 @@ Rozmiar pobierania: %3 Pokaż zaawansowane opcje - + BattleChip data missing Brak danych BattleChip - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? Brak danych BattleChip. BattleChip Gates nadal będzie działać, ale będzie brakować niektórych elementów graficznych. Czy chcesz teraz pobrać dane? - - + + Select deck file Wybierz plik deck - + Incompatible deck Niezgodny deck - + The selected deck is not compatible with this Chip Gate Wybrany deck nie jest kompatybilny z tym Chip Gate @@ -367,19 +367,19 @@ Rozmiar pobierania: %3 Wpisz kody tutaj... - - + + Autodetect (recommended) Automatyczne wykrywanie (zalecane) - - + + Select cheats file Wybierz plik z kodami - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. Nie udało się dodać niektórych kodów. Upewnij się, że są poprawnie sformatowane i/lub wypróbuj inne typy kodów. @@ -398,37 +398,37 @@ Rozmiar pobierania: %3 Przewijanie nie jest obecnie włączone - + Reset the game? Zresetować grę? - + Most games will require a reset to load the new save. Do you want to reset now? Większość gier wymaga zresetowania, aby wczytać nowy zapis. Czy chcesz teraz zresetować? - + Failed to open save file: %1 Nie udało się otworzyć pliku zapisu: %1 - + Failed to open game file: %1 Nie udało się otworzyć pliku gry: %1 - + Can't yank pack in unexpected platform! Nie można wyciągnąć pack na nieoczekiwanej platformie! - + Failed to open snapshot file for reading: %1 Nie udało się otworzyć pliku snapshot do odczytu: %1 - + Failed to open snapshot file for writing: %1 Nie udało się otworzyć pliku snapshot do zapisu: %1 @@ -477,6 +477,14 @@ Rozmiar pobierania: %3 Nie można otworzyć historii CLI do zapisu + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -716,7 +724,7 @@ Rozmiar pobierania: %3 Image files (*.png *.jpg *.bmp) - + Obrazy (*.png *.jpg *.bmp) @@ -757,52 +765,52 @@ Rozmiar pobierania: %3 Resetuj - + Export frame Eksportuj klatkę - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Nic - + Background Tło - + Window Okno - + Objwin Obiwin - + Sprite Sprite - + Backdrop Zasłona - + Frame Klatka - + %1 %2 %1 %2 @@ -818,22 +826,22 @@ Rozmiar pobierania: %3 QGBA::GBAKeyEditor - + Clear Button Wyczyść Przycisk - + Clear Analog Wyczyść Analog - + Refresh Odśwież - + Set all Ustaw wszystko @@ -3006,8 +3014,8 @@ Rozmiar pobierania: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Rozmiar pobierania: %3 Pionowy - - - + + + N/A N/D - + Export map Eksportuj mapę - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Przeglądaj + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + Start + + + + Stop + Stop + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Rozmiar pobierania: %3 Odśwież - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 bajt%2 @@ -3750,19 +3822,19 @@ Rozmiar pobierania: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Próba odłączenia gracza multiplayer, który nie jest dołączony - + Trying to get player ID for a multiplayer player that's not attached - + Próba uzyskania ID gracza w trybie wieloosobowym, który nie jest połączony - + Trying to get save ID for a multiplayer player that's not attached - + Próba uzyskania identyfikatora zapisu dla gracza multiplayer, który nie jest połączony @@ -4157,35 +4229,35 @@ Rozmiar pobierania: %3 Eksportuj OBI - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette Eksportuj paletę - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 Nie udało się otworzyć pliku palety wyjściowej: %1 @@ -4259,7 +4331,7 @@ Rozmiar pobierania: %3 QGBA::ROMInfo - + @@ -4299,18 +4371,28 @@ Rozmiar pobierania: %3 + Maker Code: + + + + + Revision: + + + + File size: Rozmiar pliku: - + CRC32: CRC32: - + Save file: - + Zapisz plik: @@ -4364,62 +4446,62 @@ Rozmiar pobierania: %3 QGBA::SaveConverter - + Save games and save states (%1) Zapisane gry i stany zapisu (%1) - + Select save game or save state Wybierz zapis gry lub stan zapisu - + Save games (%1) Zapisane gry (%1) - + Select save game Wybierz zapis gry - + Conversion failed Konwersja nie powiodła się - + Failed to convert the save game. This is probably a bug. Nie udało się przekonwertować zapisanej gry. To prawdopodobnie błąd. - + No file selected Nie wybrano pliku - + Could not open file Nie można otworzyć pliku - + No valid formats found Nie znaleziono prawidłowych formatów - + Please select a valid input file Wybierz prawidłowy plik wejściowy - + No valid conversions found Nie znaleziono prawidłowych konwersji - + Cannot convert save games between platforms Nie można konwertować zapisanych gier między platformami @@ -4445,97 +4527,97 @@ Rozmiar pobierania: %3 Plik wyjściowy - + %1 %2 save game %1 %2 zapis gry - + little endian little endian - + big endian big endian - + SRAM SRAM - + %1 flash %1 flash - + %1 EEPROM %1 EEPROM - + + RTC - + + RTC - + %1 SRAM + RTC %1 SRAM + RTC - + %1 SRAM %1 SRAM - + packed MBC2 MBC2 skompresowane - + unpacked MBC2 MBC2 nieskompresowany - + MBC6 flash MBC6 Flash - + MBC6 combined SRAM + flash MBC6 łączny SRAM + flash - + MBC6 SRAM MBC6 SRAM - + TAMA5 TAMA5 - + %1 (%2) %1 (%2) - + %1 save state with embedded %2 save game %1 stan gry z osadzonym %2 zapisem gry - + %1 SharkPort %2 save game %1 SharkPort %2 zapis gry - + %1 GameShark Advance SP %2 save game %1 GameShark Advance SP %2 zapis gry @@ -4571,32 +4653,37 @@ Rozmiar pobierania: %3 Załaduj ostatni skrypt - + Load script... Załaduj skrypt... - + + &Load most recent + + + + &Reset &Resetuj - + 0 0 - + Select script to load Wybierz skrypt do załadowania - + Lua scripts (*.lua) Skrypty Lua (*.lua) - + All files (*.*) Wszystkie pliki (*.*) @@ -4689,105 +4776,105 @@ Rozmiar pobierania: %3 QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (wymuś wersję 1.x) - + None Nic - + None (Still Image) Brak (Obraz Nieruchomy) - + Keyboard Klawiatura - + Controllers Kontrolery - + Shortcuts Skróty - - + + Shaders Shadery - + Select BIOS Wybierz BIOS - + Select directory Wybierz katalog - + Select image - Wybierz obraz + Wybierz obraz - + Image file (*.png *.jpg *.jpeg) - Plik graficzny (*.png *.jpg *.jpeg) + Plik graficzny (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never Nigdy - + Just now Właśnie teraz - + Less than an hour ago Mniej niż godzinę temu - + %n hour(s) ago %n godzinę temu @@ -4796,7 +4883,7 @@ Rozmiar pobierania: %3 - + %n day(s) ago %n dzień temu @@ -5124,37 +5211,37 @@ Rozmiar pobierania: %3 Sprawdź teraz - + Default color palette only Tylko domyślna paleta kolorów - + SGB color palette if available Paleta kolorów SGB, jeśli jest dostępna - + GBC color palette if available Paleta kolorów GBC, jeśli jest dostępna - + SGB (preferred) or GBC color palette if available Paleta kolorów SGB (preferowana) lub GBC, jeśli jest dostępna - + Game Boy Camera Game Boy Camera - + Driver: Sterownik: - + Source: Źródło: @@ -5251,7 +5338,7 @@ Rozmiar pobierania: %3 Custom border: - + Niestandardowa ramka: @@ -5287,7 +5374,7 @@ Rozmiar pobierania: %3 Rewind speed: - + Prędkość przewijania: @@ -5331,42 +5418,42 @@ Rozmiar pobierania: %3 Dodatkowe dane ładowania stanu gry: - + Models Modele - + GB only: Tylko GB: - + SGB compatible: Kompatybilny z SGB: - + GBC only: Tylko GBC: - + GBC compatible: Kompatybilny z GBC: - + SGB and GBC compatible: Kompatybilny z SGB i GBC: - + Game Boy palette Paleta Game Boy - + Preset: Ustawienie wstępne: @@ -5403,135 +5490,130 @@ Rozmiar pobierania: %3 Software - + OpenGL enhancements Ulepszenia OpenGL - + High-resolution scale: Skala o wysokiej rozdzielczości: - + (240×160) (240×160) - - XQ GBA audio (experimental) - Dźwięk wysokiej jakości GBA (eksperymentalny) - - - + GB BIOS file: Plik BIOS GB: - - - - - - - - - + + + + + + + + + Browse Przeglądaj - + Use BIOS file if found Użyj pliku BIOS, jeśli zostanie znaleziony - + Skip BIOS intro Pomiń wprowadzenie BIOS - + GBA BIOS file: Plik BIOS GBA: - + GBC BIOS file: Plik BIOS GBC: - + SGB BIOS file: Plik BIOS SGB: - + Save games Zapisane gry - - - - - + + + + + Same directory as the ROM Ten sam katalog co ROM - + Save states Stany gry - + Screenshots Zrzuty ekranu - + Patches Łatki - + Cheats Kody (cheaty) - + Log to file Loguj do pliku - + Log to console Loguj do konsoli - + Select Log File Wybierz plik dziennika - + Default BG colors: Domyślne kolory tła: - + Default sprite colors 1: Domyślne kolory sprite'ów 1: - + Default sprite colors 2: Domyślne kolory sprite'ów 2: - + Super Game Boy borders Ramki Super Game Boy @@ -5789,13 +5871,11 @@ Rozmiar pobierania: %3 - WebM WebM - MP4 MP4 @@ -5834,82 +5914,6 @@ Rozmiar pobierania: %3 Format Format - - - MKV - MKV - - - - AVI - AVI - - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - Nic - - - - FLAC - FLAC - - - - WavPack - WavPack - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - Nieskompresowany - Bitrate (kbps) @@ -5920,16 +5924,6 @@ Rozmiar pobierania: %3 ABR ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5959,80 +5953,80 @@ Rozmiar pobierania: %3 QGBA::Window - + Archives (%1) Archiwa (%1) - - + + Select ROM Wybierz ROM - + Select folder Wybierz katalog - - + + Select save Wybierz zapis - + Select patch Wybierz łatkę - + Patches (*.ips *.ups *.bps) Łatki (*.ips *.ups *.bps) - + Select e-Reader dotcode Wybierz kod kropki e-Reader - + e-Reader card (*.raw *.bin *.bmp) Karta e-Reader (*.raw *.bin *.bmp) - + Select image Wybierz obraz - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Plik obrazu (*.png *.gif *.jpg *.jpeg);;Wszystkie pliki (*) - + GameShark saves (*.sps *.xps) Zapisy GameShark (*.sps *.xps) - + Select video log Wybierz dziennik wideo - + Video logs (*.mvl) Dzienniki wideo (*.mvl) - + Crash Crash - + The game has crashed with the following error: %1 @@ -6041,699 +6035,709 @@ Rozmiar pobierania: %3 %1 - + Couldn't Start Nie udało się uruchomić - + Could not start game. Nie udało się rozpocząć gry. - + Unimplemented BIOS call Niewdrożone wywołanie BIOS - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Ta gra używa wywołania BIOS, które nie jest zaimplementowane. Aby uzyskać najlepsze wrażenia, użyj oficjalnego BIOS. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Nie udało się utworzyć odpowiedniego urządzenia wyświetlającego, powracam do wyświetlania programowego. Gry mogą działać wolno, zwłaszcza w przypadku większych okien. - + Really make portable? Naprawdę stworzyć wersję portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? To sprawi, że emulator załaduje swoją konfigurację z tego samego katalogu, co plik wykonywalny. Czy chcesz kontynuować? - + Restart needed Wymagane ponowne uruchomienie - + Some changes will not take effect until the emulator is restarted. Niektóre zmiany nie zaczną obowiązywać, dopóki emulator nie zostanie ponownie uruchomiony. - + - Player %1 of %2 - Gracz %1 z %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 FPS) - %4 - + &File &Plik - + Load &ROM... Załaduj &ROM... - + Load ROM in archive... Załaduj ROM w archiwum... - + Add folder to library... Dodaj folder do biblioteki... - + Save games (%1) Zapisane gry (%1) - + Select save game Wybierz zapis gry - + mGBA save state files (%1) Pliki stanu gry mGBA (%1) - - + + Select save state Wybierz stan - + Select e-Reader card images Wybierz obrazy kart e-Reader - + Image file (*.png *.jpg *.jpeg) Plik graficzny (*.png *.jpg *.jpeg) - + Conversion finished Konwersja zakończona - + %1 of %2 e-Reader cards converted successfully. %1 z %2 kart czytnika e-Reader zostało pomyślnie przekonwertowanych. - + Load alternate save game... Załaduj alternatywny zapis gry... - + Load temporary save game... Załaduj tymczasowy zapis gry... - + Load &patch... Wczytaj &poprawkę... - + Boot BIOS BIOS startowy - + Replace ROM... Wymień ROM... - + Scan e-Reader dotcodes... Skanuj kody kropkowe czytnika e-Reader... - + Convert e-Reader card image to raw... Konwertuj obraz karty czytnika e-Reader na surowy... - + ROM &info... &Informacje o pamięci ROM... - + Recent Ostatnie - + Make portable Stwórz wersję portable - + &Load state &Załaduj stan - + Load state file... Załaduj plik stanu… - + &Save state &Zapisz stan - + Save state file... Zapisz plik stanu... - + Quick load Szybkie załadowanie - + Quick save Szybki zapis - + Load recent Załaduj ostatnie - + Save recent Zapisz ostatnie - + Undo load state Cofnij załadowanie stanu - + Undo save state Cofnij zapisanie stanu - - + + State &%1 Stan &%1 - + Load camera image... Załaduj obraz do kamery... - + Convert save game... Konwertuj zapisaną grę... - + GameShark saves (*.gsv *.sps *.xps) Zapisy GameShark (*.gsv *.sps *.xps) - + Reset needed Wymagane zresetowanie - + Some changes will not take effect until the game is reset. Niektóre zmiany nie zaczną obowiązywać, dopóki gra nie zostanie zresetowana. - + Save games Zapisy gry - + Import GameShark Save... Importuj Zapis GameShark... - + Export GameShark Save... Eksportuj Zapis GameShark... - + Automatically determine Wykryj automatycznie - + Use player %0 save game Użyj zapis gry gracza %0 - + New multiplayer window Nowe okno dla wielu graczy - + Connect to Dolphin... Połącz z Dolphinem... - + Report bug... Zgłoś błąd... - + About... O Aplikacji... - + E&xit Z&akończ - + &Emulation &Emulacja - + &Reset &Resetuj - + Sh&utdown Za&mknij - + Yank game pak Wyciągnij Game Pak - + &Pause &Pauza - + &Next frame &Następna klatka - + Fast forward (held) Przewijanie (przytrzymaj) - + &Fast forward &Przewijanie do przodu - + Fast forward speed Prędkość przewijania do przodu - + Unbounded Bez ograniczeń - + %0x %0x - - - Increase fast forward speed - - - Decrease fast forward speed - + Increase fast forward speed + Zwiększenie prędkości przewijania do przodu + Decrease fast forward speed + Zmiejszenie prędkości przewijania do przodu + + + Rewind (held) Przewijanie (przytrzymaj) - + Re&wind Pr&zewijanie - + Step backwards Krok w tył - + Solar sensor Czujnik słoneczny - + Increase solar level Zwiększ poziom energii słonecznej - + Decrease solar level Zmniejsz poziom energii słonecznej - + Brightest solar level Najjaśniejszy poziom energii słonecznej - + Darkest solar level Najciemniejszy poziom energii słonecznej - + Brightness %1 Jasność %1 - + Game Boy Printer... Game Boy Printer... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Dźwięk/&Wideo - + Frame size Rozmiar klatki - + %1× %1× - + Toggle fullscreen Przełącz tryb pełnoekranowy - + + &Lock frame size + + + + Lock aspect ratio Zablokuj proporcje - + Force integer scaling Wymuś skalowanie całkowite - + Interframe blending Blendowanie międzyklatkowe - + Bilinear filtering Filtrowanie dwuliniowe - + Frame&skip Klatko&wanie - + Mute Wycisz - + FPS target Cel KL./S - + Native (59.7275) Natywny (59.7275) - + Take &screenshot Wykonaj &zrzut ekranu - + F12 F12 - + Record A/V... Nagraj A/W... - + Record GIF/WebP/APNG... Nagraj GIF/WebP/APNG... - + Video layers Warstwy wideo - + Audio channels Kanały audio - + Adjust layer placement... Dostosuj położenie warstw... - + &Tools &Narzędzia - + View &logs... Wyświetl &logi... - + Game &overrides... Nadpisania &ustawień gry... - + Game Pak sensors... Czujniki Game Pak... - + &Cheats... &Kody... - + Create forwarder... Utwórz forwarder... - + Settings... Ustawienia... - + Open debugger console... Otwórz konsolę debugera... - + Start &GDB server... Uruchom serwer &GDB... - + Scripting... Skrypty... - + Game state views Widoki stanu gry - + View &palette... Wyświetl &paletę... - + View &sprites... Wyświetl &sprite'y... - + View &tiles... Wyświetl &kafelki... - + View &map... Wyświetl &mapę... - + &Frame inspector... Inspektor &klatek... - + View memory... Wyświetl pamięć... - + Search memory... Przeszukaj pamięć... - + View &I/O registers... Wyświetl rejestry &we/wy... - + + Log memory &accesses... + + + + Record debug video log... Nagraj dziennik wideo debugowania... - + Stop debug video log Zatrzymaj dziennik wideo debugowania - + Exit fullscreen Wyłączyć tryb pełnoekranowy - + GameShark Button (held) Przycisk GameShark (przytrzymany) - + Autofire Turbo - + Autofire A Turbo A - + Autofire B Turbo B - + Autofire L Turbo L - + Autofire R Turbo R - + Autofire Start Turbo Start - + Autofire Select Turbo Select - + Autofire Up Turbo Góra - + Autofire Right Turbo Prawo - + Autofire Down Turbo Dół - + Autofire Left Turbo Lewo - + Clear Wyczyść @@ -6771,40 +6775,40 @@ Rozmiar pobierania: %3 ? - + Super (L) - Super (L) + Super (L) - + Super (R) - Super (R) + Super (R) - + Menu - Menu + Menu QShortcut - + Shift Shift - + Control Control - + Alt Alt - + Meta Meta diff --git a/src/platform/qt/ts/mgba-pt_BR.ts b/src/platform/qt/ts/mgba-pt_BR.ts index 2cbfde528..5b8c0df52 100644 --- a/src/platform/qt/ts/mgba-pt_BR.ts +++ b/src/platform/qt/ts/mgba-pt_BR.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) ROMs do Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs do Game Boy (%1) - + All ROMs (%1) Todas as ROMs (%1) - + %1 Video Logs (*.mvl) %1 Registros do Vídeo (*.mvl) @@ -191,17 +191,17 @@ Tamanho do download: %3 QGBA::AudioDevice - + Can't set format of context-less audio device Não pôde definir o formato do dispositivo de áudio sem contexto - + Audio device is missing its core O núcleo do dispositivo de áudio está ausente - + Writing data to read-only audio device Gravando dados no dispositivo somente-leitura do áudio @@ -209,7 +209,7 @@ Tamanho do download: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input Não pôde iniciar um processador de áudio sem entrada @@ -285,28 +285,28 @@ Tamanho do download: %3 Mostrar as opções avançadas - + BattleChip data missing Dados do BattleChip ausentes - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? Os dados do BattleChip estão ausente. Os Portais do BattleChip Gates ainda funcionarão mas alguns gráficos estarão ausentes. Você gostaria de baixar os dados agora? - - + + Select deck file Selecionar o arquivo do deck - + Incompatible deck Deck incompatível - + The selected deck is not compatible with this Chip Gate O deck selecionado não é compatível com este Portal do Chip @@ -367,19 +367,19 @@ Tamanho do download: %3 Insira os códigos aqui... - - + + Autodetect (recommended) Auto-detectar (recomendado) - - + + Select cheats file Selecionar o arquivo das trapaças - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. Algumas trapaças não puderam ser adicionadas. Por favor tenha certeza que eles estão formatadas corretamente e/ou tente outros tipos de trapaça. @@ -398,37 +398,37 @@ Tamanho do download: %3 O rebobinamento não está ativado atualmente - + Reset the game? Resetar o jogo? - + Most games will require a reset to load the new save. Do you want to reset now? A maioria dos jogos requerirão um reset pra carregar o novo save. Você quer resetar agora? - + Failed to open save file: %1 Falhou em abrir o arquivo do save: %1 - + Failed to open game file: %1 Falhou em abrir o arquivo do jogo: %1 - + Can't yank pack in unexpected platform! Não pode arrancar o pacote numa plataforma inesperada! - + Failed to open snapshot file for reading: %1 Falhou em abrir o arquivo do snapshot pra leitura: %1 - + Failed to open snapshot file for writing: %1 Falhou em abrir o arquivo do snapshot pra gravação: %1 @@ -477,6 +477,14 @@ Tamanho do download: %3 Não pôde abrir o histórico do CLI pra gravar + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -716,7 +724,7 @@ Tamanho do download: %3 Image files (*.png *.jpg *.bmp) - + Arquivo da imagem (*.png *.jpg *.bmp) @@ -757,52 +765,52 @@ Tamanho do download: %3 Resetar - + Export frame Exportar frame - + Portable Network Graphics (*.png) Gráficos Portáteis da Rede (*.png) - + None Nenhum - + Background 2º plano - + Window Janela - + Objwin Objwin - + Sprite Imagem Móvel - + Backdrop 2º Plano - + Frame Frame - + %1 %2 %1 %2 @@ -818,22 +826,22 @@ Tamanho do download: %3 QGBA::GBAKeyEditor - + Clear Button Limpar Botão - + Clear Analog Limpar Analógico - + Refresh Atualizar - + Set all Definir todos @@ -3006,8 +3014,8 @@ Tamanho do download: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Tamanho do download: %3 Vertical - - - + + + N/A N/D - + Export map Exportar mapa - + Portable Network Graphics (*.png) Gráficos Portáteis da Rede (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Explorar + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + Parar + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Tamanho do download: %3 Atualizar - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 byte%2 @@ -3750,19 +3822,19 @@ Tamanho do download: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Tentando desconectar um jogador multiplayer que não está conectado - + Trying to get player ID for a multiplayer player that's not attached - + Tentando obter a ID do jogador pra um jogador multiplayer que não está conectado - + Trying to get save ID for a multiplayer player that's not attached - + Tentando obter a ID salva pra um jogador multiplayer que não está conectado @@ -4157,35 +4229,35 @@ Tamanho do download: %3 Exportar OBJ - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette Exportar paleta - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Tabela de Cores da Adobe (*.act) - + Failed to open output palette file: %1 Falhou em abrir o arquivo de saída da paleta: %1 @@ -4259,7 +4331,7 @@ Tamanho do download: %3 QGBA::ROMInfo - + @@ -4299,18 +4371,28 @@ Tamanho do download: %3 + Maker Code: + + + + + Revision: + + + + File size: Tamanho do arquivo: - + CRC32: CRC32: - + Save file: - + Arquivo do save: @@ -4364,62 +4446,62 @@ Tamanho do download: %3 QGBA::SaveConverter - + Save games and save states (%1) Saves dos jogos e save states (%1) - + Select save game or save state Selecione o save do jogo ou save state - + Save games (%1) Saves dos jogos (%1) - + Select save game Selecione o save do jogo - + Conversion failed A conversão falhou - + Failed to convert the save game. This is probably a bug. Falhou em converter o save do jogo. Isto é provavelmente um bug. - + No file selected Nenhum arquivo selecionado - + Could not open file Não pôde abrir o arquivo - + No valid formats found Não foram encontrados formatos válidos - + Please select a valid input file Por favor selecione um arquivo de entrada válido - + No valid conversions found Não foram encontradas conversões válidas - + Cannot convert save games between platforms Não pôde converter os saves do jogo entre as plataformas @@ -4445,97 +4527,97 @@ Tamanho do download: %3 Arquivo de saída - + %1 %2 save game %1 %2 save do jogo - + little endian little endian - + big endian big endian - + SRAM SRAM - + %1 flash %1 flash - + %1 EEPROM %1 EEPROM - + + RTC - + + RTC - + %1 SRAM + RTC %1 SRAM + RTC - + %1 SRAM %1 SRAM - + packed MBC2 Empacotou o MBC2 - + unpacked MBC2 Desempacotou o MBC2 - + MBC6 flash Flash do MBC6 - + MBC6 combined SRAM + flash MBC6 SRAM combinado + flash - + MBC6 SRAM SRAM do MBC6 - + TAMA5 TAMA5 - + %1 (%2) %1 (%2) - + %1 save state with embedded %2 save game %1 save state com %2 saves do jogo embutido - + %1 SharkPort %2 save game %1 SharkPort %2 save do jogo - + %1 GameShark Advance SP %2 save game %1 GameShark Advance SP %2 save do jogo @@ -4571,32 +4653,37 @@ Tamanho do download: %3 Carregar script recente - + Load script... Carregar script... - + + &Load most recent + + + + &Reset &Resetar - + 0 0 - + Select script to load Selecione o script a carregar - + Lua scripts (*.lua) Scripts do lua (*.lua) - + All files (*.*) Todos os arquivos (*.*) @@ -4689,105 +4776,105 @@ Tamanho do download: %3 QGBA::SettingsView - - + + Qt Multimedia Multimídia do Qt - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forçar a versão 1.x) - + None Nenhum - + None (Still Image) Nenhum (Imagem Parada) - + Keyboard Teclado - + Controllers Controles - + Shortcuts Atalhos - - + + Shaders Shaders - + Select BIOS Selecionar BIOS - + Select directory Selecione o diretório - + Select image - Selecionar imagem + Selecionar imagem - + Image file (*.png *.jpg *.jpeg) - Arquivo da imagem (*.png *.jpg *.jpeg) + Arquivo da imagem (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never Nunca - + Just now Aconteceu agora - + Less than an hour ago Menos do que uma hora atrás - + %n hour(s) ago %n hora atrás @@ -4795,7 +4882,7 @@ Tamanho do download: %3 - + %n day(s) ago %n dia atrás @@ -5089,7 +5176,7 @@ Tamanho do download: %3 Custom border: - + Borda personalizada: @@ -5134,40 +5221,40 @@ Tamanho do download: %3 Rewind speed: - + Velocidade do retrocesso: - + Default color palette only Só a cor padrão da paleta - + SGB color palette if available Paleta das cores do SGB se disponível - + GBC color palette if available Paleta das cores do GBC se disponível - + SGB (preferred) or GBC color palette if available SGB (preferido) ou paleta das cores do GBC se disponível - + Game Boy Camera Câmera do Game Boy - + Driver: Driver: - + Source: Fonte: @@ -5213,7 +5300,7 @@ Tamanho do download: %3 Ativar compatibilidade dos bugs do VBA nos hacks das ROMs - + Preset: Pré-definições: @@ -5228,22 +5315,22 @@ Tamanho do download: %3 Velocidade do avanço rápido (pressionado): - + (240×160) (240×160) - + Log to file Registrar no arquivo - + Log to console Registrar no console - + Select Log File Selecionar Arquivo do Registro @@ -5381,61 +5468,56 @@ Tamanho do download: %3 Software - + OpenGL enhancements Melhorias do OpenGL - + High-resolution scale: Escala de alta-resolução: - - XQ GBA audio (experimental) - Áudio do XQ GBA (experimental) - - - + GB BIOS file: Arquivo da BIOS do GB: - - - - - - - - - + + + + + + + + + Browse Explorar - + Use BIOS file if found Usar o arquivo da BIOS se encontrado - + Skip BIOS intro Ignorar a introdução da BIOS - + GBA BIOS file: Arquivo da BIOS do GBA: - + GBC BIOS file: Arquivo da BIOS do GBC: - + SGB BIOS file: Arquivo da BIOS do SGB: @@ -5445,91 +5527,91 @@ Tamanho do download: %3 Auto-salvar o state periodicamente - + Save games Saves dos jogos - - - - - + + + + + Same directory as the ROM O mesmo diretório que a ROM - + Save states Save states - + Screenshots Screenshots - + Patches Patches - + Cheats Trapaças - + Models Modelos - + GB only: Só pro GB: - + SGB compatible: Compatível com o SGB: - + GBC only: Só pro GBC: - + GBC compatible: Compatível com o GBC: - + SGB and GBC compatible: Compatível com o SGB e o GBC: - + Game Boy palette Paleta do Game Boy - + Default BG colors: Cores padrão do 2º plano: - + Super Game Boy borders Bordas do Super Game Boy - + Default sprite colors 1: Cores padrão da imagem móvel 1: - + Default sprite colors 2: Cores padrão da imagem móvel 2: @@ -5777,7 +5859,6 @@ Tamanho do download: %3 - WebM WebM @@ -5786,19 +5867,8 @@ Tamanho do download: %3 Format Formato - - - MKV - MKV - - - - AVI - AVI - - MP4 MP4 @@ -5842,72 +5912,6 @@ Tamanho do download: %3 &Native &Nativo - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - Nenhum - - - - FLAC - FLAC - - - - WavPack - WavPack - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - Descomprimido - Bitrate (kbps) @@ -5918,16 +5922,6 @@ Tamanho do download: %3 ABR ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5957,80 +5951,80 @@ Tamanho do download: %3 QGBA::Window - + Archives (%1) Arquivos Compactados (%1) - - + + Select ROM Selecionar ROM - + Select folder Selecionar pasta - - + + Select save Selecionar save - + Select patch Selecionar patch - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Selecionar dotcode do e-Reader - + e-Reader card (*.raw *.bin *.bmp) Cartão do e-Reader (*.raw *.bin *.bmp) - + Select image Selecionar imagem - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Arquivo de imagem (*.png *.gif *.jpg *.jpeg);;Todos os arquivos (*) - + GameShark saves (*.sps *.xps) Saves do GameShark (*.sps *.xps) - + Select video log Selecionar registro do vídeo - + Video logs (*.mvl) Registros do vídeo (*.mvl) - + Crash Crash - + The game has crashed with the following error: %1 @@ -6039,699 +6033,709 @@ Tamanho do download: %3 %1 - + Unimplemented BIOS call Chamada da BIOS não implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este jogo usa uma chamada de BIOS que não está implementada. Por favor use a BIOS oficial pra uma melhor experiência. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Falhou em criar um dispositivo de exibição apropriado, voltando a exibição por software. Os jogos podem executar lentamente, especialmente com janelas maiores. - + Really make portable? Realmente tornar portátil? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Isto fará o emulador carregar sua configuração do mesmo diretório que o executável. Você quer continuar? - + Restart needed Reiniciar é necessário - + Some changes will not take effect until the emulator is restarted. Algumas mudanças não terão efeito até o emulador ser reiniciado. - + - Player %1 of %2 - Jogador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Arquivo - + Load &ROM... Carregar &ROM... - + Load ROM in archive... Carregar ROM no arquivo compactado... - + Add folder to library... Adicionar pasta a biblioteca... - + Save games Saves dos jogos - + Automatically determine Determinar automaticamente - + Use player %0 save game Usar o save do jogo %0 do jogador - + Load &patch... Carregar &patch... - + Boot BIOS Dar Boot na BIOS - + Replace ROM... Substituir a ROM... - + ROM &info... Informações da &ROM... - + Recent Recentes - + Make portable Tornar portátil - + &Load state &Carregar state - + Report bug... Reportar bug... - + About... Sobre... - + Game Pak sensors... Sensores do Game Pak... - + Clear Limpar - + Load state file... Carregar arquivo do state... - + Save games (%1) Saves dos jogos (%1) - + Select save game Selecione save do jogo - + mGBA save state files (%1) Arquivos do save state do mGBA (%1) - - + + Select save state Selecione um save state - + Select e-Reader card images Selecionar imagens do cartão do e-Reader - + Image file (*.png *.jpg *.jpeg) Arquivo da imagem (*.png *.jpg *.jpeg) - + Conversion finished Conversão concluída - + %1 of %2 e-Reader cards converted successfully. %1 de %2 cartões do e-Reader convertidos com sucesso. - + Load alternate save game... Carregar save alternativo do jogo... - + Load temporary save game... Carregar save temporário do jogo... - + Convert e-Reader card image to raw... Converter imagem do cartão do e-Reader pro natural... - + &Save state &Salvar o state - + Save state file... Arquivo do save state... - + Quick load Carregamento rápido - + Quick save Salvamento rápido - + Load recent Carregar recentes - + Save recent Salvar recentes - + Undo load state Desfazer o carregamento do state - + Undo save state Desfazer o save state - - + + State &%1 State &%1 - + Load camera image... Carregar a imagem da câmera... - + Convert save game... Converter o save do jogo... - + GameShark saves (*.gsv *.sps *.xps) Saves do GameShark (*.gsv *.sps *.xps) - + Reset needed É necessário resetar - + Some changes will not take effect until the game is reset. Algumas mudanças não terão efeito até o jogo ser resetado. - + New multiplayer window Nova janela multi-jogador - + Connect to Dolphin... Conectar ao Dolphin... - + E&xit S&air - + &Emulation &Emulação - + &Reset &Resetar - + Sh&utdown De&sligar - + Yank game pak Arrancar o game pak - + &Pause &Pausar - + &Next frame &Próximo frame - + Fast forward (held) Avanço rápido (segurado) - + &Fast forward &Avanço rápido - + Fast forward speed Velocidade do avanço rápido - + Unbounded Ilimitado - + %0x %0x - - - Increase fast forward speed - - - Decrease fast forward speed - + Increase fast forward speed + Aumentar a velocidade do avanço rápido + Decrease fast forward speed + Diminuir a velocidade do avanço rápido + + + Rewind (held) Retroceder (segurado) - + Re&wind Re&troceder - + Step backwards Voltar um passo - + Solar sensor Sensor solar - + Increase solar level Aumentar nível solar - + Decrease solar level Diminuir nível solar - + Brightest solar level Nível solar mais brilhante - + Darkest solar level Nível solar mais escuro - + Brightness %1 Brilho %1 - + Audio/&Video Áudio/&Vídeo - + Frame size Tamanho do frame - + Toggle fullscreen Alternar tela cheia - + + &Lock frame size + + + + Lock aspect ratio Travar a proporção do aspecto - + Force integer scaling Forçar o dimensionamento do inteiro - + Bilinear filtering Filtragem bilinear - + Frame&skip Frame&skip - + Mute Mudo - + FPS target FPS alvo - + Native (59.7275) Nativo (59,7275) - + Take &screenshot Tirar &screenshot - + F12 F12 - + Game Boy Printer... Impressora do Game Boy... - + BattleChip Gate... Portal do BattleChip... - + %1× %1× - + Interframe blending Mistura do interframe - + Record A/V... Gravar A/V... - + Video layers Camadas do vídeo - + Audio channels Canais de áudio - + Adjust layer placement... Ajustar posicionamento da camada... - + &Tools &Ferramentas - + View &logs... Visualizar &registros... - + Game &overrides... Substituições &do jogo... - + Couldn't Start Não Pôde Iniciar - + Could not start game. Não pôde iniciar o jogo. - + Scan e-Reader dotcodes... Escanear dotcodes do e-Reader... - + Import GameShark Save... Importar Save do GameShark... - + Export GameShark Save... Exportar Save do GameShark... - + Record GIF/WebP/APNG... Gravar GIF/WebP/APNG... - + &Cheats... &Trapaças... - + Settings... Configurações... - + Open debugger console... Abrir console do debugger... - + Start &GDB server... Iniciar servidor do &GDB... - + Scripting... Scripting... - + Create forwarder... Criar encaminhador... - + Game state views Visualizações do estado do jogo - + View &palette... Visualizar &paleta... - + View &sprites... Visualizar &imagens móveis... - + View &tiles... Visualizar &mosaicos... - + View &map... Visualizar &mapa... - + &Frame inspector... Inspetor dos &frames... - + View memory... Visualizar memória... - + Search memory... Procurar na memória... - + View &I/O registers... Visualizar registros de &E/S... - + + Log memory &accesses... + + + + Record debug video log... Gravar registro do vídeo de debug... - + Stop debug video log Parar o registro do vídeo de debug - + Exit fullscreen Sair da tela cheia - + GameShark Button (held) Botão do GameShark (segurado) - + Autofire Auto-disparar - + Autofire A Auto-disparar A - + Autofire B Auto-disparar B - + Autofire L Auto-disparar L - + Autofire R Auto-disparar R - + Autofire Start Auto-disparar Start - + Autofire Select Auto-disparar Select - + Autofire Up Auto-disparar Pra Cima - + Autofire Right Auto-disparar Direita - + Autofire Down Auto-disparar Pra Baixo - + Autofire Left Auto-disparar Esquerda @@ -6769,40 +6773,40 @@ Tamanho do download: %3 ? - + Super (L) - Super (E) + Super (E) - + Super (R) - Super (D) + Super (D) - + Menu - Menu + Menu QShortcut - + Shift Shift - + Control Control - + Alt Alt - + Meta Meta diff --git a/src/platform/qt/ts/mgba-pt.ts b/src/platform/qt/ts/mgba-pt_PT.ts similarity index 91% rename from src/platform/qt/ts/mgba-pt.ts rename to src/platform/qt/ts/mgba-pt_PT.ts index 72af03abe..f6c819d37 100644 --- a/src/platform/qt/ts/mgba-pt.ts +++ b/src/platform/qt/ts/mgba-pt_PT.ts @@ -1,25 +1,25 @@ - + QGBA - + Game Boy Advance ROMs (%1) ROMs do Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs do Game Boy (%1) - + All ROMs (%1) Todas as ROMs (%1) - + %1 Video Logs (*.mvl) %1 Registos do Vídeo (*.mvl) @@ -191,17 +191,17 @@ Tamanho da descarga: %3 QGBA::AudioDevice - + Can't set format of context-less audio device Não pôde definir o formato do aparelho de áudio sem contexto - + Audio device is missing its core O núcleo do aparelho de áudio está ausente - + Writing data to read-only audio device Gravando dados no aparelho somente-leitura do áudio @@ -209,7 +209,7 @@ Tamanho da descarga: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input Não pôde iniciar um processador de áudio sem entrada @@ -285,28 +285,28 @@ Tamanho da descarga: %3 Mostrar as opções avançadas - + BattleChip data missing Portal do BattleChip - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? Os dados do BattleChip estão ausentes. O BattleChip Gates ainda funcionará, mas alguns gráficos estarão ausentes. Gostaria de descarregar os dados agora? - - + + Select deck file Selecionar o ficheiro do deck - + Incompatible deck Deck incompatível - + The selected deck is not compatible with this Chip Gate O deck selecionado não é compatível com este Portal do Chip @@ -367,19 +367,19 @@ Tamanho da descarga: %3 Insira os códigos aqui... - - + + Autodetect (recommended) Auto-detetar (recomendado) - - + + Select cheats file Selecionar o ficheiro das trapaças - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. Algumas trapaças não puderam ser adicionadas. Por favor tenha certeza que eles estão formatadas corretamente e/ou tente outros tipos de trapaça. @@ -398,37 +398,37 @@ Tamanho da descarga: %3 O rebobinamento não está ativado atualmente - + Reset the game? Resetar o jogo? - + Most games will require a reset to load the new save. Do you want to reset now? A maioria dos jogos requerirão um reset para carregar o novo save. Quer resetar agora? - + Failed to open save file: %1 Falha ao abrir o ficheiro dde gravação: %1 - + Failed to open game file: %1 Falha ao abrir o ficheiro do jogo: %1 - + Can't yank pack in unexpected platform! Não pode arrancar o pacote numa plataforma inesperada! - + Failed to open snapshot file for reading: %1 Falha ao abrir o ficheiro do snapshot para leitura: %1 - + Failed to open snapshot file for writing: %1 Falha ao abrir o ficheiro do snapshot para gravação: %1 @@ -477,6 +477,14 @@ Tamanho da descarga: %3 Não pôde abrir o histórico do CLI para gravar + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -716,7 +724,7 @@ Tamanho da descarga: %3 Image files (*.png *.jpg *.bmp) - + Ficheiro da imagem (*.png *.jpg *.bmp) @@ -757,52 +765,52 @@ Tamanho da descarga: %3 Resetar - + Export frame Exportar frame - + Portable Network Graphics (*.png) Gráficos Portáteis da Rede (*.png) - + None Nenhum - + Background 2º plano - + Window Janela - + Objwin Objwin - + Sprite Imagem Móvel - + Backdrop 2º Plano - + Frame Frame - + %1 %2 %1 %2 @@ -818,22 +826,22 @@ Tamanho da descarga: %3 QGBA::GBAKeyEditor - + Clear Button Limpar Botão - + Clear Analog Limpar Analógico - + Refresh Atualizar - + Set all Definir todos @@ -3006,8 +3014,8 @@ Tamanho da descarga: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Tamanho da descarga: %3 Vertical - - - + + + N/A N/D - + Export map Exportar mapa - + Portable Network Graphics (*.png) Gráficos Portáteis da Rede (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Explorar + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + Parar + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Tamanho da descarga: %3 Atualizar - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 byte%2 @@ -3750,19 +3822,19 @@ Tamanho da descarga: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + A tentar desconectar um jogador multiplayer que não está conectado - + Trying to get player ID for a multiplayer player that's not attached - + A tentar obter a ID do jogador para um jogador multiplayer que não está conectado - + Trying to get save ID for a multiplayer player that's not attached - + A tentar obter a ID gravada para um jogador multiplayer que não está conectado @@ -4157,35 +4229,35 @@ Tamanho da descarga: %3 Exportar OBJ - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette Exportar paleta - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Tabela de Cores da Adobe (*.act) - + Failed to open output palette file: %1 Falha ao abrir o ficheiro de saída da paleta: %1 @@ -4259,7 +4331,7 @@ Tamanho da descarga: %3 QGBA::ROMInfo - + @@ -4299,18 +4371,28 @@ Tamanho da descarga: %3 + Maker Code: + + + + + Revision: + + + + File size: Tamanho do ficheiro: - + CRC32: CRC32: - + Save file: - + Ficheiro do save: @@ -4364,62 +4446,62 @@ Tamanho da descarga: %3 QGBA::SaveConverter - + Save games and save states (%1) Saves dos jogos e save states (%1) - + Select save game or save state Selecione o save do jogo ou save state - + Save games (%1) Saves dos jogos (%1) - + Select save game Selecione o save do jogo - + Conversion failed A conversão falhou - + Failed to convert the save game. This is probably a bug. Falhou em converter o save do jogo. Isto é provavelmente um bug. - + No file selected Nenhum ficheiro selecionado - + Could not open file Não pôde abrir o ficheiro - + No valid formats found Não foram encontrados formatos válidos - + Please select a valid input file Por favor selecione um ficheiro de entrada válido - + No valid conversions found Não foram encontradas conversões válidas - + Cannot convert save games between platforms Não pôde converter os saves do jogo entre as plataformas @@ -4445,97 +4527,97 @@ Tamanho da descarga: %3 Ficheiro de saída - + %1 %2 save game %1 %2 save do jogo - + little endian little endian - + big endian big endian - + SRAM SRAM - + %1 flash %1 flash - + %1 EEPROM %1 EEPROM - + + RTC - + + RTC - + %1 SRAM + RTC %1 SRAM + RTC - + %1 SRAM %1 SRAM - + packed MBC2 empacotou o MBC2 - + unpacked MBC2 desempacotou o MBC2 - + MBC6 flash Flash do MBC6 - + MBC6 combined SRAM + flash MBC6 SRAM combinado + flash - + MBC6 SRAM SRAM do MBC6 - + TAMA5 TAMA5 - + %1 (%2) %1 (%2) - + %1 save state with embedded %2 save game %1 save state com %2 saves do jogo embutido - + %1 SharkPort %2 save game %1 SharkPort %2 save do jogo - + %1 GameShark Advance SP %2 save game %1 GameShark Advance SP %2 save do jogo @@ -4571,32 +4653,37 @@ Tamanho da descarga: %3 Carregar script recente - + Load script... Carregar script... - + + &Load most recent + + + + &Reset &Resetar - + 0 0 - + Select script to load Selecione o script a carregar - + Lua scripts (*.lua) Scripts do lua (*.lua) - + All files (*.*) Todos os ficheiros (*.*) @@ -4689,105 +4776,105 @@ Tamanho da descarga: %3 QGBA::SettingsView - - + + Qt Multimedia Multimídia do Qt - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forçar a versão 1.x) - + None Nenhum - + None (Still Image) Nenhum (Imagem Parada) - + Keyboard Teclado - + Controllers Controles - + Shortcuts Atalhos - - + + Shaders Shaders - + Select BIOS Selecionar BIOS - + Select directory Selecione o diretório - + Select image - Selecionar imagem + Selecionar imagem - + Image file (*.png *.jpg *.jpeg) - Ficheiro da imagem (*.png *.jpg *.jpeg) + Ficheiro da imagem (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never Nunca - + Just now Aconteceu agora - + Less than an hour ago Menos do que uma hora atrás - + %n hour(s) ago %n hora atrás @@ -4795,7 +4882,7 @@ Tamanho da descarga: %3 - + %n day(s) ago %n dia atrás @@ -5122,37 +5209,37 @@ Tamanho da descarga: %3 Verificar agora - + Default color palette only Só a cor padrão da paleta - + SGB color palette if available Paleta das cores do SGB se disponível - + GBC color palette if available Paleta das cores do GBC se disponível - + SGB (preferred) or GBC color palette if available SGB (preferido) ou paleta das cores do GBC se disponível - + Game Boy Camera Câmara do Game Boy - + Driver: Driver: - + Source: Fonte: @@ -5249,7 +5336,7 @@ Tamanho da descarga: %3 Custom border: - + Borda personalizada: @@ -5285,7 +5372,7 @@ Tamanho da descarga: %3 Rewind speed: - + Velocidade do retrocesso: @@ -5329,42 +5416,42 @@ Tamanho da descarga: %3 Carregar dados extras do state: - + Models Modelos - + GB only: Só para o GB: - + SGB compatible: Compatível com o SGB: - + GBC only: Só para o GBC: - + GBC compatible: Compatível com o GBC: - + SGB and GBC compatible: Compatível com o SGB e o GBC: - + Game Boy palette Paleta do Game Boy - + Preset: Pré-definições: @@ -5401,135 +5488,130 @@ Tamanho da descarga: %3 Software - + OpenGL enhancements Melhorias do OpenGL - + High-resolution scale: Escala de alta-resolução: - + (240×160) (240×160) - - XQ GBA audio (experimental) - Áudio do XQ GBA (experimental) - - - + GB BIOS file: Ficheiro da BIOS do GB: - - - - - - - - - + + + + + + + + + Browse Explorar - + Use BIOS file if found Usar o ficheiro da BIOS se encontrado - + Skip BIOS intro Ignorar a introdução da BIOS - + GBA BIOS file: Ficheiro da BIOS do GBA: - + GBC BIOS file: Ficheiro da BIOS do GBC: - + SGB BIOS file: Ficheiro da BIOS do SGB: - + Save games Saves dos jogos - - - - - + + + + + Same directory as the ROM O mesmo diretório que a ROM - + Save states Save states - + Screenshots Screenshots - + Patches Patches - + Cheats Trapaças - + Log to file Registar ao ficheiro - + Log to console Registar à console - + Select Log File Selecionar Ficheiro de Registo - + Default BG colors: Cores padrão do 2º plano: - + Default sprite colors 1: Cores padrão da imagem móvel 1: - + Default sprite colors 2: Cores padrão da imagem móvel 2: - + Super Game Boy borders Bordas do Super Game Boy @@ -5787,13 +5869,11 @@ Tamanho da descarga: %3 - WebM WebM - MP4 MP4 @@ -5832,82 +5912,6 @@ Tamanho da descarga: %3 Format Formato - - - MKV - MKV - - - - AVI - AVI - - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - Nenhum - - - - FLAC - FLAC - - - - WavPack - WavPack - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - Descomprimido - Bitrate (kbps) @@ -5918,16 +5922,6 @@ Tamanho da descarga: %3 ABR ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5957,80 +5951,80 @@ Tamanho da descarga: %3 QGBA::Window - + Archives (%1) Ficheiros Compactados (%1) - - + + Select ROM Selecionar ROM - + Select folder Selecionar pasta - - + + Select save Selecionar save - + Select patch Selecionar patch - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Selecionar dotcode do e-Reader - + e-Reader card (*.raw *.bin *.bmp) Cartão do e-Reader (*.raw *.bin *.bmp) - + Select image Selecionar imagem - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Ficheiro de imagem (*.png *.gif *.jpg *.jpeg);;Todos os ficheiros (*) - + GameShark saves (*.sps *.xps) Saves do GameShark (*.sps *.xps) - + Select video log Selecionar registo do vídeo - + Video logs (*.mvl) Registos do vídeo (*.mvl) - + Crash Crash - + The game has crashed with the following error: %1 @@ -6039,699 +6033,709 @@ Tamanho da descarga: %3 %1 - + Couldn't Start Não Pôde Iniciar - + Could not start game. Não pôde iniciar o jogo. - + Unimplemented BIOS call Chamada da BIOS não implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este jogo usa uma chamada de BIOS que não está implementada. Por favor use a BIOS oficial para uma melhor experiência. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Falhou em criar um aparelho de exibição apropriado, voltando a exibição por software. Os jogos podem executar lentamente, especialmente com janelas maiores. - + Really make portable? Realmente tornar portátil? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Isto fará o emulador carregar a configuração dele do mesmo diretório que o executável. Quer continuar? - + Restart needed Reiniciar é necessário - + Some changes will not take effect until the emulator is restarted. Algumas mudanças não terão efeito até o emulador ser reiniciado. - + - Player %1 of %2 - Jogador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Ficheiro - + Load &ROM... Carregar &ROM... - + Load ROM in archive... Carregar ROM no arquivo... - + Add folder to library... Adicionar pasta a biblioteca... - + Save games (%1) Saves dos jogos (%1) - + Select save game Selecione save do jogo - + mGBA save state files (%1) Ficheiro do save state do mGBA (%1) - - + + Select save state Selecione um save state - + Select e-Reader card images Selecionar imagens do cartão do e-Reader - + Image file (*.png *.jpg *.jpeg) Ficheiro da imagem (*.png *.jpg *.jpeg) - + Conversion finished Conversão concluída - + %1 of %2 e-Reader cards converted successfully. %1 de %2 cartões do e-Reader convertidos com sucesso. - + Load alternate save game... Carregar save alternativo do jogo... - + Load temporary save game... Carregar save temporário do jogo... - + Load &patch... Carregar &patch... - + Boot BIOS Dar Boot na BIOS - + Replace ROM... Substituir a ROM... - + Scan e-Reader dotcodes... Escanear dotcodes do e-Reader... - + Convert e-Reader card image to raw... Converter imagem do cartão do e-Reader para natural... - + ROM &info... Informações da &ROM... - + Recent Recentes - + Make portable Tornar portátil - + &Load state &Carregar state - + Load state file... Carregar ficheiro do state... - + &Save state &Gravar o state - + Save state file... Ficheiro do save state... - + Quick load Carregamento rápido - + Quick save Salvamento rápido - + Load recent Carregar recentes - + Save recent Gravar recentes - + Undo load state Desfazer o carregamento do state - + Undo save state Desfazer o save state - - + + State &%1 State &%1 - + Load camera image... Carregar a imagem da câmara... - + Convert save game... Converter o save do jogo... - + GameShark saves (*.gsv *.sps *.xps) Saves do GameShark (*.gsv *.sps *.xps) - + Reset needed É necessário resetar - + Some changes will not take effect until the game is reset. Algumas mudanças não terão efeito até o jogo ser resetado. - + Save games Saves dos jogos - + Import GameShark Save... Importar Save do GameShark... - + Export GameShark Save... Exportar Save do GameShark... - + Automatically determine Determinar automaticamente - + Use player %0 save game Usar o save do jogo %0 do jogador - + New multiplayer window Nova janela multi-jogador - + Connect to Dolphin... Conectar ao Dolphin... - + Report bug... Reportar bug... - + About... Sobre... - + E&xit S&air - + &Emulation &Emulação - + &Reset &Resetar - + Sh&utdown De&sligar - + Yank game pak Arrancar o game pak - + &Pause &Pausar - + &Next frame &Próximo frame - + Fast forward (held) Avanço rápido (segurado) - + &Fast forward &Avanço rápido - + Fast forward speed Velocidade do avanço rápido - + Unbounded Ilimitado - + %0x %0x - - - Increase fast forward speed - - - Decrease fast forward speed - + Increase fast forward speed + Aumentar a velocidade do avanço rápido + Decrease fast forward speed + Diminuir a velocidade do avanço rápido + + + Rewind (held) Retroceder (segurado) - + Re&wind Re&troceder - + Step backwards Voltar um passo - + Solar sensor Sensor solar - + Increase solar level Aumentar nível solar - + Decrease solar level Diminuir nível solar - + Brightest solar level Nível solar mais brilhante - + Darkest solar level Nível solar mais escuro - + Brightness %1 Brilho %1 - + Game Boy Printer... Impressora do Game Boy... - + BattleChip Gate... Portal do BattleChip... - + Audio/&Video Áudio/&Vídeo - + Frame size Tamanho do frame - + %1× %1× - + Toggle fullscreen Alternar ecrã inteiro - + + &Lock frame size + + + + Lock aspect ratio Travar a proporção do aspeto - + Force integer scaling Forçar o dimensionamento do inteiro - + Interframe blending Mistura do interframe - + Bilinear filtering Filtragem bilinear - + Frame&skip Frame&skip - + Mute Mudo - + FPS target FPS alvo - + Native (59.7275) Nativo (59,7275) - + Take &screenshot Tirar &screenshot - + F12 F12 - + Record A/V... Gravar A/V... - + Record GIF/WebP/APNG... Gravar GIF/WebP/APNG... - + Video layers Camadas do vídeo - + Audio channels Canais de áudio - + Adjust layer placement... Ajustar posicionamento da camada... - + &Tools &Ferramentas - + View &logs... Visualizar &registos... - + Game &overrides... Substituições &do jogo... - + Game Pak sensors... Sensores do Game Pak... - + &Cheats... &Trapaças... - + Create forwarder... Criar encaminhador... - + Settings... Configurações... - + Open debugger console... Abrir console do debugger... - + Start &GDB server... Iniciar servidor do &GDB... - + Scripting... Scripting... - + Game state views Visualizações do estado do jogo - + View &palette... Visualizar &paleta... - + View &sprites... Visualizar &imagens móveis... - + View &tiles... Visualizar &ladrilhos... - + View &map... Visualizar &mapa... - + &Frame inspector... Inspetor dos &frames... - + View memory... Visualizar memória... - + Search memory... Procurar na memória... - + View &I/O registers... Visualizar registos de &E/S... - + + Log memory &accesses... + + + + Record debug video log... Gravar registo do vídeo de debug... - + Stop debug video log Parar o registo do vídeo de debug - + Exit fullscreen Sair do ecrã inteiro - + GameShark Button (held) Botão do GameShark (segurado) - + Autofire Auto-disparar - + Autofire A Auto-disparar A - + Autofire B Auto-disparar B - + Autofire L Auto-disparar L - + Autofire R Auto-disparar R - + Autofire Start Auto-disparar Start - + Autofire Select Auto-disparar Select - + Autofire Up Auto-disparar Para Cima - + Autofire Right Auto-disparar Direita - + Autofire Down Auto-disparar Para Baixo - + Autofire Left Auto-disparar Esquerda - + Clear Limpar @@ -6769,40 +6773,40 @@ Tamanho da descarga: %3 ? - + Super (L) - Super (E) + Super (E) - + Super (R) - Super (D) + Super (D) - + Menu - Menu + Menu QShortcut - + Shift Shift - + Control Control - + Alt Alt - + Meta Meta diff --git a/src/platform/qt/ts/mgba-ru.ts b/src/platform/qt/ts/mgba-ru.ts index 17147a467..5f130f18e 100644 --- a/src/platform/qt/ts/mgba-ru.ts +++ b/src/platform/qt/ts/mgba-ru.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) Игры Game Boy Advance (%1) - + Game Boy ROMs (%1) Игры Game Boy (%1) - + All ROMs (%1) Все игры (%1) - + %1 Video Logs (*.mvl) Журналы видео %1 (*.mvl) @@ -191,17 +191,17 @@ Download size: %3 QGBA::AudioDevice - + Can't set format of context-less audio device Невозможно установить формат для аудиоустройства без контекста - + Audio device is missing its core Отсутствует ядро аудиоустройства - + Writing data to read-only audio device Запись данных в аудиоустройство только для чтения @@ -209,7 +209,7 @@ Download size: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input Невозможно запустить аудиопроцессор без входных данных @@ -285,28 +285,28 @@ Download size: %3 Расширенные настройки - + BattleChip data missing Отсутствуют данные BattleChip - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? Отсутствуют данные BattleChip. BattleChip Gates будут работать, но часть графики будет отсутствовать. Скачать данные сейчас? - - + + Select deck file Выберите файл колоды - + Incompatible deck Колода несовместима - + The selected deck is not compatible with this Chip Gate Выбранная колода несовместима с этим Chip Gate @@ -367,19 +367,19 @@ Download size: %3 Введите свои читкоды сюда... - - + + Autodetect (recommended) Автоопределение (рекомендовано) - - + + Select cheats file Выберите файл с чит-кодами - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. Некоторые читы не были добавлены. Убедитесь, что они правильного формата, и/или измените тип чита. @@ -398,37 +398,37 @@ Download size: %3 Обратная перемотка выключена - + Reset the game? Перезагрузить игру? - + Most games will require a reset to load the new save. Do you want to reset now? Большинству игр нужна перезагрузка, чтобы загрузить новое сохранение. Перезагрузить сейчас? - + Failed to open save file: %1 Не удалось открыть файл сохранения: %1 - + Failed to open game file: %1 Не удалось открыть файл игры: %1 - + Can't yank pack in unexpected platform! Невозможно пнуть картридж на неожиданной платформе! - + Failed to open snapshot file for reading: %1 Не удалось открыть файл изображения для считывания: %1 - + Failed to open snapshot file for writing: %1 Не удалось открыть файл изображения для записи: %1 @@ -477,6 +477,14 @@ Download size: %3 Не удалось открыть историю CLI на запись + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -757,52 +765,52 @@ Download size: %3 Сброс - + Export frame Экспорт кадра - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Нет - + Background Фон - + Window Окно - + Objwin Objwin - + Sprite Спрайт - + Backdrop Подложка - + Frame Кадр - + %1 %2 %1 %2 @@ -818,22 +826,22 @@ Download size: %3 QGBA::GBAKeyEditor - + Clear Button Сброс кнопки - + Clear Analog Сброс аналога - + Refresh Обновить - + Set all Назначить все @@ -3006,8 +3014,8 @@ Download size: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Download size: %3 Вертикально - - - + + + N/A Н/Д - + Export map Экспорт карты - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Открыть + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Download size: %3 Обновить - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 @@ -3750,17 +3822,17 @@ Download size: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -4157,35 +4229,35 @@ Download size: %3 Экспорт OBJ - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette Экспорт палитры - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 Не удалось открыть файл палитры: %1 @@ -4259,7 +4331,7 @@ Download size: %3 QGBA::ROMInfo - + @@ -4299,16 +4371,26 @@ Download size: %3 + Maker Code: + + + + + Revision: + + + + File size: Размер файла: - + CRC32: CRC32: - + Save file: @@ -4364,62 +4446,62 @@ Download size: %3 QGBA::SaveConverter - + Save games and save states (%1) Игровые сохранения и сохранения состояний (%1) - + Select save game or save state Выбор игрового сохранения или сохранения состояния - + Save games (%1) Игровые сохранения (%1) - + Select save game Выбор игрового сохранения - + Conversion failed Ошибка конвертации - + Failed to convert the save game. This is probably a bug. Не удалось сконвертировать игровое сохранение. Возможно, это баг. - + No file selected Не выбран файл - + Could not open file Не удалось открыть файл - + No valid formats found Совместимые форматы не найдены - + Please select a valid input file Пожалуйста, выберите совместимый входной файл - + No valid conversions found Совместимые конверсии не найдены - + Cannot convert save games between platforms Нельзя сконвертировать сохранения для разных платформ @@ -4445,97 +4527,97 @@ Download size: %3 Выходной файл - + %1 %2 save game - + little endian - + big endian - + SRAM SRAM - + %1 flash - + %1 EEPROM - + + RTC - + %1 SRAM + RTC - + %1 SRAM - + packed MBC2 - + unpacked MBC2 - + MBC6 flash - + MBC6 combined SRAM + flash - + MBC6 SRAM - + TAMA5 - + %1 (%2) - + %1 save state with embedded %2 save game - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4571,32 +4653,37 @@ Download size: %3 Загрузить недавний скрипт - + Load script... Загрузить скрипт... - + + &Load most recent + + + + &Reset Перезагрузить (&R/&К) - + 0 0 - + Select script to load Выбрать скрипт для загрузки - + Lua scripts (*.lua) Скрипты Lua (*.lua) - + All files (*.*) Все файлы (*.*) @@ -4689,105 +4776,105 @@ Download size: %3 QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Программный рендеринг (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) - + None Нет - + None (Still Image) Нет (статичное изображение) - + Keyboard Клавиатура - + Controllers Контроллеры - + Shortcuts Сочетания клавиш - - + + Shaders Шейдеры - + Select BIOS Выбор BIOS - + Select directory Выбор папки - + Select image Выбор изображения - + Image file (*.png *.jpg *.jpeg) Файл изображения (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never Никогда - + Just now Только сейчас - + Less than an hour ago Менее часа назад - + %n hour(s) ago %n час назад @@ -4796,7 +4883,7 @@ Download size: %3 - + %n day(s) ago %n день назад @@ -5141,75 +5228,75 @@ Download size: %3 Rewind speed: - + Скорость перемотки: - + Models Модели - + GB only: Только GB: - + SGB compatible: Совместимость с SGB: - + GBC only: Только GBC: - + GBC compatible: Совместимость с GBC: - + SGB and GBC compatible: Совместимость с GBC и SGB: - + Game Boy palette Палитра Game Boy - + Default color palette only Только цветовая палитра по умолчанию - + SGB color palette if available Цветовая палитра SGB (если доступна) - + GBC color palette if available Цветовая палитра GBC (если доступна) - + SGB (preferred) or GBC color palette if available Цветовая палитра SGB (предпочтительно) или GBC (если доступны) - + Game Boy Camera - + Driver: Драйвер: - + Source: Источник: @@ -5231,7 +5318,7 @@ Download size: %3 Language - + Язык @@ -5300,7 +5387,7 @@ Download size: %3 Включить совместимость с VBA для ROM-хаков - + Preset: Пресет: @@ -5322,7 +5409,7 @@ Download size: %3 Fast forward speed: - Скорость перемотки: + Скорость перемотки (ускр.): @@ -5403,135 +5490,130 @@ Download size: %3 Программный - + OpenGL enhancements Улучшения OpenGL - + High-resolution scale: Масштаб высокого разрешения: - + (240×160) (240×160) - - XQ GBA audio (experimental) - Аудио XQ GBA (экспериментально) - - - + GB BIOS file: Файл GB BIOS: - - - - - - - - - + + + + + + + + + Browse Открыть - + Use BIOS file if found Использовать файл BIOS, если найден - + Skip BIOS intro Пропустить интро BIOS - + GBA BIOS file: Файл GBA BIOS: - + GBC BIOS file: Файл GBC BIOS: - + SGB BIOS file: Файл SGB BIOS: - + Save games Сохранения - - - - - + + + + + Same directory as the ROM Директория, в которой находится ROM - + Save states Сохранения состояния - + Screenshots Скриншоты - + Patches Патчи - + Cheats Читы - + Log to file Сохранять журнал в файл - + Log to console Выводить на консоль - + Select Log File Выбрать файл журнала - + Default BG colors: Цвета фона по умолчанию: - + Super Game Boy borders Рамки Super Game Boy - + Default sprite colors 1: 1-е цвета по умолчанию для спрайта: - + Default sprite colors 2: 2-е цвета по умолчанию для спрайта: @@ -5789,7 +5871,6 @@ Download size: %3 - WebM WebM @@ -5823,19 +5904,8 @@ Download size: %3 Format Формат - - - MKV - MKV - - - - AVI - AVI - - MP4 MP4 @@ -5844,72 +5914,6 @@ Download size: %3 4K 4K - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - Нет - - - - FLAC - FLAC - - - - WavPack - WavPack - - - - Opus - Opus - - - - Vorbis - - - - - MP3 - MP3 - - - - AAC - - - - - Uncompressed - Без сжатия - Bitrate (kbps) @@ -5920,16 +5924,6 @@ Download size: %3 ABR - - - H.264 - - - - - H.264 (NVENC) - - VBR @@ -5959,80 +5953,80 @@ Download size: %3 QGBA::Window - + Archives (%1) Архивы (%1) - - + + Select ROM Выбор игры - + Select folder Выбор папки - - + + Select save Выбор сохранения - + Select patch Выбор патча - + Patches (*.ips *.ups *.bps) Патчи (*.ips *.ups *.bps) - + Select e-Reader dotcode Выбор карточки e-Reader - + e-Reader card (*.raw *.bin *.bmp) Карточка e-Reader (*.raw *.bin *.bmp) - + Select image Выбор изображения - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Файл изображения (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) Сохранения GameShark (*.sps *.xps) - + Select video log Выбор видеолога - + Video logs (*.mvl) Видеологи (*.mvl) - + Crash Сбой - + The game has crashed with the following error: %1 @@ -6041,699 +6035,709 @@ Download size: %3 %1 - + Couldn't Start Запуск не удался - + Could not start game. Не удалось запустить игру. - + Unimplemented BIOS call Неизвестный вызов BIOS - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Игра использует нереализованный вызов BIOS. Пожалуйста, воспользуйтесь официальным BIOS для лучшей совместимости. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Не удалось создать устройство отображения, возврат к программному режиму. Игры могут идти медленнее, особенно в окнах больших размеров. - + Really make portable? Перейти в портативный режим? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? После этого эмулятор будет загружать конфигурацию из папки с исполняемым файлом. Продолжить? - + Restart needed Требуется перезапуск - + Some changes will not take effect until the emulator is restarted. Для применения некоторых изменений требуется перезапустить эмулятор. - + - Player %1 of %2 - Игрок %1 из %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File &Файл - + Load &ROM... Загрузить &ROM... - + Load ROM in archive... Загрузить игру из архива... - + Add folder to library... Добавить папку в библиотеку... - + Save games (%1) Игровые сохранения (%1) - + Select save game Выбор игрового сохранения - + mGBA save state files (%1) Файл сохранения состояния mGBA (%1) - - + + Select save state Выбор сохранения состояния - + Select e-Reader card images Выбор изображения карточки e-Reader - + Image file (*.png *.jpg *.jpeg) Файл изображения (*.png *.jpg *.jpeg) - + Conversion finished Конвертация завершена - + %1 of %2 e-Reader cards converted successfully. %1 из %2 карточек e-Reader успешно сконвертировано. - + Load alternate save game... Загрузить альтернативное сохранение... - + Load temporary save game... Загрузить временное сохранение... - + Load &patch... Загрузить &патч... - + Boot BIOS Загрузиться в BIOS - + Replace ROM... Заменить ROM... - + Scan e-Reader dotcodes... Сканировать dot-коды e-Reader... - + Convert e-Reader card image to raw... Конвертировать карту e-Reader в raw... - + ROM &info... Информация об &игре... - + Recent Недавние - + Make portable Портативный режим - + &Load state &Загрузить состояние - + Load state file... Загрузить состояние из файла... - + &Save state &Сохранить состояние - + Save state file... Сохранить состояние в файл... - + Quick load Быстрая загрузка - + Quick save Быстрое сохранение - + Load recent Загрузить недавнее - + Save recent Сохранить в недавнее - + Undo load state Отмена загрузки состояния - + Undo save state Отмена сохранения состояния - - + + State &%1 Слот &%1 - + Load camera image... Загрузить изображение с камеры... - + Convert save game... Конвертировать игровое сохранение... - + GameShark saves (*.gsv *.sps *.xps) Сохранения GameShark (*.gsv *.sps *.xps) - + Reset needed Необходима перезагрузка - + Some changes will not take effect until the game is reset. Некоторые изменения не войдут в силу, пока игра не перезагружена. - + Save games Сохранения - + Import GameShark Save... Импорт сохранения GameShark... - + Export GameShark Save... Экспорт сохранения GameShark... - + Automatically determine Определить автоматически - + Use player %0 save game Использовать сохранение игрока %0 - + New multiplayer window Новое окно мультиплеера - + Connect to Dolphin... Соединение с Dolphin... - + Report bug... Сообщить об ошибке... - + About... О программе... - + E&xit &Выход - + &Emulation &Эмуляция - + &Reset Перезагрузить (&R/&К) - + Sh&utdown Выключить (&U/&Г) - + Yank game pak Пнуть картридж - + &Pause Пау&за - + &Next frame Следующий кадр (&N/&Т) - + Fast forward (held) Перемотка (удержание) - + &Fast forward Перемотк&а - + Fast forward speed Скорость перемотки - + Unbounded Неограниченная - + %0x %0x - + Increase fast forward speed - + Decrease fast forward speed - + Rewind (held) Обратная перемотка (удержание) - + Re&wind Обратная перемотка (&W/&Ц) - + Step backwards Шаг назад - + Solar sensor Датчик солнца - + Increase solar level Усилить солнечный свет - + Decrease solar level Ослабить солнечный свет - + Brightest solar level Ярчайшее солнце - + Darkest solar level Тусклейшее солнце - + Brightness %1 Яркость %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video Аудио/Видео (&V/&М) - + Frame size Размер кадра - + %1× %1× - + Toggle fullscreen Переключить полноэкранный режим - + + &Lock frame size + + + + Lock aspect ratio Зафиксировать соотношение сторон - + Force integer scaling Принудительное целочисленное масштабирование - + Interframe blending Межкадровое смешение - + Bilinear filtering Билинейная фильтрация - + Frame&skip Пропуск кадров (&S/&Ы) - + Mute Выключить звук - + FPS target Целевой FPS - + Native (59.7275) Родной (59.7275) - + Take &screenshot Снять скриншот (&S/&Ы) - + F12 F12 - + Record A/V... Записать аудио/видео... - + Record GIF/WebP/APNG... Записать GIF/WebP/APNG... - + Video layers Видеослои - + Audio channels Аудиоканалы - + Adjust layer placement... Настроить расположение слоёв... - + &Tools Инструм&енты - + View &logs... Посмотреть в журнал... (&L/&Д) - + Game &overrides... Переопределения для этой игры... (&О/&Щ) - + Game Pak sensors... Датчики в Game Pak... - + &Cheats... Читы... (&C/&С) - + Create forwarder... - + Settings... Настройки... - + Open debugger console... Открыть консоль отладки... - + Start &GDB server... Запустить сервер &GDB... - + Scripting... Скрипты... - + Game state views Просмотр состояния игры - + View &palette... Просмотр палитры... (&P/&З) - + View &sprites... Просмотр спрайтов... (&S/&Ы) - + View &tiles... Просмотр тайлов... (&T/&Е) - + View &map... Просмотр карты... (&M/&Ь) - + &Frame inspector... Изучение фрейм&а... - + View memory... Просмотр памяти... - + Search memory... Поиск в памяти... - + View &I/O registers... Просмотр регистров &I/O... - + + Log memory &accesses... + + + + Record debug video log... Запись отладочного видеожурнала... - + Stop debug video log Закончить запись отладочного видеожурнала - + Exit fullscreen Выйти из полноэкранного режима - + GameShark Button (held) Кнопка GameShark (удерживается) - + Autofire Автострельба - + Autofire A A (автострельба) - + Autofire B B (автострельба) - + Autofire L L (автострельба) - + Autofire R R (автострельба) - + Autofire Start Start (автострельба) - + Autofire Select Select (автострельба) - + Autofire Up Вверх (автострельба) - + Autofire Right Вправо (автострельба) - + Autofire Down Вниз (автострельба) - + Autofire Left Влево (автострельба) - + Clear Очистить @@ -6771,17 +6775,17 @@ Download size: %3 ? - + Super (L) - + Super (R) - + Menu Меню @@ -6789,22 +6793,22 @@ Download size: %3 QShortcut - + Shift - + Control - + Alt - + Meta diff --git a/src/platform/qt/ts/mgba-sv.ts b/src/platform/qt/ts/mgba-sv.ts index 55df22b52..4017ea489 100644 --- a/src/platform/qt/ts/mgba-sv.ts +++ b/src/platform/qt/ts/mgba-sv.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) @@ -191,17 +191,17 @@ Nedladdningsstorlek: %3 QGBA::AudioDevice - + Can't set format of context-less audio device Det går inte att ställa in formatet för kontextlös ljudenhet - + Audio device is missing its core Ljudenheten saknar kärnan - + Writing data to read-only audio device Skriver data till skrivskyddad ljudenhet @@ -209,7 +209,7 @@ Nedladdningsstorlek: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input Kan inte starta en ljudprocessor utan ingång @@ -285,28 +285,28 @@ Nedladdningsstorlek: %3 Visa avancerat - + BattleChip data missing BattleChip-data saknas - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? BattleChip-data saknas. BattleChip Gates fungerar fortfarande, men viss grafik kommer att saknas. Vill du ladda ner datan nu? - - + + Select deck file Välj deck-fil - + Incompatible deck Inkompatibelt deck - + The selected deck is not compatible with this Chip Gate Den valda deck är inte kompatibel med denna Chip Gate @@ -367,19 +367,19 @@ Nedladdningsstorlek: %3 - - + + Autodetect (recommended) - - + + Select cheats file - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. @@ -398,37 +398,37 @@ Nedladdningsstorlek: %3 - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -477,6 +477,14 @@ Nedladdningsstorlek: %3 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -757,52 +765,52 @@ Nedladdningsstorlek: %3 - + Export frame - + Portable Network Graphics (*.png) - + None - + Background - + Window - + Objwin - + Sprite - + Backdrop - + Frame - + %1 %2 @@ -818,22 +826,22 @@ Nedladdningsstorlek: %3 QGBA::GBAKeyEditor - + Clear Button - + Clear Analog - + Refresh - + Set all @@ -3006,8 +3014,8 @@ Nedladdningsstorlek: %3 QGBA::KeyEditor - - + + --- @@ -3378,23 +3386,87 @@ Nedladdningsstorlek: %3 - - - + + + N/A - + Export map - + Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Nedladdningsstorlek: %3 - + (%0/%1×) - + (⅟%0×) - + (%0×) - + %1 byte%2 @@ -3750,17 +3822,17 @@ Nedladdningsstorlek: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -4157,35 +4229,35 @@ Nedladdningsstorlek: %3 - + #%0 - + 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette - + Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 @@ -4259,7 +4331,7 @@ Nedladdningsstorlek: %3 QGBA::ROMInfo - + @@ -4299,16 +4371,26 @@ Nedladdningsstorlek: %3 - File size: + Maker Code: - CRC32: + Revision: + File size: + + + + + CRC32: + + + + Save file: @@ -4364,62 +4446,62 @@ Nedladdningsstorlek: %3 QGBA::SaveConverter - + Save games and save states (%1) - + Select save game or save state - + Save games (%1) - + Select save game - + Conversion failed - + Failed to convert the save game. This is probably a bug. - + No file selected - + Could not open file - + No valid formats found - + Please select a valid input file - + No valid conversions found - + Cannot convert save games between platforms @@ -4445,97 +4527,97 @@ Nedladdningsstorlek: %3 - + %1 %2 save game - + little endian - + big endian - + SRAM - + %1 flash - + %1 EEPROM - + + RTC - + %1 SRAM + RTC - + %1 SRAM - + packed MBC2 - + unpacked MBC2 - + MBC6 flash - + MBC6 combined SRAM + flash - + MBC6 SRAM - + TAMA5 - + %1 (%2) - + %1 save state with embedded %2 save game - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4571,32 +4653,37 @@ Nedladdningsstorlek: %3 - + Load script... - + + &Load most recent + + + + &Reset - + 0 - + Select script to load - + Lua scripts (*.lua) - + All files (*.*) @@ -4689,105 +4776,105 @@ Nedladdningsstorlek: %3 QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None - + None (Still Image) - + Keyboard - + Controllers - + Shortcuts - - + + Shaders - + Select BIOS - + Select directory - + Select image - + Image file (*.png *.jpg *.jpeg) - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago @@ -4795,7 +4882,7 @@ Nedladdningsstorlek: %3 - + %n day(s) ago @@ -5122,37 +5209,37 @@ Nedladdningsstorlek: %3 - + Default color palette only - + SGB color palette if available - + GBC color palette if available - + SGB (preferred) or GBC color palette if available - + Game Boy Camera - + Driver: - + Source: @@ -5329,42 +5416,42 @@ Nedladdningsstorlek: %3 - + Models - + GB only: - + SGB compatible: - + GBC only: - + GBC compatible: - + SGB and GBC compatible: - + Game Boy palette - + Preset: @@ -5401,135 +5488,130 @@ Nedladdningsstorlek: %3 - + OpenGL enhancements - + High-resolution scale: - + (240×160) - - XQ GBA audio (experimental) - - - - + GB BIOS file: - - - - - - - - - + + + + + + + + + Browse - + Use BIOS file if found - + Skip BIOS intro - + GBA BIOS file: - + GBC BIOS file: - + SGB BIOS file: - + Save games - - - - - + + + + + Same directory as the ROM - + Save states - + Screenshots - + Patches - + Cheats Cheats - + Log to file - + Log to console - + Select Log File - + Default BG colors: - + Default sprite colors 1: - + Default sprite colors 2: - + Super Game Boy borders @@ -5787,13 +5869,11 @@ Nedladdningsstorlek: %3 - WebM - MP4 @@ -5832,82 +5912,6 @@ Nedladdningsstorlek: %3 Format - - - MKV - - - - - AVI - - - - - HEVC - - - - - HEVC (NVENC) - - - - - VP8 - - - - - VP9 - - - - - FFV1 - - - - - - None - - - - - FLAC - - - - - WavPack - - - - - Opus - - - - - Vorbis - - - - - MP3 - - - - - AAC - - - - - Uncompressed - - Bitrate (kbps) @@ -5918,16 +5922,6 @@ Nedladdningsstorlek: %3 ABR - - - H.264 - - - - - H.264 (NVENC) - - VBR @@ -5957,779 +5951,789 @@ Nedladdningsstorlek: %3 QGBA::Window - + Archives (%1) - - + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Increase fast forward speed - + Decrease fast forward speed - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - - Lock aspect ratio - - - - - Force integer scaling - - - - - Interframe blending - - - - - Bilinear filtering + + &Lock frame size + Lock aspect ratio + + + + + Force integer scaling + + + + + Interframe blending + + + + + Bilinear filtering + + + + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Create forwarder... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + Game state views - + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + + Log memory &accesses... + + + + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -6767,17 +6771,17 @@ Nedladdningsstorlek: %3 - + Super (L) - + Super (R) - + Menu @@ -6785,22 +6789,22 @@ Nedladdningsstorlek: %3 QShortcut - + Shift - + Control - + Alt - + Meta diff --git a/src/platform/qt/ts/mgba-template.ts b/src/platform/qt/ts/mgba-template.ts index 61b57b820..8cd293d9b 100644 --- a/src/platform/qt/ts/mgba-template.ts +++ b/src/platform/qt/ts/mgba-template.ts @@ -4,22 +4,22 @@ QGBA - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) @@ -185,17 +185,17 @@ Download size: %3 QGBA::AudioDevice - + Can't set format of context-less audio device - + Audio device is missing its core - + Writing data to read-only audio device @@ -203,7 +203,7 @@ Download size: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input @@ -279,28 +279,28 @@ Download size: %3 - + BattleChip data missing - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? - - + + Select deck file - + Incompatible deck - + The selected deck is not compatible with this Chip Gate @@ -361,19 +361,19 @@ Download size: %3 - - + + Autodetect (recommended) - - + + Select cheats file - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. @@ -392,37 +392,37 @@ Download size: %3 - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -471,6 +471,14 @@ Download size: %3 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -751,52 +759,52 @@ Download size: %3 - + Export frame - + Portable Network Graphics (*.png) - + None - + Background - + Window - + Objwin - + Sprite - + Backdrop - + Frame - + %1 %2 @@ -812,22 +820,22 @@ Download size: %3 QGBA::GBAKeyEditor - + Clear Button - + Clear Analog - + Refresh - + Set all @@ -3000,8 +3008,8 @@ Download size: %3 QGBA::KeyEditor - - + + --- @@ -3372,23 +3380,87 @@ Download size: %3 - - - + + + N/A - + Export map - + Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3635,22 +3707,22 @@ Download size: %3 - + (%0/%1×) - + (⅟%0×) - + (%0×) - + %1 byte%2 @@ -3744,17 +3816,17 @@ Download size: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -4151,35 +4223,35 @@ Download size: %3 - + #%0 - + 0x%0 + + - - 0x%0 (%1) - + Export palette - + Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 @@ -4253,7 +4325,7 @@ Download size: %3 QGBA::ROMInfo - + @@ -4293,16 +4365,26 @@ Download size: %3 - File size: + Maker Code: - CRC32: + Revision: + File size: + + + + + CRC32: + + + + Save file: @@ -4358,62 +4440,62 @@ Download size: %3 QGBA::SaveConverter - + Save games and save states (%1) - + Select save game or save state - + Save games (%1) - + Select save game - + Conversion failed - + Failed to convert the save game. This is probably a bug. - + No file selected - + Could not open file - + No valid formats found - + Please select a valid input file - + No valid conversions found - + Cannot convert save games between platforms @@ -4439,97 +4521,97 @@ Download size: %3 - + %1 %2 save game - + little endian - + big endian - + SRAM - + %1 flash - + %1 EEPROM - + + RTC - + %1 SRAM + RTC - + %1 SRAM - + packed MBC2 - + unpacked MBC2 - + MBC6 flash - + MBC6 combined SRAM + flash - + MBC6 SRAM - + TAMA5 - + %1 (%2) - + %1 save state with embedded %2 save game - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4565,32 +4647,37 @@ Download size: %3 - + Load script... - + + &Load most recent + + + + &Reset - + 0 - + Select script to load - + Lua scripts (*.lua) - + All files (*.*) @@ -4683,112 +4770,112 @@ Download size: %3 QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None - + None (Still Image) - + Keyboard - + Controllers - + Shortcuts - - + + Shaders - + Select BIOS - + Select directory - + Select image - + Image file (*.png *.jpg *.jpeg) - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -5114,37 +5201,37 @@ Download size: %3 - + Default color palette only - + SGB color palette if available - + GBC color palette if available - + SGB (preferred) or GBC color palette if available - + Game Boy Camera - + Driver: - + Source: @@ -5321,42 +5408,42 @@ Download size: %3 - + Models - + GB only: - + SGB compatible: - + GBC only: - + GBC compatible: - + SGB and GBC compatible: - + Game Boy palette - + Preset: @@ -5393,135 +5480,130 @@ Download size: %3 - + OpenGL enhancements - + High-resolution scale: - + (240×160) - - XQ GBA audio (experimental) - - - - + GB BIOS file: - - - - - - - - - + + + + + + + + + Browse - + Use BIOS file if found - + Skip BIOS intro - + GBA BIOS file: - + GBC BIOS file: - + SGB BIOS file: - + Save games - - - - - + + + + + Same directory as the ROM - + Save states - + Screenshots - + Patches - + Cheats - + Log to file - + Log to console - + Select Log File - + Default BG colors: - + Default sprite colors 1: - + Default sprite colors 2: - + Super Game Boy borders @@ -5779,13 +5861,11 @@ Download size: %3 - WebM - MP4 @@ -5824,82 +5904,6 @@ Download size: %3 Format - - - MKV - - - - - AVI - - - - - HEVC - - - - - HEVC (NVENC) - - - - - VP8 - - - - - VP9 - - - - - FFV1 - - - - - - None - - - - - FLAC - - - - - WavPack - - - - - Opus - - - - - Vorbis - - - - - MP3 - - - - - AAC - - - - - Uncompressed - - Bitrate (kbps) @@ -5910,16 +5914,6 @@ Download size: %3 ABR - - - H.264 - - - - - H.264 (NVENC) - - VBR @@ -5949,779 +5943,789 @@ Download size: %3 QGBA::Window - + Archives (%1) - - + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Increase fast forward speed - + Decrease fast forward speed - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - - Lock aspect ratio - - - - - Force integer scaling - - - - - Interframe blending - - - - - Bilinear filtering + + &Lock frame size + Lock aspect ratio + + + + + Force integer scaling + + + + + Interframe blending + + + + + Bilinear filtering + + + + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Create forwarder... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + Game state views - + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + + Log memory &accesses... + + + + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -6759,17 +6763,17 @@ Download size: %3 - + Super (L) - + Super (R) - + Menu @@ -6777,22 +6781,22 @@ Download size: %3 QShortcut - + Shift - + Control - + Alt - + Meta diff --git a/src/platform/qt/ts/mgba-tr.ts b/src/platform/qt/ts/mgba-tr.ts index d239b59c2..59e085531 100644 --- a/src/platform/qt/ts/mgba-tr.ts +++ b/src/platform/qt/ts/mgba-tr.ts @@ -4,24 +4,24 @@ QGBA - + Game Boy Advance ROMs (%1) - Game Boy Advance ROMları (%1) + Game Boy Advance ROM'ları (%1) - + Game Boy ROMs (%1) - Game Boy ROMları (%1) + Game Boy ROM'ları (%1) - + All ROMs (%1) - Bütün ROMlar (%1) + Bütün ROM'lar (%1) - + %1 Video Logs (*.mvl) - + %1 Video Günlükleri (*.mvl) @@ -64,47 +64,52 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. An update is available - + Bir güncelleme mevcut An update to %1 is available. - + %1 için bir güncelleme mevcut. + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + +Şimdi indirip yüklemek istiyor musunuz? İndirme işlemi tamamlandığında öykünücüyü yeniden başlatmanız gerekecektir. Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + +Otomatik güncelleme bu platformda mevcut değildir. Güncellemek istiyorsanız bunu manuel olarak yapmanız gerekecektir. Current version: %1 New version: %2 Download size: %3 - + Güncel sürüm: %1 +Yeni sürüm: %2 +İndirme boyutu: %3 Downloading update... - + Güncelleme indiriliyor... Downloading failed. Please update manually. - + İndirme başarısız oldu. Lütfen manuel olarak güncelleyin. Downloading done. Press OK to restart %1 and install the update. - + İndirme tamamlandı. %1 yeniden başlatmak ve güncellemeyi yüklemek için Tamam'a basın. @@ -112,22 +117,22 @@ Download size: %3 Stable - + Kararlı Development - + Geliştirme Unknown - Bilinmeyen + Bilinmeyen (None) - + (Yok) @@ -186,27 +191,27 @@ Download size: %3 QGBA::AudioDevice - + Can't set format of context-less audio device - + Bağlamdan bağımsız ses cihazının formatı ayarlanamıyor - + Audio device is missing its core - + Ses cihazının çekirdeği eksik - + Writing data to read-only audio device - + Salt okunur ses cihazına veri yazma QGBA::AudioProcessorQt - + Can't start an audio processor without input - + Girişsiz ses işlemcisi başlatılamaz @@ -214,7 +219,7 @@ Download size: %3 Can't start an audio processor without input - + Girişsiz ses işlemcisi başlatılamaz @@ -280,30 +285,30 @@ Download size: %3 Gelişmişi göster - + BattleChip data missing - + BattleChip verisi yok - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? - + BattleChip verisi yok. Bazı grafikler olmadan BattleChip Gates hala çalışır. Verileri şimdi indirmek istermisin? - - + + Select deck file - + Deste dosyası seç - + Incompatible deck - + Uyumsuz deste - + The selected deck is not compatible with this Chip Gate - + Seçilen deste bu Chip Gate ile uyumlu değildir @@ -329,7 +334,7 @@ Download size: %3 Add New Code - + Yeni Kod Ekle @@ -339,12 +344,12 @@ Download size: %3 Add Lines - + Satır ekle Code type - + Kod tipi @@ -362,21 +367,21 @@ Download size: %3 Kodları buraya gir... - - + + Autodetect (recommended) - + Otoseç (tavsiye edilir) - - + + Select cheats file Oyun hileleri seçin - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. - + Bazı hileler eklenemedi. Lütfen onların doğru formatlandığından emin ol ve/yada başa hile tiplerini dene. @@ -393,37 +398,37 @@ Download size: %3 - + Reset the game? - + Oyun sıfırlansım mı? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Kayıt dosyası açılamadı: %1 - + Failed to open game file: %1 Oyun dosyası açılamadı: %1 - + Can't yank pack in unexpected platform! Beklenmedik bir platformda kartı çıkaramazsın! - + Failed to open snapshot file for reading: %1 Anlık görüntü dosyası okuma için açılamadı: %1 - + Failed to open snapshot file for writing: %1 Anlık görüntü dosyası yazma için açılamadı: %1 @@ -472,6 +477,14 @@ Download size: %3 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -752,52 +765,52 @@ Download size: %3 Sıfırla - + Export frame Kareyi Dışarı Aktar - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + None Hiçbiri - + Background Arka Plan - + Window Pencere - + Objwin Nes. Pen. - + Sprite Sprite - + Backdrop Arka fon - + Frame Kare - + %1 %2 %1 %2 @@ -813,22 +826,22 @@ Download size: %3 QGBA::GBAKeyEditor - + Clear Button Tuşu Temizle - + Clear Analog Analogu Temizle - + Refresh Yenile - + Set all Tümüne ayarla @@ -3001,8 +3014,8 @@ Download size: %3 QGBA::KeyEditor - - + + --- @@ -3373,23 +3386,87 @@ Download size: %3 Dikey - - - + + + N/A N/A - + Export map Haritayı dışarı aktar - + Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + Gözat + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + Başlat + + + + Stop + Durdur + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3636,22 +3713,22 @@ Download size: %3 Yenile - + (%0/%1×) - + (⅟%0×) - + (%0×) - + %1 byte%2 @@ -3745,17 +3822,17 @@ Download size: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + Trying to get player ID for a multiplayer player that's not attached - + Trying to get save ID for a multiplayer player that's not attached @@ -4152,35 +4229,35 @@ Download size: %3 OBJ dışarı aktar - + #%0 - + 0x%0 + + - - 0x%0 (%1) - + Export palette Paleti dışarı aktar - + Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 Çıkış paleti dosyası açılamadı:%1 @@ -4254,7 +4331,7 @@ Download size: %3 QGBA::ROMInfo - + @@ -4294,16 +4371,26 @@ Download size: %3 + Maker Code: + + + + + Revision: + + + + File size: Dosya boyutu: - + CRC32: - + Save file: @@ -4359,62 +4446,62 @@ Download size: %3 QGBA::SaveConverter - + Save games and save states (%1) Kayıtlı oyunlar ve kayıtlı durumlar (%1) - + Select save game or save state Kayıtlı oyun veya kayıtlı durum seç - + Save games (%1) Kayıtlı oyunlar (%1) - + Select save game Kayıtlı oyun seç - + Conversion failed Dönüştürme başarısız - + Failed to convert the save game. This is probably a bug. Kayıtlı oyunu dönüştürme başarısız. Muhtemelen bir hata meydana geldi. - + No file selected Seçili dosya yok - + Could not open file Dosya açılamadı - + No valid formats found Geçerli türler bulunamadı - + Please select a valid input file Lütfen geçerli bir giriş dosyası seç - + No valid conversions found Geçerli dönüştürme bulunamadı - + Cannot convert save games between platforms Kayıtlı oyunlar platformlar arasında dönüştürülemez @@ -4440,97 +4527,97 @@ Download size: %3 Çıkış dosyası - + %1 %2 save game %1 %2 kayıtlı oyun - + little endian little endian - + big endian big endian - + SRAM SRAM - + %1 flash %1 flash - + %1 EEPROM %1 EEPROM - + + RTC - + %1 SRAM + RTC %1 SRAM + RTC - + %1 SRAM %1 SRAM - + packed MBC2 paketli MBC2 - + unpacked MBC2 paketlenmemiş MBC2 - + MBC6 flash MBC6 flash - + MBC6 combined SRAM + flash MBC6 ile birleştirilmiş SRAM + flash - + MBC6 SRAM MBC6 SRAM - + TAMA5 TAMA5 - + %1 (%2) %1 (%2) - + %1 save state with embedded %2 save game Gömülü %2 kayıtlı oyunla %1 kayıt durumu - + %1 SharkPort %2 save game - + %1 GameShark Advance SP %2 save game @@ -4566,32 +4653,37 @@ Download size: %3 - + Load script... - + + &Load most recent + + + + &Reset &Reset - + 0 4K {0?} - + Select script to load - + Lua scripts (*.lua) - + All files (*.*) @@ -4684,112 +4776,112 @@ Download size: %3 QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) Yazılım - + OpenGL OpenGL - + OpenGL (force version 1.x) - + None Hiçbiri - + None (Still Image) - + Keyboard Klavye - + Controllers - + Shortcuts Kısayollar - - + + Shaders Gölgelendiricler - + Select BIOS BIOS seç - + Select directory Yolu seç - + Select image Resim seç - + Image file (*.png *.jpg *.jpeg) Görüntü dosyası (*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -5135,72 +5227,72 @@ Download size: %3 - + Models Modeller - + GB only: Sadece GB: - + SGB compatible: SGB uyumlu: - + GBC only: Sadece GBC: - + GBC compatible: Uyumlu GBC: - + SGB and GBC compatible: Uyumlu SGB ve GBC: - + Game Boy palette Game Boy paleti - + Default color palette only Sadece varsayılan renk paleti - + SGB color palette if available Mevcutsa SGB renk paketi - + GBC color palette if available Mevcutsa GBC renk paketi - + SGB (preferred) or GBC color palette if available Mevcutsa SGB (tercih edilen) ya da GBC renk paketi - + Game Boy Camera Game Boy Kamera - + Driver: Sürücü: - + Source: Kaynak: @@ -5291,7 +5383,7 @@ Download size: %3 ROM hacklerinde VBA hata uyumluluğunu etkinleştir - + Preset: Ön ayar: @@ -5394,135 +5486,130 @@ Download size: %3 Yazılım - + OpenGL enhancements OpenGL geliştirmeleri - + High-resolution scale: Yüksek kalite ölçeği: - + (240×160) (240×160) - - XQ GBA audio (experimental) - XQ GBA ses (deneysel) - - - + GB BIOS file: GB BIOS dosyası: - - - - - - - - - + + + + + + + + + Browse Gözat - + Use BIOS file if found Varsa BIOS dosyasını kullan - + Skip BIOS intro BIOS girişini atla - + GBA BIOS file: GBA BIOS dosyası: - + GBC BIOS file: GBC BIOS dosyası: - + SGB BIOS file: SGB BIOS dosyası: - + Save games Oyunları kaydet - - - - - + + + + + Same directory as the ROM ROM ile aynı dizin - + Save states Konum kaydedici - + Screenshots Ekran Görüntüleri - + Patches Yamalar - + Cheats Hileler - + Log to file Dosyaya günlüğünü gir - + Log to console Konsola günlüğünü gir - + Select Log File Günlük Dosyasını Seç - + Default BG colors: - + Super Game Boy borders Super Game Boy sınırları - + Default sprite colors 1: Varsayılan sprite renkleri 1: - + Default sprite colors 2: Varsayılan sprite renkleri 2: @@ -5780,7 +5867,6 @@ Download size: %3 - WebM @@ -5814,19 +5900,8 @@ Download size: %3 Format Format - - - MKV - - - - - AVI - - - MP4 @@ -5835,72 +5910,6 @@ Download size: %3 4K 4K - - - HEVC - - - - - HEVC (NVENC) - - - - - VP8 - - - - - VP9 - - - - - FFV1 - - - - - - None - Hiçbiri - - - - FLAC - - - - - WavPack - - - - - Opus - - - - - Vorbis - - - - - MP3 - - - - - AAC - - - - - Uncompressed - Sıkıştırılmamış - Bitrate (kbps) @@ -5911,16 +5920,6 @@ Download size: %3 ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5950,100 +5949,100 @@ Download size: %3 QGBA::Window - + Archives (%1) Arşivler (%1) - - + + Select ROM ROM seç - + Select folder Klasör seç - - + + Select save Kayıt seç - + Select patch Yama seç - + Patches (*.ips *.ups *.bps) Yamalar (*.ips *.ups *.bps) - + Select e-Reader dotcode e-Okuyucu nokta kodunu seç - + e-Reader card (*.raw *.bin *.bmp) e-Okuyucu kart (*.raw *.bin *.bmp) - + Select e-Reader card images e-Okuyucu kartından görüntüleri seç - + Image file (*.png *.jpg *.jpeg) Görüntü dosyası (*.png *.jpg *.jpeg) - + Conversion finished Dönüştürme tamamlandı - + %1 of %2 e-Reader cards converted successfully. %1 / %2 e-Okuyucu kartları dönüştürme tamamlandı. - + Select image Resim seç - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Resim dosyası (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) GameShark kayıtları (*.sps *.xps) - + Select video log Video günlüğü seç - + Video logs (*.mvl) Video günlükleri (*.mvl) - + Crash Çökme - + The game has crashed with the following error: %1 @@ -6052,679 +6051,689 @@ Download size: %3 %1 - + Unimplemented BIOS call Uygulanmamış BIOS girişi - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Oyun BIOS dosyasına ihtiyacı var. Lütfen en iyi deneyim için resmi BIOS'u kullanın. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Uygun görüntü cihazı oluşturma başarısız, yazılım ekranına dönülüyor. Oyunlar özellikle daha büyük ekranlarda yavaş çalışabilir. - + Really make portable? Taşınabilir yapılsın mı? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - Emülatörün yapılandırmasını yürütülebilir dosya ile aynı dizinden yüklemesini sağlar. Devam etmek istiyor musun? + Öyküncünün yapılandırmasını yürütülebilir dosya ile aynı dizinden yüklemesini sağlar. Devam etmek istiyor musunuz? - + Restart needed Yeniden başlatma gerekli - + Some changes will not take effect until the emulator is restarted. - Bazı değişiklikler emülatör yeniden başlatılıncaya kadar etkili olmaz. + Bazı değişiklikler öyküncü yeniden başlatılıncaya kadar etkili olmaz. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... &ROM yükle... - + Load ROM in archive... ROM'u arşivden yükle ... - + Add folder to library... Kütüphaneye klasör ekle ... - + Save games Oyunları kaydet - + Automatically determine - + Use player %0 save game - + Load &patch... &Patch yükle... - + Boot BIOS BIOS boot et - + Replace ROM... ROM değişti... - + Create forwarder... - + Game state views - + + Log memory &accesses... + + + + Convert e-Reader card image to raw... e-Okuyucu kart resimlerini rawa dönüştür... - + ROM &info... ROM &info... - + Recent Son kullanılanlar - + Make portable Portatif yap - + &Load state &Kaydedilmiş konum yükle - + Load state file... Kaydedilmiş konum dosyası yükle... - + &Save state &Konumu kaydet - + Save state file... Konum dosyasını kaydet... - + Quick load Hızlı Yükle - + Quick save Hızlı kaydet - + Load recent En son yükle - + Save recent Hızlı kaydet - + Undo load state Kaydedilen konum yüklemeyi geri al - + Undo save state Konum kaydetmeyi geri al - - + + State &%1 Konum &%1 - + Load camera image... Kamera resmini yükle ... - + Convert save game... Kayıtlı oyun dömnüştürülüyor... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + New multiplayer window Yeni çokoyunculu ekranı - + Connect to Dolphin... Dolphin'e Bağlan... - + Report bug... Hata rapor et... - + About... Hakkında... - + E&xit Çıkış - + &Emulation Emülasyon - + &Reset &Reset - + Sh&utdown Kapat - + Yank game pak - + &Pause &Durdur - + &Next frame &Sonraki kare - + Fast forward (held) İleriye sar(basılı tutun) - + &Fast forward &İleriye sar - + Fast forward speed İleriye sarma hızı - + Unbounded - + %0x - + Increase fast forward speed - + Decrease fast forward speed - + Rewind (held) Geri sar (basılı tutun) - + Re&wind Geri sar - + Step backwards Geriye doğru adım - + Solar sensor - + Increase solar level Solar seviyesini arttır - + Decrease solar level Solar seviyesini düşür - + Brightest solar level En parlak solar seviyesi - + Darkest solar level En karanlık solar seviyesi - + Brightness %1 Parlaklık:%1 - + Game Boy Printer... Game Boy yazıcısı... - + BattleChip Gate... - + Audio/&Video Ses/&Video - + Frame size Çerçeve boyutu - + Toggle fullscreen Tamekranı aç/kapa - + + &Lock frame size + + + + Lock aspect ratio En boy oranını kilitle - + Force integer scaling Tamsayılı ölçeklendirmeyi zorla - + Bilinear filtering Bilinear filtreleme - + Frame&skip Kare atlama - + Mute Sessiz - + FPS target FPS hedefi - + Native (59.7275) - + Take &screenshot Ekran görüntüsü al - + F12 - + Video layers - + Audio channels Ses kanalları - + Adjust layer placement... Katman yerleşimini ayarlayın... - + &Tools &Araçlar - + View &logs... Kayıtları görüntüle... - + Game &overrides... & Oyunun üzerine yazılanlar... - + Couldn't Start Başlatılamadı - + Save games (%1) Kayıtlı oyunlar (%1) - + Select save game Kayıtlı oyun seç - + mGBA save state files (%1) mGBA kayıt durum dosyası (%1) - - + + Select save state Kayıt durumu seç - + Could not start game. Oyun başlatılamadı. - + Load alternate save game... Alternatif kayıtlı oyun yükle... - + Load temporary save game... Geçici kayıtlı oyunu yükle... - + Scan e-Reader dotcodes... e-Okuyucu noktakodları tara... - + Import GameShark Save... GameShark kaydını içeri aktar... - + Export GameShark Save... GameShark kaydını dışarı aktar... - + %1× %1× - + Interframe blending Kareler-arası Karıştırma - + Record A/V... A/V Kayıt... - + Record GIF/WebP/APNG... GIF/WebP/APNG Kayıt... - + Game Pak sensors... Oyun Kartuş sensörleri... - + &Cheats... &Hileler... - + Settings... Ayarlar... - + Open debugger console... Hata ayıklayıcı konsolunu aç ... - + Start &GDB server... &GDB sunucusunu başlat... - + Scripting... - + View &palette... &Renk Paletini gör... - + View &sprites... &Spriteları gör... - + View &tiles... &Desenleri gör... - + View &map... &Haritayı gör - + &Frame inspector... &Kare denetçisi... - + View memory... Hafıza gör... - + Search memory... Hafızada ara... - + View &I/O registers... &I/O kayıtlarını görüntüle - + Record debug video log... Hata ayıklama video günlüğünü kaydet... - + Stop debug video log Hata ayıklama video günlüğünü durdur - + Exit fullscreen Tam ekrandan çık - + GameShark Button (held) GameShark Butonu (basılı tutun) - + Autofire Otomatik basma - + Autofire A Otomatik basma A - + Autofire B Otomatik basma B - + Autofire L Otomatik basma L - + Autofire R Otomatik basma R - + Autofire Start Otomatik basma Start - + Autofire Select Otomatik basma Select - + Autofire Up Otomatik basma Up - + Autofire Right Otomatik basma Right - + Autofire Down Otomatik basma Down - + Autofire Left Otomatik basma Sol - + Clear Temizle @@ -6762,17 +6771,17 @@ Download size: %3 - + Super (L) Süper (L) - + Super (R) Süper (R) - + Menu Menü @@ -6780,22 +6789,22 @@ Download size: %3 QShortcut - + Shift Shift - + Control Kontrol - + Alt Alt - + Meta Derece diff --git a/src/platform/qt/ts/mgba-zh_CN.ts b/src/platform/qt/ts/mgba-zh_CN.ts index 150ad5404..0a0dfef75 100644 --- a/src/platform/qt/ts/mgba-zh_CN.ts +++ b/src/platform/qt/ts/mgba-zh_CN.ts @@ -4,24 +4,24 @@ QGBA - + Game Boy Advance ROMs (%1) - Game Boy Advance ROM (%1) + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - Game Boy ROM (%1) + Game Boy ROMs (%1) - + All ROMs (%1) - 所有 ROM (%1) + 所有 ROMs (%1) - + %1 Video Logs (*.mvl) - %1 视频日志 (*.mvl) + %1 视频日志 (*.mvl) @@ -191,17 +191,17 @@ Download size: %3 QGBA::AudioDevice - + Can't set format of context-less audio device 无法设置无上下文音频设备的格式 - + Audio device is missing its core 音频设备缺少其核心 - + Writing data to read-only audio device 将数据写入只读音频设备 @@ -209,7 +209,7 @@ Download size: %3 QGBA::AudioProcessorQt - + Can't start an audio processor without input 没有输入无法启动音频处理器 @@ -285,28 +285,28 @@ Download size: %3 显示高级选项 - + BattleChip data missing 缺失 BattleChip 数据 - + BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? 缺少 BattleChip 数据。BattleChip Gate 仍然可以使用,但一些图形将会丢失。您要立即下载数据吗? - - + + Select deck file 选择卡座文件 - + Incompatible deck 不兼容的卡座 - + The selected deck is not compatible with this Chip Gate 选定的卡座与此 Chip Gate 不兼容 @@ -367,19 +367,19 @@ Download size: %3 在此处输入代码... - - + + Autodetect (recommended) 自动检测(推荐) - - + + Select cheats file 选择作弊码文件 - + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. 无法添加某些作弊码。请确认它们的格式是否正确并且/或尝试其它的作弊类型。 @@ -398,37 +398,37 @@ Download size: %3 当前未开启倒带 - + Reset the game? 要重置游戏吗? - + Most games will require a reset to load the new save. Do you want to reset now? 大多数游戏需要重置才能加载新的存档。您要立即重启吗? - + Failed to open save file: %1 打开存档失败: %1 - + Failed to open game file: %1 打开游戏文件失败: %1 - + Can't yank pack in unexpected platform! 无法在意外平台上抽出卡带! - + Failed to open snapshot file for reading: %1 读取快照文件失败: %1 - + Failed to open snapshot file for writing: %1 写入快照文件失败: %1 @@ -477,6 +477,14 @@ Download size: %3 无法打开用于写入的 CLI 历史 + + QGBA::DisplayGL + + + Failed to create an OpenGL 3 context, trying old-style... + + + QGBA::DolphinConnector @@ -530,12 +538,12 @@ Download size: %3 3DS - + 3DS Vita - + Vita @@ -561,7 +569,7 @@ Download size: %3 Background - 背景 + 背景 @@ -591,7 +599,7 @@ Download size: %3 Browse - 浏览 + 浏览 @@ -631,12 +639,12 @@ Download size: %3 3DS - + 3DS Vita - + Vita @@ -716,7 +724,7 @@ Download size: %3 Image files (*.png *.jpg *.bmp) - + 图像文件 (*.png *.jpg *.bmp) @@ -757,52 +765,52 @@ Download size: %3 重置 - + Export frame 导出框架 - + Portable Network Graphics (*.png) 便携式网络图形 (*.png) - + None - + Background 背景 - + Window 窗口 - + Objwin Objwin - + Sprite 精灵图 - + Backdrop 背幕 - + Frame - + %1 %2 %1 %2 @@ -818,22 +826,22 @@ Download size: %3 QGBA::GBAKeyEditor - + Clear Button 清除按键 - + Clear Analog 清除模拟控制 - + Refresh 刷新 - + Set all 全部设置 @@ -975,37 +983,37 @@ Download size: %3 Game Boy (DMG) - + Game Boy (DMG) Game Boy Pocket (MGB) - + Game Boy Pocket (MGB) Super Game Boy (SGB) - + Super Game Boy (SGB) Super Game Boy 2 (SGB) - + Super Game Boy 2 (SGB) Game Boy Color (CGB) - + Game Boy Color (CGB) Game Boy Advance (AGB) - + Game Boy Advance (AGB) Super Game Boy Color (SGB + CGB) - + Super Game Boy Color (SGB + CGB) @@ -1015,27 +1023,27 @@ Download size: %3 MBC1 - + MBC1 MBC2 - + MBC2 MBC3 - + MBC3 MBC3 + RTC - + MBC3 + 实时时钟 MBC5 - + MBC5 @@ -1045,7 +1053,7 @@ Download size: %3 MBC6 - + MBC6 @@ -1055,17 +1063,17 @@ Download size: %3 MMM01 - + MMM01 HuC-1 - + HuC-1 HuC-3 - + HuC-3 @@ -1080,17 +1088,17 @@ Download size: %3 Wisdom Tree - + Wisdom Tree NT (old 1) - + NT (旧 1) NT (old 2) - + NT (旧 2) @@ -1105,32 +1113,32 @@ Download size: %3 BBD - + BBD Hitek - + Hitek GGB-81 - + GGB-81 Li Cheng - + Li Cheng Sachen (MMC1) - + Sachen (MMC1) Sachen (MMC2) - + Sachen (MMC2) @@ -3006,8 +3014,8 @@ Download size: %3 QGBA::KeyEditor - - + + --- --- @@ -3378,23 +3386,87 @@ Download size: %3 垂直 - - - + + + N/A - + Export map 导出映射 - + Portable Network Graphics (*.png) 便携式网络图形 (*.png) + + QGBA::MemoryAccessLogView + + + Memory access logging + + + + + Log file + + + + + Browse + 浏览 + + + + Log additional information (uses 3× space) + + + + + Load existing file if present + + + + + Regions + + + + + Export ROM snapshot + + + + + Start + + + + + Stop + 停止 + + + + Failed to open memory log file + + + + + + Select access log file + + + + + Memory access logs (*.mal) + + + QGBA::MemoryDump @@ -3641,22 +3713,22 @@ Download size: %3 刷新 - + (%0/%1×) (%0/%1×) - + (⅟%0×) (⅟%0×) - + (%0×) (%0×) - + %1 byte%2 %1 字节%2 @@ -3750,19 +3822,19 @@ Download size: %3 QGBA::MultiplayerController - + Trying to detach a multiplayer player that's not attached - + 尝试断开与未连接的多人玩家的连接 - + Trying to get player ID for a multiplayer player that's not attached - + 尝试获取未连接的多人玩家的 ID - + Trying to get save ID for a multiplayer player that's not attached - + 尝试获取未连接的多人玩家的存档 ID @@ -4157,35 +4229,35 @@ Download size: %3 导出 OBJ - + #%0 #%0 - + 0x%0 0x%0 + + - - 0x%0 (%1) 0x%0 (%1) - + Export palette 导出调色板 - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows 调色板 (*.pal);;Adobe 颜色表 (*.act) - + Failed to open output palette file: %1 打开输出调色板文件失败: %1 @@ -4259,7 +4331,7 @@ Download size: %3 QGBA::ROMInfo - + @@ -4299,18 +4371,28 @@ Download size: %3 + Maker Code: + + + + + Revision: + + + + File size: 文件大小: - + CRC32: CRC32: - + Save file: - + 保存文件: @@ -4364,62 +4446,62 @@ Download size: %3 QGBA::SaveConverter - + Save games and save states (%1) - 保存游戏和即时存档(%1) + 保存游戏和即时存档 (%1) - + Select save game or save state 选择保存游戏或即时存档 - + Save games (%1) - 保存游戏(%1) + 保存游戏 (%1) - + Select save game 选择保存游戏 - + Conversion failed 转换失败 - + Failed to convert the save game. This is probably a bug. 未能转换保存游戏。这可能是一个错误。 - + No file selected 未选择文件 - + Could not open file 无法打开文件 - + No valid formats found 未找到有效格式 - + Please select a valid input file 请选择一个有效的输入文件 - + No valid conversions found 未发现有效转换 - + Cannot convert save games between platforms 无法在平台之间转换保存游戏 @@ -4445,97 +4527,97 @@ Download size: %3 输出文件 - + %1 %2 save game %1 %2 保存游戏 - + little endian 小端 - + big endian 大端 - + SRAM - + %1 flash %1 闪存 - + %1 EEPROM - + + RTC - + %1 SRAM + RTC - + %1 SRAM - + packed MBC2 包装的 MBC2 - + unpacked MBC2 未包装的 MBC2 - + MBC6 flash MBC6 闪存 - + MBC6 combined SRAM + flash MBC6组合SRAM+闪存 - + MBC6 SRAM MBC6 SRAM - + TAMA5 - + %1 (%2) %1(%2) - + %1 save state with embedded %2 save game 带嵌入的 %2 保存游戏的 %1 保存状态 - + %1 SharkPort %2 save game %1 SharkPort %2 存档 - + %1 GameShark Advance SP %2 save game %1 GameShark Advance SP %2 存档 @@ -4571,32 +4653,37 @@ Download size: %3 载入历史脚本 - + Load script... 载入脚本... - + + &Load most recent + + + + &Reset 重置(&R) - + 0 - + Select script to load 选择要载入的脚本 - + Lua scripts (*.lua) Lua 脚本 (*.lua) - + All files (*.*) 所有文件 (*.*) @@ -4689,112 +4776,112 @@ Download size: %3 QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) 软件渲染 (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (强制版本 1.x) - + None - + None (Still Image) 无 (静止图像) - + Keyboard 键盘 - + Controllers 控制器 - + Shortcuts 快捷键 - - + + Shaders 着色器 - + Select BIOS 选择 BIOS - + Select directory 选择目录 - + Select image - 选择图片 + 选择图片 - + Image file (*.png *.jpg *.jpeg) - 图像文件(*.png *.jpg *.jpeg) + 图像文件(*.png *.jpg *.jpeg) - + (%1×%2) (%1×%2) - + Never 从不 - + Just now 刚刚 - + Less than an hour ago 不到一小时前 - + %n hour(s) ago %n 小时前 - + %n day(s) ago %n 天前 @@ -5120,37 +5207,37 @@ Download size: %3 立即检查更新 - + Default color palette only 只使用默认调色板 - + SGB color palette if available 可用时使用 SGB 调色板 - + GBC color palette if available 可用时使用 GBC 调色板 - + SGB (preferred) or GBC color palette if available 可用时使用 SGB(首选)或 GBC 调色板 - + Game Boy Camera Game Boy Camera - + Driver: 驱动: - + Source: 来源: @@ -5247,7 +5334,7 @@ Download size: %3 Custom border: - + 自定义边框: @@ -5283,7 +5370,7 @@ Download size: %3 Rewind speed: - + 倒带速度: @@ -5327,42 +5414,42 @@ Download size: %3 载入存档附加数据: - + Models 型号 - + GB only: 仅 GB: - + SGB compatible: 兼容 SGB: - + GBC only: 仅 GBC: - + GBC compatible: 兼容 GBC: - + SGB and GBC compatible: 兼容 SGB 和 GBC: - + Game Boy palette Game Boy 调色板 - + Preset: 预设: @@ -5399,135 +5486,130 @@ Download size: %3 软件 - + OpenGL enhancements OpenGL 增强 - + High-resolution scale: 高分辨率比例: - + (240×160) (240×160) - - XQ GBA audio (experimental) - XQ GBA 音频 (实验性) - - - + GB BIOS file: GB BIOS 文件: - - - - - - - - - + + + + + + + + + Browse 浏览 - + Use BIOS file if found 当可用时使用 BIOS 文件 - + Skip BIOS intro 跳过 BIOS 启动画面 - + GBA BIOS file: GBA BIOS 文件: - + GBC BIOS file: GBC BIOS 文件: - + SGB BIOS file: SGB BIOS 文件: - + Save games 游戏存档 - - - - - + + + + + Same directory as the ROM 与 ROM 所在目录相同 - + Save states 即时存档 - + Screenshots 截图 - + Patches 补丁 - + Cheats 作弊码 - + Log to file 记录日志到文件 - + Log to console 记录日志到控制台 - + Select Log File 选择日志文件 - + Default BG colors: 默认背景色: - + Default sprite colors 1: 默认精灵图颜色 1: - + Default sprite colors 2: 默认精灵图颜色 2: - + Super Game Boy borders Super Game Boy 边框 @@ -5785,13 +5867,11 @@ Download size: %3 - WebM WebM - MP4 MP4 @@ -5830,82 +5910,6 @@ Download size: %3 Format 格式 - - - MKV - MKV - - - - AVI - AVI - - - - HEVC - HEVC - - - - HEVC (NVENC) - HEVC (NVENC) - - - - VP8 - VP8 - - - - VP9 - VP9 - - - - FFV1 - FFV1 - - - - - None - - - - - FLAC - FLAC - - - - WavPack - - - - - Opus - Opus - - - - Vorbis - Vorbis - - - - MP3 - MP3 - - - - AAC - AAC - - - - Uncompressed - 未压缩 - Bitrate (kbps) @@ -5916,16 +5920,6 @@ Download size: %3 ABR ABR - - - H.264 - H.264 - - - - H.264 (NVENC) - H.264 (NVENC) - VBR @@ -5955,80 +5949,80 @@ Download size: %3 QGBA::Window - + Archives (%1) 压缩文件 (%1) - - + + Select ROM 选择 ROM - + Select folder 选择文件夹 - - + + Select save 选择存档 - + Select patch 选择补丁 - + Patches (*.ips *.ups *.bps) 补丁 (*.ips *.ups *.bps) - + Select e-Reader dotcode 选择 e-Reader 点码 - + e-Reader card (*.raw *.bin *.bmp) e-Reader 卡 (*.raw *.bin *.bmp) - + Select image 选择图片 - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 图像文件 (*.png *.gif *.jpg *.jpeg);;所有文件 (*) - + GameShark saves (*.sps *.xps) GameShark 存档 (*.sps *.xps) - + Select video log 选择视频日志 - + Video logs (*.mvl) 视频日志文件 (*.mvl) - + Crash 崩溃 - + The game has crashed with the following error: %1 @@ -6037,699 +6031,709 @@ Download size: %3 %1 - + Couldn't Start 无法启动 - + Could not start game. 无法启动游戏。 - + Unimplemented BIOS call 未实现的 BIOS 调用 - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. 此游戏使用尚未实现的 BIOS 调用。请使用官方 BIOS 以获得最佳体验。 - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. 无法创建适合的显示设备,正在回滚到软件显示。游戏的运行速度(特别在大窗口的情况下)可能会变慢。 - + Really make portable? 确定进行程序便携化? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? 进行此操作后,模拟器将从其可执行文件所在目录中载入模拟器配置。您想继续吗? - + Restart needed 需要重新启动 - + Some changes will not take effect until the emulator is restarted. 更改将在模拟器下次重新启动时生效。 - + - Player %1 of %2 - 玩家 %1 共 %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + %1 - %2 (%3 fps) - %4 - + &File 文件(&F) - + Load &ROM... 载入 ROM(&R)... - + Load ROM in archive... 从压缩文件中载入 ROM... - + Add folder to library... 将文件夹添加到库中... - + Save games (%1) - 保存游戏(%1) + 保存游戏 (%1) - + Select save game 选择保存游戏 - + mGBA save state files (%1) - mGBA 即时存档文件(%1) + mGBA 即时存档文件 (%1) - - + + Select save state 选择即时存档 - + Select e-Reader card images 选择 e-Reader 卡片图像 - + Image file (*.png *.jpg *.jpeg) 图像文件(*.png *.jpg *.jpeg) - + Conversion finished 转换完成 - + %1 of %2 e-Reader cards converted successfully. 成功转换了 %1 张(共 %2 张)e-Reader 卡片。 - + Load alternate save game... 加载备用保存游戏... - + Load temporary save game... 加载临时保存游戏... - + Load &patch... 载入补丁(&P)... - + Boot BIOS 引导 BIOS - + Replace ROM... 替换 ROM... - + Scan e-Reader dotcodes... 扫描 e-Reader 点码... - + Convert e-Reader card image to raw... 将 e-Reader 卡片图像转换为原始数据... - + ROM &info... ROM 信息(&I)... - + Recent 最近打开 - + Make portable 程序便携化 - + &Load state 载入即时存档(&L) - + Load state file... 载入即时存档文件... - + &Save state 保存即时存档(&S) - + Save state file... 保存即时存档文件... - + Quick load 快速读档 - + Quick save 快速存档 - + Load recent 载入最近存档 - + Save recent 保存最近存档 - + Undo load state 撤消读档 - + Undo save state 撤消存档 - - + + State &%1 即时存档 (&%1) - + Load camera image... 载入相机图片... - + Convert save game... 转换保存游戏... - + GameShark saves (*.gsv *.sps *.xps) GameShark 存档 (*.gsv *.sps *.xps) - + Reset needed 需要重启 - + Some changes will not take effect until the game is reset. 某些改动需要重新启动才会生效。 - + Save games 游戏存档 - + Import GameShark Save... 导入 GameShark 存档... - + Export GameShark Save... 导出 GameShark 存档... - + Automatically determine 自动终止 - + Use player %0 save game 使用玩家 %0 存档 - + New multiplayer window 新建多人游戏窗口 - + Connect to Dolphin... 连接到 Dolphin... - + Report bug... 报告错误... - + About... 关于... - + E&xit 退出(&X) - + &Emulation 模拟(&E) - + &Reset 重置(&R) - + Sh&utdown 关机(&U) - + Yank game pak 快速抽出游戏卡带 - + &Pause 暂停(&P) - + &Next frame 下一帧(&N) - + Fast forward (held) 快进 (长按) - + &Fast forward 快进(&F) - + Fast forward speed 快进速度 - + Unbounded 不限制 - + %0x %0x - - - Increase fast forward speed - - - Decrease fast forward speed - + Increase fast forward speed + 加快快进速度 + Decrease fast forward speed + 降低快进速度 + + + Rewind (held) 倒带 (长按) - + Re&wind 倒带(&W) - + Step backwards 步退 - + Solar sensor 太阳光传感器 - + Increase solar level 增加太阳光等级 - + Decrease solar level 降低太阳光等级 - + Brightest solar level 太阳光等级为最亮 - + Darkest solar level 太阳光等级为最暗 - + Brightness %1 亮度 %1 - + Game Boy Printer... Game Boy 打印机... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video 音频/视频(&V) - + Frame size 画面大小 - + %1× %1× - + Toggle fullscreen 切换全屏 - + + &Lock frame size + + + + Lock aspect ratio 锁定纵横比 - + Force integer scaling 强制整数缩放 - + Interframe blending 帧间混合 - + Bilinear filtering 双线性过滤 - + Frame&skip 跳帧(&S) - + Mute 静音 - + FPS target 目标 FPS - + Native (59.7275) 原生 (59.7275) - + Take &screenshot 截图(&S) - + F12 F12 - + Record A/V... 录制音频/视频... - + Record GIF/WebP/APNG... 录制 GIF/WebP/APNG... - + Video layers 视频图层 - + Audio channels 音频声道 - + Adjust layer placement... 调整图层布局... - + &Tools 工具(&T) - + View &logs... 查看日志(&L)... - + Game &overrides... 覆写游戏(&O)... - + Game Pak sensors... 游戏卡带传感器... - + &Cheats... 作弊码(&C)... - + Create forwarder... 创建转发器... - + Settings... 设置... - + Open debugger console... 打开调试器控制台... - + Start &GDB server... 打开 GDB 服务器(&G)... - + Scripting... 脚本... - + Game state views 游戏状态视图 - + View &palette... 查看调色板(&P)... - + View &sprites... 查看精灵图(&S)... - + View &tiles... 查看图块(&T)... - + View &map... 查看映射(&M)... - + &Frame inspector... 帧检查器(&F)... - + View memory... 查看内存... - + Search memory... 搜索内存... - + View &I/O registers... 查看 I/O 寄存器(&I)... - + + Log memory &accesses... + + + + Record debug video log... 记录调试视频日志... - + Stop debug video log 停止记录调试视频日志 - + Exit fullscreen 退出全屏 - + GameShark Button (held) GameShark 键 (长按) - + Autofire 连发 - + Autofire A 连发 A - + Autofire B 连发 B - + Autofire L 连发 L - + Autofire R 连发 R - + Autofire Start 连发 Start - + Autofire Select 连发 Select - + Autofire Up 连发 上 - + Autofire Right 连发 右 - + Autofire Down 连发 下 - + Autofire Left 连发 左 - + Clear 清除 @@ -6744,7 +6748,7 @@ Download size: %3 %1 kiB - + %1 千字节 @@ -6767,40 +6771,40 @@ Download size: %3 ? - + Super (L) - Super(L) + Super (L) - + Super (R) - Super(R) + Super (R) - + Menu - 菜单 + 菜单 QShortcut - + Shift Shift - + Control Control - + Alt Alt - + Meta Meta diff --git a/src/platform/qt/utils.cpp b/src/platform/qt/utils.cpp index 99859dbc4..c445c41b8 100644 --- a/src/platform/qt/utils.cpp +++ b/src/platform/qt/utils.cpp @@ -138,7 +138,14 @@ bool extractMatchingFile(VDir* dir, std::function filter) continue; } VFile* outfile = VFileOpen(target.toUtf8().constData(), O_WRONLY | O_TRUNC | O_CREAT); + if (!outfile) { + return false; + } VFile* infile = dir->openFile(dir, entry->name(entry), O_RDONLY); + if (!infile) { + outfile->close(outfile); + return false; + } VFileDevice::copyFile(infile, outfile); infile->close(infile); outfile->close(outfile); diff --git a/src/platform/sdl/CMakeLists.txt b/src/platform/sdl/CMakeLists.txt index cacf0bc48..d62c74694 100644 --- a/src/platform/sdl/CMakeLists.txt +++ b/src/platform/sdl/CMakeLists.txt @@ -22,6 +22,9 @@ if (SDL_VERSION EQUAL "2") endif() endif() + if(APPLE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.7") + endif() set(SDLMAIN_LIBRARY ${SDL2MAIN_LIBRARY}) endif() endif() @@ -37,6 +40,7 @@ endif() if (NOT SDL2_FOUND AND NOT SDL_FOUND) set(SDL_FOUND OFF PARENT_SCOPE) + set(BUILD_SDL OFF PARENT_SCOPE) return() endif() @@ -67,47 +71,29 @@ endif() set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libsdl${SDL_VERSION_DEBIAN}" PARENT_SCOPE) -file(GLOB PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sdl-*.c) +file(GLOB PLATFORM_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sdl-*.c) set(PLATFORM_LIBRARY ${SDL_LIBRARY} ${SDLMAIN_LIBRARY} ${SDL_LIBRARY} ${PIXMAN-1_LIBRARIES}) -include_directories(${CMAKE_SOURCE_DIR}/src/platform/sdl ${PIXMAN-1_INCLUDE_DIRS} ${SDL_INCLUDE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${PIXMAN-1_INCLUDE_DIRS} ${SDL_INCLUDE_DIR}) set(SDL_INCLUDE_DIR "${SDL_INCLUDE_DIR}" PARENT_SCOPE) set(SDL_LIBRARY "${SDL_LIBRARY}" PARENT_SCOPE) set(SDLMAIN_LIBRARY "${SDLMAIN_LIBRARY}" PARENT_SCOPE) -set(MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/main.c) +set(MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/main.c) -if(BUILD_RASPI) - add_definitions(-DBUILD_RASPI) - list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gles2.c ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c ${CMAKE_SOURCE_DIR}/src/platform/sdl/rpi-common.c) - list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gles2-sdl.c) - set(OPENGLES2_LIBRARY "-lEGL -lGLESv2 -lbcm_host") - set(BUILD_GLES2 ON CACHE BOOL "Using OpenGL|ES 2" FORCE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fgnu89-inline") - add_executable(${BINARY_NAME}-rpi ${PLATFORM_SRC} ${MAIN_SRC}) - set_target_properties(${BINARY_NAME}-rpi PROPERTIES COMPILE_DEFINITIONS "${FEATURE_DEFINES};${FUNCTION_DEFINES}") - target_link_libraries(${BINARY_NAME}-rpi ${BINARY_NAME} ${PLATFORM_LIBRARY} ${OPENGLES2_LIBRARY}) - install(TARGETS ${BINARY_NAME}-rpi DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-rpi) - unset(OPENGLES2_INCLUDE_DIR CACHE) # Clear NOTFOUND +if(BUILD_GL) + list(APPEND MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gl-sdl.c) + list(APPEND PLATFORM_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gl-common.c) endif() - -if(BUILD_PANDORA) - list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/pandora-sdl.c) +if(BUILD_GLES2) + list(APPEND MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gles2-sdl.c) + list(APPEND PLATFORM_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gl-common.c) + include_directories(${OPENGLES2_INCLUDE_DIR}) +endif() +if(SDL_VERSION EQUAL "2") + list(APPEND MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sw-sdl2.c) else() - if(BUILD_GL) - list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-sdl.c) - list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c) - endif() - if(BUILD_GLES2) - list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gles2-sdl.c) - list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c) - include_directories(${OPENGLES2_INCLUDE_DIR}) - endif() - if(SDL_VERSION EQUAL "2") - list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sw-sdl2.c) - else() - list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sw-sdl1.c) - endif() + list(APPEND MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sw-sdl1.c) endif() if(ENABLE_SCRIPTING) @@ -126,7 +112,7 @@ else() endif() install(TARGETS ${BINARY_NAME}-sdl DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-sdl) if(UNIX) - install(FILES ${CMAKE_SOURCE_DIR}/doc/mgba.6 DESTINATION ${MANDIR}/man6 COMPONENT ${BINARY_NAME}-sdl) + install(FILES ${PROJECT_SOURCE_DIR}/doc/mgba.6 DESTINATION ${MANDIR}/man6 COMPONENT ${BINARY_NAME}-sdl) endif() if(DISTBUILD AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") diff --git a/src/platform/sdl/gl-common.c b/src/platform/sdl/gl-common.c index 076429f6b..f2ccdd7e2 100644 --- a/src/platform/sdl/gl-common.c +++ b/src/platform/sdl/gl-common.c @@ -15,7 +15,7 @@ #endif void mSDLGLDoViewport(int w, int h, struct VideoBackend* v) { - v->contextResized(v, w, h); + v->contextResized(v, w, h, 0, 0); v->clear(v); v->swap(v); v->clear(v); @@ -135,19 +135,11 @@ void mSDLGLCommonRunloop(struct mSDLRenderer* renderer, void* user) { if (mSDLGLCommonLoadBackground(v)) { renderer->player.windowUpdated = true; - - struct mRectangle frame; - v->layerDimensions(v, VIDEO_LAYER_IMAGE, &frame); - int i; - for (i = 0; i < VIDEO_LAYER_IMAGE; ++i) { - struct mRectangle dims; - v->layerDimensions(v, i, &dims); - mRectangleCenter(&frame, &dims); - v->setLayerDimensions(v, i, &dims); - } - + VideoBackendRecenter(v, 1); #if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_SetWindowSize(renderer->window, frame.width * renderer->ratio, frame.height * renderer->ratio); + int width, height; + v->imageSize(v, VIDEO_LAYER_IMAGE, &width, &height); + SDL_SetWindowSize(renderer->window, width * renderer->ratio, height * renderer->ratio); #endif } @@ -170,11 +162,12 @@ void mSDLGLCommonRunloop(struct mSDLRenderer* renderer, void* user) { renderer->core->currentVideoSize(renderer->core, &renderer->width, &renderer->height); struct mRectangle dims; v->layerDimensions(v, VIDEO_LAYER_IMAGE, &dims); - if (renderer->width != dims.width || renderer->height != dims.height) { + if (dims.width < 0 || dims.height < 0 || renderer->width != (unsigned) dims.width || renderer->height != (unsigned) dims.height) { renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, renderer->width); dims.width = renderer->width; dims.height = renderer->height; v->setLayerDimensions(v, VIDEO_LAYER_IMAGE, &dims); + VideoBackendRecenter(v, 1); } if (mCoreSyncWaitFrameStart(&context->impl->sync)) { diff --git a/src/platform/sdl/gles2-sdl.c b/src/platform/sdl/gles2-sdl.c index 9bae33b95..a4aa386df 100644 --- a/src/platform/sdl/gles2-sdl.c +++ b/src/platform/sdl/gles2-sdl.c @@ -6,9 +6,6 @@ #include "main.h" #include "gl-common.h" -#ifdef BUILD_RASPI -#include "rpi-common.h" -#endif #include @@ -43,11 +40,7 @@ bool mSDLGLES2Init(struct mSDLRenderer* renderer) { renderer->gl2.d.lockAspectRatio = renderer->lockAspectRatio; renderer->gl2.d.lockIntegerScaling = renderer->lockIntegerScaling; renderer->gl2.d.filter = renderer->filter; -#ifdef BUILD_RASPI - renderer->gl2.d.swap = mRPIGLCommonSwap; -#else renderer->gl2.d.swap = mSDLGLCommonSwap; -#endif renderer->gl2.d.init(&renderer->gl2.d, 0); struct mRectangle dims = { @@ -66,13 +59,7 @@ void mSDLGLES2Deinit(struct mSDLRenderer* renderer) { if (renderer->gl2.d.deinit) { renderer->gl2.d.deinit(&renderer->gl2.d); } -#ifdef BUILD_RASPI - eglMakeCurrent(renderer->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroySurface(renderer->eglDisplay, renderer->eglSurface); - eglDestroyContext(renderer->eglDisplay, renderer->eglContext); - eglTerminate(renderer->eglDisplay); - bcm_host_deinit(); -#elif SDL_VERSION_ATLEAST(2, 0, 0) +#if SDL_VERSION_ATLEAST(2, 0, 0) SDL_GL_DeleteContext(renderer->glCtx); #endif free(renderer->outputBuffer); diff --git a/src/platform/sdl/main.c b/src/platform/sdl/main.c index 2d9a74ae8..4debea3ee 100644 --- a/src/platform/sdl/main.c +++ b/src/platform/sdl/main.c @@ -7,12 +7,6 @@ #include -#ifdef USE_GDB_STUB -#include -#endif -#ifdef USE_EDITLINE -#include "feature/editline/cli-el-backend.h" -#endif #ifdef ENABLE_SCRIPTING #include @@ -21,7 +15,6 @@ #endif #endif -#include #include #include #include @@ -54,6 +47,7 @@ static void _loadState(struct mCoreThread* thread) { int main(int argc, char** argv) { #ifdef _WIN32 AttachConsole(ATTACH_PARENT_PROCESS); + freopen("CONOUT$", "w", stdout); #endif struct mSDLRenderer renderer = {0}; @@ -116,16 +110,6 @@ int main(int argc, char** argv) { opts.width = renderer.width * renderer.ratio; opts.height = renderer.height * renderer.ratio; - struct mCheatDevice* device = NULL; - if (args.cheatsFile && (device = renderer.core->cheatDevice(renderer.core))) { - struct VFile* vf = VFileOpen(args.cheatsFile, O_RDONLY); - if (vf) { - mCheatDeviceClear(device); - mCheatParseFile(device, vf); - vf->close(vf); - } - } - mInputMapInit(&renderer.core->inputMap, &GBAInputInfo); mCoreInitConfig(renderer.core, PORT); mArgumentsApply(&args, &subparser, 1, &renderer.core->config); @@ -149,11 +133,7 @@ int main(int argc, char** argv) { mSDLGLCreate(&renderer); } else #elif defined(BUILD_GLES2) || defined(USE_EPOXY) -#ifdef BUILD_RASPI - mRPIGLCommonInit(&renderer); -#else if (mSDLGLCommonInit(&renderer)) -#endif { mSDLGLES2Create(&renderer); } else @@ -177,7 +157,7 @@ int main(int argc, char** argv) { mSDLPlayerLoadConfig(&renderer.player, mCoreConfigGetInput(&renderer.core->config)); #if SDL_VERSION_ATLEAST(2, 0, 0) - renderer.core->setPeripheral(renderer.core, mPERIPH_RUMBLE, &renderer.player.rumble.d); + renderer.core->setPeripheral(renderer.core, mPERIPH_RUMBLE, &renderer.player.rumble.d.d); #endif int ret; @@ -189,10 +169,6 @@ int main(int argc, char** argv) { mSDLDetachPlayer(&renderer.events, &renderer.player); mInputMapDeinit(&renderer.core->inputMap); - if (device) { - mCheatDeviceDestroy(device); - } - mSDLDeinit(&renderer); mStandardLoggerDeinit(&_logger); @@ -231,43 +207,21 @@ int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args) { return 1; } mCoreAutoloadSave(renderer->core); - mCoreAutoloadCheats(renderer->core); + mArgumentsApplyFileLoads(args, renderer->core); #ifdef ENABLE_SCRIPTING struct mScriptBridge* bridge = mScriptBridgeCreate(); #ifdef ENABLE_PYTHON mPythonSetup(bridge); #endif -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS CLIDebuggerScriptEngineInstall(bridge); #endif #endif -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS struct mDebugger debugger; - bool hasDebugger = false; - mDebuggerInit(&debugger); -#ifdef USE_EDITLINE - if (args->debugCli) { - struct mDebuggerModule* module = mDebuggerCreateModule(DEBUGGER_CLI, renderer->core); - if (module) { - struct CLIDebugger* cliDebugger = (struct CLIDebugger*) module; - CLIDebuggerAttachBackend(cliDebugger, CLIDebuggerEditLineBackendCreate()); - mDebuggerAttachModule(&debugger, module); - hasDebugger = true; - } - } -#endif - -#ifdef USE_GDB_STUB - if (args->debugGdb) { - struct mDebuggerModule* module = mDebuggerCreateModule(DEBUGGER_GDB, renderer->core); - if (module) { - mDebuggerAttachModule(&debugger, module); - hasDebugger = true; - } - } -#endif + bool hasDebugger = mArgumentsApplyDebugger(args, renderer->core, &debugger); if (hasDebugger) { mDebuggerAttach(&debugger, renderer->core); @@ -275,18 +229,11 @@ int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args) { #ifdef ENABLE_SCRIPTING mScriptBridgeSetDebugger(bridge, &debugger); #endif + } else { + mDebuggerDeinit(&debugger); } #endif - if (args->patch) { - struct VFile* patch = VFileOpen(args->patch, O_RDONLY); - if (patch) { - renderer->core->loadPatch(renderer->core, patch); - } - } else { - mCoreAutoloadPatch(renderer->core); - } - renderer->audio.samples = renderer->core->opts.audioBuffers; renderer->audio.sampleRate = 44100; thread.logger.logger = &_logger.d; @@ -341,7 +288,7 @@ int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args) { mScriptBridgeDestroy(bridge); #endif -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS if (hasDebugger) { renderer->core->detachDebugger(renderer->core); mDebuggerDeinit(&debugger); diff --git a/src/platform/sdl/main.h b/src/platform/sdl/main.h index 10135da2f..8c2f517d7 100644 --- a/src/platform/sdl/main.h +++ b/src/platform/sdl/main.h @@ -18,17 +18,6 @@ CXX_GUARD_START #include "platform/opengl/gl.h" #endif -#ifdef BUILD_RASPI -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" -#include -#include - -#include -#pragma GCC diagnostic pop -#endif - #if defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) #include "gl-common.h" #include "platform/opengl/gles2.h" @@ -41,7 +30,7 @@ CXX_GUARD_START struct mCore; struct mSDLRenderer { struct mCore* core; - color_t* outputBuffer; + mColor* outputBuffer; struct mSDLAudio audio; struct mSDLEvents events; @@ -82,19 +71,6 @@ struct mSDLRenderer { pixman_image_t* pix; pixman_image_t* screenpix; #endif - -#ifdef BUILD_RASPI - EGLDisplay eglDisplay; - EGLSurface eglSurface; - EGLContext eglContext; - EGL_DISPMANX_WINDOW_T eglWindow; -#endif - -#ifdef BUILD_PANDORA - int fb; - int odd; - void* base[2]; -#endif }; void mSDLSWCreate(struct mSDLRenderer* renderer); diff --git a/src/platform/sdl/pandora-sdl.c b/src/platform/sdl/pandora-sdl.c deleted file mode 100644 index 673d419b6..000000000 --- a/src/platform/sdl/pandora-sdl.c +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (c) 2013-2015 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/. */ -#include "main.h" - -#include "gba/supervisor/thread.h" - -#include -#include -#include -#include - -#ifndef FBIO_WAITFORVSYNC -#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) -#endif - -static bool mSDLInit(struct SDLSoftwareRenderer* renderer); -static void mSDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer); -static void mSDLDeinit(struct SDLSoftwareRenderer* renderer); - -void mSDLGLCreate(struct SDLSoftwareRenderer* renderer) { - renderer->init = mSDLInit; - renderer->deinit = mSDLDeinit; - renderer->runloop = mSDLRunloop; -} - -void mSDLSWCreate(struct SDLSoftwareRenderer* renderer) { - renderer->init = mSDLInit; - renderer->deinit = mSDLDeinit; - renderer->runloop = mSDLRunloop; -} - -bool mSDLInit(struct SDLSoftwareRenderer* renderer) { - SDL_SetVideoMode(800, 480, 16, SDL_FULLSCREEN); - - renderer->odd = 0; - renderer->fb = open("/dev/fb1", O_RDWR); - if (renderer->fb < 0) { - return false; - } - - struct omapfb_plane_info plane; - struct omapfb_mem_info mem; - if (ioctl(renderer->fb, OMAPFB_QUERY_PLANE, &plane) < 0) { - return false; - } - if (ioctl(renderer->fb, OMAPFB_QUERY_MEM, &mem) < 0) { - return false; - } - - if (plane.enabled) { - plane.enabled = 0; - ioctl(renderer->fb, OMAPFB_SETUP_PLANE, &plane); - } - - mem.size = GBA_VIDEO_HORIZONTAL_PIXELS * GBA_VIDEO_VERTICAL_PIXELS * 4; - ioctl(renderer->fb, OMAPFB_SETUP_MEM, &mem); - - plane.enabled = 1; - plane.pos_x = 40; - plane.pos_y = 0; - plane.out_width = 720; - plane.out_height = 480; - ioctl(renderer->fb, OMAPFB_SETUP_PLANE, &plane); - - struct fb_var_screeninfo info; - ioctl(renderer->fb, FBIOGET_VSCREENINFO, &info); - info.xres = GBA_VIDEO_HORIZONTAL_PIXELS; - info.yres = GBA_VIDEO_VERTICAL_PIXELS; - info.xres_virtual = GBA_VIDEO_HORIZONTAL_PIXELS; - info.yres_virtual = GBA_VIDEO_VERTICAL_PIXELS * 2; - info.bits_per_pixel = 16; - ioctl(renderer->fb, FBIOPUT_VSCREENINFO, &info); - - renderer->odd = 0; - renderer->base[0] = mmap(0, GBA_VIDEO_HORIZONTAL_PIXELS * GBA_VIDEO_VERTICAL_PIXELS * 4, PROT_READ | PROT_WRITE, MAP_SHARED, renderer->fb, 0); - renderer->base[1] = (uint16_t*) renderer->base[0] + GBA_VIDEO_HORIZONTAL_PIXELS * GBA_VIDEO_VERTICAL_PIXELS; - - renderer->d.outputBuffer = renderer->base[0]; - renderer->d.outputBufferStride = GBA_VIDEO_HORIZONTAL_PIXELS; - return true; -} - -void mSDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) { - SDL_Event event; - - while (context->state < THREAD_EXITING) { - while (SDL_PollEvent(&event)) { - mSDLHandleEventGBA(context, &renderer->player, &event); - } - - if (mCoreSyncWaitFrameStart(&context->sync)) { - struct fb_var_screeninfo info; - ioctl(renderer->fb, FBIOGET_VSCREENINFO, &info); - info.yoffset = GBA_VIDEO_VERTICAL_PIXELS * renderer->odd; - ioctl(renderer->fb, FBIOPAN_DISPLAY, &info); - - int arg = 0; - ioctl(renderer->fb, FBIO_WAITFORVSYNC, &arg); - - renderer->odd = !renderer->odd; - renderer->d.outputBuffer = renderer->base[renderer->odd]; - } - mCoreSyncWaitFrameEnd(&context->sync); - } -} - -void mSDLDeinit(struct SDLSoftwareRenderer* renderer) { - munmap(renderer->base[0], GBA_VIDEO_HORIZONTAL_PIXELS * GBA_VIDEO_VERTICAL_PIXELS * 4); - - struct omapfb_plane_info plane; - struct omapfb_mem_info mem; - ioctl(renderer->fb, OMAPFB_QUERY_PLANE, &plane); - ioctl(renderer->fb, OMAPFB_QUERY_MEM, &mem); - - mem.size = 0; - ioctl(renderer->fb, OMAPFB_SETUP_MEM, &mem); - - plane.enabled = 0; - plane.pos_x = 0; - plane.pos_y = 0; - plane.out_width = 0; - plane.out_height = 0; - ioctl(renderer->fb, OMAPFB_SETUP_PLANE, &plane); - - close(renderer->fb); -} diff --git a/src/platform/sdl/rpi-common.c b/src/platform/sdl/rpi-common.c deleted file mode 100644 index be141718e..000000000 --- a/src/platform/sdl/rpi-common.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (c) 2013-2015 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/. */ -#include "main.h" - -#include - -void mRPIGLCommonSwap(struct VideoBackend* context) { - struct mSDLRenderer* renderer = (struct mSDLRenderer*) context->user; - eglSwapBuffers(renderer->eglDisplay, renderer->eglSurface); -} - -void mRPIGLCommonInit(struct mSDLRenderer* renderer) { - bcm_host_init(); - renderer->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - int major, minor; - if (EGL_FALSE == eglInitialize(renderer->eglDisplay, &major, &minor)) { - printf("Failed to initialize EGL"); - return false; - } - - if (EGL_FALSE == eglBindAPI(EGL_OPENGL_ES_API)) { - printf("Failed to get GLES API"); - return false; - } - - const EGLint requestConfig[] = { - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 5, - EGL_BLUE_SIZE, 5, - EGL_ALPHA_SIZE, 1, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_NONE - }; - - EGLConfig config; - EGLint numConfigs; - - if (EGL_FALSE == eglChooseConfig(renderer->eglDisplay, requestConfig, &config, 1, &numConfigs)) { - printf("Failed to choose EGL config\n"); - return false; - } - - const EGLint contextAttributes[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - int dispWidth = 240, dispHeight = 160, adjWidth; - renderer->eglContext = eglCreateContext(renderer->eglDisplay, config, EGL_NO_CONTEXT, contextAttributes); - graphics_get_display_size(0, &dispWidth, &dispHeight); - adjWidth = dispHeight / 2 * 3; - - DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0); - DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); - - VC_RECT_T destRect = { - .x = (dispWidth - adjWidth) / 2, - .y = 0, - .width = adjWidth, - .height = dispHeight - }; - - VC_RECT_T srcRect = { - .x = 0, - .y = 0, - .width = 240 << 16, - .height = 160 << 16 - }; - - DISPMANX_ELEMENT_HANDLE_T element = vc_dispmanx_element_add(update, display, 0, &destRect, 0, &srcRect, DISPMANX_PROTECTION_NONE, 0, 0, 0); - vc_dispmanx_update_submit_sync(update); - - renderer->eglWindow.element = element; - renderer->eglWindow.width = dispWidth; - renderer->eglWindow.height = dispHeight; - - renderer->eglSurface = eglCreateWindowSurface(renderer->eglDisplay, config, &renderer->eglWindow, 0); - if (EGL_FALSE == eglMakeCurrent(renderer->eglDisplay, renderer->eglSurface, renderer->eglSurface, renderer->eglContext)) { - return false; - } -} diff --git a/src/platform/sdl/rpi-common.h b/src/platform/sdl/rpi-common.h deleted file mode 100644 index b58532de5..000000000 --- a/src/platform/sdl/rpi-common.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (c) 2013-2015 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 SDL_RPI_COMMON_H -#define SDL_RPI_COMMON_H - -#include - -CXX_GUARD_START - -#include "main.h" - -void mRPIGLCommonSwap(struct VideoBackend* context); -void mRPIGLCommonInit(struct mSDLRenderer* renderer); - -CXX_GUARD_END - -#endif diff --git a/src/platform/sdl/sdl-audio.c b/src/platform/sdl/sdl-audio.c index f1666aa4e..d90ad95d3 100644 --- a/src/platform/sdl/sdl-audio.c +++ b/src/platform/sdl/sdl-audio.c @@ -7,12 +7,6 @@ #include #include -#include -#include - -#include - -#define BUFFER_SIZE (GBA_AUDIO_SAMPLES >> 2) mLOG_DEFINE_CATEGORY(SDL_AUDIO, "SDL Audio", "platform.sdl.audio"); @@ -47,6 +41,10 @@ bool mSDLInitAudio(struct mSDLAudio* context, struct mCoreThread* threadContext) } context->core = 0; + mAudioBufferInit(&context->buffer, context->samples, context->obtainedSpec.channels); + mAudioResamplerInit(&context->resampler, mINTERPOLATOR_SINC); + mAudioResamplerSetDestination(&context->resampler, &context->buffer, context->obtainedSpec.freq); + if (threadContext) { context->core = threadContext->core; context->sync = &threadContext->impl->sync; @@ -70,6 +68,8 @@ void mSDLDeinitAudio(struct mSDLAudio* context) { SDL_PauseAudio(1); SDL_CloseAudio(); #endif + mAudioBufferDeinit(&context->buffer); + mAudioResamplerDeinit(&context->resampler); SDL_QuitSubSystem(SDL_INIT_AUDIO); } @@ -97,32 +97,25 @@ static void _mSDLAudioCallback(void* context, Uint8* data, int len) { memset(data, 0, len); return; } - blip_t* left = NULL; - blip_t* right = NULL; - int32_t clockRate = GBA_ARM7TDMI_FREQUENCY; + struct mAudioBuffer* buffer = NULL; + unsigned sampleRate = 32768; if (audioContext->core) { - left = audioContext->core->getAudioChannel(audioContext->core, 0); - right = audioContext->core->getAudioChannel(audioContext->core, 1); - clockRate = audioContext->core->frequency(audioContext->core); + buffer = audioContext->core->getAudioBuffer(audioContext->core); + sampleRate = audioContext->core->audioSampleRate(audioContext->core); } double fauxClock = 1; if (audioContext->sync) { - if (audioContext->sync->fpsTarget > 0) { - fauxClock = GBAAudioCalculateRatio(1, audioContext->sync->fpsTarget, 1); + if (audioContext->sync->fpsTarget > 0 && audioContext->core) { + fauxClock = mCoreCalculateFramerateRatio(audioContext->core, audioContext->sync->fpsTarget); } mCoreSyncLockAudio(audioContext->sync); + audioContext->sync->audioHighWater = audioContext->samples + audioContext->resampler.highWaterMark + audioContext->resampler.lowWaterMark; + audioContext->sync->audioHighWater *= sampleRate / (fauxClock * audioContext->obtainedSpec.freq); } - blip_set_rates(left, clockRate, audioContext->obtainedSpec.freq * fauxClock); - blip_set_rates(right, clockRate, audioContext->obtainedSpec.freq * fauxClock); + mAudioResamplerSetSource(&audioContext->resampler, buffer, sampleRate / fauxClock, true); + mAudioResamplerProcess(&audioContext->resampler); len /= 2 * audioContext->obtainedSpec.channels; - int available = blip_samples_avail(left); - if (available > len) { - available = len; - } - blip_read_samples(left, (short*) data, available, audioContext->obtainedSpec.channels == 2); - if (audioContext->obtainedSpec.channels == 2) { - blip_read_samples(right, ((short*) data) + 1, available, 1); - } + int available = mAudioBufferRead(&audioContext->buffer, (int16_t*) data, len); if (audioContext->sync) { mCoreSyncConsumeAudio(audioContext->sync); diff --git a/src/platform/sdl/sdl-audio.h b/src/platform/sdl/sdl-audio.h index 2ae920af4..b8fa00c85 100644 --- a/src/platform/sdl/sdl-audio.h +++ b/src/platform/sdl/sdl-audio.h @@ -11,6 +11,8 @@ CXX_GUARD_START #include +#include +#include #include // Altivec sometimes defines this @@ -30,6 +32,8 @@ struct mSDLAudio { unsigned sampleRate; // State + struct mAudioBuffer buffer; + struct mAudioResampler resampler; SDL_AudioSpec desiredSpec; SDL_AudioSpec obtainedSpec; #if SDL_VERSION_ATLEAST(2, 0, 0) diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index a675ff2c0..ca8345d22 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -22,15 +22,14 @@ #endif #define GYRO_STEPS 100 -#define RUMBLE_PWM 16 -#define RUMBLE_STEPS 2 +#define RUMBLE_THRESHOLD 1.f / 128.f mLOG_DEFINE_CATEGORY(SDL_EVENTS, "SDL Events", "platform.sdl.events"); DEFINE_VECTOR(SDL_JoystickList, struct SDL_JoystickCombo); #if SDL_VERSION_ATLEAST(2, 0, 0) -static void _mSDLSetRumble(struct mRumble* rumble, int enable); +static void _mSDLSetRumble(struct mRumbleIntegrator* rumble, float level); #endif static int32_t _mSDLReadTiltX(struct mRotationSource* rumble); static int32_t _mSDLReadTiltY(struct mRotationSource* rumble); @@ -143,18 +142,6 @@ void mSDLEventsLoadConfig(struct mSDLEvents* context, const struct Configuration } void mSDLInitBindingsGBA(struct mInputMap* inputMap) { -#ifdef BUILD_PANDORA - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_PAGEDOWN, GBA_KEY_A); - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_END, GBA_KEY_B); - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_RSHIFT, GBA_KEY_L); - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_RCTRL, GBA_KEY_R); - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_LALT, GBA_KEY_START); - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_LCTRL, GBA_KEY_SELECT); - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_UP, GBA_KEY_UP); - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_DOWN, GBA_KEY_DOWN); - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_LEFT, GBA_KEY_LEFT); - mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_RIGHT, GBA_KEY_RIGHT); -#else mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_x, GBA_KEY_A); mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_z, GBA_KEY_B); mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_a, GBA_KEY_L); @@ -165,14 +152,31 @@ void mSDLInitBindingsGBA(struct mInputMap* inputMap) { mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_DOWN, GBA_KEY_DOWN); mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_LEFT, GBA_KEY_LEFT); mInputBindKey(inputMap, SDL_BINDING_KEY, SDLK_RIGHT, GBA_KEY_RIGHT); -#endif +#if SDL_VERSION_ATLEAST(2, 0, 0) + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_A, GBA_KEY_A); + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_B, GBA_KEY_B); + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, GBA_KEY_L); + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, GBA_KEY_R); + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_START, GBA_KEY_START); + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_BACK, GBA_KEY_SELECT); + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_DPAD_UP, GBA_KEY_UP); + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_DPAD_DOWN, GBA_KEY_DOWN); + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_DPAD_LEFT, GBA_KEY_LEFT); + mInputBindKey(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, GBA_KEY_RIGHT); + + struct mInputAxis description = (struct mInputAxis) { GBA_KEY_RIGHT, GBA_KEY_LEFT, 0x4000, -0x4000 }; + mInputBindAxis(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_AXIS_LEFTX, &description); + description = (struct mInputAxis) { GBA_KEY_DOWN, GBA_KEY_UP, 0x4000, -0x4000 }; + mInputBindAxis(inputMap, SDL_BINDING_CONTROLLER, SDL_CONTROLLER_AXIS_LEFTY, &description); +#else struct mInputAxis description = { GBA_KEY_RIGHT, GBA_KEY_LEFT, 0x4000, -0x4000 }; mInputBindAxis(inputMap, SDL_BINDING_BUTTON, 0, &description); description = (struct mInputAxis) { GBA_KEY_DOWN, GBA_KEY_UP, 0x4000, -0x4000 }; mInputBindAxis(inputMap, SDL_BINDING_BUTTON, 1, &description); mInputBindHat(inputMap, SDL_BINDING_BUTTON, 0, &GBAInputInfo.hat); +#endif } bool mSDLAttachPlayer(struct mSDLEvents* events, struct mSDLPlayer* player) { @@ -183,9 +187,8 @@ bool mSDLAttachPlayer(struct mSDLEvents* events, struct mSDLPlayer* player) { } #if SDL_VERSION_ATLEAST(2, 0, 0) + mRumbleIntegratorInit(&player->rumble.d); player->rumble.d.setRumble = _mSDLSetRumble; - CircleBufferInit(&player->rumble.history, RUMBLE_PWM); - player->rumble.level = 0; player->rumble.activeLevel = 0; player->rumble.p = player; #endif @@ -201,7 +204,7 @@ bool mSDLAttachPlayer(struct mSDLEvents* events, struct mSDLPlayer* player) { player->rotation.gyroY = 1; player->rotation.gyroZ = -1; player->rotation.zDelta = 0; - CircleBufferInit(&player->rotation.zHistory, sizeof(float) * GYRO_STEPS); + mCircleBufferInit(&player->rotation.zHistory, sizeof(float) * GYRO_STEPS); player->rotation.p = player; player->playerId = events->playersAttached; @@ -275,26 +278,25 @@ void mSDLDetachPlayer(struct mSDLEvents* events, struct mSDLPlayer* player) { } } --events->playersAttached; - CircleBufferDeinit(&player->rotation.zHistory); -#if SDL_VERSION_ATLEAST(2, 0, 0) - CircleBufferDeinit(&player->rumble.history); -#endif + mCircleBufferDeinit(&player->rotation.zHistory); } void mSDLPlayerLoadConfig(struct mSDLPlayer* context, const struct Configuration* config) { mInputMapLoad(context->bindings, SDL_BINDING_KEY, config); if (context->joystick) { - mInputMapLoad(context->bindings, SDL_BINDING_BUTTON, config); #if SDL_VERSION_ATLEAST(2, 0, 0) + mInputMapLoad(context->bindings, SDL_BINDING_CONTROLLER, config); char name[34] = {0}; SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(context->joystick->joystick), name, sizeof(name)); + mInputProfileLoad(context->bindings, SDL_BINDING_CONTROLLER, config, name); #else + mInputMapLoad(context->bindings, SDL_BINDING_BUTTON, config); const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick->joystick)); if (!name) { return; } -#endif mInputProfileLoad(context->bindings, SDL_BINDING_BUTTON, config, name); +#endif const char* value; char* end; @@ -410,7 +412,7 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration* if (events->preferredJoysticks[i] && strcmp(events->preferredJoysticks[i], joystickName) == 0) { events->players[i]->joystick = joystick; if (config) { - mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName); + mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_CONTROLLER, config, joystickName); } return; } @@ -421,7 +423,7 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration* } events->players[i]->joystick = joystick; if (config && joystickName[0]) { - mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName); + mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_CONTROLLER, config, joystickName); } break; } @@ -485,7 +487,7 @@ static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer* } if (event->type == SDL_KEYDOWN) { switch (event->keysym.sym) { -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS case SDLK_F11: if (context->core->debugger) { mDebuggerEnter(context->core->debugger, DEBUGGER_ENTER_MANUAL, NULL); @@ -502,11 +504,6 @@ static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer* context->frameCallback = _pauseAfterFrame; mCoreThreadUnpause(context); return; -#ifdef BUILD_PANDORA - case SDLK_ESCAPE: - mCoreThreadEnd(context); - return; -#endif default: if ((event->keysym.mod & GUI_MOD) && (event->keysym.mod & GUI_MOD) == event->keysym.mod) { switch (event->keysym.sym) { @@ -574,6 +571,45 @@ static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer* } } +#if SDL_VERSION_ATLEAST(2, 0, 0) +static void _mSDLHandleControllerButton(struct mCoreThread* context, struct mSDLPlayer* sdlContext, const struct SDL_ControllerButtonEvent* event) { + int key = 0; + key = mInputMapKey(sdlContext->bindings, SDL_BINDING_CONTROLLER, event->button); + if (key == -1) { + return; + } + + mCoreThreadInterrupt(context); + if (event->type == SDL_CONTROLLERBUTTONDOWN) { + context->core->addKeys(context->core, 1 << key); + } else { + context->core->clearKeys(context->core, 1 << key); + } + mCoreThreadContinue(context); +} + +static void _mSDLHandleControllerAxis(struct mCoreThread* context, struct mSDLPlayer* sdlContext, const struct SDL_ControllerAxisEvent* event) { + int clearKeys = ~mInputClearAxis(sdlContext->bindings, SDL_BINDING_CONTROLLER, event->axis, -1); + int newKeys = 0; + int key = mInputMapAxis(sdlContext->bindings, SDL_BINDING_CONTROLLER, event->axis, event->value); + if (key != -1) { + newKeys |= 1 << key; + } + clearKeys &= ~newKeys; + mCoreThreadInterrupt(context); + context->core->clearKeys(context->core, clearKeys); + context->core->addKeys(context->core, newKeys); + mCoreThreadContinue(context); +} + +static void _mSDLHandleWindowEvent(struct mSDLPlayer* sdlContext, const struct SDL_WindowEvent* event) { + switch (event->event) { + case SDL_WINDOWEVENT_SIZE_CHANGED: + sdlContext->windowUpdated = 1; + break; + } +} +#else static void _mSDLHandleJoyButton(struct mCoreThread* context, struct mSDLPlayer* sdlContext, const struct SDL_JoyButtonEvent* event) { int key = 0; key = mInputMapKey(sdlContext->bindings, SDL_BINDING_BUTTON, event->button); @@ -616,16 +652,6 @@ static void _mSDLHandleJoyAxis(struct mCoreThread* context, struct mSDLPlayer* s context->core->clearKeys(context->core, clearKeys); context->core->addKeys(context->core, newKeys); mCoreThreadContinue(context); - -} - -#if SDL_VERSION_ATLEAST(2, 0, 0) -static void _mSDLHandleWindowEvent(struct mSDLPlayer* sdlContext, const struct SDL_WindowEvent* event) { - switch (event->event) { - case SDL_WINDOWEVENT_SIZE_CHANGED: - sdlContext->windowUpdated = 1; - break; - } } #endif @@ -638,17 +664,19 @@ void mSDLHandleEvent(struct mCoreThread* context, struct mSDLPlayer* sdlContext, case SDL_WINDOWEVENT: _mSDLHandleWindowEvent(sdlContext, &event->window); break; + case SDL_CONTROLLERBUTTONDOWN: + case SDL_CONTROLLERBUTTONUP: + _mSDLHandleControllerButton(context, sdlContext, &event->cbutton); + break; + case SDL_CONTROLLERAXISMOTION: + _mSDLHandleControllerAxis(context, sdlContext, &event->caxis); + break; #else case SDL_VIDEORESIZE: sdlContext->newWidth = event->resize.w; sdlContext->newHeight = event->resize.h; sdlContext->windowUpdated = 1; break; -#endif - case SDL_KEYDOWN: - case SDL_KEYUP: - _mSDLHandleKeypress(context, sdlContext, &event->key); - break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: _mSDLHandleJoyButton(context, sdlContext, &event->jbutton); @@ -659,45 +687,50 @@ void mSDLHandleEvent(struct mCoreThread* context, struct mSDLPlayer* sdlContext, case SDL_JOYAXISMOTION: _mSDLHandleJoyAxis(context, sdlContext, &event->jaxis); break; +#endif + case SDL_KEYDOWN: + case SDL_KEYUP: + _mSDLHandleKeypress(context, sdlContext, &event->key); + break; } } #if SDL_VERSION_ATLEAST(2, 0, 0) -static void _mSDLSetRumble(struct mRumble* rumble, int enable) { +static void _mSDLSetRumble(struct mRumbleIntegrator* rumble, float level) { struct mSDLRumble* sdlRumble = (struct mSDLRumble*) rumble; - if (!sdlRumble->p->joystick + if (!sdlRumble->p->joystick) { + return; + } + #if !SDL_VERSION_ATLEAST(2, 0, 9) - || !sdlRumble->p->joystick->haptic || !SDL_HapticRumbleSupported(sdlRumble->p->joystick->haptic) + if (!sdlRumble->p->joystick->haptic || !SDL_HapticRumbleSupported(sdlRumble->p->joystick->haptic)) { + return; + } #endif - ) { + +#if SDL_VERSION_ATLEAST(2, 0, 18) + if (!sdlRumble->p->joystick->controller || !SDL_GameControllerHasRumble(sdlRumble->p->joystick->controller)) { return; } - int8_t originalLevel = sdlRumble->level; - sdlRumble->level += enable; - if (CircleBufferSize(&sdlRumble->history) == RUMBLE_PWM) { - int8_t oldLevel; - CircleBufferRead8(&sdlRumble->history, &oldLevel); - sdlRumble->level -= oldLevel; - } - CircleBufferWrite8(&sdlRumble->history, enable); - if (sdlRumble->level == originalLevel) { - return; - } - float activeLevel = ceil(RUMBLE_STEPS * sdlRumble->level / (float) RUMBLE_PWM) / RUMBLE_STEPS; - if (fabsf(sdlRumble->activeLevel - activeLevel) < 0.75 / RUMBLE_STEPS) { - return; - } - sdlRumble->activeLevel = activeLevel; +#endif + #if SDL_VERSION_ATLEAST(2, 0, 9) - SDL_JoystickRumble(sdlRumble->p->joystick->joystick, activeLevel * 0xFFFF, activeLevel * 0xFFFF, 500); + if (sdlRumble->activeLevel > RUMBLE_THRESHOLD || level > RUMBLE_THRESHOLD) { + if (sdlRumble->p->joystick->controller) { + SDL_GameControllerRumble(sdlRumble->p->joystick->controller, level * 0xFFFF, level * 0xFFFF, 67); + } else { + SDL_JoystickRumble(sdlRumble->p->joystick->joystick, level * 0xFFFF, level * 0xFFFF, 67); + } + } #else - if (sdlRumble->activeLevel > 0.5 / RUMBLE_STEPS) { + if (sdlRumble->activeLevel > RUMBLE_THRESHOLD || level > RUMBLE_THRESHOLD) { SDL_HapticRumbleStop(sdlRumble->p->joystick->haptic); - SDL_HapticRumblePlay(sdlRumble->p->joystick->haptic, activeLevel, 500); + SDL_HapticRumblePlay(sdlRumble->p->joystick->haptic, level, 500); } else { SDL_HapticRumbleStop(sdlRumble->p->joystick->haptic); } #endif + sdlRumble->activeLevel = level; } #endif @@ -754,14 +787,14 @@ static void _mSDLRotationSample(struct mRotationSource* source) { float theta[3]; int count = SDL_GameControllerGetSensorData(controller, SDL_SENSOR_GYRO, theta, 3); if (count >= 0) { - rotation->zDelta = theta[1] / -10.f; + rotation->zDelta = theta[1] / -20.f; } return; } } #endif if (rotation->gyroZ >= 0) { - rotation->zDelta = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroZ) / 1.e5f; + rotation->zDelta = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroZ) / 2.e5f; return; } @@ -782,10 +815,10 @@ static void _mSDLRotationSample(struct mRotationSource* source) { rotation->oldY = y; float oldZ = 0; - if (CircleBufferSize(&rotation->zHistory) == GYRO_STEPS * sizeof(float)) { - CircleBufferRead32(&rotation->zHistory, (int32_t*) &oldZ); + if (mCircleBufferSize(&rotation->zHistory) == GYRO_STEPS * sizeof(float)) { + mCircleBufferRead32(&rotation->zHistory, (int32_t*) &oldZ); } - CircleBufferWrite32(&rotation->zHistory, theta.i); + mCircleBufferWrite32(&rotation->zHistory, theta.i); rotation->zDelta += theta.f - oldZ; } @@ -817,4 +850,221 @@ void mSDLSetScreensaverSuspendable(struct mSDLEvents* events, bool suspendable) SDL_EnableScreenSaver(); } } + +static const char* const buttonNamesXbox360[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "A", + [SDL_CONTROLLER_BUTTON_B] = "B", + [SDL_CONTROLLER_BUTTON_X] = "X", + [SDL_CONTROLLER_BUTTON_Y] = "Y", + [SDL_CONTROLLER_BUTTON_BACK] = "Back", + [SDL_CONTROLLER_BUTTON_GUIDE] = "Xbox", + [SDL_CONTROLLER_BUTTON_START] = "Start", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "LS", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "RS", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "LB", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "RB", +#if SDL_VERSION_ATLEAST(2, 0, 14) + [SDL_CONTROLLER_BUTTON_MISC1] = "Misc", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +#endif +}; + +#if SDL_VERSION_ATLEAST(2, 0, 12) +static const char* const buttonNamesXboxOne[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "A", + [SDL_CONTROLLER_BUTTON_B] = "B", + [SDL_CONTROLLER_BUTTON_X] = "X", + [SDL_CONTROLLER_BUTTON_Y] = "Y", + [SDL_CONTROLLER_BUTTON_BACK] = "View", + [SDL_CONTROLLER_BUTTON_GUIDE] = "Xbox", + [SDL_CONTROLLER_BUTTON_START] = "Menu", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "LS", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "RS", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "LB", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "RB", +#if SDL_VERSION_ATLEAST(2, 0, 14) + [SDL_CONTROLLER_BUTTON_MISC1] = "Share", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +#endif +}; + +static const char* const buttonNamesPlayStation[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "×", + [SDL_CONTROLLER_BUTTON_B] = "○", + [SDL_CONTROLLER_BUTTON_X] = "□", + [SDL_CONTROLLER_BUTTON_Y] = "△", + [SDL_CONTROLLER_BUTTON_BACK] = "Share", + [SDL_CONTROLLER_BUTTON_GUIDE] = "PS", + [SDL_CONTROLLER_BUTTON_START] = "Options", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "L3", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "R3", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "L1", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "R1", +#if SDL_VERSION_ATLEAST(2, 0, 14) + [SDL_CONTROLLER_BUTTON_MISC1] = "Misc", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +#endif +}; + +static const char* const buttonNamesNintedo[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "A", + [SDL_CONTROLLER_BUTTON_B] = "B", + [SDL_CONTROLLER_BUTTON_X] = "X", + [SDL_CONTROLLER_BUTTON_Y] = "Y", + [SDL_CONTROLLER_BUTTON_BACK] = "-", + [SDL_CONTROLLER_BUTTON_GUIDE] = "Home", + [SDL_CONTROLLER_BUTTON_START] = "+", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "LS", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "RS", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "L", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "R", +#if SDL_VERSION_ATLEAST(2, 0, 14) + [SDL_CONTROLLER_BUTTON_MISC1] = "Share", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +#endif +}; + +static const char* const buttonNamesGeneric[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_A] = "A", + [SDL_CONTROLLER_BUTTON_B] = "B", + [SDL_CONTROLLER_BUTTON_X] = "X", + [SDL_CONTROLLER_BUTTON_Y] = "Y", + [SDL_CONTROLLER_BUTTON_BACK] = "Select", + [SDL_CONTROLLER_BUTTON_GUIDE] = "Guide", + [SDL_CONTROLLER_BUTTON_START] = "Start", + [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "LS", + [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "RS", + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = "LB", + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "RB", +#if SDL_VERSION_ATLEAST(2, 0, 14) + [SDL_CONTROLLER_BUTTON_MISC1] = "Misc", + [SDL_CONTROLLER_BUTTON_PADDLE1] = "P1", + [SDL_CONTROLLER_BUTTON_PADDLE2] = "P2", + [SDL_CONTROLLER_BUTTON_PADDLE3] = "P3", + [SDL_CONTROLLER_BUTTON_PADDLE4] = "P4", + [SDL_CONTROLLER_BUTTON_TOUCHPAD] = "Touch", +#endif +}; +#endif + +const char* mSDLButtonName(SDL_GameController* controller, SDL_GameControllerButton button) { + const char* const* buttonNames = buttonNamesXbox360; + +#if SDL_VERSION_ATLEAST(2, 0, 12) + switch (SDL_GameControllerGetType(controller)) { + case SDL_CONTROLLER_TYPE_XBOX360: + buttonNames = buttonNamesXbox360; + break; + case SDL_CONTROLLER_TYPE_XBOXONE: + buttonNames = buttonNamesXboxOne; + break; + case SDL_CONTROLLER_TYPE_PS3: + case SDL_CONTROLLER_TYPE_PS4: +#if SDL_VERSION_ATLEAST(2, 0, 14) + case SDL_CONTROLLER_TYPE_PS5: +#endif + buttonNames = buttonNamesPlayStation; + break; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + buttonNames = buttonNamesNintedo; + break; + default: + buttonNames = buttonNamesGeneric; + break; + } +#endif + + switch (button) { + case SDL_CONTROLLER_BUTTON_DPAD_UP: + return "D↑"; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: + return "D↓"; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + return "D←"; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + return "D→"; + default: + return buttonNames[button]; + case SDL_CONTROLLER_BUTTON_INVALID: + case SDL_CONTROLLER_BUTTON_MAX: + break; + } + return NULL; +} + +static const char* const axisNamesXbox[SDL_CONTROLLER_AXIS_MAX] = { + [SDL_CONTROLLER_AXIS_TRIGGERLEFT] = "LT", + [SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = "RT", +}; + +#if SDL_VERSION_ATLEAST(2, 0, 12) +static const char* const axisNamesPlayStation[SDL_CONTROLLER_AXIS_MAX] = { + [SDL_CONTROLLER_AXIS_TRIGGERLEFT] = "L3", + [SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = "R3", +}; + +static const char* const axisNamesNintendo[SDL_CONTROLLER_AXIS_MAX] = { + [SDL_CONTROLLER_AXIS_TRIGGERLEFT] = "ZL", + [SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = "ZR", +}; +#endif + +const char* mSDLAxisName(SDL_GameController* controller, SDL_GameControllerAxis axis) { + const char* const* axisNames = axisNamesXbox; + +#if SDL_VERSION_ATLEAST(2, 0, 12) + switch (SDL_GameControllerGetType(controller)) { + case SDL_CONTROLLER_TYPE_XBOX360: + case SDL_CONTROLLER_TYPE_XBOXONE: + default: + axisNames = axisNamesXbox; + break; + case SDL_CONTROLLER_TYPE_PS3: + case SDL_CONTROLLER_TYPE_PS4: +#if SDL_VERSION_ATLEAST(2, 0, 14) + case SDL_CONTROLLER_TYPE_PS5: +#endif + axisNames = axisNamesPlayStation; + break; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + axisNames = axisNamesNintendo; + break; + } +#endif + + switch (axis) { + case SDL_CONTROLLER_AXIS_LEFTX: + return "X"; + case SDL_CONTROLLER_AXIS_LEFTY: + return "Y"; + case SDL_CONTROLLER_AXIS_RIGHTX: + return "RX"; + case SDL_CONTROLLER_AXIS_RIGHTY: + return "RY"; + case SDL_CONTROLLER_AXIS_TRIGGERLEFT: + case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: + return axisNames[axis]; + case SDL_CONTROLLER_AXIS_INVALID: + case SDL_CONTROLLER_AXIS_MAX: + break; + } + return NULL; +} + #endif diff --git a/src/platform/sdl/sdl-events.h b/src/platform/sdl/sdl-events.h index 8bdbd7c0b..59b7c7e92 100644 --- a/src/platform/sdl/sdl-events.h +++ b/src/platform/sdl/sdl-events.h @@ -29,6 +29,7 @@ mLOG_DECLARE_CATEGORY(SDL_EVENTS); #define SDL_BINDING_KEY 0x53444C4BU #define SDL_BINDING_BUTTON 0x53444C42U +#define SDL_BINDING_CONTROLLER 0x53444C43U #define MAX_PLAYERS 4 @@ -70,12 +71,9 @@ struct mSDLPlayer { SDL_Window* window; struct mSDLRumble { - struct mRumble d; + struct mRumbleIntegrator d; struct mSDLPlayer* p; - - int level; float activeLevel; - struct CircleBuffer history; } rumble; #else int newWidth; @@ -97,7 +95,7 @@ struct mSDLPlayer { int gyroY; int gyroZ; float gyroSensitivity; - struct CircleBuffer zHistory; + struct mCircleBuffer zHistory; int oldX; int oldY; float zDelta; @@ -125,6 +123,9 @@ void mSDLHandleEvent(struct mCoreThread* context, struct mSDLPlayer* sdlContext, void mSDLSuspendScreensaver(struct mSDLEvents*); void mSDLResumeScreensaver(struct mSDLEvents*); void mSDLSetScreensaverSuspendable(struct mSDLEvents*, bool suspendable); + +const char* mSDLButtonName(SDL_GameController*, SDL_GameControllerButton); +const char* mSDLAxisName(SDL_GameController*, SDL_GameControllerAxis); #endif CXX_GUARD_END diff --git a/src/platform/sdl/sw-sdl2.c b/src/platform/sdl/sw-sdl2.c index 75ad1c2ea..734ee903c 100644 --- a/src/platform/sdl/sw-sdl2.c +++ b/src/platform/sdl/sw-sdl2.c @@ -22,7 +22,7 @@ void mSDLSWCreate(struct mSDLRenderer* renderer) { bool mSDLSWInit(struct mSDLRenderer* renderer) { unsigned width, height; renderer->core->baseVideoSize(renderer->core, &width, &height); - renderer->window = SDL_CreateWindow(projectName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer->player.fullscreen)); + renderer->window = SDL_CreateWindow(projectName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_FULLSCREEN_DESKTOP * renderer->player.fullscreen); SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight); renderer->player.window = renderer->window; renderer->sdlRenderer = SDL_CreateRenderer(renderer->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); diff --git a/src/platform/switch/CMakeLists.txt b/src/platform/switch/CMakeLists.txt index a12473b4c..66e5b6f4a 100644 --- a/src/platform/switch/CMakeLists.txt +++ b/src/platform/switch/CMakeLists.txt @@ -4,8 +4,8 @@ find_program(BUILD_ROMFS build_romfs) find_library(GLAPI_LIBRARY glapi REQUIRED) find_library(EGL_LIBRARY EGL REQUIRED) -set(OS_DEFINES _GNU_SOURCE IOAPI_NO_64) -list(APPEND CORE_VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c) +set(OS_DEFINES _GNU_SOURCE IOAPI_NO_64 ENABLE_VFS_FD) +list(APPEND VFS_SRC ${PROJECT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${PROJECT_SOURCE_DIR}/src/util/vfs/vfs-dirent.c) list(APPEND GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c) include_directories(AFTER ${OPENGLES3_INCLUDE_DIR} ${OPENGL_EGL_INCLUDE_DIR}) @@ -17,7 +17,7 @@ else() find_library(NOUVEAU_LIBRARY drm_nouveau REQUIRED) list(APPEND OS_LIB nx) endif() -set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE) +set(VFS_SRC ${VFS_SRC} PARENT_SCOPE) set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE) set(OS_LIB ${OS_LIB} PARENT_SCOPE) @@ -39,11 +39,11 @@ add_custom_command(OUTPUT control.nacp add_custom_command(OUTPUT romfs.bin COMMAND ${CMAKE_COMMAND} -E make_directory romfs - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/res/font-new.png" romfs/ + COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/res/font-new.png" romfs/ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/fileassoc.cfg.in" romfs/ COMMAND ${BUILD_ROMFS} romfs romfs.bin COMMAND ${CMAKE_COMMAND} -E remove_directory romfs - DEPENDS "${CMAKE_SOURCE_DIR}/res/font-new.png" "${CMAKE_CURRENT_SOURCE_DIR}/fileassoc.cfg.in") + DEPENDS "${PROJECT_SOURCE_DIR}/res/font-new.png" "${CMAKE_CURRENT_SOURCE_DIR}/fileassoc.cfg.in") add_custom_target(${BINARY_NAME}.nro ALL ${ELF2NRO} ${BINARY_NAME}.elf ${BINARY_NAME}.nro --romfs=romfs.bin --nacp=control.nacp --icon="${CMAKE_CURRENT_SOURCE_DIR}/icon.jpg" diff --git a/src/platform/switch/main.c b/src/platform/switch/main.c index 3e891ab3d..6cd7bc3b8 100644 --- a/src/platform/switch/main.c +++ b/src/platform/switch/main.c @@ -4,7 +4,6 @@ * 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/. */ #include "feature/gui/gui-runner.h" -#include #include #include #include @@ -14,22 +13,17 @@ #include #include +#include #include #include #include #include #define AUTO_INPUT 0x4E585031 -#define SAMPLES 0x200 -#define N_BUFFERS 4 +#define SAMPLES 0x400 +#define N_BUFFERS 6 #define ANALOG_DEADZONE 0x4000 -#if (SAMPLES * 4) < 0x1000 -#define BUFFER_SIZE 0x1000 -#else -#define BUFFER_SIZE (SAMPLES * 4) -#endif - TimeType __nx_time_type = TimeType_UserSystemClock; static EGLDisplay s_display; @@ -85,18 +79,17 @@ static GLuint oldTex; static GLuint screenshotTex; static struct GUIFont* font; -static color_t* frameBuffer; +static mColor* frameBuffer; static struct mAVStream stream; static struct mSwitchRumble { - struct mRumble d; - int up; - int down; + struct mRumbleIntegrator d; HidVibrationValue value; } rumble; static struct mRotationSource rotation = {0}; -static int audioBufferActive; -static AudioOutBuffer audoutBuffer[N_BUFFERS]; -static int enqueuedBuffers; +static AudioDriver audrenDriver; +static AudioDriverWaveBuf audrvBuffer[N_BUFFERS]; +static struct mStereoSample* audioBuffer[N_BUFFERS]; +static double fpsRatio = 1; static bool frameLimiter = true; static unsigned framecount = 0; static unsigned framecap = 10; @@ -116,8 +109,6 @@ static float gyroZ = 0; static float tiltX = 0; static float tiltY = 0; -static struct mStereoSample audioBuffer[N_BUFFERS][BUFFER_SIZE / 4] __attribute__((__aligned__(0x1000))); - static enum ScreenMode { SM_PA, SM_AF, @@ -125,6 +116,12 @@ static enum ScreenMode { SM_MAX } screenMode = SM_PA; +static enum FilterMode { + FM_NEAREST, + FM_LINEAR, + FM_MAX +} filterMode = FM_NEAREST; + static bool eglInit() { s_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (!s_display) { @@ -268,20 +265,17 @@ static void _updateRenderer(struct mGUIRunner* runner, bool gl) { } } -static int _audioWait(u64 timeout) { - AudioOutBuffer* releasedBuffers; - u32 nReleasedBuffers = 0; - Result rc; - if (timeout) { - rc = audoutWaitPlayFinish(&releasedBuffers, &nReleasedBuffers, timeout); - } else { - rc = audoutGetReleasedAudioOutBuffer(&releasedBuffers, &nReleasedBuffers); +static void _resetSampleRate(u32 samplerate) { + if (!samplerate) { + samplerate = 32768; } - if (R_FAILED(rc)) { - return 0; - } - enqueuedBuffers -= nReleasedBuffers; - return nReleasedBuffers; + audrvVoiceInit(&audrenDriver, 0, 2, PcmFormat_Int16, samplerate / fpsRatio); + audrvVoiceSetDestinationMix(&audrenDriver, 0, AUDREN_FINAL_MIX_ID); + audrvVoiceSetMixFactor(&audrenDriver, 0, 1.0f, 0, 0); + audrvVoiceSetMixFactor(&audrenDriver, 0, 0.0f, 0, 1); + audrvVoiceSetMixFactor(&audrenDriver, 0, 0.0f, 1, 0); + audrvVoiceSetMixFactor(&audrenDriver, 0, 1.0f, 1, 1); + audrvUpdate(&audrenDriver); } static void _setup(struct mGUIRunner* runner) { @@ -302,7 +296,8 @@ static void _setup(struct mGUIRunner* runner) { } _updateRenderer(runner, fakeBool); - runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble.d); + mRumbleIntegratorReset(&rumble.d); + runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble.d.d); runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation); runner->core->setAVStream(runner->core, &stream); @@ -314,23 +309,27 @@ static void _setup(struct mGUIRunner* runner) { if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { screenMode = mode; } + if (mCoreConfigGetUIntValue(&runner->config, "filterMode", &mode) && mode < FM_MAX) { + filterMode = mode; + } runner->core->setAudioBufferSize(runner->core, SAMPLES); + + u32 samplerate = runner->core->audioSampleRate(runner->core); + fpsRatio = mCoreCalculateFramerateRatio(runner->core, 60.0); + _resetSampleRate(samplerate); } static void _gameLoaded(struct mGUIRunner* runner) { - u32 samplerate = audoutGetSampleRate(); - - double ratio = GBAAudioCalculateRatio(1, 60.0, 1); - blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), samplerate * ratio); - blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), samplerate * ratio); - mCoreConfigGetUIntValue(&runner->config, "fastForwardCap", &framecap); unsigned mode; if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { screenMode = mode; } + if (mCoreConfigGetUIntValue(&runner->config, "filterMode", &mode) && mode < FM_MAX) { + filterMode = mode; + } int fakeBool; if (mCoreConfigGetIntValue(&runner->config, "interframeBlending", &fakeBool)) { @@ -364,23 +363,24 @@ static void _gameLoaded(struct mGUIRunner* runner) { runner->core->reloadConfigOption(runner->core, "videoScale", &runner->config); } } - - rumble.up = 0; - rumble.down = 0; } static void _gameUnloaded(struct mGUIRunner* runner) { + UNUSED(runner); HidVibrationValue values[4]; memcpy(&values[0], &vibrationStop, sizeof(rumble.value)); memcpy(&values[1], &vibrationStop, sizeof(rumble.value)); memcpy(&values[2], &vibrationStop, sizeof(rumble.value)); memcpy(&values[3], &vibrationStop, sizeof(rumble.value)); hidSendVibrationValues(vibrationDeviceHandles, values, 4); + audrvVoiceStop(&audrenDriver, 0); } static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded, bool blendTop) { glViewport(0, 1080 - vheight, vwidth, vheight); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterMode == FM_LINEAR ? GL_LINEAR : GL_NEAREST); + glUseProgram(program); glBindVertexArray(vao); float inwidth = width; @@ -393,6 +393,7 @@ static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, float aspectY = inheight / vheight; float max = 1.f; switch (screenMode) { + case SM_MAX: // This should never get hit, so just fall through to silence warning case SM_PA: if (aspectX > aspectY) { max = floor(1.f / aspectX); @@ -505,27 +506,15 @@ static void _drawFrame(struct mGUIRunner* runner, bool faded) { _drawTex(runner, width, height, faded, false); } - HidVibrationValue values[4]; - if (rumble.up) { - rumble.value.amp_low = rumble.up / (float) (rumble.up + rumble.down); - rumble.value.amp_high = rumble.up / (float) (rumble.up + rumble.down); - memcpy(&values[0], &rumble.value, sizeof(rumble.value)); - memcpy(&values[1], &rumble.value, sizeof(rumble.value)); - memcpy(&values[2], &rumble.value, sizeof(rumble.value)); - memcpy(&values[3], &rumble.value, sizeof(rumble.value)); - } else { - memcpy(&values[0], &vibrationStop, sizeof(rumble.value)); - memcpy(&values[1], &vibrationStop, sizeof(rumble.value)); - memcpy(&values[2], &vibrationStop, sizeof(rumble.value)); - memcpy(&values[3], &vibrationStop, sizeof(rumble.value)); - } + memcpy(&values[0], &rumble.value, sizeof(rumble.value)); + memcpy(&values[1], &rumble.value, sizeof(rumble.value)); + memcpy(&values[2], &rumble.value, sizeof(rumble.value)); + memcpy(&values[3], &rumble.value, sizeof(rumble.value)); hidSendVibrationValues(vibrationDeviceHandles, values, 4); - rumble.up = 0; - rumble.down = 0; } -static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, unsigned width, unsigned height, bool faded) { +static void _drawScreenshot(struct mGUIRunner* runner, const mColor* pixels, unsigned width, unsigned height, bool faded) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, screenshotTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); @@ -551,9 +540,7 @@ static void _incrementScreenMode(struct mGUIRunner* runner) { static void _setFrameLimiter(struct mGUIRunner* runner, bool limit) { UNUSED(runner); if (!frameLimiter && limit) { - while (enqueuedBuffers > 2) { - _audioWait(100000000); - } + audrenWaitFrame(); } frameLimiter = limit; eglSwapInterval(s_surface, limit); @@ -577,41 +564,49 @@ static bool _running(struct mGUIRunner* runner) { return appletMainLoop(); } -static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { +static void _audioRateChanged(struct mAVStream* stream, uint32_t samplerate) { UNUSED(stream); - _audioWait(0); - while (enqueuedBuffers >= N_BUFFERS - 1) { - if (!frameLimiter) { - blip_clear(left); - blip_clear(right); - return; - } - _audioWait(10000000); - } - if (enqueuedBuffers >= N_BUFFERS) { - blip_clear(left); - blip_clear(right); - return; - } - struct mStereoSample* samples = audioBuffer[audioBufferActive]; - blip_read_samples(left, &samples[0].left, SAMPLES, true); - blip_read_samples(right, &samples[0].right, SAMPLES, true); - audoutAppendAudioOutBuffer(&audoutBuffer[audioBufferActive]); - ++audioBufferActive; - audioBufferActive %= N_BUFFERS; - ++enqueuedBuffers; + _resetSampleRate(samplerate); } -void _setRumble(struct mRumble* rumble, int enable) { - struct mSwitchRumble* sr = (struct mSwitchRumble*) rumble; - if (enable) { - ++sr->up; - } else { - ++sr->down; +static void _postAudioBuffer(struct mAVStream* stream, struct mAudioBuffer* buffer) { + UNUSED(stream); + int i; + while (true) { + audrvUpdate(&audrenDriver); + for (i = 0; i < N_BUFFERS; ++i) { + if (audrvBuffer[i].state == AudioDriverWaveBufState_Free || audrvBuffer[i].state == AudioDriverWaveBufState_Done) { + break; + } + } + if (i < N_BUFFERS) { + break; + } + if (!frameLimiter) { + mAudioBufferClear(buffer); + return; + } + audrenWaitFrame(); } + struct mStereoSample* samples = audioBuffer[i]; + mAudioBufferRead(buffer, (int16_t*) samples, SAMPLES); + armDCacheFlush(samples, SAMPLES * sizeof(struct mStereoSample)); + audrvVoiceAddWaveBuf(&audrenDriver, 0, &audrvBuffer[i]); + + if (!audrvVoiceIsPlaying(&audrenDriver, 0)) { + audrvVoiceStart(&audrenDriver, 0); + } + audrvUpdate(&audrenDriver); +} + +void _setRumble(struct mRumbleIntegrator* rumble, float level) { + struct mSwitchRumble* sr = (struct mSwitchRumble*) rumble; + sr->value.amp_low = level; + sr->value.amp_high = level; } void _sampleRotation(struct mRotationSource* source) { + UNUSED(source); HidSixAxisSensorState sixaxis = {0}; u64 styles = padGetStyleSet(&pad); if (styles & HidNpadStyleTag_NpadHandheld) { @@ -630,7 +625,7 @@ void _sampleRotation(struct mRotationSource* source) { } tiltX = sixaxis.acceleration.x * 3e8f; tiltY = sixaxis.acceleration.y * -3e8f; - gyroZ = sixaxis.angular_velocity.z * -1.1e9f; + gyroZ = sixaxis.angular_velocity.z * -5.5e8f; } int32_t _readTiltX(struct mRotationSource* source) { @@ -711,21 +706,18 @@ static void glInit(void) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glGenTextures(1, &oldTex); glBindTexture(GL_TEXTURE_2D, oldTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glGenTextures(1, &screenshotTex); glBindTexture(GL_TEXTURE_2D, screenshotTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glGenBuffers(1, &pbo); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); @@ -817,6 +809,7 @@ static void hidSetup(void) { padConfigureInput(1, HidNpadStyleSet_NpadStandard); padInitializeDefault(&pad); + mRumbleIntegratorInit(&rumble.d); rumble.d.setRumble = _setRumble; rumble.value.freq_low = 120.0; rumble.value.freq_high = 180.0; @@ -854,9 +847,26 @@ int main(int argc, char* argv[]) { nxlinkStdio(); eglInit(); romfsInit(); - audoutInitialize(); psmInitialize(); + const AudioRendererConfig audren = { + .output_rate = AudioRendererOutputRate_48kHz, + .num_voices = 24, + .num_effects = 0, + .num_sinks = 1, + .num_mix_objs = 1, + .num_mix_buffers = 2, + }; + const u8 channels[] = { 0, 1 }; + audrenInitialize(&audren); + audrvCreate(&audrenDriver, &audren, 2); + struct mStereoSample* buffers = memalign(AUDREN_MEMPOOL_ALIGNMENT, SAMPLES * N_BUFFERS * sizeof(struct mStereoSample)); + int mempool = audrvMemPoolAdd(&audrenDriver, buffers, SAMPLES * N_BUFFERS * sizeof(struct mStereoSample)); + audrvMemPoolAttach(&audrenDriver, mempool); + audrvDeviceSinkAdd(&audrenDriver, AUDREN_DEFAULT_DEVICE_NAME, 2, channels); + audrvUpdate(&audrenDriver); + audrenStartAudioRenderer(); + font = GUIFontCreate(); vmode = appletGetOperationMode(); @@ -876,17 +886,15 @@ int main(int argc, char* argv[]) { stream.postVideoFrame = NULL; stream.postAudioFrame = NULL; stream.postAudioBuffer = _postAudioBuffer; + stream.audioRateChanged = _audioRateChanged; - memset(audioBuffer, 0, sizeof(audioBuffer)); - audioBufferActive = 0; - enqueuedBuffers = 0; size_t i; for (i = 0; i < N_BUFFERS; ++i) { - audoutBuffer[i].next = NULL; - audoutBuffer[i].buffer = audioBuffer[i]; - audoutBuffer[i].buffer_size = BUFFER_SIZE; - audoutBuffer[i].data_size = SAMPLES * 4; - audoutBuffer[i].data_offset = 0; + audrvBuffer[i].data_raw = buffers; + audrvBuffer[i].size = SAMPLES * N_BUFFERS * sizeof(struct mStereoSample); + audrvBuffer[i].start_sample_offset = SAMPLES * i; + audrvBuffer[i].end_sample_offset = SAMPLES * (i + 1); + audioBuffer[i] = &buffers[SAMPLES * i]; } bool illuminanceAvailable = false; @@ -981,11 +989,22 @@ int main(int argc, char* argv[]) { }, .nStates = 16 }, + { + .title = "Filtering", + .data = GUI_V_S("filterMode"), + .submenu = 0, + .state = FM_NEAREST, + .validStates = (const char*[]) { + "None", + "Bilinear", + }, + .nStates = 2 + }, { .title = "GPU-accelerated renderer", .data = GUI_V_S("hwaccelVideo"), .submenu = 0, - .state = 0, + .state = FM_NEAREST, .validStates = (const char*[]) { "Off", "On", @@ -1027,7 +1046,7 @@ int main(int argc, char* argv[]) { .nStates = 2 }, }, - .nConfigExtra = 5, + .nConfigExtra = 6, .setup = _setup, .teardown = NULL, .gameLoaded = _gameLoaded, @@ -1052,8 +1071,6 @@ int main(int argc, char* argv[]) { _mapKey(&runner.params.keyMap, AUTO_INPUT, HidNpadButton_Left, GUI_INPUT_LEFT); _mapKey(&runner.params.keyMap, AUTO_INPUT, HidNpadButton_Right, GUI_INPUT_RIGHT); - audoutStartAudioOut(); - if (argc > 0) { struct VFile* vf = VFileOpen("romfs:/fileassoc.cfg.in", O_RDONLY); if (vf) { @@ -1086,7 +1103,8 @@ int main(int argc, char* argv[]) { mGUIDeinit(&runner); - audoutStopAudioOut(); + audrvClose(&audrenDriver); + audrenExit(); GUIFontDestroy(font); glDeinit(); diff --git a/src/platform/test/CMakeLists.txt b/src/platform/test/CMakeLists.txt index 5e20cb41e..3172c6c88 100644 --- a/src/platform/test/CMakeLists.txt +++ b/src/platform/test/CMakeLists.txt @@ -8,7 +8,7 @@ if(BUILD_PERF) target_link_libraries(${BINARY_NAME}-perf ${BINARY_NAME} ${PERF_LIB} ${OS_LIB}) set_target_properties(${BINARY_NAME}-perf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") install(TARGETS ${BINARY_NAME}-perf DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-perf) - install(FILES "${CMAKE_SOURCE_DIR}/tools/perf.py" DESTINATION "${LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf) + install(FILES "${PROJECT_SOURCE_DIR}/tools/perf.py" DESTINATION "${LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf) endif() if(BUILD_TEST) @@ -27,7 +27,7 @@ if(BUILD_SUITE) link_directories(${CMOCKA_LIBRARY_DIRS}) foreach(TEST IN LISTS TEST_SRC) - string(REPLACE "${CMAKE_SOURCE_DIR}/src/" "" TEST_NAME "${TEST}") + string(REPLACE "${PROJECT_SOURCE_DIR}/src/" "" TEST_NAME "${TEST}") string(REPLACE "/" "-" TEST_NAME "${TEST_NAME}") string(REPLACE "-test" "" TEST_NAME "${TEST_NAME}") string(REPLACE ".c" "" TEST_NAME "${TEST_NAME}") diff --git a/src/platform/test/cinema-main.c b/src/platform/test/cinema-main.c index 01d864bd8..cc1bad862 100644 --- a/src/platform/test/cinema-main.c +++ b/src/platform/test/cinema-main.c @@ -684,7 +684,7 @@ static void _cinemaDimensionsChanged(struct mAVStream* stream, unsigned width, u } } -static void _cinemaVideoFrame(struct mAVStream* stream, const color_t* pixels, size_t stride) { +static void _cinemaVideoFrame(struct mAVStream* stream, const mColor* pixels, size_t stride) { struct CInemaStream* cistream = (struct CInemaStream*) stream; cistream->image->stride = stride; size_t bufferSize = cistream->image->stride * cistream->image->height * BYTES_PER_PIXEL; @@ -1177,7 +1177,7 @@ void CInemaTestRun(struct CInemaTest* test) { if (test->status == CI_ERROR) { break; } - bool failed = false; + bool failed = true; if (baselineFound) { int max = 0; failed = !_compareImages(test, &image, &expected, &max, diffs ? &diff : NULL); diff --git a/src/platform/test/fuzz-main.c b/src/platform/test/fuzz-main.c index 17abe0c1c..143edaba1 100644 --- a/src/platform/test/fuzz-main.c +++ b/src/platform/test/fuzz-main.c @@ -3,7 +3,6 @@ * 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/. */ -#include #include #include #include @@ -100,9 +99,6 @@ int main(int argc, char** argv) { cleanExit = false; goto loadError; } - if (args.patch) { - core->loadPatch(core, VFileOpen(args.patch, O_RDONLY)); - } struct VFile* savestate = 0; struct VFile* savestateOverlay = 0; @@ -113,7 +109,7 @@ int main(int argc, char** argv) { } if (fuzzOpts.ssOverlay) { overlayOffset = fuzzOpts.overlayOffset; - if (overlayOffset < core->stateSize(core)) { + if (overlayOffset <= core->stateSize(core)) { savestateOverlay = VFileOpen(fuzzOpts.ssOverlay, O_RDONLY); } free(fuzzOpts.ssOverlay); @@ -137,36 +133,31 @@ int main(int argc, char** argv) { hasDebugger = true; } - struct mCheatDevice* device; - if (args.cheatsFile && (device = core->cheatDevice(core))) { - struct VFile* vf = VFileOpen(args.cheatsFile, O_RDONLY); - if (vf) { - mCheatDeviceClear(device); - mCheatParseFile(device, vf); - vf->close(vf); - } - } + mArgumentsApplyFileLoads(&args, core); if (savestate) { if (!savestateOverlay) { - mCoreLoadStateNamed(core, savestate, 0); + mCoreLoadStateNamed(core, savestate, SAVESTATE_ALL); } else { - size_t size = core->stateSize(core); - uint8_t* state = malloc(size); - savestate->read(savestate, state, size); - savestateOverlay->read(savestateOverlay, state + overlayOffset, size - overlayOffset); - core->loadState(core, state); - free(state); + size_t size = savestate->size(savestate); + void* mapped = savestate->map(savestate, size, MAP_READ); + struct VFile* newState = VFileMemChunk(mapped, size); + savestate->unmap(savestate, mapped, size); + newState->seek(newState, overlayOffset, SEEK_SET); + uint8_t buffer[2048]; + int read; + while ((read = savestateOverlay->read(savestateOverlay, buffer, sizeof(buffer))) > 0) { + newState->write(newState, buffer, read); + } savestateOverlay->close(savestateOverlay); - savestateOverlay = 0; + savestateOverlay = NULL; + mCoreLoadStateNamed(core, newState, SAVESTATE_ALL); + newState->close(newState); } savestate->close(savestate); - savestate = 0; + savestate = NULL; } - blip_set_rates(core->getAudioChannel(core, 0), core->frequency(core), 0x8000); - blip_set_rates(core->getAudioChannel(core, 1), core->frequency(core), 0x8000); - _fuzzRunloop(core, fuzzOpts.frames); if (hasDebugger) { @@ -199,8 +190,7 @@ static void _fuzzRunloop(struct mCore* core, int frames) { do { core->runFrame(core); --frames; - blip_clear(core->getAudioChannel(core, 0)); - blip_clear(core->getAudioChannel(core, 1)); + mAudioBufferClear(core->getAudioBuffer(core)); } while (frames > 0 && !_dispatchExiting); } diff --git a/src/platform/test/perf-main.c b/src/platform/test/perf-main.c index 668205296..26a3715eb 100644 --- a/src/platform/test/perf-main.c +++ b/src/platform/test/perf-main.c @@ -3,7 +3,6 @@ * 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/. */ -#include #include #include #include @@ -197,8 +196,6 @@ bool _mPerfRunCore(const char* fname, const struct mArguments* args, const struc } // TODO: Put back debugger - char gameCode[9] = { 0 }; - core->init(core); if (!perfOpts->noVideo) { core->setVideoBuffer(core, _outputBuffer, 256); @@ -227,7 +224,8 @@ bool _mPerfRunCore(const char* fname, const struct mArguments* args, const struc mCoreLoadStateNamed(core, _savestate, 0); } - core->getGameCode(core, gameCode); + struct mGameInfo info; + core->getGameInfo(core, &info); int frames = perfOpts->frames; if (!frames) { @@ -256,7 +254,7 @@ bool _mPerfRunCore(const char* fname, const struct mArguments* args, const struc } else { rendererName = "software"; } - snprintf(buffer, sizeof(buffer), "%s,%i,%" PRIu64 ",%s\n", gameCode, frames, duration, rendererName); + snprintf(buffer, sizeof(buffer), "%s-%s,%i,%" PRIu64 ",%s\n", info.system, info.code, frames, duration, rendererName); printf("%s", buffer); if (_socket != INVALID_SOCKET) { SocketSend(_socket, buffer, strlen(buffer)); diff --git a/src/platform/test/rom-test-main.c b/src/platform/test/rom-test-main.c index 6a8962743..be9f36e8e 100644 --- a/src/platform/test/rom-test-main.c +++ b/src/platform/test/rom-test-main.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2022 Jeffrey Pfau +/* Copyright (c) 2013-2023 Jeffrey Pfau * Copyright (c) 2022 Felix Jones * * This Source Code Form is subject to the terms of the Mozilla Public @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef M_CORE_GBA #include #endif @@ -92,6 +93,7 @@ int main(int argc, char * argv[]) { mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "remove"); mCoreConfigSetDefaultIntValue(&core->config, "logToStdout", true); + mCoreLoadConfig(core); mStandardLoggerInit(&_logger); mStandardLoggerConfig(&_logger, &core->config); @@ -137,38 +139,52 @@ int main(int argc, char * argv[]) { if (!mCoreLoadFile(core, args.fname)) { goto loadError; } - if (args.patch) { - core->loadPatch(core, VFileOpen(args.patch, O_RDONLY)); - } - struct VFile* savestate = NULL; +#ifdef ENABLE_DEBUGGERS + struct mDebugger debugger; + mDebuggerInit(&debugger); + bool hasDebugger = mArgumentsApplyDebugger(&args, core, &debugger); - if (args.savestate) { - savestate = VFileOpen(args.savestate, O_RDONLY); + if (hasDebugger) { + mDebuggerAttach(&debugger, core); + mDebuggerEnter(&debugger, DEBUGGER_ENTER_MANUAL, NULL); + } else { + mDebuggerDeinit(&debugger); } +#endif core->reset(core); - struct mCheatDevice* device; - if (args.cheatsFile && (device = core->cheatDevice(core))) { - struct VFile* vf = VFileOpen(args.cheatsFile, O_RDONLY); - if (vf) { - mCheatDeviceClear(device); - mCheatParseFile(device, vf); - vf->close(vf); - } - } + mArgumentsApplyFileLoads(&args, core); + struct VFile* savestate = NULL; + if (args.savestate) { + savestate = VFileOpen(args.savestate, O_RDONLY); + } if (savestate) { mCoreLoadStateNamed(core, savestate, 0); savestate->close(savestate); } +#ifdef ENABLE_DEBUGGERS + if (hasDebugger) { + do { + mDebuggerRun(&debugger); + } while (!_dispatchExiting && debugger.state != DEBUGGER_SHUTDOWN); + } else +#endif do { core->runLoop(core); } while (!_dispatchExiting); core->unloadROM(core); + +#ifdef ENABLE_DEBUGGERS + if (hasDebugger) { + core->detachDebugger(core); + mDebuggerDeinit(&debugger); + } +#endif cleanExit = true; loadError: diff --git a/src/platform/wii/CMakeLists.txt b/src/platform/wii/CMakeLists.txt index 3fead14c8..a5f77e84d 100644 --- a/src/platform/wii/CMakeLists.txt +++ b/src/platform/wii/CMakeLists.txt @@ -8,15 +8,15 @@ if(WIIDRC_LIBRARY) add_definitions(-DWIIDRC) endif() -set(OS_DEFINES _GNU_SOURCE COLOR_16_BIT COLOR_5_6_5 IOAPI_NO_64 FIXED_ROM_BUFFER) -list(APPEND CORE_VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-devlist.c) +set(OS_DEFINES _GNU_SOURCE COLOR_16_BIT COLOR_5_6_5 IOAPI_NO_64 FIXED_ROM_BUFFER ENABLE_VFS_FD) +list(APPEND VFS_SRC ${PROJECT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${PROJECT_SOURCE_DIR}/src/util/vfs/vfs-dirent.c ${PROJECT_SOURCE_DIR}/src/util/vfs/vfs-devlist.c) include_directories(${CMAKE_CURRENT_BINARY_DIR}) list(APPEND OS_LIB wiiuse bte fat ogc) set(OS_LIB ${OS_LIB} PARENT_SCOPE) source_group("Wii-specific code" FILES ${OS_SRC}) -set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE) +set(VFS_SRC ${VFS_SRC} PARENT_SCOPE) set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE) list(APPEND GUI_SRC ${CMAKE_CURRENT_BINARY_DIR}/font.c ${CMAKE_CURRENT_BINARY_DIR}/icons.c ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c) @@ -30,8 +30,8 @@ if(WIIDRC_LIBRARY) endif() add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/font.tpl - COMMAND ${GXTEXCONV} -i ${CMAKE_SOURCE_DIR}/res/font2x.png -o font.tpl colfmt=5 mipmap=no - MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/res/font2x.png + COMMAND ${GXTEXCONV} -i ${PROJECT_SOURCE_DIR}/res/font2x.png -o font.tpl colfmt=5 mipmap=no + MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/res/font2x.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/font.c @@ -40,8 +40,8 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/font.c WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.tpl - COMMAND ${GXTEXCONV} -i ${CMAKE_SOURCE_DIR}/res/icons2x.png -o icons.tpl colfmt=5 mipmap=no - MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/res/icons2x.png + COMMAND ${GXTEXCONV} -i ${PROJECT_SOURCE_DIR}/res/icons2x.png -o icons.tpl colfmt=5 mipmap=no + MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/res/icons2x.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.c diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index db3ed7242..f05e00897 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -14,13 +14,13 @@ #include -#include #include #include "feature/gui/gui-runner.h" #include #include #include #include +#include #include #include #include @@ -76,9 +76,10 @@ static enum VideoMode { static void _retraceCallback(u32 count); -static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right); +static void _postAudioBuffer(struct mAVStream* stream, struct mAudioBuffer*); +static void _audioRateChanged(struct mAVStream* stream, unsigned); static void _audioDMA(void); -static void _setRumble(struct mRumble* rumble, int enable); +static void _setRumble(struct mRumble* rumble, bool enable, uint32_t sinceLast); static void _sampleRotation(struct mRotationSource* source); static int32_t _readTiltX(struct mRotationSource* source); static int32_t _readTiltY(struct mRotationSource* source); @@ -141,12 +142,15 @@ static void* framebuffer[2] = { 0, 0 }; static int whichFb = 0; static struct AudioBuffer { - struct mStereoSample samples[SAMPLES] __attribute__((__aligned__(32))); - volatile size_t size; -} audioBuffer[BUFFERS] = {0}; + int16_t samples[SAMPLES * 2] __attribute__((__aligned__(32))); + volatile bool full; +} audioBuffers[BUFFERS] = {0}; +static struct mAudioBuffer audioBuffer; static volatile int currentAudioBuffer = 0; static volatile int nextAudioBuffer = 0; -static double audioSampleRate = 60.0 / 1.001; +static double fps = 60.0 / 1.001; +static double fpsRatio = 1; +static struct mAudioResampler resampler; static struct GUIFont* font; @@ -160,7 +164,7 @@ static void reconfigureScreen(struct mGUIRunner* runner) { wAdjust = 1.f; hAdjust = 1.f; guiScale = GUI_SCALE; - audioSampleRate = 60.0 / 1.001; + fps = 60.0 / 1.001; s32 signalMode = CONF_GetVideo(); @@ -208,7 +212,7 @@ static void reconfigureScreen(struct mGUIRunner* runner) { break; } wAdjust = 0.5f; - audioSampleRate = 90.0 / 1.50436; + fps = 90.0 / 1.50436; guiScale = GUI_SCALE_240p; break; } @@ -246,11 +250,6 @@ static void reconfigureScreen(struct mGUIRunner* runner) { if (runner) { runner->params.width = vmode->fbWidth * guiScale * wAdjust; runner->params.height = vmode->efbHeight * guiScale * hAdjust; - if (runner->core) { - double ratio = GBAAudioCalculateRatio(1, audioSampleRate, 1); - blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), 48000 * ratio); - blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), 48000 * ratio); - } } } @@ -269,7 +268,10 @@ int main(int argc, char* argv[]) { AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ); AUDIO_RegisterDMACallback(_audioDMA); - memset(audioBuffer, 0, sizeof(audioBuffer)); + memset(audioBuffers, 0, sizeof(audioBuffers)); + mAudioBufferInit(&audioBuffer, SAMPLES * BUFFERS, 2); + mAudioResamplerInit(&resampler, mINTERPOLATOR_COSINE); + mAudioResamplerSetDestination(&resampler, &audioBuffer, 48000); #ifdef FIXED_ROM_BUFFER romBufferSize = GBA_SIZE_ROM0; romBuffer = SYS_GetArena2Lo(); @@ -348,6 +350,7 @@ int main(int argc, char* argv[]) { stream.postVideoFrame = NULL; stream.postAudioFrame = NULL; stream.postAudioBuffer = _postAudioBuffer; + stream.audioRateChanged = _audioRateChanged; struct mGUIRunner runner = { .params = { @@ -663,6 +666,9 @@ int main(int argc, char* argv[]) { VIDEO_WaitVSync(); mGUIDeinit(&runner); + mAudioResamplerDeinit(&resampler); + mAudioBufferDeinit(&audioBuffer); + free(fifo); free(texmem); free(rescaleTexmem); @@ -678,45 +684,54 @@ int main(int argc, char* argv[]) { } static void _audioDMA(void) { - struct AudioBuffer* buffer = &audioBuffer[currentAudioBuffer]; - if (buffer->size != SAMPLES) { + struct AudioBuffer* buffer = &audioBuffers[currentAudioBuffer]; + if (!buffer->full) { + printf("Recv %i %i%s", currentAudioBuffer, buffer->full, buffer->full ? "" : "!"); return; } DCFlushRange(buffer->samples, SAMPLES * sizeof(struct mStereoSample)); AUDIO_InitDMA((u32) buffer->samples, SAMPLES * sizeof(struct mStereoSample)); - buffer->size = 0; + buffer->full = false; currentAudioBuffer = (currentAudioBuffer + 1) % BUFFERS; } -static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { +static void _postAudioBuffer(struct mAVStream* stream, struct mAudioBuffer* buf) { UNUSED(stream); - + UNUSED(buf); + mAudioResamplerProcess(&resampler); u32 level = 0; + bool gotAudio = false; _CPU_ISR_Disable(level); - struct AudioBuffer* buffer = &audioBuffer[nextAudioBuffer]; - int available = blip_samples_avail(left); - if (available + buffer->size > SAMPLES) { - available = SAMPLES - buffer->size; - } - if (available > 0) { - // These appear to be reversed for AUDIO_InitDMA - blip_read_samples(left, &buffer->samples[buffer->size].right, available, true); - blip_read_samples(right, &buffer->samples[buffer->size].left, available, true); - buffer->size += available; - } - if (buffer->size == SAMPLES) { - int next = (nextAudioBuffer + 1) % BUFFERS; - if ((currentAudioBuffer + BUFFERS - next) % BUFFERS != 1) { - nextAudioBuffer = next; - } - if (!AUDIO_GetDMAEnableFlag()) { - _audioDMA(); - AUDIO_StartDMA(); + while (mAudioBufferAvailable(&audioBuffer) >= SAMPLES) { + struct AudioBuffer* buffer = &audioBuffers[nextAudioBuffer]; + if (buffer->full) { + printf("Send %i %i%s", nextAudioBuffer, buffer->full, buffer->full ? "!!" : ""); + break; } + mAudioBufferRead(&audioBuffer, buffer->samples, SAMPLES); + buffer->full = true; + nextAudioBuffer = (nextAudioBuffer + 1) % BUFFERS; + gotAudio = true; + } + if (gotAudio && !AUDIO_GetDMAEnableFlag()) { + _audioDMA(); + AUDIO_StartDMA(); } _CPU_ISR_Restore(level); } +static void _audioRateChanged(struct mAVStream* stream, unsigned sampleRate) { + UNUSED(stream); + if (!sampleRate) { + return; + } + if (!resampler.source || !resampler.destination) { + return; + } + mAudioResamplerProcess(&resampler); + mAudioResamplerSetSource(&resampler, resampler.source, sampleRate / fpsRatio, true); +} + static void _drawStart(void) { VIDEO_SetBlack(false); @@ -1416,15 +1431,15 @@ void _setup(struct mGUIRunner* runner) { nextAudioBuffer = 0; currentAudioBuffer = 0; - int i; - for (i = 0; i < BUFFERS; ++i) { - audioBuffer[i].size = 0; - } + memset(audioBuffers, 0, sizeof(audioBuffers)); runner->core->setAudioBufferSize(runner->core, SAMPLES); - double ratio = GBAAudioCalculateRatio(1, audioSampleRate, 1); - blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), 48000 * ratio); - blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), 48000 * ratio); + fpsRatio = mCoreCalculateFramerateRatio(runner->core, fps); + unsigned sampleRate = runner->core->audioSampleRate(runner->core); + if (!sampleRate) { + sampleRate = 32768; + } + mAudioResamplerSetSource(&resampler, runner->core->getAudioBuffer(runner->core), sampleRate / fpsRatio, true); frameLimiter = true; } @@ -1433,6 +1448,7 @@ void _gameUnloaded(struct mGUIRunner* runner) { UNUSED(runner); AUDIO_StopDMA(); frameLimiter = true; + mAudioBufferClear(&audioBuffer); VIDEO_SetBlack(true); VIDEO_Flush(); VIDEO_WaitVSync(); @@ -1706,8 +1722,9 @@ void _incrementScreenMode(struct mGUIRunner* runner) { } } -void _setRumble(struct mRumble* rumble, int enable) { +void _setRumble(struct mRumble* rumble, bool enable, uint32_t sinceLast) { UNUSED(rumble); + UNUSED(sinceLast); WPAD_Rumble(0, enable); if (enable) { PAD_ControlMotor(0, PAD_MOTOR_RUMBLE); @@ -1731,7 +1748,7 @@ void _sampleRotation(struct mRotationSource* source) { return; } gyroZ = exp.mp.rz - 0x1FA0; - gyroZ <<= 18; + gyroZ <<= 17; } int32_t _readTiltX(struct mRotationSource* source) { diff --git a/src/platform/windows/setup/setup.iss.in b/src/platform/windows/setup/setup.iss.in index 3aad9ef1b..7fdda053e 100644 --- a/src/platform/windows/setup/setup.iss.in +++ b/src/platform/windows/setup/setup.iss.in @@ -32,10 +32,11 @@ DefaultDirName={pf}\{#AppName} DefaultGroupName={#AppName} AllowNoIcons=yes DirExistsWarning=no +DisableDirPage=no ChangesAssociations=True AppendDefaultDirName=False UninstallDisplayIcon={app}\{#AppName}.exe -MinVersion=0,6.0 +MinVersion=6.1 AlwaysShowDirOnReadyPage=True UsePreviousSetupType=True UsePreviousTasks=True @@ -52,7 +53,7 @@ OutputBaseFilename={#AppName}-setup-{#CleanVersionString}-win{#WinBits} UsePreviousLanguage=False DisableWelcomePage=False VersionInfoDescription={#AppName} is an open-source Game Boy Advance emulator -VersionInfoCopyright= 20132022 Jeffrey Pfau +VersionInfoCopyright= 20132024 Jeffrey Pfau VersionInfoProductName={#AppName} VersionInfoVersion={#AppVer} Compression=lzma2/ultra diff --git a/src/script/CMakeLists.txt b/src/script/CMakeLists.txt index 0f64514c0..19802c278 100644 --- a/src/script/CMakeLists.txt +++ b/src/script/CMakeLists.txt @@ -1,6 +1,7 @@ include(ExportDirectory) set(SOURCE_FILES canvas.c + console.c context.c input.c image.c @@ -12,7 +13,7 @@ set(TEST_FILES test/classes.c test/types.c) -if(USE_JSON_C) +if(USE_JSON_C AND ENABLE_VFS) list(APPEND SOURCE_FILES storage.c) endif() diff --git a/src/script/canvas.c b/src/script/canvas.c index 5e931943d..0a0ce5b80 100644 --- a/src/script/canvas.c +++ b/src/script/canvas.c @@ -157,10 +157,8 @@ static struct mScriptValue* mScriptCanvasLayerCreate(struct mScriptCanvasContext } struct mScriptCanvasLayer* layer = &context->overlays[next]; - if (layer->image) { - // This shouldn't exist yet - abort(); - } + // This shouldn't exist yet + mASSERT(!layer->image); layer->image = mImageCreate(w, h, mCOLOR_ABGR8); layer->dirty = true; diff --git a/src/script/console.c b/src/script/console.c new file mode 100644 index 000000000..d908534f6 --- /dev/null +++ b/src/script/console.c @@ -0,0 +1,141 @@ +/* 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/. */ +#include + +#include + +struct mScriptConsole { + struct mLogger* logger; + mScriptContextBufferFactory textBufferFactory; + void* textBufferContext; +}; + +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; +} diff --git a/src/script/context.c b/src/script/context.c index 090daf66d..d9afd55a1 100644 --- a/src/script/context.c +++ b/src/script/context.c @@ -424,6 +424,7 @@ bool mScriptContextLoadVF(struct mScriptContext* context, const char* name, stru return info.context->load(info.context, name, vf); } +#ifdef ENABLE_VFS bool mScriptContextLoadFile(struct mScriptContext* context, const char* path) { struct VFile* vf = VFileOpen(path, O_RDONLY); if (!vf) { @@ -433,6 +434,7 @@ bool mScriptContextLoadFile(struct mScriptContext* context, const char* path) { vf->close(vf); return ret; } +#endif struct mScriptContext* mScriptActiveContext(void) { return ThreadLocalGetValue(_threadContext); @@ -456,9 +458,7 @@ bool mScriptContextActivate(struct mScriptContext* context) { void mScriptContextDeactivate(struct mScriptContext* context) { #ifndef NDEBUG struct mScriptContext* threadContext = ThreadLocalGetValue(_threadContext); - if (threadContext != context) { - abort(); - } + mASSERT(threadContext == context); #endif --context->threadDepth; @@ -481,7 +481,7 @@ bool mScriptInvoke(const struct mScriptValue* val, struct mScriptFrame* frame) { return false; } const struct mScriptTypeFunction* signature = &val->type->details.function; - if (!mScriptCoerceFrame(&signature->parameters, &frame->arguments)) { + if (!mScriptCoerceFrame(&signature->parameters, &frame->arguments, &frame->arguments)) { return false; } const struct mScriptFunction* fn = val->value.opaque; diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 32ed0d13e..732d54e99 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -40,12 +40,12 @@ static void _freeFrame(struct mScriptList* frame); static void _autofreeFrame(struct mScriptContext* context, struct mScriptList* frame); struct mScriptEngineContextLua; -static bool _luaPushFrame(struct mScriptEngineContextLua*, struct mScriptList*); -static bool _luaPopFrame(struct mScriptEngineContextLua*, struct mScriptList*); +static bool _luaPushFrame(struct mScriptEngineContextLua*, lua_State*, struct mScriptList*); +static bool _luaPopFrame(struct mScriptEngineContextLua*, lua_State*, struct mScriptList*); static bool _luaInvoke(struct mScriptEngineContextLua*, struct mScriptFrame*); -static struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool pop); -static bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue*); +static struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, lua_State*, bool pop); +static bool _luaWrap(struct mScriptEngineContextLua* luaContext, lua_State*, struct mScriptValue*); static void _luaDeref(struct mScriptValue*); @@ -516,14 +516,14 @@ bool _luaIsScript(struct mScriptEngineContext* ctx, const char* name, struct VFi struct mScriptValue* _luaGetGlobal(struct mScriptEngineContext* ctx, const char* name) { struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx; lua_getglobal(luaContext->lua, name); - return _luaCoerce(luaContext, true); + return _luaCoerce(luaContext, luaContext->lua, true); } bool _luaSetGlobal(struct mScriptEngineContext* ctx, const char* name, struct mScriptValue* value) { struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx; if (!value) { lua_pushnil(luaContext->lua); - } else if (!_luaWrap(luaContext, value)) { + } else if (!_luaWrap(luaContext, luaContext->lua, value)) { return false; } lua_setglobal(luaContext->lua, name); @@ -540,7 +540,7 @@ struct mScriptValue* _luaRootScope(struct mScriptEngineContext* ctx) { struct mScriptValue* key; lua_pop(luaContext->lua, 1); - key = _luaCoerce(luaContext, false); + key = _luaCoerce(luaContext, luaContext->lua, false); mScriptValueWrap(key, mScriptListAppend(list->value.list)); mScriptValueRef(key); mScriptContextFillPool(luaContext->d.context, key); @@ -550,60 +550,60 @@ struct mScriptValue* _luaRootScope(struct mScriptEngineContext* ctx) { return list; } -struct mScriptValue* _luaCoerceFunction(struct mScriptEngineContextLua* luaContext) { +struct mScriptValue* _luaCoerceFunction(struct mScriptEngineContextLua* luaContext, lua_State* lua) { struct mScriptValue* value = mScriptValueAlloc(&mSTLuaFunc); struct mScriptFunction* fn = calloc(1, sizeof(*fn)); struct mScriptEngineContextLuaRef* ref = calloc(1, sizeof(*ref)); fn->call = _luaCall; fn->context = ref; ref->context = luaContext; - ref->ref = luaL_ref(luaContext->lua, LUA_REGISTRYINDEX); + ref->ref = luaL_ref(lua, LUA_REGISTRYINDEX); value->value.opaque = fn; return value; } -struct mScriptValue* _luaCoerceTable(struct mScriptEngineContextLua* luaContext, struct Table* markedObjects) { +struct mScriptValue* _luaCoerceTable(struct mScriptEngineContextLua* luaContext, lua_State* lua, struct Table* markedObjects) { struct mScriptValue* table = mScriptValueAlloc(mSCRIPT_TYPE_MS_TABLE); bool isList = true; - lua_pushnil(luaContext->lua); + lua_pushnil(lua); const void* tablePointer; - while (lua_next(luaContext->lua, -2) != 0) { + while (lua_next(lua, -2) != 0) { struct mScriptValue* value = NULL; - int type = lua_type(luaContext->lua, -1); + int type = lua_type(lua, -1); switch (type) { case LUA_TNUMBER: case LUA_TBOOLEAN: case LUA_TSTRING: case LUA_TFUNCTION: - value = _luaCoerce(luaContext, true); + value = _luaCoerce(luaContext, lua, true); break; case LUA_TTABLE: - tablePointer = lua_topointer(luaContext->lua, -1); + tablePointer = lua_topointer(lua, -1); // Ensure this table doesn't contain any cycles if (!HashTableLookupBinary(markedObjects, &tablePointer, sizeof(tablePointer))) { HashTableInsertBinary(markedObjects, &tablePointer, sizeof(tablePointer), (void*) tablePointer); - value = _luaCoerceTable(luaContext, markedObjects); + value = _luaCoerceTable(luaContext, lua, markedObjects); } default: break; } if (!value) { - lua_pop(luaContext->lua, type == LUA_TTABLE ? 2 : 3); + lua_pop(lua, type == LUA_TTABLE ? 2 : 3); mScriptValueDeref(table); return NULL; } struct mScriptValue* key = NULL; - type = lua_type(luaContext->lua, -1); + type = lua_type(lua, -1); switch (type) { case LUA_TBOOLEAN: case LUA_TSTRING: isList = false; // Fall through case LUA_TNUMBER: - key = _luaCoerce(luaContext, false); + key = _luaCoerce(luaContext, lua, false); break; default: // Limit keys to hashable types @@ -611,7 +611,7 @@ struct mScriptValue* _luaCoerceTable(struct mScriptEngineContextLua* luaContext, } if (!key) { - lua_pop(luaContext->lua, 2); + lua_pop(lua, 2); mScriptValueDeref(table); return false; } @@ -619,7 +619,7 @@ struct mScriptValue* _luaCoerceTable(struct mScriptEngineContextLua* luaContext, mScriptValueDeref(key); mScriptValueDeref(value); } - lua_pop(luaContext->lua, 1); + lua_pop(lua, 1); size_t len = mScriptTableSize(table); if (!isList || !len) { @@ -652,9 +652,9 @@ struct mScriptValue* _luaCoerceTable(struct mScriptEngineContextLua* luaContext, return list; } -struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool pop) { - if (lua_isnone(luaContext->lua, -1)) { - lua_pop(luaContext->lua, 1); +struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, lua_State* lua, bool pop) { + if (lua_isnone(lua, -1)) { + lua_pop(lua, 1); return NULL; } @@ -662,27 +662,27 @@ struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool const void* buffer; struct Table markedObjects; struct mScriptValue* value = NULL; - switch (lua_type(luaContext->lua, -1)) { + switch (lua_type(lua, -1)) { case LUA_TNIL: value = &mScriptValueNull; break; case LUA_TNUMBER: #if LUA_VERSION_NUM >= 503 - if (lua_isinteger(luaContext->lua, -1)) { + if (lua_isinteger(lua, -1)) { value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S64); - value->value.s64 = lua_tointeger(luaContext->lua, -1); + value->value.s64 = lua_tointeger(lua, -1); break; } #endif value = mScriptValueAlloc(mSCRIPT_TYPE_MS_F64); - value->value.f64 = lua_tonumber(luaContext->lua, -1); + value->value.f64 = lua_tonumber(lua, -1); break; case LUA_TBOOLEAN: value = mScriptValueAlloc(mSCRIPT_TYPE_MS_BOOL); - value->value.u32 = lua_toboolean(luaContext->lua, -1); + value->value.u32 = lua_toboolean(lua, -1); break; case LUA_TSTRING: - buffer = lua_tolstring(luaContext->lua, -1, &size); + buffer = lua_tolstring(lua, -1, &size); value = mScriptStringCreateFromBytes(buffer, size); break; case LUA_TFUNCTION: @@ -690,35 +690,35 @@ struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool if (!pop) { break; } - return _luaCoerceFunction(luaContext); + return _luaCoerceFunction(luaContext, lua); case LUA_TTABLE: // This function pops the value internally if (!pop) { break; } HashTableInit(&markedObjects, 0, NULL); - value = _luaCoerceTable(luaContext, &markedObjects); + value = _luaCoerceTable(luaContext, lua, &markedObjects); HashTableDeinit(&markedObjects); return value; case LUA_TUSERDATA: - if (!lua_getmetatable(luaContext->lua, -1)) { + if (!lua_getmetatable(lua, -1)) { break; } - luaL_getmetatable(luaContext->lua, "mSTStruct"); - if (!lua_rawequal(luaContext->lua, -1, -2)) { - lua_pop(luaContext->lua, 1); - luaL_getmetatable(luaContext->lua, "mSTList"); - if (!lua_rawequal(luaContext->lua, -1, -2)) { - lua_pop(luaContext->lua, 1); - luaL_getmetatable(luaContext->lua, "mSTTable"); - if (!lua_rawequal(luaContext->lua, -1, -2)) { - lua_pop(luaContext->lua, 2); + luaL_getmetatable(lua, "mSTStruct"); + if (!lua_rawequal(lua, -1, -2)) { + lua_pop(lua, 1); + luaL_getmetatable(lua, "mSTList"); + if (!lua_rawequal(lua, -1, -2)) { + lua_pop(lua, 1); + luaL_getmetatable(lua, "mSTTable"); + if (!lua_rawequal(lua, -1, -2)) { + lua_pop(lua, 2); break; } } } - lua_pop(luaContext->lua, 2); - value = lua_touserdata(luaContext->lua, -1); + lua_pop(lua, 2); + value = lua_touserdata(lua, -1); value = mScriptContextAccessWeakref(luaContext->d.context, value); if (value->type->base == mSCRIPT_TYPE_WRAPPER) { value = mScriptValueUnwrap(value); @@ -729,14 +729,14 @@ struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool break; } if (pop) { - lua_pop(luaContext->lua, 1); + lua_pop(lua, 1); } return value; } -bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* value) { +bool _luaWrap(struct mScriptEngineContextLua* luaContext, lua_State* lua, struct mScriptValue* value) { if (!value) { - lua_pushnil(luaContext->lua); + lua_pushnil(lua); return true; } uint32_t weakref; @@ -744,7 +744,7 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v if (value->type->base == mSCRIPT_TYPE_WRAPPER) { value = mScriptValueUnwrap(value); if (!value) { - lua_pushnil(luaContext->lua); + lua_pushnil(lua); return true; } mScriptContextFillPool(luaContext->d.context, value); @@ -778,7 +778,7 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v weakref = value->value.u32; value = mScriptContextAccessWeakref(luaContext->d.context, value); if (!value) { - lua_pushnil(luaContext->lua); + lua_pushnil(lua); return true; } needsWeakref = true; @@ -787,95 +787,95 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v struct mScriptValue* newValue; switch (value->type->base) { case mSCRIPT_TYPE_VOID: - lua_pushnil(luaContext->lua); + lua_pushnil(lua); break; case mSCRIPT_TYPE_SINT: if (value->type->size <= 4) { - lua_pushinteger(luaContext->lua, value->value.s32); + lua_pushinteger(lua, value->value.s32); } else if (value->type->size == 8) { - lua_pushinteger(luaContext->lua, value->value.s64); + lua_pushinteger(lua, value->value.s64); } else { ok = false; } break; case mSCRIPT_TYPE_UINT: if (value->type == mSCRIPT_TYPE_MS_BOOL) { - lua_pushboolean(luaContext->lua, !!value->value.u32); + lua_pushboolean(lua, !!value->value.u32); } else if (value->type->size <= 4) { - lua_pushinteger(luaContext->lua, value->value.u32); + lua_pushinteger(lua, value->value.u32); } else if (value->type->size == 8) { - lua_pushinteger(luaContext->lua, value->value.u64); + lua_pushinteger(lua, value->value.u64); } else { ok = false; } break; case mSCRIPT_TYPE_FLOAT: if (value->type->size == 4) { - lua_pushnumber(luaContext->lua, value->value.f32); + lua_pushnumber(lua, value->value.f32); } else if (value->type->size == 8) { - lua_pushnumber(luaContext->lua, value->value.f64); + lua_pushnumber(lua, value->value.f64); } else { ok = false; } break; case mSCRIPT_TYPE_STRING: if (!value->value.string) { - lua_pushnil(luaContext->lua); + lua_pushnil(lua); break; } if (value->type == mSCRIPT_TYPE_MS_STR) { - lua_pushlstring(luaContext->lua, value->value.string->buffer, value->value.string->size); + lua_pushlstring(lua, value->value.string->buffer, value->value.string->size); break; } if (value->type == mSCRIPT_TYPE_MS_CHARP) { - lua_pushstring(luaContext->lua, value->value.copaque); + lua_pushstring(lua, value->value.copaque); break; } ok = false; break; case mSCRIPT_TYPE_LIST: - newValue = lua_newuserdata(luaContext->lua, sizeof(*newValue)); + newValue = lua_newuserdata(lua, sizeof(*newValue)); if (needsWeakref) { *newValue = mSCRIPT_MAKE(WEAKREF, weakref); } else { mScriptValueRef(value); mScriptValueWrap(value, newValue); } - lua_getfield(luaContext->lua, LUA_REGISTRYINDEX, "mSTList"); - lua_setmetatable(luaContext->lua, -2); + lua_getfield(lua, LUA_REGISTRYINDEX, "mSTList"); + lua_setmetatable(lua, -2); break; case mSCRIPT_TYPE_TABLE: - newValue = lua_newuserdata(luaContext->lua, sizeof(*newValue)); + newValue = lua_newuserdata(lua, sizeof(*newValue)); if (needsWeakref) { *newValue = mSCRIPT_MAKE(WEAKREF, weakref); } else { mScriptValueRef(value); mScriptValueWrap(value, newValue); } - lua_getfield(luaContext->lua, LUA_REGISTRYINDEX, "mSTTable"); - lua_setmetatable(luaContext->lua, -2); + lua_getfield(lua, LUA_REGISTRYINDEX, "mSTTable"); + lua_setmetatable(lua, -2); break; case mSCRIPT_TYPE_FUNCTION: - newValue = lua_newuserdata(luaContext->lua, sizeof(*newValue)); + newValue = lua_newuserdata(lua, sizeof(*newValue)); newValue->type = value->type; newValue->refs = mSCRIPT_VALUE_UNREF; newValue->type->alloc(newValue); - lua_pushcclosure(luaContext->lua, _luaThunk, 1); + lua_pushcclosure(lua, _luaThunk, 1); break; case mSCRIPT_TYPE_OBJECT: if (!value->value.opaque) { - lua_pushnil(luaContext->lua); + lua_pushnil(lua); break; } - newValue = lua_newuserdata(luaContext->lua, sizeof(*newValue)); + newValue = lua_newuserdata(lua, sizeof(*newValue)); if (needsWeakref) { *newValue = mSCRIPT_MAKE(WEAKREF, weakref); } else { mScriptValueRef(value); mScriptValueWrap(value, newValue); } - lua_getfield(luaContext->lua, LUA_REGISTRYINDEX, "mSTStruct"); - lua_setmetatable(luaContext->lua, -2); + lua_getfield(lua, LUA_REGISTRYINDEX, "mSTStruct"); + lua_setmetatable(lua, -2); break; default: ok = false; @@ -1032,31 +1032,31 @@ const char* _luaGetError(struct mScriptEngineContext* context) { return luaContext->lastError; } -bool _luaPushFrame(struct mScriptEngineContextLua* luaContext, struct mScriptList* frame) { +bool _luaPushFrame(struct mScriptEngineContextLua* luaContext, lua_State* lua, struct mScriptList* frame) { bool ok = true; if (frame) { size_t i; for (i = 0; i < mScriptListSize(frame); ++i) { struct mScriptValue* value = mScriptListGetPointer(frame, i); - if (!_luaWrap(luaContext, value)) { + if (!_luaWrap(luaContext, lua, value)) { ok = false; break; } } } if (!ok) { - lua_pop(luaContext->lua, lua_gettop(luaContext->lua)); + lua_pop(lua, lua_gettop(lua)); } return ok; } -bool _luaPopFrame(struct mScriptEngineContextLua* luaContext, struct mScriptList* frame) { - int count = lua_gettop(luaContext->lua); +bool _luaPopFrame(struct mScriptEngineContextLua* luaContext, lua_State* lua, struct mScriptList* frame) { + int count = lua_gettop(lua); bool ok = true; if (frame) { int i; for (i = 0; i < count; ++i) { - struct mScriptValue* value = _luaCoerce(luaContext, true); + struct mScriptValue* value = _luaCoerce(luaContext, lua, true); if (!value) { ok = false; break; @@ -1068,7 +1068,7 @@ bool _luaPopFrame(struct mScriptEngineContextLua* luaContext, struct mScriptList } } if (count > i) { - lua_pop(luaContext->lua, count - i); + lua_pop(lua, count - i); } if (ok) { @@ -1127,7 +1127,7 @@ bool _luaInvoke(struct mScriptEngineContextLua* luaContext, struct mScriptFrame* return false; } - if (frame && !_luaPushFrame(luaContext, &frame->arguments)) { + if (frame && !_luaPushFrame(luaContext, luaContext->lua, &frame->arguments)) { mScriptContextDeactivate(luaContext->d.context); return false; } @@ -1143,7 +1143,7 @@ bool _luaInvoke(struct mScriptEngineContextLua* luaContext, struct mScriptFrame* if (ret == LUA_ERRRUN) { luaContext->lastError = strdup(lua_tostring(luaContext->lua, -1)); lua_pop(luaContext->lua, 1); - + _luaError(luaContext); } mScriptContextDeactivate(luaContext->d.context); @@ -1151,7 +1151,7 @@ bool _luaInvoke(struct mScriptEngineContextLua* luaContext, struct mScriptFrame* return false; } - if (frame && !_luaPopFrame(luaContext, &frame->returnValues)) { + if (frame && !_luaPopFrame(luaContext, luaContext->lua, &frame->returnValues)) { mScriptContextDrainPool(luaContext->d.context); return false; } @@ -1184,10 +1184,6 @@ static struct mScriptEngineContextLua* _luaGetContext(lua_State* lua) { struct mScriptEngineContextLua* luaContext = lua_touserdata(lua, -1); lua_pop(lua, 1); - if (luaContext->lua != lua) { - lua_pushliteral(lua, "Function called from invalid context"); - lua_error(lua); - } return luaContext; } @@ -1195,7 +1191,7 @@ int _luaThunk(lua_State* lua) { struct mScriptEngineContextLua* luaContext = _luaGetContext(lua); struct mScriptFrame frame; mScriptFrameInit(&frame); - if (!_luaPopFrame(luaContext, &frame.arguments)) { + if (!_luaPopFrame(luaContext, lua, &frame.arguments)) { _freeFrame(&frame.arguments); mScriptContextDrainPool(luaContext->d.context); mScriptFrameDeinit(&frame); @@ -1212,7 +1208,7 @@ int _luaThunk(lua_State* lua) { return lua_error(lua); } - bool ok = _luaPushFrame(luaContext, &frame.returnValues); + bool ok = _luaPushFrame(luaContext, lua, &frame.returnValues); mScriptContextDrainPool(luaContext->d.context); mScriptFrameDeinit(&frame); if (!ok) { @@ -1220,7 +1216,7 @@ int _luaThunk(lua_State* lua) { return lua_error(lua); } - return lua_gettop(luaContext->lua); + return lua_gettop(lua); } int _luaGetObject(lua_State* lua) { @@ -1251,7 +1247,7 @@ int _luaGetObject(lua_State* lua) { return lua_error(lua); } - if (!_luaWrap(luaContext, &val)) { + if (!_luaWrap(luaContext, lua, &val)) { luaL_traceback(lua, lua, "Error translating value from runtime", 1); return lua_error(lua); } @@ -1263,7 +1259,7 @@ int _luaSetObject(lua_State* lua) { char key[MAX_KEY_SIZE]; const char* keyPtr = lua_tostring(lua, -2); struct mScriptValue* obj = lua_touserdata(lua, -3); - struct mScriptValue* val = _luaCoerce(luaContext, true); + struct mScriptValue* val = _luaCoerce(luaContext, lua, true); if (!keyPtr) { lua_pop(lua, 2); @@ -1312,12 +1308,12 @@ static int _luaGcObject(lua_State* lua) { int _luaGetTable(lua_State* lua) { struct mScriptEngineContextLua* luaContext = _luaGetContext(lua); char key[MAX_KEY_SIZE]; - int type = lua_type(luaContext->lua, -1); + int type = lua_type(lua, -1); const char* keyPtr = NULL; int64_t intKey; switch (type) { case LUA_TNUMBER: - intKey = lua_tointeger(luaContext->lua, -1); + intKey = lua_tointeger(lua, -1); break; case LUA_TSTRING: keyPtr = lua_tostring(lua, -1); @@ -1355,7 +1351,7 @@ int _luaGetTable(lua_State* lua) { return 0; } - if (!_luaWrap(luaContext, val)) { + if (!_luaWrap(luaContext, lua, val)) { luaL_traceback(lua, lua, "Error translating value from runtime", 1); return lua_error(lua); } @@ -1378,7 +1374,7 @@ int _luaLenTable(lua_State* lua) { struct mScriptValue val = mSCRIPT_MAKE_U64(mScriptTableSize(obj)); - if (!_luaWrap(luaContext, &val)) { + if (!_luaWrap(luaContext, lua, &val)) { luaL_traceback(lua, lua, "Error translating value from runtime", 1); return lua_error(lua); } @@ -1388,12 +1384,12 @@ int _luaLenTable(lua_State* lua) { static int _luaNextTable(lua_State* lua) { struct mScriptEngineContextLua* luaContext = _luaGetContext(lua); char key[MAX_KEY_SIZE]; - int type = lua_type(luaContext->lua, -1); + int type = lua_type(lua, -1); const char* keyPtr = NULL; struct mScriptValue keyVal = {0}; switch (type) { case LUA_TNUMBER: - keyVal = mSCRIPT_MAKE_S64(lua_tointeger(luaContext->lua, -1)); + keyVal = mSCRIPT_MAKE_S64(lua_tointeger(lua, -1)); break; case LUA_TSTRING: keyPtr = lua_tostring(lua, -1); @@ -1429,12 +1425,12 @@ static int _luaNextTable(lua_State* lua) { } } - if (!_luaWrap(luaContext, mScriptTableIteratorGetKey(table, &iter))) { + if (!_luaWrap(luaContext, lua, mScriptTableIteratorGetKey(table, &iter))) { luaL_traceback(lua, lua, "Iteration error", 1); return lua_error(lua); } - if (!_luaWrap(luaContext, mScriptTableIteratorGetValue(table, &iter))) { + if (!_luaWrap(luaContext, lua, mScriptTableIteratorGetValue(table, &iter))) { luaL_traceback(lua, lua, "Iteration error", 1); return lua_error(lua); } @@ -1453,9 +1449,9 @@ int _luaGetList(lua_State* lua) { struct mScriptEngineContextLua* luaContext = _luaGetContext(lua); ssize_t index; #if LUA_VERSION_NUM >= 503 - index = lua_tointeger(luaContext->lua, -1); + index = lua_tointeger(lua, -1); #else - index = lua_tonumber(luaContext->lua, -1); + index = lua_tonumber(lua, -1); #endif struct mScriptValue* obj = lua_touserdata(lua, -2); lua_pop(lua, 2); @@ -1481,7 +1477,7 @@ int _luaGetList(lua_State* lua) { --index; struct mScriptValue* val = mScriptListGetPointer(list, index); - if (!_luaWrap(luaContext, val)) { + if (!_luaWrap(luaContext, lua, val)) { luaL_traceback(lua, lua, "Error translating value from runtime", 1); return lua_error(lua); } @@ -1509,21 +1505,21 @@ static int _luaLenList(lua_State* lua) { static int _luaRequireShim(lua_State* lua) { struct mScriptEngineContextLua* luaContext = _luaGetContext(lua); - int oldtop = lua_gettop(luaContext->lua); + int oldtop = lua_gettop(lua); const char* path = lua_tostring(lua, lua_upvalueindex(1)); - lua_getglobal(luaContext->lua, "package"); + lua_getglobal(lua, "package"); - lua_pushliteral(luaContext->lua, "path"); - lua_pushstring(luaContext->lua, path); - lua_pushliteral(luaContext->lua, "/?.lua;"); - lua_pushstring(luaContext->lua, path); - lua_pushliteral(luaContext->lua, "/?/init.lua;"); - lua_pushliteral(luaContext->lua, "path"); - lua_gettable(luaContext->lua, -7); - char* oldpath = strdup(lua_tostring(luaContext->lua, -1)); - lua_concat(luaContext->lua, 5); - lua_settable(luaContext->lua, -3); + lua_pushliteral(lua, "path"); + lua_pushstring(lua, path); + lua_pushliteral(lua, "/?.lua;"); + lua_pushstring(lua, path); + lua_pushliteral(lua, "/?/init.lua;"); + lua_pushliteral(lua, "path"); + lua_gettable(lua, -7); + char* oldpath = strdup(lua_tostring(lua, -1)); + lua_concat(lua, 5); + lua_settable(lua, -3); #ifdef _WIN32 #define DLL "dll" @@ -1532,42 +1528,42 @@ static int _luaRequireShim(lua_State* lua) { #else #define DLL "so" #endif - lua_pushliteral(luaContext->lua, "cpath"); - lua_pushstring(luaContext->lua, path); - lua_pushliteral(luaContext->lua, "/?." DLL ";"); - lua_pushstring(luaContext->lua, path); - lua_pushliteral(luaContext->lua, "/?/init." DLL ";"); - lua_pushliteral(luaContext->lua, "cpath"); - lua_gettable(luaContext->lua, -7); - char* oldcpath = strdup(lua_tostring(luaContext->lua, -1)); - lua_concat(luaContext->lua, 5); - lua_settable(luaContext->lua, -3); + lua_pushliteral(lua, "cpath"); + lua_pushstring(lua, path); + lua_pushliteral(lua, "/?." DLL ";"); + lua_pushstring(lua, path); + lua_pushliteral(lua, "/?/init." DLL ";"); + lua_pushliteral(lua, "cpath"); + lua_gettable(lua, -7); + char* oldcpath = strdup(lua_tostring(lua, -1)); + lua_concat(lua, 5); + lua_settable(lua, -3); - lua_pop(luaContext->lua, 1); + lua_pop(lua, 1); - lua_rawgeti(luaContext->lua, LUA_REGISTRYINDEX, luaContext->require); - lua_insert(luaContext->lua, -2); - int ret = lua_pcall(luaContext->lua, 1, LUA_MULTRET, 0); + lua_rawgeti(lua, LUA_REGISTRYINDEX, luaContext->require); + lua_insert(lua, -2); + int ret = lua_pcall(lua, 1, LUA_MULTRET, 0); - lua_getglobal(luaContext->lua, "package"); + lua_getglobal(lua, "package"); - lua_pushliteral(luaContext->lua, "path"); - lua_pushstring(luaContext->lua, oldpath); - lua_settable(luaContext->lua, -3); + lua_pushliteral(lua, "path"); + lua_pushstring(lua, oldpath); + lua_settable(lua, -3); - lua_pushliteral(luaContext->lua, "cpath"); - lua_pushstring(luaContext->lua, oldcpath); - lua_settable(luaContext->lua, -3); + lua_pushliteral(lua, "cpath"); + lua_pushstring(lua, oldcpath); + lua_settable(lua, -3); - lua_pop(luaContext->lua, 1); + lua_pop(lua, 1); free(oldpath); free(oldcpath); if (ret) { - return lua_error(luaContext->lua); + return lua_error(lua); } - int newtop = lua_gettop(luaContext->lua); + int newtop = lua_gettop(lua); return newtop - oldtop + 1; } diff --git a/src/script/image.c b/src/script/image.c index f056c7d49..533af131f 100644 --- a/src/script/image.c +++ b/src/script/image.c @@ -29,6 +29,7 @@ static struct mScriptValue* _mImageNew(unsigned width, unsigned height) { return result; } +#ifdef ENABLE_VFS static struct mScriptValue* _mImageLoad(const char* path) { struct mImage* image = mImageLoad(path); if (!image) { @@ -39,6 +40,7 @@ static struct mScriptValue* _mImageLoad(const char* path) { result->flags = mSCRIPT_VALUE_FLAG_DEINIT; return result; } +#endif static struct mScriptValue* _mImageNewPainter(struct mScriptValue* image) { mScriptValueRef(image); @@ -54,16 +56,10 @@ static struct mScriptValue* _mImageNewPainter(struct mScriptValue* image) { mSCRIPT_DECLARE_STRUCT_C_METHOD(mImage, U32, getPixel, mImageGetPixel, 2, U32, x, U32, y); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mImage, setPixel, mImageSetPixel, 3, U32, x, U32, y, U32, color); -mSCRIPT_DECLARE_STRUCT_C_METHOD_WITH_DEFAULTS(mImage, BOOL, save, mImageSave, 2, CHARP, path, CHARP, format); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mImage, _deinit, mImageDestroy, 0); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mImage, drawImageOpaque, mImageBlit, 3, CS(mImage), image, U32, x, U32, y); mSCRIPT_DECLARE_STRUCT_VOID_METHOD_WITH_DEFAULTS(mImage, drawImage, mImageCompositeWithAlpha, 4, CS(mImage), image, U32, x, U32, y, F32, alpha); -mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mImage, save) - mSCRIPT_NO_DEFAULT, - mSCRIPT_CHARP("PNG") -mSCRIPT_DEFINE_DEFAULTS_END; - mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mImage, drawImage) mSCRIPT_NO_DEFAULT, mSCRIPT_NO_DEFAULT, @@ -71,13 +67,23 @@ mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mImage, drawImage) mSCRIPT_F32(1.0f) mSCRIPT_DEFINE_DEFAULTS_END; +#ifdef ENABLE_VFS +mSCRIPT_DECLARE_STRUCT_C_METHOD_WITH_DEFAULTS(mImage, BOOL, save, mImageSave, 2, CHARP, path, CHARP, format); +mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mImage, save) + mSCRIPT_NO_DEFAULT, + mSCRIPT_CHARP("PNG") +mSCRIPT_DEFINE_DEFAULTS_END; +#endif + mSCRIPT_DEFINE_STRUCT(mImage) mSCRIPT_DEFINE_CLASS_DOCSTRING( "A single, static image." ) mSCRIPT_DEFINE_STRUCT_DEINIT(mImage) +#ifdef ENABLE_VFS mSCRIPT_DEFINE_DOCSTRING("Save the image to a file. Currently, only `PNG` format is supported") mSCRIPT_DEFINE_STRUCT_METHOD(mImage, save) +#endif mSCRIPT_DEFINE_DOCSTRING("Get the ARGB value of the pixel at a given coordinate") mSCRIPT_DEFINE_STRUCT_METHOD(mImage, getPixel) mSCRIPT_DEFINE_DOCSTRING("Set the ARGB value of the pixel at a given coordinate") @@ -93,7 +99,9 @@ mSCRIPT_DEFINE_STRUCT(mImage) mSCRIPT_DEFINE_END; mSCRIPT_BIND_FUNCTION(mImageNew_Binding, W(mImage), _mImageNew, 2, U32, width, U32, height); +#ifdef ENABLE_VFS mSCRIPT_BIND_FUNCTION(mImageLoad_Binding, W(mImage), _mImageLoad, 1, CHARP, path); +#endif mSCRIPT_BIND_FUNCTION(mImageNewPainter_Binding, W(mScriptPainter), _mImageNewPainter, 1, W(mImage), image); void _mPainterSetBlend(struct mPainter* painter, bool enable) { @@ -131,6 +139,7 @@ static struct mScriptValue* _mScriptPainterGet(struct mScriptPainter* painter, c void _mScriptPainterDeinit(struct mScriptPainter* painter) { mScriptValueDeref(painter->image); + free(painter); } mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, setBlend, _mPainterSetBlend, 1, BOOL, enable); @@ -141,6 +150,7 @@ mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, setStrokeColor, _mPainterSetStrokeC mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, drawRectangle, mPainterDrawRectangle, 4, S32, x, S32, y, S32, width, S32, height); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, drawLine, mPainterDrawLine, 4, S32, x1, S32, y1, S32, x2, S32, y2); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, drawCircle, mPainterDrawCircle, 3, S32, x, S32, y, S32, diameter); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mPainter, drawMask, mPainterDrawMask, 3, CS(mImage), mask, S32, x, S32, y); mSCRIPT_DEFINE_STRUCT(mPainter) mSCRIPT_DEFINE_CLASS_DOCSTRING( @@ -162,6 +172,13 @@ mSCRIPT_DEFINE_STRUCT(mPainter) mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, drawLine) mSCRIPT_DEFINE_DOCSTRING("Draw a circle with the specified diameter with the given origin at the top-left corner of the bounding box") mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, drawCircle) + mSCRIPT_DEFINE_DOCSTRING( + "Draw a mask image with each color channel multiplied by the current fill color. This can " + "be useful for displaying graphics with dynamic colors. By making a grayscale template " + "image on a transparent background in advance, a script can set the fill color to a desired " + "target color and use this function to draw it into a destination image." + ) + mSCRIPT_DEFINE_STRUCT_METHOD(mPainter, drawMask) mSCRIPT_DEFINE_END; mSCRIPT_DECLARE_STRUCT_METHOD(mScriptPainter, W(mPainter), _get, _mScriptPainterGet, 1, CHARP, name); @@ -177,12 +194,16 @@ mSCRIPT_DEFINE_END; void mScriptContextAttachImage(struct mScriptContext* context) { mScriptContextExportNamespace(context, "image", (struct mScriptKVPair[]) { mSCRIPT_KV_PAIR(new, &mImageNew_Binding), +#ifdef ENABLE_VFS mSCRIPT_KV_PAIR(load, &mImageLoad_Binding), +#endif mSCRIPT_KV_PAIR(newPainter, &mImageNewPainter_Binding), mSCRIPT_KV_SENTINEL }); mScriptContextSetDocstring(context, "image", "Methods for creating struct::mImage and struct::mPainter instances"); mScriptContextSetDocstring(context, "image.new", "Create a new image with the given dimensions"); +#ifdef ENABLE_VFS mScriptContextSetDocstring(context, "image.load", "Load an image from a path. Currently, only `PNG` format is supported"); +#endif mScriptContextSetDocstring(context, "image.newPainter", "Create a new painter from an existing image"); } diff --git a/src/script/input.c b/src/script/input.c index c103fa82c..1cb9f488b 100644 --- a/src/script/input.c +++ b/src/script/input.c @@ -35,20 +35,28 @@ struct mScriptInputContext { }; static void _mScriptInputDeinit(struct mScriptInputContext*); -static bool _mScriptInputIsKeyActive(const struct mScriptInputContext*, struct mScriptValue*); +static bool _mScriptInputIsKeyActiveStr(const struct mScriptInputContext*, const char*); +static bool _mScriptInputIsKeyActiveNum(const struct mScriptInputContext*, uint32_t); static struct mScriptValue* _mScriptInputActiveKeys(const struct mScriptInputContext*); mSCRIPT_DECLARE_STRUCT(mScriptInputContext); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptInputContext, _deinit, _mScriptInputDeinit, 0); -mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, BOOL, isKeyActive, _mScriptInputIsKeyActive, 1, WRAPPER, key); +mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, BOOL, isKeyActiveStr, _mScriptInputIsKeyActiveStr, 1, CHARP, key); +mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, BOOL, isKeyActiveNum, _mScriptInputIsKeyActiveNum, 1, U32, key); +mSCRIPT_DECLARE_STRUCT_OVERLOADED_C_METHOD(mScriptInputContext, BOOL, isKeyActive); mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, WLIST, activeKeys, _mScriptInputActiveKeys, 0); +mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOADS(mScriptInputContext, isKeyActive) + mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(mScriptInputContext, isKeyActiveStr) + mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(mScriptInputContext, isKeyActiveNum) +mSCRIPT_DEFINE_OVERLOADS_END; + mSCRIPT_DEFINE_STRUCT(mScriptInputContext) mSCRIPT_DEFINE_STRUCT_DEINIT(mScriptInputContext) mSCRIPT_DEFINE_DOCSTRING("Sequence number of the next event to be emitted") mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptInputContext, U64, seq) mSCRIPT_DEFINE_DOCSTRING("Check if a given keyboard key is currently held. The input can be either the printable character for a key, the numerical Unicode codepoint, or a special value from C.KEY") - mSCRIPT_DEFINE_STRUCT_METHOD(mScriptInputContext, isKeyActive) + mSCRIPT_DEFINE_STRUCT_OVERLOADED_METHOD(mScriptInputContext, isKeyActive) mSCRIPT_DEFINE_DOCSTRING("Get a list of the currently active keys. The values are Unicode codepoints or special key values from C.KEY, not strings, so make sure to convert as needed") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptInputContext, activeKeys) mSCRIPT_DEFINE_DOCSTRING("The currently active gamepad, if any") @@ -319,33 +327,18 @@ void _mScriptInputDeinit(struct mScriptInputContext* context) { TableDeinit(&context->activeKeys); } -bool _mScriptInputIsKeyActive(const struct mScriptInputContext* context, struct mScriptValue* value) { +bool _mScriptInputIsKeyActiveStr(const struct mScriptInputContext* context, const char* value) { uint32_t key; - struct mScriptValue intValue; - size_t length; - const char* strbuf; - - switch (value->type->base) { - case mSCRIPT_TYPE_SINT: - case mSCRIPT_TYPE_UINT: - case mSCRIPT_TYPE_FLOAT: - if (!mScriptCast(mSCRIPT_TYPE_MS_U32, value, &intValue)) { - return false; - } - key = intValue.value.u32; - break; - case mSCRIPT_TYPE_STRING: - if (value->value.string->length > 1) { - return false; - } - strbuf = value->value.string->buffer; - length = value->value.string->size; - key = utf8Char(&strbuf, &length); - break; - default: + size_t length = strlen(value); + key = utf8Char(&value, &length); + if (length > 0) { return false; } + void* down = TableLookup(&context->activeKeys, key); + return down != NULL; +} +bool _mScriptInputIsKeyActiveNum(const struct mScriptInputContext* context, uint32_t key) { void* down = TableLookup(&context->activeKeys, key); return down != NULL; } diff --git a/src/script/socket.c b/src/script/socket.c index 5b2e95b60..4684c243e 100644 --- a/src/script/socket.c +++ b/src/script/socket.c @@ -28,7 +28,9 @@ static const struct _mScriptSocketErrorMapping { { ECONNREFUSED, mSCRIPT_SOCKERR_CONNECTION_REFUSED }, { EACCES, mSCRIPT_SOCKERR_DENIED }, { EPERM, mSCRIPT_SOCKERR_DENIED }, +#ifdef ENOTRECOVERABLE { ENOTRECOVERABLE, mSCRIPT_SOCKERR_FAILED }, +#endif { ENETUNREACH, mSCRIPT_SOCKERR_NETWORK_UNREACHABLE }, { ETIMEDOUT, mSCRIPT_SOCKERR_TIMEOUT }, { EINVAL, mSCRIPT_SOCKERR_UNSUPPORTED }, diff --git a/src/script/stdlib.c b/src/script/stdlib.c index 33ec0b751..6e81cfd86 100644 --- a/src/script/stdlib.c +++ b/src/script/stdlib.c @@ -160,7 +160,7 @@ void mScriptContextAttachStdlib(struct mScriptContext* context) { mSCRIPT_KV_SENTINEL }); #endif -#ifdef USE_DEBUGGERS +#ifdef ENABLE_DEBUGGERS mScriptContextExportConstants(context, "WATCHPOINT_TYPE", (struct mScriptKVPair[]) { mSCRIPT_CONSTANT_PAIR(WATCHPOINT, WRITE), mSCRIPT_CONSTANT_PAIR(WATCHPOINT, READ), diff --git a/src/script/test/classes.c b/src/script/test/classes.c index f7c5eb128..e0ce39d47 100644 --- a/src/script/test/classes.c +++ b/src/script/test/classes.c @@ -57,6 +57,11 @@ struct TestH { int32_t j; }; +struct TestI { + uint32_t num; + const char* str; +}; + static int32_t testAi0(struct TestA* a) { return a->i; } @@ -114,6 +119,14 @@ static void testSetC(struct TestG* g, const char* name, const char* val) { g->c = val; } +static void callNum(struct TestI* i, uint32_t num) { + i->num = num; +} + +static void callStr(struct TestI* i, const char* str) { + i->str = str; +} + #define MEMBER_A_DOCSTRING "Member a" mSCRIPT_DECLARE_STRUCT(TestA); @@ -201,12 +214,25 @@ mSCRIPT_DEFINE_STRUCT(TestG) mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(TestG, setC) mSCRIPT_DEFINE_END; - mSCRIPT_DEFINE_STRUCT(TestH) mSCRIPT_DEFINE_STRUCT_MEMBER(TestH, S32, i) mSCRIPT_DEFINE_STRUCT_CONST_MEMBER(TestH, S32, j) mSCRIPT_DEFINE_END; +mSCRIPT_DECLARE_STRUCT(TestI); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(TestI, callStr, callStr, 1, CHARP, value); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(TestI, callNum, callNum, 1, U32, value); +mSCRIPT_DECLARE_STRUCT_OVERLOADED_VOID_METHOD(TestI, call); + +mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOADS(TestI, call) + mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(TestI, callStr) + mSCRIPT_DEFINE_STRUCT_METHOD_OVERLOAD(TestI, callNum) +mSCRIPT_DEFINE_OVERLOADS_END; + +mSCRIPT_DEFINE_STRUCT(TestI) + mSCRIPT_DEFINE_STRUCT_OVERLOADED_METHOD(TestI, call) +mSCRIPT_DEFINE_END; + M_TEST_DEFINE(testALayout) { struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestA)->details.cls; assert_false(cls->init); @@ -1184,6 +1210,44 @@ M_TEST_DEFINE(testHSet) { assert_false(cls->init); } +M_TEST_DEFINE(testOverloadsBasic) { + struct mScriptTypeClass* cls = mSCRIPT_TYPE_MS_S(TestI)->details.cls; + assert_false(cls->init); + mScriptClassInit(cls); + assert_true(cls->init); + + struct TestI s = { + .num = 0, + .str = NULL, + }; + + struct mScriptValue sval = mSCRIPT_MAKE_S(TestI, &s); + struct mScriptValue fn; + struct mScriptFrame frame; + + assert_true(mScriptObjectGet(&sval, "call", &fn)); + + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, S(TestI), &s); + mSCRIPT_PUSH(&frame.arguments, U32, 1); + assert_true(mScriptInvoke(&fn, &frame)); + mScriptFrameDeinit(&frame); + assert_int_equal(s.num, 1); + assert_null(s.str); + + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, S(TestI), &s); + mSCRIPT_PUSH(&frame.arguments, CHARP, "called"); + assert_true(mScriptInvoke(&fn, &frame)); + mScriptFrameDeinit(&frame); + assert_int_equal(s.num, 1); + assert_string_equal(s.str, "called"); + + assert_true(cls->init); + mScriptClassDeinit(cls); + assert_false(cls->init); +} + M_TEST_SUITE_DEFINE(mScriptClasses, cmocka_unit_test(testALayout), cmocka_unit_test(testASignatures), @@ -1201,4 +1265,5 @@ M_TEST_SUITE_DEFINE(mScriptClasses, cmocka_unit_test(testFDeinit), cmocka_unit_test(testGSet), cmocka_unit_test(testHSet), + cmocka_unit_test(testOverloadsBasic), ) diff --git a/src/script/test/input.c b/src/script/test/input.c index 4c689a6ef..641e1c6ab 100644 --- a/src/script/test/input.c +++ b/src/script/test/input.c @@ -172,6 +172,43 @@ M_TEST_DEFINE(clearKeys) { mScriptContextDeinit(&context); } +M_TEST_DEFINE(numericKeys) { + SETUP_LUA; + + TEST_PROGRAM("assert(not input:isKeyActive(C.KEY.F1))"); + + TEST_PROGRAM( + "activeKey = false\n" + "state = nil\n" + "function cb(ev)\n" + " assert(ev.type == C.EV_TYPE.KEY)\n" + " activeKey = ev.key\n" + " state = ev.state\n" + "end\n" + "id = callbacks:add('key', cb)\n" + "assert(id)\n" + "assert(not activeKey)\n" + ); + + struct mScriptKeyEvent keyEvent = { + .d = { .type = mSCRIPT_EV_TYPE_KEY }, + .state = mSCRIPT_INPUT_STATE_DOWN, + .key = mSCRIPT_KEY_F1 + }; + mScriptContextFireEvent(&context, &keyEvent.d); + + TEST_PROGRAM("assert(input:isKeyActive(C.KEY.F1))"); + TEST_PROGRAM("assert(activeKey == C.KEY.F1)"); + TEST_PROGRAM("assert(state == C.INPUT_STATE.DOWN)"); + + keyEvent.state = mSCRIPT_INPUT_STATE_UP; + mScriptContextFireEvent(&context, &keyEvent.d); + + TEST_PROGRAM("assert(not input:isKeyActive(C.KEY.F1))"); + TEST_PROGRAM("assert(state == C.INPUT_STATE.UP)"); + + mScriptContextDeinit(&context); +} M_TEST_DEFINE(gamepadExport) { SETUP_LUA; @@ -219,5 +256,6 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptInput, cmocka_unit_test(fireKey), cmocka_unit_test(activeKeys), cmocka_unit_test(clearKeys), + cmocka_unit_test(numericKeys), cmocka_unit_test(gamepadExport), ) diff --git a/src/script/test/types.c b/src/script/test/types.c index 5c66b3f76..67b6fba9a 100644 --- a/src/script/test/types.c +++ b/src/script/test/types.c @@ -372,25 +372,25 @@ M_TEST_DEFINE(wrongConst) { mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, S(Test), &a); signature.entries[0] = mSCRIPT_TYPE_MS_S(Test); - assert_true(mScriptCoerceFrame(&signature, &frame.arguments)); + assert_true(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, CS(Test), &a); signature.entries[0] = mSCRIPT_TYPE_MS_CS(Test); - assert_true(mScriptCoerceFrame(&signature, &frame.arguments)); + assert_true(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, S(Test), &a); signature.entries[0] = mSCRIPT_TYPE_MS_CS(Test); - assert_true(mScriptCoerceFrame(&signature, &frame.arguments)); + assert_true(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, CS(Test), &a); signature.entries[0] = mSCRIPT_TYPE_MS_S(Test); - assert_false(mScriptCoerceFrame(&signature, &frame.arguments)); + assert_false(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); @@ -402,7 +402,7 @@ M_TEST_DEFINE(wrongConst) { mSCRIPT_PUSH(&frame.arguments, S(Test), &a); assert_false(mScriptPopCSTest(&frame.arguments, &cb)); signature.entries[0] = mSCRIPT_TYPE_MS_CS(Test); - assert_true(mScriptCoerceFrame(&signature, &frame.arguments)); + assert_true(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments)); assert_true(mScriptPopCSTest(&frame.arguments, &cb)); mScriptFrameDeinit(&frame); @@ -410,7 +410,7 @@ M_TEST_DEFINE(wrongConst) { mSCRIPT_PUSH(&frame.arguments, CS(Test), &a); assert_false(mScriptPopSTest(&frame.arguments, &b)); signature.entries[0] = mSCRIPT_TYPE_MS_S(Test); - assert_false(mScriptCoerceFrame(&signature, &frame.arguments)); + assert_false(mScriptCoerceFrame(&signature, &frame.arguments, &frame.arguments)); assert_false(mScriptPopSTest(&frame.arguments, &b)); mScriptFrameDeinit(&frame); diff --git a/src/script/types.c b/src/script/types.c index 20f945839..00422d20c 100644 --- a/src/script/types.c +++ b/src/script/types.c @@ -895,9 +895,8 @@ struct mScriptValue* mScriptValueAlloc(const struct mScriptType* type) { } void mScriptValueRef(struct mScriptValue* val) { - if (val->refs == INT_MAX) { - abort(); - } else if (val->refs == mSCRIPT_VALUE_UNREF) { + mASSERT(val->refs != INT_MAX); + if (val->refs == mSCRIPT_VALUE_UNREF) { return; } ++val->refs; @@ -1238,9 +1237,8 @@ static void _mScriptClassInit(struct mScriptTypeClass* cls, const struct mScript member->docstring = docstring; docstring = NULL; } - if (detail->info.member.type->details.function.parameters.count != 3) { - abort(); - } + mASSERT(detail->info.member.type->base == mSCRIPT_TYPE_FUNCTION); + mASSERT(detail->info.member.type->details.function.parameters.count == 3); HashTableInsert(&cls->setters, detail->info.member.type->details.function.parameters.entries[2]->name, member); break; case mSCRIPT_CLASS_INIT_INTERNAL: @@ -1445,7 +1443,7 @@ static struct mScriptClassMember* _findSetter(const struct mScriptTypeClass* cls if (m) { return m; } - + switch (type->base) { case mSCRIPT_TYPE_SINT: if (type->size < 2) { @@ -1773,21 +1771,24 @@ bool mScriptCast(const struct mScriptType* type, const struct mScriptValue* inpu return false; } -bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, struct mScriptList* frame) { - if (types->count < mScriptListSize(frame) && !types->variable) { +bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, const struct mScriptList* input, struct mScriptList* output) { + if (types->count < mScriptListSize(input) && !types->variable) { return false; } - if (types->count > mScriptListSize(frame) && !types->variable && !types->defaults) { + if (types->count > mScriptListSize(input) && !types->variable && !types->defaults) { return false; } + if (output) { + mScriptListResize(output, mScriptListSize(input) - mScriptListSize(output)); + } size_t i; - for (i = 0; i < mScriptListSize(frame) && i < types->count; ++i) { - if (types->entries[i] == mScriptListGetPointer(frame, i)->type) { + for (i = 0; i < mScriptListSize(input) && i < types->count; ++i) { + if (types->entries[i] == mScriptListGetConstPointer(input, i)->type) { continue; } - struct mScriptValue* unwrapped = NULL; - if (mScriptListGetPointer(frame, i)->type->base == mSCRIPT_TYPE_WRAPPER) { - unwrapped = mScriptValueUnwrap(mScriptListGetPointer(frame, i)); + const struct mScriptValue* unwrapped = NULL; + if (mScriptListGetConstPointer(input, i)->type->base == mSCRIPT_TYPE_WRAPPER) { + unwrapped = mScriptValueUnwrapConst(mScriptListGetConstPointer(input, i)); if (types->entries[i]->base == mSCRIPT_TYPE_WRAPPER) { if (types->entries[i]->details.type == unwrapped->type) { continue; @@ -1796,7 +1797,12 @@ bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, struct mScriptList continue; } } - if (!mScriptCast(types->entries[i], mScriptListGetPointer(frame, i), mScriptListGetPointer(frame, i))) { + struct mScriptValue fakeVal; + struct mScriptValue* castTo = &fakeVal; + if (output) { + castTo = mScriptListGetPointer(output, i); + } + if (!mScriptCast(types->entries[i], mScriptListGetConstPointer(input, i), castTo)) { return false; } } @@ -1808,11 +1814,26 @@ bool mScriptCoerceFrame(const struct mScriptTypeTuple* types, struct mScriptList if (!types->defaults[i].type) { return false; } - memcpy(mScriptListAppend(frame), &types->defaults[i], sizeof(struct mScriptValue)); + if (output) { + memcpy(mScriptListAppend(output), &types->defaults[i], sizeof(struct mScriptValue)); + } } return true; } +const struct mScriptFunctionOverload* mScriptFunctionFindOverload(const struct mScriptFunctionOverload* overloads, struct mScriptList* frame) { + size_t i; + for (i = 0; overloads[i].type; ++i) { + if (overloads[i].type->base != mSCRIPT_TYPE_FUNCTION) { + continue; + } + if (mScriptCoerceFrame(&overloads[i].type->details.function.parameters, frame, NULL)) { + return &overloads[i]; + } + } + return NULL; +} + static void addTypesFromTuple(struct Table* types, const struct mScriptTypeTuple* tuple) { size_t i; for (i = 0; i < tuple->count; ++i) { diff --git a/src/third-party/blip_buf/blip_buf.c b/src/third-party/blip_buf/blip_buf.c deleted file mode 100644 index 6bc7da8bd..000000000 --- a/src/third-party/blip_buf/blip_buf.c +++ /dev/null @@ -1,344 +0,0 @@ -/* blip_buf 1.1.0. http://www.slack.net/~ant/ */ - -#include - -#include -#include -#include -#include - -/* Library Copyright (C) 2003-2009 Shay Green. 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#if defined (BLARGG_TEST) && BLARGG_TEST - #include "blargg_test.h" -#endif - -/* Equivalent to ULONG_MAX >= 0xFFFFFFFF00000000. -Avoids constants that don't fit in 32 bits. */ -#if ULONG_MAX/0xFFFFFFFF > 0xFFFFFFFF - typedef unsigned long fixed_t; - enum { pre_shift = 32 }; - -#elif defined(ULLONG_MAX) - typedef unsigned long long fixed_t; - enum { pre_shift = 32 }; - -#else - typedef unsigned fixed_t; - enum { pre_shift = 0 }; - -#endif - -enum { time_bits = pre_shift + 20 }; - -static fixed_t const time_unit = (fixed_t) 1 << time_bits; - -enum { bass_shift = 9 }; /* affects high-pass filter breakpoint frequency */ -enum { end_frame_extra = 2 }; /* allows deltas slightly after frame length */ - -enum { half_width = 8 }; -enum { buf_extra = half_width*2 + end_frame_extra }; -enum { phase_bits = 5 }; -enum { phase_count = 1 << phase_bits }; -enum { delta_bits = 15 }; -enum { delta_unit = 1 << delta_bits }; -enum { frac_bits = time_bits - pre_shift }; - -/* We could eliminate avail and encode whole samples in offset, but that would -limit the total buffered samples to blip_max_frame. That could only be -increased by decreasing time_bits, which would reduce resample ratio accuracy. -*/ - -/** Sample buffer that resamples to output rate and accumulates samples -until they're read out */ -struct blip_t -{ - fixed_t factor; - fixed_t offset; - int avail; - int size; - int integrator; -}; - -typedef int buf_t; - -/* probably not totally portable */ -#define SAMPLES( buf ) ((buf_t*) ((buf) + 1)) - -/* Arithmetic (sign-preserving) right shift */ -#define ARITH_SHIFT( n, shift ) \ - ((n) >> (shift)) - -enum { max_sample = +32767 }; -enum { min_sample = -32768 }; - -#define CLAMP( n ) \ - {\ - if ( (short) n != n )\ - n = ARITH_SHIFT( n, 16 ) ^ max_sample;\ - } - -static void check_assumptions( void ) -{ - int n; - - #if INT_MAX < 0x7FFFFFFF || UINT_MAX < 0xFFFFFFFF - #error "int must be at least 32 bits" - #endif - - assert( (-3 >> 1) == -2 ); /* right shift must preserve sign */ - - n = max_sample * 2; - CLAMP( n ); - assert( n == max_sample ); - - n = min_sample * 2; - CLAMP( n ); - assert( n == min_sample ); - - assert( blip_max_ratio <= time_unit ); - assert( blip_max_frame <= (fixed_t) -1 >> time_bits ); -} - -blip_t* blip_new( int size ) -{ - blip_t* m; - assert( size >= 0 ); - - m = (blip_t*) malloc( sizeof *m + (size + buf_extra) * sizeof (buf_t) ); - if ( m ) - { - m->factor = time_unit / blip_max_ratio; - m->size = size; - blip_clear( m ); - check_assumptions(); - } - return m; -} - -void blip_delete( blip_t* m ) -{ - if ( m != NULL ) - { - /* Clear fields in case user tries to use after freeing */ - memset( m, 0, sizeof *m ); - free( m ); - } -} - -void blip_set_rates( blip_t* m, double clock_rate, double sample_rate ) -{ - double factor = time_unit * sample_rate / clock_rate; - m->factor = (fixed_t) factor; - - /* Fails if clock_rate exceeds maximum, relative to sample_rate */ - assert( 0 <= factor - m->factor && factor - m->factor < 1 ); - - /* Avoid requiring math.h. Equivalent to - m->factor = (int) ceil( factor ) */ - if ( m->factor < factor ) - m->factor++; - - /* At this point, factor is most likely rounded up, but could still - have been rounded down in the floating-point calculation. */ -} - -void blip_clear( blip_t* m ) -{ - /* We could set offset to 0, factor/2, or factor-1. 0 is suitable if - factor is rounded up. factor-1 is suitable if factor is rounded down. - Since we don't know rounding direction, factor/2 accommodates either, - with the slight loss of showing an error in half the time. Since for - a 64-bit factor this is years, the halving isn't a problem. */ - - m->offset = m->factor / 2; - m->avail = 0; - m->integrator = 0; - memset( SAMPLES( m ), 0, (m->size + buf_extra) * sizeof (buf_t) ); -} - -int blip_clocks_needed( const blip_t* m, int samples ) -{ - fixed_t needed; - - /* Fails if buffer can't hold that many more samples */ - assert( samples >= 0 && m->avail + samples <= m->size ); - - needed = (fixed_t) samples * time_unit; - if ( needed < m->offset ) - return 0; - - return (needed - m->offset + m->factor - 1) / m->factor; -} - -void blip_end_frame( blip_t* m, unsigned t ) -{ - fixed_t off = t * m->factor + m->offset; - m->avail += off >> time_bits; - m->offset = off & (time_unit - 1); - - /* Fails if buffer size was exceeded */ - assert( m->avail <= m->size ); -} - -int blip_samples_avail( const blip_t* m ) -{ - return m->avail; -} - -static void remove_samples( blip_t* m, int count ) -{ - buf_t* buf = SAMPLES( m ); - int remain = m->avail + buf_extra - count; - m->avail -= count; - - memmove( &buf [0], &buf [count], remain * sizeof buf [0] ); - memset( &buf [remain], 0, count * sizeof buf [0] ); -} - -int blip_read_samples( blip_t* m, short out [], int count, int stereo ) -{ - assert( count >= 0 ); - - if ( count > m->avail ) - count = m->avail; - - if ( count ) - { - int const step = stereo ? 2 : 1; - buf_t const* in = SAMPLES( m ); - buf_t const* end = in + count; - int sum = m->integrator; - do - { - /* Eliminate fraction */ - int s = ARITH_SHIFT( sum, delta_bits ); - - sum += *in++; - - CLAMP( s ); - - *out = s; - out += step; - - /* High-pass filter */ - sum -= s << (delta_bits - bass_shift); - } - while ( in != end ); - m->integrator = sum; - - remove_samples( m, count ); - } - - return count; -} - -/* Things that didn't help performance on x86: - __attribute__((aligned(128))) - #define short int - restrict -*/ - -/* Sinc_Generator( 0.9, 0.55, 4.5 ) */ -static short const bl_step [phase_count + 1] [half_width] = -{ -{ 43, -115, 350, -488, 1136, -914, 5861,21022}, -{ 44, -118, 348, -473, 1076, -799, 5274,21001}, -{ 45, -121, 344, -454, 1011, -677, 4706,20936}, -{ 46, -122, 336, -431, 942, -549, 4156,20829}, -{ 47, -123, 327, -404, 868, -418, 3629,20679}, -{ 47, -122, 316, -375, 792, -285, 3124,20488}, -{ 47, -120, 303, -344, 714, -151, 2644,20256}, -{ 46, -117, 289, -310, 634, -17, 2188,19985}, -{ 46, -114, 273, -275, 553, 117, 1758,19675}, -{ 44, -108, 255, -237, 471, 247, 1356,19327}, -{ 43, -103, 237, -199, 390, 373, 981,18944}, -{ 42, -98, 218, -160, 310, 495, 633,18527}, -{ 40, -91, 198, -121, 231, 611, 314,18078}, -{ 38, -84, 178, -81, 153, 722, 22,17599}, -{ 36, -76, 157, -43, 80, 824, -241,17092}, -{ 34, -68, 135, -3, 8, 919, -476,16558}, -{ 32, -61, 115, 34, -60, 1006, -683,16001}, -{ 29, -52, 94, 70, -123, 1083, -862,15422}, -{ 27, -44, 73, 106, -184, 1152,-1015,14824}, -{ 25, -36, 53, 139, -239, 1211,-1142,14210}, -{ 22, -27, 34, 170, -290, 1261,-1244,13582}, -{ 20, -20, 16, 199, -335, 1301,-1322,12942}, -{ 18, -12, -3, 226, -375, 1331,-1376,12293}, -{ 15, -4, -19, 250, -410, 1351,-1408,11638}, -{ 13, 3, -35, 272, -439, 1361,-1419,10979}, -{ 11, 9, -49, 292, -464, 1362,-1410,10319}, -{ 9, 16, -63, 309, -483, 1354,-1383, 9660}, -{ 7, 22, -75, 322, -496, 1337,-1339, 9005}, -{ 6, 26, -85, 333, -504, 1312,-1280, 8355}, -{ 4, 31, -94, 341, -507, 1278,-1205, 7713}, -{ 3, 35, -102, 347, -506, 1238,-1119, 7082}, -{ 1, 40, -110, 350, -499, 1190,-1021, 6464}, -{ 0, 43, -115, 350, -488, 1136, -914, 5861} -}; - -/* Shifting by pre_shift allows calculation using unsigned int rather than -possibly-wider fixed_t. On 32-bit platforms, this is likely more efficient. -And by having pre_shift 32, a 32-bit platform can easily do the shift by -simply ignoring the low half. */ - -void blip_add_delta( blip_t* m, unsigned time, int delta ) -{ - unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift); - buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits); - - int const phase_shift = frac_bits - phase_bits; - int phase = fixed >> phase_shift & (phase_count - 1); - short const* in = bl_step [phase]; - short const* rev = bl_step [phase_count - phase]; - - int interp = fixed >> (phase_shift - delta_bits) & (delta_unit - 1); - int delta2 = (delta * interp) >> delta_bits; - delta -= delta2; - - /* Fails if buffer size was exceeded */ - assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] ); - - out [0] += in[0]*delta + in[half_width+0]*delta2; - out [1] += in[1]*delta + in[half_width+1]*delta2; - out [2] += in[2]*delta + in[half_width+2]*delta2; - out [3] += in[3]*delta + in[half_width+3]*delta2; - out [4] += in[4]*delta + in[half_width+4]*delta2; - out [5] += in[5]*delta + in[half_width+5]*delta2; - out [6] += in[6]*delta + in[half_width+6]*delta2; - out [7] += in[7]*delta + in[half_width+7]*delta2; - - in = rev; - out [ 8] += in[7]*delta + in[7-half_width]*delta2; - out [ 9] += in[6]*delta + in[6-half_width]*delta2; - out [10] += in[5]*delta + in[5-half_width]*delta2; - out [11] += in[4]*delta + in[4-half_width]*delta2; - out [12] += in[3]*delta + in[3-half_width]*delta2; - out [13] += in[2]*delta + in[2-half_width]*delta2; - out [14] += in[1]*delta + in[1-half_width]*delta2; - out [15] += in[0]*delta + in[0-half_width]*delta2; -} - -void blip_add_delta_fast( blip_t* m, unsigned time, int delta ) -{ - unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift); - buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits); - - int interp = fixed >> (frac_bits - delta_bits) & (delta_unit - 1); - int delta2 = delta * interp; - - /* Fails if buffer size was exceeded */ - assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] ); - - out [7] += delta * delta_unit - delta2; - out [8] += delta2; -} diff --git a/src/third-party/blip_buf/license.txt b/src/third-party/blip_buf/license.txt deleted file mode 100644 index 5faba9d48..000000000 --- a/src/third-party/blip_buf/license.txt +++ /dev/null @@ -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. - - - Copyright (C) - - 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. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/src/third-party/discord-rpc/include/rapidjson/document.h b/src/third-party/discord-rpc/include/rapidjson/document.h index e3e20dfbd..b0f1f70be 100644 --- a/src/third-party/discord-rpc/include/rapidjson/document.h +++ b/src/third-party/discord-rpc/include/rapidjson/document.h @@ -316,8 +316,6 @@ struct GenericStringRef { GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} - GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; } - //! implicit conversion to plain CharType pointer operator const Ch *() const { return s; } diff --git a/src/script/docgen.c b/src/tools/docgen.c similarity index 97% rename from src/script/docgen.c rename to src/tools/docgen.c index f57fb8d44..cdabb472c 100644 --- a/src/script/docgen.c +++ b/src/tools/docgen.c @@ -190,6 +190,14 @@ void explainClass(struct mScriptTypeClass* cls, int level) { fprintf(out, "%s readonly: true\n", indent); } fprintf(out, "%s type: %s\n", indent, details->info.member.type->name); + if (details->info.member.overloads) { + fprintf(out, "%s overloads:\n", indent); + size_t i; + for (i = 0; details->info.member.overloads[i].type; ++i) { + mScriptTypeAdd(&types, details->info.member.overloads[i].type); + fprintf(out, "%s - %s\n", indent, details->info.member.overloads[i].type->name); + } + } break; case mSCRIPT_CLASS_INIT_END: break; diff --git a/src/tools/font-sdf.c b/src/tools/font-sdf.c new file mode 100644 index 000000000..0ddcdc645 --- /dev/null +++ b/src/tools/font-sdf.c @@ -0,0 +1,136 @@ +/* Copyright (c) 2013-2023 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/. */ +#include +#include +#include + +void createSdf(const struct mImage* src, struct mImage* dst, int x, int y, int w, int h) { + int i, j, ii, jj, z; + + static const int kernel[] = { + 11, 9, 8, 9, 11, + 9, 6, 4, 6, 9, + 8, 4, 0, 4, 8, + 9, 6, 4, 6, 9, + 11, 9, 8, 9, 11, + }; + const int* kc = &kernel[12]; + + for (j = y; j < y + h; ++j) { + for (i = x; i < x + w; ++i) { + if (mImageGetPixel(src, i, j) & 0xFFFFFF) { + mImageSetPixelRaw(dst, i, j, 0xFF); + } else { + mImageSetPixelRaw(dst, i, j, 1); + } + } + } + + for (z = 0; z < 16; ++z) { + int left = w * h; + for (j = y; j < y + h; ++j) { + for (i = x; i < x + w; ++i) { + int raw = mImageGetPixelRaw(dst, i, j) - 0x80; + int neighbors = raw; + for (jj = -2; jj < 3; ++jj) { + for (ii = -2; ii < 3; ++ii) { + if (!ii && !jj) { + continue; + } + if (i + ii - x < 0 || j + jj - y < 0) { + continue; + } + if (i + ii - x >= w || j + jj - y >= h) { + continue; + } + int neighbor = mImageGetPixelRaw(dst, i + ii, j + jj) - 0x80; + if (raw > 0) { + if (neighbor < 0) { + if ((!ii && (jj == -1 || jj == 1)) || (!jj && (ii == -1 || ii == 1))) { + neighbors = 1; + jj = 5; + break; + } + continue; + } + if (neighbor == 0x7F) { + continue; + } + if (neighbor + kc[ii + jj * 5] < neighbors) { + neighbors = neighbor + kc[ii + jj * 5]; + } + } else if (raw < 0) { + if (neighbor > 0) { + if ((!ii && (jj == -1 || jj == 1)) || (!jj && (ii == -1 || ii == 1))) { + neighbors = -4; + jj = 5; + break; + } + continue; + } + if (neighbor == -0x7F) { + continue; + } + if (neighbor - kc[ii + jj * 5] > neighbors) { + neighbors = neighbor - kc[ii + jj * 5]; + } + } + } + } + if (neighbors == raw) { + --left; + } else { + mImageSetPixelRaw(dst, i, j, neighbors + 0x80); + } + if (!left) { + break; + } + } + if (!left) { + break; + } + } + if (!left) { + break; + } + } +} + +int main(int argc, char* argv[]) { + struct mImage* source; + struct mImage* output; + + if (argc != 3) { + return 1; + } + source = mImageLoad(argv[1]); + if (!source) { + return 2; + } + output = mImageCreate(source->width, source->height, mCOLOR_L8); + if (!output) { + return 3; + } + + int i; + for (i = 0; i < 128; ++i) { + createSdf(source, output, (i & 0xF) << 6, (i & ~0xF) << 2, 64, 64); + } + for (i = 0; i < GUI_ICON_MAX; ++i) { + struct GUIIconMetric metric = defaultIconMetrics[i]; + metric.width += metric.x & 0xF; + metric.height += metric.y & 0xF; + metric.x &= ~0xF; + metric.y &= ~0xF; + createSdf(source, output, metric.x * 4, metric.y * 4 + 512, toPow2(metric.width) * 4, toPow2(metric.height) * 4); + } + if (!mImageSave(output, argv[2], NULL)) { + return 4; + } + mImageDestroy(source); + mImageDestroy(output); + return 0; +} diff --git a/src/feature/updater-main.c b/src/tools/updater-main.c similarity index 99% rename from src/feature/updater-main.c rename to src/tools/updater-main.c index 6a1e2a822..a27a07a08 100644 --- a/src/feature/updater-main.c +++ b/src/tools/updater-main.c @@ -271,7 +271,7 @@ int main(int argc, char* argv[]) { // Cross-dev, need to copy manually int infd = open(updateArchive, O_RDONLY); int outfd = -1; - if (infd >= 0) { + if (infd < 0) { ok = 2; } else { outfd = open(bin, O_CREAT | O_WRONLY | O_TRUNC, 0755); diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index eb82215d7..2f4ba2dcd 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -6,6 +6,7 @@ set(BASE_SOURCE_FILES formatting.c gbk-table.c hash.c + md5.c string.c table.c vector.c @@ -13,12 +14,15 @@ set(BASE_SOURCE_FILES set(SOURCE_FILES ${BASE_SOURCE_FILES} + audio-buffer.c + audio-resampler.c convolve.c elf-read.c geometry.c image.c image/export.c image/png-io.c + interpolator.c patch.c patch-fast.c patch-ips.c @@ -35,8 +39,10 @@ set(GUI_FILES gui/menu.c) set(TEST_FILES + test/circle-buffer.c test/color.c test/geometry.c + test/hash.c test/image.c test/sfo.c test/string-parser.c diff --git a/src/util/audio-buffer.c b/src/util/audio-buffer.c new file mode 100644 index 000000000..028946b48 --- /dev/null +++ b/src/util/audio-buffer.c @@ -0,0 +1,62 @@ +/* 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/. */ +#include + +#include + +void mAudioBufferInit(struct mAudioBuffer* buffer, size_t capacity, unsigned channels) { + mCircleBufferInit(&buffer->data, capacity * channels * sizeof(int16_t)); + buffer->channels = channels; +} + +void mAudioBufferDeinit(struct mAudioBuffer* buffer) { + mCircleBufferDeinit(&buffer->data); +} + +size_t mAudioBufferAvailable(const struct mAudioBuffer* buffer) { + return mCircleBufferSize(&buffer->data) / (buffer->channels * sizeof(int16_t)); +} + +size_t mAudioBufferCapacity(const struct mAudioBuffer* buffer) { + return mCircleBufferCapacity(&buffer->data) / (buffer->channels * sizeof(int16_t)); +} + +void mAudioBufferClear(struct mAudioBuffer* buffer) { + mCircleBufferClear(&buffer->data); +} + +int16_t mAudioBufferPeek(const struct mAudioBuffer* buffer, unsigned channel, size_t offset) { + int16_t sample; + if (!mCircleBufferDump(&buffer->data, &sample, sizeof(int16_t), (offset * buffer->channels + channel) * sizeof(int16_t))) { + return 0; + } + return sample; +} + +size_t mAudioBufferDump(const struct mAudioBuffer* buffer, int16_t* samples, size_t count, size_t offset) { + return mCircleBufferDump(&buffer->data, + samples, + count * buffer->channels * sizeof(int16_t), + offset * buffer->channels * sizeof(int16_t)) / + (buffer->channels * sizeof(int16_t)); +} + +size_t mAudioBufferRead(struct mAudioBuffer* buffer, int16_t* samples, size_t count) { + return mCircleBufferRead(&buffer->data, samples, count * buffer->channels * sizeof(int16_t)) / + (buffer->channels * sizeof(int16_t)); +} + +size_t mAudioBufferWrite(struct mAudioBuffer* buffer, const int16_t* samples, size_t count) { + size_t free = mCircleBufferCapacity(&buffer->data) - mCircleBufferSize(&buffer->data); + if (count * buffer->channels * sizeof(int16_t) > free) { + if (!free) { + return 0; + } + count = free / (buffer->channels * sizeof(int16_t)); + } + return mCircleBufferWrite(&buffer->data, samples, count * buffer->channels * sizeof(int16_t)) / + (buffer->channels * sizeof(int16_t)); +} diff --git a/src/util/audio-resampler.c b/src/util/audio-resampler.c new file mode 100644 index 000000000..554f4744b --- /dev/null +++ b/src/util/audio-resampler.c @@ -0,0 +1,109 @@ +/* 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/. */ +#include + +#include + +#define MAX_CHANNELS 2 + +struct mAudioResamplerData { + struct mAudioResampler* resampler; + unsigned channel; +}; + +static int16_t _sampleAt(int index, const void* context) { + const struct mAudioResamplerData* data = context; + if (index < 0) { + return 0; + } + return mAudioBufferPeek(data->resampler->source, data->channel, index); +} + +void mAudioResamplerInit(struct mAudioResampler* resampler, enum mInterpolatorType interpType) { + memset(resampler, 0, sizeof(*resampler)); + resampler->interpType = interpType; + switch (interpType) { + case mINTERPOLATOR_SINC: + mInterpolatorSincInit(&resampler->sinc, 0, 0); + resampler->lowWaterMark = resampler->sinc.width; + resampler->highWaterMark = resampler->sinc.width; + break; + case mINTERPOLATOR_COSINE: + mInterpolatorCosineInit(&resampler->cosine, 0); + resampler->lowWaterMark = 0; + resampler->highWaterMark = 1; + break; + } +} + +void mAudioResamplerDeinit(struct mAudioResampler* resampler) { + switch (resampler->interpType) { + case mINTERPOLATOR_SINC: + mInterpolatorSincDeinit(&resampler->sinc); + break; + case mINTERPOLATOR_COSINE: + mInterpolatorCosineDeinit(&resampler->cosine); + break; + } + resampler->source = NULL; + resampler->destination = NULL; +} + +void mAudioResamplerSetSource(struct mAudioResampler* resampler, struct mAudioBuffer* source, double rate, bool consume) { + resampler->source = source; + resampler->sourceRate = rate; + resampler->consume = consume; +} + +void mAudioResamplerSetDestination(struct mAudioResampler* resampler, struct mAudioBuffer* destination, double rate) { + resampler->destination = destination; + resampler->destRate = rate; +} + +size_t mAudioResamplerProcess(struct mAudioResampler* resampler) { + int16_t sampleBuffer[MAX_CHANNELS] = {0}; + double timestep = resampler->sourceRate / resampler->destRate; + double timestamp = resampler->timestamp; + struct mInterpolator* interp = &resampler->interp; + struct mAudioResamplerData context = { + .resampler = resampler, + }; + struct mInterpolationData data = { + .at = _sampleAt, + .context = &context, + }; + + size_t read = 0; + mASSERT(resampler->source->channels <= MAX_CHANNELS); + + while (true) { + if (timestamp + resampler->highWaterMark >= mAudioBufferAvailable(resampler->source)) { + break; + } + if (mAudioBufferAvailable(resampler->destination) == mAudioBufferCapacity(resampler->destination)) { + break; + } + + size_t channel; + for (channel = 0; channel < resampler->source->channels; ++channel) { + context.channel = channel; + sampleBuffer[channel] = interp->interpolate(interp, &data, timestamp, timestep); + } + if (!mAudioBufferWrite(resampler->destination, sampleBuffer, 1)) { + break; + } + timestamp += timestep; + ++read; + } + + if (resampler->consume && timestamp > resampler->lowWaterMark) { + size_t drop = timestamp - resampler->lowWaterMark; + drop = mAudioBufferRead(resampler->source, NULL, drop); + timestamp -= drop; + } + resampler->timestamp = timestamp; + return read; +} diff --git a/src/util/circle-buffer.c b/src/util/circle-buffer.c index c77a71eba..cd13c082f 100644 --- a/src/util/circle-buffer.c +++ b/src/util/circle-buffer.c @@ -6,7 +6,7 @@ #include #ifndef NDEBUG -static int _checkIntegrity(struct CircleBuffer* buffer) { +static int _checkIntegrity(struct mCircleBuffer* buffer) { if ((int8_t*) buffer->writePtr - (int8_t*) buffer->readPtr == (ssize_t) buffer->size) { return 1; } @@ -20,32 +20,32 @@ static int _checkIntegrity(struct CircleBuffer* buffer) { } #endif -void CircleBufferInit(struct CircleBuffer* buffer, unsigned capacity) { +void mCircleBufferInit(struct mCircleBuffer* buffer, unsigned capacity) { buffer->data = malloc(capacity); buffer->capacity = capacity; - CircleBufferClear(buffer); + mCircleBufferClear(buffer); } -void CircleBufferDeinit(struct CircleBuffer* buffer) { +void mCircleBufferDeinit(struct mCircleBuffer* buffer) { free(buffer->data); buffer->data = 0; } -size_t CircleBufferSize(const struct CircleBuffer* buffer) { +size_t mCircleBufferSize(const struct mCircleBuffer* buffer) { return buffer->size; } -size_t CircleBufferCapacity(const struct CircleBuffer* buffer) { +size_t mCircleBufferCapacity(const struct mCircleBuffer* buffer) { return buffer->capacity; } -void CircleBufferClear(struct CircleBuffer* buffer) { +void mCircleBufferClear(struct mCircleBuffer* buffer) { buffer->size = 0; buffer->readPtr = buffer->data; buffer->writePtr = buffer->data; } -int CircleBufferWrite8(struct CircleBuffer* buffer, int8_t value) { +int mCircleBufferWrite8(struct mCircleBuffer* buffer, int8_t value) { int8_t* data = buffer->writePtr; if (buffer->size + sizeof(int8_t) > buffer->capacity) { return 0; @@ -59,25 +59,21 @@ int CircleBufferWrite8(struct CircleBuffer* buffer, int8_t value) { buffer->writePtr = buffer->data; } buffer->size += sizeof(int8_t); -#ifndef NDEBUG - if (!_checkIntegrity(buffer)) { - abort(); - } -#endif + mASSERT_DEBUG(_checkIntegrity(buffer)); return 1; } -int CircleBufferWrite32(struct CircleBuffer* buffer, int32_t value) { +int mCircleBufferWrite32(struct mCircleBuffer* buffer, int32_t value) { int32_t* data = buffer->writePtr; if (buffer->size + sizeof(int32_t) > buffer->capacity) { return 0; } - if ((intptr_t) data & 0x3) { + if (((intptr_t) data & 0x3) || (uintptr_t) data - (uintptr_t) buffer->data > buffer->capacity - sizeof(int32_t)) { int written = 0; - written += CircleBufferWrite8(buffer, ((int8_t*) &value)[0]); - written += CircleBufferWrite8(buffer, ((int8_t*) &value)[1]); - written += CircleBufferWrite8(buffer, ((int8_t*) &value)[2]); - written += CircleBufferWrite8(buffer, ((int8_t*) &value)[3]); + written += mCircleBufferWrite8(buffer, ((int8_t*) &value)[0]); + written += mCircleBufferWrite8(buffer, ((int8_t*) &value)[1]); + written += mCircleBufferWrite8(buffer, ((int8_t*) &value)[2]); + written += mCircleBufferWrite8(buffer, ((int8_t*) &value)[3]); return written; } *data = value; @@ -89,23 +85,19 @@ int CircleBufferWrite32(struct CircleBuffer* buffer, int32_t value) { buffer->writePtr = buffer->data; } buffer->size += sizeof(int32_t); -#ifndef NDEBUG - if (!_checkIntegrity(buffer)) { - abort(); - } -#endif + mASSERT_DEBUG(_checkIntegrity(buffer)); return 4; } -int CircleBufferWrite16(struct CircleBuffer* buffer, int16_t value) { +int mCircleBufferWrite16(struct mCircleBuffer* buffer, int16_t value) { int16_t* data = buffer->writePtr; if (buffer->size + sizeof(int16_t) > buffer->capacity) { return 0; } - if ((intptr_t) data & 0x3) { + if (((intptr_t) data & 0x1) || (uintptr_t) data - (uintptr_t) buffer->data > buffer->capacity - sizeof(int16_t)) { int written = 0; - written += CircleBufferWrite8(buffer, ((int8_t*) &value)[0]); - written += CircleBufferWrite8(buffer, ((int8_t*) &value)[1]); + written += mCircleBufferWrite8(buffer, ((int8_t*) &value)[0]); + written += mCircleBufferWrite8(buffer, ((int8_t*) &value)[1]); return written; } *data = value; @@ -117,15 +109,11 @@ int CircleBufferWrite16(struct CircleBuffer* buffer, int16_t value) { buffer->writePtr = buffer->data; } buffer->size += sizeof(int16_t); -#ifndef NDEBUG - if (!_checkIntegrity(buffer)) { - abort(); - } -#endif + mASSERT_DEBUG(_checkIntegrity(buffer)); return 2; } -size_t CircleBufferWrite(struct CircleBuffer* buffer, const void* input, size_t length) { +size_t mCircleBufferWrite(struct mCircleBuffer* buffer, const void* input, size_t length) { int8_t* data = buffer->writePtr; if (buffer->size + length > buffer->capacity) { return 0; @@ -145,15 +133,18 @@ size_t CircleBufferWrite(struct CircleBuffer* buffer, const void* input, size_t } buffer->size += length; -#ifndef NDEBUG - if (!_checkIntegrity(buffer)) { - abort(); - } -#endif + mASSERT_DEBUG(_checkIntegrity(buffer)); return length; } -int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value) { +size_t mCircleBufferWriteTruncate(struct mCircleBuffer* buffer, const void* input, size_t length) { + if (buffer->size + length > buffer->capacity) { + length = buffer->capacity - buffer->size; + } + return mCircleBufferWrite(buffer, input, length); +} + +int mCircleBufferRead8(struct mCircleBuffer* buffer, int8_t* value) { int8_t* data = buffer->readPtr; if (buffer->size < sizeof(int8_t)) { return 0; @@ -167,23 +158,19 @@ int CircleBufferRead8(struct CircleBuffer* buffer, int8_t* value) { buffer->readPtr = buffer->data; } buffer->size -= sizeof(int8_t); -#ifndef NDEBUG - if (!_checkIntegrity(buffer)) { - abort(); - } -#endif + mASSERT_DEBUG(_checkIntegrity(buffer)); return 1; } -int CircleBufferRead16(struct CircleBuffer* buffer, int16_t* value) { +int mCircleBufferRead16(struct mCircleBuffer* buffer, int16_t* value) { int16_t* data = buffer->readPtr; if (buffer->size < sizeof(int16_t)) { return 0; } - if ((intptr_t) data & 0x3) { + if (((intptr_t) data & 0x1) || (uintptr_t) data - (uintptr_t) buffer->data > buffer->capacity - sizeof(int16_t)) { int read = 0; - read += CircleBufferRead8(buffer, &((int8_t*) value)[0]); - read += CircleBufferRead8(buffer, &((int8_t*) value)[1]); + read += mCircleBufferRead8(buffer, &((int8_t*) value)[0]); + read += mCircleBufferRead8(buffer, &((int8_t*) value)[1]); return read; } *value = *data; @@ -195,25 +182,21 @@ int CircleBufferRead16(struct CircleBuffer* buffer, int16_t* value) { buffer->readPtr = buffer->data; } buffer->size -= sizeof(int16_t); -#ifndef NDEBUG - if (!_checkIntegrity(buffer)) { - abort(); - } -#endif + mASSERT_DEBUG(_checkIntegrity(buffer)); return 2; } -int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value) { +int mCircleBufferRead32(struct mCircleBuffer* buffer, int32_t* value) { int32_t* data = buffer->readPtr; if (buffer->size < sizeof(int32_t)) { return 0; } - if ((intptr_t) data & 0x3) { + if (((intptr_t) data & 0x3) || (uintptr_t) data - (uintptr_t) buffer->data > buffer->capacity - sizeof(int32_t)) { int read = 0; - read += CircleBufferRead8(buffer, &((int8_t*) value)[0]); - read += CircleBufferRead8(buffer, &((int8_t*) value)[1]); - read += CircleBufferRead8(buffer, &((int8_t*) value)[2]); - read += CircleBufferRead8(buffer, &((int8_t*) value)[3]); + read += mCircleBufferRead8(buffer, &((int8_t*) value)[0]); + read += mCircleBufferRead8(buffer, &((int8_t*) value)[1]); + read += mCircleBufferRead8(buffer, &((int8_t*) value)[2]); + read += mCircleBufferRead8(buffer, &((int8_t*) value)[3]); return read; } *value = *data; @@ -225,15 +208,11 @@ int CircleBufferRead32(struct CircleBuffer* buffer, int32_t* value) { buffer->readPtr = buffer->data; } buffer->size -= sizeof(int32_t); -#ifndef NDEBUG - if (!_checkIntegrity(buffer)) { - abort(); - } -#endif + mASSERT_DEBUG(_checkIntegrity(buffer)); return 4; } -size_t CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length) { +size_t mCircleBufferRead(struct mCircleBuffer* buffer, void* output, size_t length) { int8_t* data = buffer->readPtr; if (buffer->size == 0) { return 0; @@ -243,36 +222,47 @@ size_t CircleBufferRead(struct CircleBuffer* buffer, void* output, size_t length } size_t remaining = buffer->capacity - ((int8_t*) data - (int8_t*) buffer->data); if (length <= remaining) { - memcpy(output, data, length); + if (output) { + memcpy(output, data, length); + } if (length == remaining) { buffer->readPtr = buffer->data; } else { buffer->readPtr = (int8_t*) data + length; } } else { - memcpy(output, data, remaining); - memcpy((int8_t*) output + remaining, buffer->data, length - remaining); + if (output) { + memcpy(output, data, remaining); + memcpy((int8_t*) output + remaining, buffer->data, length - remaining); + } buffer->readPtr = (int8_t*) buffer->data + length - remaining; } buffer->size -= length; -#ifndef NDEBUG - if (!_checkIntegrity(buffer)) { - abort(); - } -#endif + mASSERT_DEBUG(_checkIntegrity(buffer)); return length; } -size_t CircleBufferDump(const struct CircleBuffer* buffer, void* output, size_t length) { +size_t mCircleBufferDump(const struct mCircleBuffer* buffer, void* output, size_t length, size_t offset) { int8_t* data = buffer->readPtr; - if (buffer->size == 0) { + if (buffer->size <= offset) { return 0; } - if (length > buffer->size) { - length = buffer->size; + if (length > buffer->size - offset) { + length = buffer->size - offset; } - size_t remaining = buffer->capacity - ((int8_t*) data - (int8_t*) buffer->data); + size_t remaining = buffer->capacity - ((uintptr_t) data - (uintptr_t) buffer->data); + if (offset) { + if (remaining >= offset) { + data += offset; + remaining -= offset; + } else { + offset -= remaining; + data = buffer->data; + data += offset; + } + } + if (length <= remaining) { memcpy(output, data, length); } else { diff --git a/src/util/configuration.c b/src/util/configuration.c index dbcefef8f..8b7320b5c 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -160,6 +160,7 @@ static char* _vfgets(char* stream, int size, void* user) { return 0; } +#ifdef ENABLE_VFS bool ConfigurationRead(struct Configuration* configuration, const char* path) { struct VFile* vf = VFileOpen(path, O_RDONLY); if (!vf) { @@ -170,12 +171,6 @@ bool ConfigurationRead(struct Configuration* configuration, const char* path) { return res; } -bool ConfigurationReadVFile(struct Configuration* configuration, struct VFile* vf) { - HashTableClear(&configuration->root); - HashTableClear(&configuration->sections); - return ini_parse_stream(_vfgets, vf, _iniRead, configuration) == 0; -} - bool ConfigurationWrite(const struct Configuration* configuration, const char* path) { struct VFile* vf = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); if (!vf) { @@ -186,12 +181,6 @@ bool ConfigurationWrite(const struct Configuration* configuration, const char* p return res; } -bool ConfigurationWriteVFile(const struct Configuration* configuration, struct VFile* vf) { - HashTableEnumerate(&configuration->root, _keyHandler, vf); - HashTableEnumerate(&configuration->sections, _sectionHandler, vf); - return true; -} - bool ConfigurationWriteSection(const struct Configuration* configuration, const char* path, const char* section) { const struct Table* currentSection = &configuration->root; struct VFile* vf = VFileOpen(path, O_WRONLY | O_CREAT | O_APPEND); @@ -213,6 +202,19 @@ bool ConfigurationWriteSection(const struct Configuration* configuration, const vf->close(vf); return true; } +#endif + +bool ConfigurationReadVFile(struct Configuration* configuration, struct VFile* vf) { + HashTableClear(&configuration->root); + HashTableClear(&configuration->sections); + return ini_parse_stream(_vfgets, vf, _iniRead, configuration) == 0; +} + +bool ConfigurationWriteVFile(const struct Configuration* configuration, struct VFile* vf) { + HashTableEnumerate(&configuration->root, _keyHandler, vf); + HashTableEnumerate(&configuration->sections, _sectionHandler, vf); + return true; +} void ConfigurationEnumerateSections(const struct Configuration* configuration, void (*handler)(const char* sectionName, void* user), void* user) { struct ConfigurationSectionHandlerData handlerData = { handler, user }; diff --git a/src/util/crc32.c b/src/util/crc32.c index 24f611111..7c1fcda55 100644 --- a/src/util/crc32.c +++ b/src/util/crc32.c @@ -103,7 +103,7 @@ uint32_t doCrc32(const void* buf, size_t size) { #ifndef HAVE_CRC32 uint32_t crc32(uint32_t crc, const void* buf, size_t size) { const uint8_t* p = buf; - + crc = ~crc; for (size_t i = 0; i < size; ++i) { crc = crc32Table[(crc ^ p[i]) & 0xFF] ^ (crc >> 8); diff --git a/src/util/formatting.c b/src/util/formatting.c index e1e1c0bf0..2506ddc9c 100644 --- a/src/util/formatting.c +++ b/src/util/formatting.c @@ -46,26 +46,26 @@ float strtof_l(const char* restrict str, char** restrict end, locale_t locale) { #endif int ftostr_u(char* restrict str, size_t size, float f) { -#if HAVE_LOCALE +#ifdef HAVE_LOCALE locale_t l = newlocale(LC_NUMERIC_MASK, "C", 0); #else locale_t l = "C"; #endif int res = ftostr_l(str, size, f, l); -#if HAVE_LOCALE +#ifdef HAVE_LOCALE freelocale(l); #endif return res; } float strtof_u(const char* restrict str, char** restrict end) { -#if HAVE_LOCALE +#ifdef HAVE_LOCALE locale_t l = newlocale(LC_NUMERIC_MASK, "C", 0); #else locale_t l = "C"; #endif float res = strtof_l(str, end, l); -#if HAVE_LOCALE +#ifdef HAVE_LOCALE freelocale(l); #endif return res; diff --git a/src/util/gui/menu.c b/src/util/gui/menu.c index 584f2d0d5..f0c624f17 100644 --- a/src/util/gui/menu.c +++ b/src/util/gui/menu.c @@ -18,30 +18,33 @@ DEFINE_VECTOR(GUIMenuItemList, struct GUIMenuItem); DEFINE_VECTOR(GUIMenuSavedList, struct GUIMenuSavedState); void _itemNext(struct GUIMenuItem* item, bool wrap) { - if (item->state < item->nStates - 1) { + if (wrap || item->state < item->nStates - 1) { unsigned oldState = item->state; do { ++item->state; + if (item->state >= item->nStates) { + item->state -= item->nStates; + } } while (!item->validStates[item->state] && item->state < item->nStates - 1); if (!item->validStates[item->state]) { item->state = oldState; } - } else if (wrap) { - item->state = 0; } } void _itemPrev(struct GUIMenuItem* item, bool wrap) { - if (item->state > 0) { + if (wrap || item->state > 0) { unsigned oldState = item->state; do { - --item->state; + if (item->state > 0) { + --item->state; + } else { + item->state = item->nStates - 1; + } } while (!item->validStates[item->state] && item->state > 0); if (!item->validStates[item->state]) { item->state = oldState; } - } else if (wrap) { - item->state = item->nStates - 1; } } diff --git a/src/util/hash.c b/src/util/hash.c index ed070e86c..1ac0b56e2 100644 --- a/src/util/hash.c +++ b/src/util/hash.c @@ -69,9 +69,9 @@ uint32_t hash32(const void* key, size_t len, uint32_t seed) { k1 *= c1; k1 = ROTL32(k1, 15); k1 *= c2; - + h1 ^= k1; - h1 = ROTL32(h1, 13); + h1 = ROTL32(h1, 13); h1 = h1 * 5 + 0xe6546b64; } @@ -105,4 +105,4 @@ uint32_t hash32(const void* key, size_t len, uint32_t seed) { h1 = fmix32(h1); return h1; -} +} diff --git a/src/util/image.c b/src/util/image.c index a0fefafe7..e5ee9f9e2 100644 --- a/src/util/image.c +++ b/src/util/image.c @@ -42,6 +42,53 @@ memcpy((void*) (DST), &_color, (DEPTH)); \ } while (0); +static uint32_t _mColorMultiply(uint32_t colorA, uint32_t colorB) { + uint32_t color = 0; + + uint32_t a, b; + a = colorA & 0xFF; + b = colorB & 0xFF; + b = a * b; + b /= 0xFF; + if (b > 0xFF) { + color |= 0xFF; + } else { + color |= b; + } + + a = (colorA >> 8) & 0xFF; + b = (colorB >> 8) & 0xFF; + b = a * b; + b /= 0xFF; + if (b > 0xFF) { + color |= 0xFF00; + } else { + color |= b << 8; + } + + a = (colorA >> 16) & 0xFF; + b = (colorB >> 16) & 0xFF; + b = a * b; + b /= 0xFF; + if (b > 0xFF) { + color |= 0xFF0000; + } else { + color |= b << 16; + } + + a = (colorA >> 24) & 0xFF; + b = (colorB >> 24) & 0xFF; + b = a * b; + b /= 0xFF; + if (b > 0xFF) { + color |= 0xFF000000; + } else { + color |= b << 24; + } + + return color; +} + struct mImage* mImageCreate(unsigned width, unsigned height, enum mColorFormat format) { return mImageCreateWithStride(width, height, width, format); } @@ -85,6 +132,7 @@ struct mImage* mImageCreateFromConstBuffer(unsigned width, unsigned height, unsi return image; } +#ifdef ENABLE_VFS struct mImage* mImageLoad(const char* path) { struct VFile* vf = VFileOpen(path, O_RDONLY); if (!vf) { @@ -94,6 +142,7 @@ struct mImage* mImageLoad(const char* path) { vf->close(vf); return image; } +#endif #ifdef USE_PNG static struct mImage* mImageLoadPNG(struct VFile* vf) { @@ -252,6 +301,7 @@ void mImageDestroy(struct mImage* image) { free(image); } +#ifdef ENABLE_VFS bool mImageSave(const struct mImage* image, const char* path, const char* format) { struct VFile* vf = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); if (!vf) { @@ -267,6 +317,7 @@ bool mImageSave(const struct mImage* image, const char* path, const char* format vf->close(vf); return success; } +#endif #ifdef USE_PNG bool mImageSavePNG(const struct mImage* image, struct VFile* vf) { @@ -395,18 +446,18 @@ void mImageSetPaletteEntry(struct mImage* image, unsigned index, uint32_t color) image->palette[index] = color; } -#define COMPOSITE_BOUNDS_INIT \ +#define COMPOSITE_BOUNDS_INIT(SOURCE, DEST) \ struct mRectangle dstRect = { \ .x = 0, \ .y = 0, \ - .width = image->width, \ - .height = image->height \ + .width = (DEST)->width, \ + .height = (DEST)->height \ }; \ struct mRectangle srcRect = { \ .x = x, \ .y = y, \ - .width = source->width, \ - .height = source->height \ + .width = (SOURCE)->width, \ + .height = (SOURCE)->height \ }; \ if (!mRectangleIntersection(&srcRect, &dstRect)) { \ return; \ @@ -436,7 +487,7 @@ void mImageBlit(struct mImage* image, const struct mImage* source, int x, int y) return; } - COMPOSITE_BOUNDS_INIT; + COMPOSITE_BOUNDS_INIT(source, image); for (y = 0; y < srcRect.height; ++y) { uintptr_t srcPixel = (uintptr_t) PIXEL(source, srcStartX, srcStartY + y); @@ -461,7 +512,7 @@ void mImageComposite(struct mImage* image, const struct mImage* source, int x, i return; } - COMPOSITE_BOUNDS_INIT; + COMPOSITE_BOUNDS_INIT(source, image); for (y = 0; y < srcRect.height; ++y) { uintptr_t srcPixel = (uintptr_t) PIXEL(source, srcStartX, srcStartY + y); @@ -498,7 +549,7 @@ void mImageCompositeWithAlpha(struct mImage* image, const struct mImage* source, alpha = 256; } - COMPOSITE_BOUNDS_INIT; + COMPOSITE_BOUNDS_INIT(source, image); int fixedAlpha = alpha * 0x200; @@ -821,14 +872,41 @@ void mPainterDrawCircle(struct mPainter* painter, int x, int y, int diameter) { } } +void mPainterDrawMask(struct mPainter* painter, const struct mImage* mask, int x, int y) { + if (!painter->fill) { + return; + } + + COMPOSITE_BOUNDS_INIT(mask, painter->backing); + + for (y = 0; y < srcRect.height; ++y) { + uintptr_t dstPixel = (uintptr_t) PIXEL(painter->backing, dstStartX, dstStartY + y); + uintptr_t maskPixel = (uintptr_t) PIXEL(mask, srcStartX, srcStartY + y); + for (x = 0; x < srcRect.width; ++x, dstPixel += painter->backing->depth, maskPixel += mask->depth) { + uint32_t color; + GET_PIXEL(color, maskPixel, mask->depth); + color = mColorConvert(color, mask->format, mCOLOR_ARGB8); + color = _mColorMultiply(painter->fillColor, color); + if (painter->blend || painter->fillColor < 0xFF000000) { + uint32_t current; + GET_PIXEL(current, dstPixel, painter->backing->depth); + current = mColorConvert(current, painter->backing->format, mCOLOR_ARGB8); + color = mColorMixARGB8(color, current); + } + color = mColorConvert(color, mCOLOR_ARGB8, painter->backing->format); + PUT_PIXEL(color, dstPixel, painter->backing->depth); + } + } +} + uint32_t mColorConvert(uint32_t color, enum mColorFormat from, enum mColorFormat to) { if (from == to) { return color; } - int r; - int g; - int b; + int r = 0; + int g = 0; + int b = 0; int a = 0xFF; switch (from) { diff --git a/src/util/image/png-io.c b/src/util/image/png-io.c index e7df1d64f..0207e03a8 100644 --- a/src/util/image/png-io.c +++ b/src/util/image/png-io.c @@ -62,7 +62,7 @@ static png_infop _pngWriteHeader(png_structp png, unsigned width, unsigned heigh } png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height, enum mColorFormat fmt) { - int type; + int type = -1; switch (fmt) { case mCOLOR_XBGR8: case mCOLOR_XRGB8: @@ -94,6 +94,9 @@ png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height, enum type = PNG_COLOR_TYPE_PALETTE; break; } + if (type < 0) { + return NULL; + } return _pngWriteHeader(png, width, height, NULL, 0, type); } @@ -373,6 +376,7 @@ bool PNGWritePixels(png_structp png, unsigned width, unsigned height, unsigned s } else { depth = 3; } + stride *= mColorFormatBytes(fmt); png_bytep row = malloc(sizeof(png_byte) * width * depth); if (!row) { return false; @@ -383,7 +387,6 @@ bool PNGWritePixels(png_structp png, unsigned width, unsigned height, unsigned s return false; } const png_byte* pixelRow = pixelData; - stride *= mColorFormatBytes(fmt); unsigned i; for (i = 0; i < height; ++i, pixelRow += stride) { switch (fmt) { diff --git a/src/util/interpolator.c b/src/util/interpolator.c new file mode 100644 index 000000000..a69d19e81 --- /dev/null +++ b/src/util/interpolator.c @@ -0,0 +1,116 @@ +/* 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/. */ +#include + +enum { + mSINC_RESOLUTION = 8192, + mSINC_WIDTH = 8, + + mCOSINE_RESOLUTION = 8192, +}; + +static int16_t mInterpolatorSincInterpolate(const struct mInterpolator*, const struct mInterpolationData*, double time, double sampleStep); +static int16_t mInterpolatorCosineInterpolate(const struct mInterpolator*, const struct mInterpolationData*, double time, double sampleStep); + +void mInterpolatorSincInit(struct mInterpolatorSinc* interp, unsigned resolution, unsigned width) { + interp->d.interpolate = mInterpolatorSincInterpolate; + + if (!resolution) { + resolution = mSINC_RESOLUTION; + } + if (!width) { + width = mSINC_WIDTH; + } + unsigned samples = resolution * width; + double dy = M_PI / samples; + double y = dy; + double dx = dy * width; + double x = dx; + + interp->sincLut = calloc(samples + 1, sizeof(double)); + interp->windowLut = calloc(samples + 1, sizeof(double)); + + interp->sincLut[0] = 0; + interp->windowLut[0] = 1; + + interp->width = width; + interp->resolution = resolution; + + unsigned i; + for (i = 1; i <= samples; ++i, x += dx, y += dy) { + interp->sincLut[i] = x < width ? sin(x) / x : 0.0; + // Three term Nuttall window with continuous first derivative + interp->windowLut[i] = 0.40897 + 0.5 * cos(y) + 0.09103 * cos(2 * y); + } +} + +void mInterpolatorSincDeinit(struct mInterpolatorSinc* interp) { + free(interp->sincLut); + free(interp->windowLut); +} + +int16_t mInterpolatorSincInterpolate(const struct mInterpolator* interpolator, const struct mInterpolationData* data, double time, double sampleStep) { + struct mInterpolatorSinc* interp = (struct mInterpolatorSinc*) interpolator; + int index = time; + double subsample = time - floor(time); + unsigned step = sampleStep < 1 ? interp->resolution * sampleStep : interp->resolution; + unsigned yShift = subsample * step; + unsigned xShift = subsample * interp->resolution; + double sum = 0.0; + double kernelSum = 0.0; + double kernel; + + int i; + for (i = 1 - (int) interp->width; i <= (int) interp->width; ++i) { + unsigned window = (i >= 0 ? i : -i) * interp->resolution; + if (yShift > window) { + window = yShift - window; + } else { + window -= yShift; + } + + unsigned sinc = (i >= 0 ? i : -i) * step; + if (xShift > sinc) { + sinc = xShift - sinc; + } else { + sinc -= xShift; + } + + kernel = interp->sincLut[sinc] * interp->windowLut[window]; + kernelSum += kernel; + sum += data->at(index + i, data->context) * kernel; + } + return sum / kernelSum; +} + +void mInterpolatorCosineInit(struct mInterpolatorCosine* interp, unsigned resolution) { + interp->d.interpolate = mInterpolatorCosineInterpolate; + + if (!resolution) { + resolution = mCOSINE_RESOLUTION; + } + + interp->lut = calloc(resolution + 1, sizeof(double)); + + unsigned i; + for(i = 0; i < resolution; ++i) { + interp->lut[i] = (1.0 - cos(M_PI * i / resolution) * M_PI) * 0.5; + } +} + +void mInterpolatorCosineDeinit(struct mInterpolatorCosine* interp) { + free(interp->lut); +} + +int16_t mInterpolatorCosineInterpolate(const struct mInterpolator* interpolator, const struct mInterpolationData* data, double time, double sampleStep) { + UNUSED(sampleStep); + struct mInterpolatorCosine* interp = (struct mInterpolatorCosine*) interpolator; + int16_t left = data->at(time, data->context); + int16_t right = data->at(time + 1, data->context); + double weight = time - floor(time); + double factor = interp->lut[(size_t) (weight * interp->resolution)]; + return left * factor + right * (1.0 - factor); +} diff --git a/src/util/md5.c b/src/util/md5.c new file mode 100644 index 000000000..9eaa4903b --- /dev/null +++ b/src/util/md5.c @@ -0,0 +1,228 @@ +/* Copyright (c) 2013-2014 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/. + * + * Based on https://github.com/Zunawe/md5-c + * Originally released under the Unlicense + * + * Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm + */ +#include + +#include + +/* + * Constants defined by the MD5 algorithm + */ +#define A 0x67452301 +#define B 0xEFCDAB89 +#define C 0x98BADCFE +#define D 0x10325476 + +static const uint32_t S[] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }; + +static const uint32_t K[] = { 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, + 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, + 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, + 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, + 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, + 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, + 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, + 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, + 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, + 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, + 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, + 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, + 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, + 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, + 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, + 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 }; + +/* + * Padding used to make the size (in bits) of the input congruent to 448 mod 512 + */ +static const uint8_t PADDING[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* + * Bit-manipulation functions defined by the MD5 algorithm + */ +#define F(X, Y, Z) (((X) & (Y)) | (~(X) & (Z))) +#define G(X, Y, Z) (((X) & (Z)) | ((Y) & ~(Z))) +#define H(X, Y, Z) ((X) ^ (Y) ^ (Z)) +#define I(X, Y, Z) ((Y) ^ ((X) | ~(Z))) + +/* + * Rotates a 32-bit word left by n bits + */ +static uint32_t rotateLeft(uint32_t x, uint32_t n) { + return (x << n) | (x >> (32 - n)); +} + +/* + * Step on 512 bits of input with the main MD5 algorithm. + */ +static void md5Step(uint32_t* buffer, const uint32_t* input) { + uint32_t AA = buffer[0]; + uint32_t BB = buffer[1]; + uint32_t CC = buffer[2]; + uint32_t DD = buffer[3]; + + uint32_t E; + + unsigned j; + + for (unsigned i = 0; i < 64; ++i) { + switch (i / 16) { + case 0: + E = F(BB, CC, DD); + j = i & 0xF; + break; + case 1: + E = G(BB, CC, DD); + j = ((i * 5) + 1) & 0xF; + break; + case 2: + E = H(BB, CC, DD); + j = ((i * 3) + 5) & 0xF; + break; + default: + E = I(BB, CC, DD); + j = (i * 7) & 0xF; + break; + } + + uint32_t temp = DD; + DD = CC; + CC = BB; + BB += rotateLeft(AA + E + K[i] + input[j], S[i]); + AA = temp; + } + + buffer[0] += AA; + buffer[1] += BB; + buffer[2] += CC; + buffer[3] += DD; +} + +/* + * Initialize a context + */ +void md5Init(struct MD5Context* ctx) { + memset(ctx, 0, sizeof(*ctx)); + + ctx->buffer[0] = A; + ctx->buffer[1] = B; + ctx->buffer[2] = C; + ctx->buffer[3] = D; +} + +/* + * Add some amount of input to the context + * + * If the input fills out a block of 512 bits, apply the algorithm (md5Step) + * and save the result in the buffer. Also updates the overall size. + */ +void md5Update(struct MD5Context* ctx, const void* input, size_t len) { + uint32_t buffer[16]; + unsigned offset = ctx->size & 0x3F; + const uint8_t* inputBuffer = input; + ctx->size += len; + + // Copy each byte in input_buffer into the next space in our context input + unsigned i; + for (i = 0; i < len; ++i) { + ctx->input[offset] = inputBuffer[i]; + + // If we've filled our context input, copy it into our local array input + // then reset the offset to 0 and fill in a new buffer. + // Every time we fill out a chunk, we run it through the algorithm + // to enable some back and forth between cpu and i/o + if (offset < 0x3F) { + ++offset; + continue; + } + + unsigned j; + for (j = 0; j < 16; ++j) { + // Convert to little-endian + // The local variable `input` our 512-bit chunk separated into 32-bit words + // we can use in calculations + LOAD_32LE(buffer[j], j * 4, ctx->input); + } + md5Step(ctx->buffer, buffer); + offset = 0; + } +} + +/* + * Pad the current input to get to 448 bits, append the size in bits to the very end, + * and save the result of the final iteration into digest. + */ +void md5Finalize(struct MD5Context* ctx) { + uint32_t input[16]; + int offset = ctx->size & 0x3F; + unsigned paddingLength = offset < 56 ? 56 - offset : (56 + 64) - offset; + + // Fill in the padding and undo the changes to size that resulted from the update + md5Update(ctx, PADDING, paddingLength); + ctx->size -= paddingLength; + + // Do a final update (internal to this function) + // Last two 32-bit words are the two halves of the size (converted from bytes to bits) + unsigned j; + for (j = 0; j < 14; ++j) { + LOAD_32LE(input[j], j * 4, ctx->input); + } + input[14] = (uint32_t) (ctx->size * 8); + input[15] = (uint32_t) ((ctx->size * 8ULL) >> 32); + + md5Step(ctx->buffer, input); + + // Move the result into digest (convert from little-endian) + unsigned i; + for (i = 0; i < 4; ++i) { + STORE_32LE(ctx->buffer[i], i * 4, ctx->digest); + } +} + +void md5Buffer(const void* input, size_t len, uint8_t* result) { + struct MD5Context ctx; + md5Init(&ctx); + md5Update(&ctx, input, len); + md5Finalize(&ctx); + memcpy(result, ctx.digest, sizeof(ctx.digest)); +} + +bool md5File(struct VFile* vf, uint8_t* result) { + struct MD5Context ctx; + uint8_t buffer[2048]; + md5Init(&ctx); + + ssize_t read; + ssize_t position = vf->seek(vf, 0, SEEK_CUR); + if (vf->seek(vf, 0, SEEK_SET) < 0) { + return false; + } + while ((read = vf->read(vf, buffer, sizeof(buffer))) > 0) { + md5Update(&ctx, buffer, read); + } + vf->seek(vf, position, SEEK_SET); + if (read < 0) { + return false; + } + md5Finalize(&ctx); + memcpy(result, ctx.digest, sizeof(ctx.digest)); + return true; +} diff --git a/src/util/patch-ups.c b/src/util/patch-ups.c index bce88e74d..72d0e14a8 100644 --- a/src/util/patch-ups.c +++ b/src/util/patch-ups.c @@ -23,7 +23,7 @@ static size_t _UPSOutputSize(struct Patch* patch, size_t inSize); static bool _UPSApplyPatch(struct Patch* patch, const void* in, size_t inSize, void* out, size_t outSize); static bool _BPSApplyPatch(struct Patch* patch, const void* in, size_t inSize, void* out, size_t outSize); -static size_t _decodeLength(struct VFile* vf, struct CircleBuffer* buffer); +static size_t _decodeLength(struct VFile* vf, struct mCircleBuffer* buffer); bool loadPatchUPS(struct Patch* patch) { patch->vf->seek(patch->vf, 0, SEEK_SET); @@ -77,42 +77,42 @@ bool _UPSApplyPatch(struct Patch* patch, const void* in, size_t inSize, void* ou return false; } - struct CircleBuffer buffer; + struct mCircleBuffer buffer; memcpy(out, in, inSize > outSize ? outSize : inSize); size_t offset = 0; size_t alreadyRead = 0; uint8_t* buf = out; - CircleBufferInit(&buffer, BUFFER_SIZE); + mCircleBufferInit(&buffer, BUFFER_SIZE); while (alreadyRead < filesize + IN_CHECKSUM) { offset += _decodeLength(patch->vf, &buffer); int8_t byte; while (true) { - if (!CircleBufferSize(&buffer)) { + if (!mCircleBufferSize(&buffer)) { uint8_t block[BUFFER_SIZE]; ssize_t read = patch->vf->read(patch->vf, block, sizeof(block)); if (read < 1) { - CircleBufferDeinit(&buffer); + mCircleBufferDeinit(&buffer); return false; } - CircleBufferWrite(&buffer, block, read); + mCircleBufferWrite(&buffer, block, read); } - CircleBufferRead8(&buffer, &byte); + mCircleBufferRead8(&buffer, &byte); if (!byte) { break; } if (offset >= outSize) { - CircleBufferDeinit(&buffer); + mCircleBufferDeinit(&buffer); return false; } buf[offset] ^= byte; ++offset; } ++offset; - alreadyRead = patch->vf->seek(patch->vf, 0, SEEK_CUR) - CircleBufferSize(&buffer); + alreadyRead = patch->vf->seek(patch->vf, 0, SEEK_CUR) - mCircleBufferSize(&buffer); } - CircleBufferDeinit(&buffer); + mCircleBufferDeinit(&buffer); uint32_t goodCrc32; patch->vf->seek(patch->vf, OUT_CHECKSUM, SEEK_END); @@ -223,21 +223,21 @@ bool _BPSApplyPatch(struct Patch* patch, const void* in, size_t inSize, void* ou return true; } -size_t _decodeLength(struct VFile* vf, struct CircleBuffer* buffer) { +size_t _decodeLength(struct VFile* vf, struct mCircleBuffer* buffer) { size_t shift = 1; size_t value = 0; uint8_t byte; while (true) { if (buffer) { - if (!CircleBufferSize(buffer)) { + if (!mCircleBufferSize(buffer)) { uint8_t block[BUFFER_SIZE]; ssize_t read = vf->read(vf, block, sizeof(block)); if (read < 1) { return false; } - CircleBufferWrite(buffer, block, read); + mCircleBufferWrite(buffer, block, read); } - CircleBufferRead8(buffer, (int8_t*) &byte); + mCircleBufferRead8(buffer, (int8_t*) &byte); } else { if (vf->read(vf, &byte, 1) != 1) { break; diff --git a/src/util/sfo.c b/src/util/sfo.c index 90142897b..47d5f2702 100644 --- a/src/util/sfo.c +++ b/src/util/sfo.c @@ -91,7 +91,7 @@ bool SfoAddStrValue(struct Table* sfo, const char* name, const char* value) { HashTableInsert(sfo, name, entry); } entry->type = PSF_TYPE_STR; - entry->data.str = value; + entry->data.str = value; return true; } @@ -161,6 +161,9 @@ bool SfoWrite(struct Table* sfo, struct VFile* vf) { case PSF_TYPE_U32: sortedEntries[i].size = 4; break; + default: + free(sortedEntries); + return false; } } dataSize += ALIGN4(sortedEntries[i].size); @@ -206,9 +209,7 @@ bool SfoWrite(struct Table* sfo, struct VFile* vf) { } } - if (keysSize != ALIGN4(keysOffset) || dataSize != dataOffset) { - abort(); - } + mASSERT(keysSize == ALIGN4(keysOffset) && dataSize == dataOffset); free(sortedEntries); diff --git a/src/util/string.c b/src/util/string.c index 1a2ffe7a4..4a9e35de5 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -177,16 +177,12 @@ size_t toUtf8(uint32_t unichar, char* buffer) { buffer[2] = (unichar & 0x3F) | 0x80; return 3; } - if (unichar < 0x200000) { - buffer[0] = (unichar >> 18) | 0xF0; - buffer[1] = ((unichar >> 12) & 0x3F) | 0x80; - buffer[2] = ((unichar >> 6) & 0x3F) | 0x80; - buffer[3] = (unichar & 0x3F) | 0x80; - return 4; - } - // This shouldn't be possible - return 0; + buffer[0] = (unichar >> 18) | 0xF0; + buffer[1] = ((unichar >> 12) & 0x3F) | 0x80; + buffer[2] = ((unichar >> 6) & 0x3F) | 0x80; + buffer[3] = (unichar & 0x3F) | 0x80; + return 4; } size_t toUtf16(uint32_t unichar, uint16_t* buffer) { @@ -289,9 +285,6 @@ char* latin1ToUtf8(const char* latin1, size_t length) { size_t utf8TotalBytes = 0; size_t utf8Length = 0; for (offset = 0; offset < length; ++offset) { - if (length == 0) { - break; - } uint8_t unichar = latin1[offset]; size_t bytes = toUtf8(unichar, buffer); utf8Length += bytes; diff --git a/src/util/test/circle-buffer.c b/src/util/test/circle-buffer.c new file mode 100644 index 000000000..bff0c9485 --- /dev/null +++ b/src/util/test/circle-buffer.c @@ -0,0 +1,995 @@ +/* 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/. */ +#include "util/test/suite.h" + +#include + +M_TEST_DEFINE(basicCircle) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int8_t i; + for (i = 0; i < 63; ++i) { + assert_int_equal(mCircleBufferWrite8(&buffer, i), 1); + } + for (i = 0; i < 63; ++i) { + int8_t value; + assert_int_equal(mCircleBufferRead8(&buffer, &value), 1); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(basicAlignment16) { + struct mCircleBuffer buffer; + int8_t i8; + + mCircleBufferInit(&buffer, 64); + + // Aligned buffer + int16_t i; + for (i = 0; i < 31; ++i) { + assert_int_equal(mCircleBufferWrite16(&buffer, i), 2); + } + for (i = 0; i < 31; ++i) { + int16_t value; + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + assert_int_equal(value, i); + } + + // Misaligned buffer + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 31; ++i) { + assert_int_equal(mCircleBufferWrite16(&buffer, i), 2); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 31; ++i) { + int16_t value; + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(basicAlignment32) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + // Aligned buffer + int32_t i; + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i), 4); + } + for (i = 0; i < 15; ++i) { + int32_t value; + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i); + } + + // Singly misaligned buffer + int8_t i8; + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i), 4); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 15; ++i) { + int32_t value; + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i); + } + + // Doubly misaligned buffer + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 1), 1); + + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i), 4); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + + for (i = 0; i < 15; ++i) { + int32_t value; + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i); + } + + // Triply misaligned buffer + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 1), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 2), 1); + + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i), 4); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + + for (i = 0; i < 15; ++i) { + int32_t value; + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(capacity) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int8_t i; + for (i = 0; i < 64; ++i) { + assert_int_equal(mCircleBufferWrite8(&buffer, i), 1); + } + for (i = 0; i < 64; ++i) { + int8_t value; + assert_int_equal(mCircleBufferRead8(&buffer, &value), 1); + assert_int_equal(value, i); + } + + for (i = 0; i < 64; ++i) { + assert_int_equal(mCircleBufferWrite8(&buffer, i), 1); + } + assert_int_equal(mCircleBufferWrite8(&buffer, 64), 0); + + for (i = 0; i < 64; ++i) { + int8_t value; + assert_int_equal(mCircleBufferRead8(&buffer, &value), 1); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(overflowWrap8) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int8_t value; + int8_t i; + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &value), 1); + for (i = 0; i < 63; ++i) { + assert_int_equal(mCircleBufferWrite8(&buffer, i), 1); + } + assert_int_equal(mCircleBufferRead8(&buffer, &value), 1); + for (i = 0; i < 63; ++i) { + assert_int_equal(mCircleBufferRead8(&buffer, &value), 1); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(overflowWrap16) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int16_t value; + int16_t i; + assert_int_equal(mCircleBufferWrite16(&buffer, 0), 2); + assert_int_equal(mCircleBufferWrite16(&buffer, 0), 2); + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + for (i = 0; i < 31; ++i) { + assert_int_equal(mCircleBufferWrite16(&buffer, i), 2); + } + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + for (i = 0; i < 31; ++i) { + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(overflowWrap16_1) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int8_t i8; + int16_t value; + int16_t i; + assert_int_equal(mCircleBufferWrite16(&buffer, 0), 2); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + for (i = 0; i < 31; ++i) { + assert_int_equal(mCircleBufferWrite16(&buffer, i), 2); + } + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 31; ++i) { + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(overflowWrap32) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int32_t value; + int32_t i; + assert_int_equal(mCircleBufferWrite32(&buffer, 0), 4); + assert_int_equal(mCircleBufferWrite32(&buffer, 0), 4); + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i), 4); + } + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(overflowWrap32_1) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int8_t i8; + int32_t value; + int32_t i; + assert_int_equal(mCircleBufferWrite32(&buffer, 0), 4); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i), 4); + } + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(overflowWrap32_2) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int16_t i16; + int32_t value; + int32_t i; + assert_int_equal(mCircleBufferWrite32(&buffer, 0), 4); + assert_int_equal(mCircleBufferWrite16(&buffer, 0), 2); + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i), 4); + } + assert_int_equal(mCircleBufferRead16(&buffer, &i16), 2); + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(overflowWrap32_3) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int8_t i8; + int32_t value; + int32_t i; + assert_int_equal(mCircleBufferWrite32(&buffer, 0), 4); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i), 4); + } + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 15; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(weirdSize16) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 15); + + // Aligned, no overflow wrap + int16_t value; + int16_t i; + for (i = 0; i < 7; ++i) { + assert_int_equal(mCircleBufferWrite16(&buffer, i * 0x102), 2); + } + assert_int_equal(mCircleBufferWrite16(&buffer, 7), 0); + for (i = 0; i < 7; ++i) { + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + assert_int_equal(value, i * 0x102); + } + + // Misaligned, no overflow wrap + mCircleBufferClear(&buffer); + int8_t i8; + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 7; ++i) { + assert_int_equal(mCircleBufferWrite16(&buffer, i * 0x102), 2); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 7; ++i) { + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + assert_int_equal(value, i * 0x102); + } + + // Aligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 6; ++i) { + assert_int_equal(mCircleBufferWrite16(&buffer, i * 0x102), 2); + } + assert_int_equal(mCircleBufferWrite16(&buffer, 6 * 0x102), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite16(&buffer, 6 * 0x102), 2); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 7; ++i) { + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + assert_int_equal(value, i * 0x102); + } + + // Misaligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 6; ++i) { + assert_int_equal(mCircleBufferWrite16(&buffer, i * 0x102), 2); + } + assert_int_equal(mCircleBufferWrite16(&buffer, 6 * 0x102), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite16(&buffer, 6 * 0x102), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite16(&buffer, 6 * 0x102), 2); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 7; ++i) { + assert_int_equal(mCircleBufferRead16(&buffer, &value), 2); + assert_int_equal(value, i * 0x102); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(weirdSize32_1) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 13); + + // Aligned, no overflow wrap + int32_t value; + int32_t i; + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 3), 0); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Misaligned, no overflow wrap + mCircleBufferClear(&buffer); + int8_t i8; + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Aligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 2; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 4); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Misaligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 2; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 4); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(weirdSize32_2) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 14); + + // Aligned, no overflow wrap + int32_t value; + int8_t i8; + int32_t i; + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 3), 0); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Singly misaligned, no overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Doubly misaligned, no overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Aligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 2; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 4); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Singly misaligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 2; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 4); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Doubly misaligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 2; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 4); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(weirdSize32_3) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 15); + + // Aligned, no overflow wrap + int32_t value; + int8_t i8; + int32_t i; + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 3), 0); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Singly misaligned, no overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Doubly misaligned, no overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Triply misaligned, no overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Aligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 2; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 4); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Singly misaligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 2; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 4); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Doubly misaligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 2; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 4); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + // Triply misaligned, overflow wrap + mCircleBufferClear(&buffer); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + assert_int_equal(mCircleBufferWrite8(&buffer, 0), 1); + + for (i = 0; i < 2; ++i) { + assert_int_equal(mCircleBufferWrite32(&buffer, i * 0x1020304), 4); + } + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 0); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferWrite32(&buffer, 2 * 0x1020304), 4); + + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + assert_int_equal(mCircleBufferRead8(&buffer, &i8), 1); + for (i = 0; i < 3; ++i) { + assert_int_equal(mCircleBufferRead32(&buffer, &value), 4); + assert_int_equal(value, i * 0x1020304); + } + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(overCapacity16) { + struct mCircleBuffer buffer; + + mCircleBufferInit(&buffer, 64); + + int8_t i; + for (i = 0; i < 63; ++i) { + assert_int_equal(mCircleBufferWrite8(&buffer, i), 1); + } + assert_int_equal(mCircleBufferWrite16(&buffer, 0xFFFF), 0); + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(writeLenCapacity) { + struct mCircleBuffer buffer; + const char* data = " Lorem ipsum dolor sit amet, consectetur adipiscing elit placerat."; + char databuf[64]; + + mCircleBufferInit(&buffer, 64); + + assert_int_equal(mCircleBufferWrite(&buffer, data, 64), 64); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_int_equal(mCircleBufferRead(&buffer, databuf, 64), 64); + assert_int_equal(mCircleBufferSize(&buffer), 0); + assert_memory_equal(data, databuf, 64); + + assert_int_equal(mCircleBufferWrite(&buffer, data, 48), 48); + assert_int_equal(mCircleBufferSize(&buffer), 48); + assert_int_equal(mCircleBufferWrite(&buffer, data, 48), 0); + assert_int_equal(mCircleBufferSize(&buffer), 48); + assert_int_equal(mCircleBufferRead(&buffer, databuf, 64), 48); + assert_memory_equal(data, databuf, 48); + + assert_int_equal(mCircleBufferWrite(&buffer, data, 48), 48); + assert_int_equal(mCircleBufferSize(&buffer), 48); + assert_int_equal(mCircleBufferWrite(&buffer, data, 16), 16); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_int_equal(mCircleBufferRead(&buffer, databuf, 64), 64); + assert_int_equal(mCircleBufferSize(&buffer), 0); + assert_memory_equal(data, databuf, 48); + assert_memory_equal(data, &databuf[48], 16); + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(writeTruncate) { + struct mCircleBuffer buffer; + const char* data = " Lorem ipsum dolor sit amet, consectetur adipiscing elit placerat."; + char databuf[64]; + + mCircleBufferInit(&buffer, 64); + + assert_int_equal(mCircleBufferWriteTruncate(&buffer, data, 64), 64); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_int_equal(mCircleBufferRead(&buffer, databuf, 64), 64); + assert_int_equal(mCircleBufferSize(&buffer), 0); + assert_memory_equal(data, databuf, 64); + + assert_int_equal(mCircleBufferWriteTruncate(&buffer, data, 48), 48); + assert_int_equal(mCircleBufferSize(&buffer), 48); + assert_int_equal(mCircleBufferWrite(&buffer, data, 48), 0); + assert_int_equal(mCircleBufferSize(&buffer), 48); + assert_int_equal(mCircleBufferWriteTruncate(&buffer, data, 48), 16); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_int_equal(mCircleBufferRead(&buffer, databuf, 64), 64); + assert_memory_equal(data, databuf, 48); + assert_memory_equal(data, &databuf[48], 16); + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(dumpBasic) { + struct mCircleBuffer buffer; + const char* data = " Lorem ipsum dolor sit amet, consectetur adipiscing elit placerat."; + char databuf[64]; + + mCircleBufferInit(&buffer, 64); + + assert_int_equal(mCircleBufferWrite(&buffer, data, 64), 64); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 64, 0), 64); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_memory_equal(data, databuf, 64); + assert_int_equal(mCircleBufferRead(&buffer, databuf, 64), 64); + assert_int_equal(mCircleBufferSize(&buffer), 0); + assert_memory_equal(data, databuf, 64); + + assert_int_equal(mCircleBufferWrite(&buffer, data, 48), 48); + assert_int_equal(mCircleBufferSize(&buffer), 48); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 48, 0), 48); + assert_int_equal(mCircleBufferSize(&buffer), 48); + assert_memory_equal(data, databuf, 48); + assert_int_equal(mCircleBufferRead(&buffer, databuf, 16), 16); + assert_int_equal(mCircleBufferSize(&buffer), 32); + assert_memory_equal(data, databuf, 16); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 48, 0), 32); + assert_int_equal(mCircleBufferSize(&buffer), 32); + assert_memory_equal(&data[16], databuf, 32); + + assert_int_equal(mCircleBufferWrite(&buffer, data, 32), 32); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 64, 0), 64); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_memory_equal(&data[16], databuf, 32); + assert_memory_equal(data, &databuf[32], 32); + assert_int_equal(mCircleBufferRead(&buffer, databuf, 64), 64); + assert_memory_equal(&data[16], databuf, 32); + assert_memory_equal(data, &databuf[32], 32); + assert_int_equal(mCircleBufferSize(&buffer), 0); + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(dumpOffset) { + struct mCircleBuffer buffer; + const char* data = " Lorem ipsum dolor sit amet, consectetur adipiscing elit placerat."; + char databuf[64]; + + mCircleBufferInit(&buffer, 64); + + assert_int_equal(mCircleBufferWrite(&buffer, data, 48), 48); + assert_int_equal(mCircleBufferSize(&buffer), 48); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 32, 0), 32); + assert_memory_equal(data, databuf, 32); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 32, 16), 32); + assert_memory_equal(&data[16], databuf, 32); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 32, 32), 16); + assert_memory_equal(&data[32], databuf, 16); + + assert_int_equal(mCircleBufferRead(&buffer, databuf, 16), 16); + assert_int_equal(mCircleBufferSize(&buffer), 32); + assert_memory_equal(data, databuf, 16); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 32, 0), 32); + assert_memory_equal(&data[16], databuf, 32); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 32, 16), 16); + assert_memory_equal(&data[32], databuf, 16); + + assert_int_equal(mCircleBufferWrite(&buffer, data, 32), 32); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 32, 0), 32); + assert_memory_equal(&data[16], databuf, 32); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 32, 16), 32); + assert_memory_equal(&data[32], databuf, 16); + assert_memory_equal(data, &databuf[16], 16); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 32, 32), 32); + assert_memory_equal(data, databuf, 32); + assert_int_equal(mCircleBufferDump(&buffer, databuf, 32, 48), 16); + assert_memory_equal(&data[16], databuf, 16); + + mCircleBufferDeinit(&buffer); +} + +M_TEST_DEFINE(dumpOffsetWrap) { + struct mCircleBuffer buffer; + const char* data = " Lorem ipsum dolor sit amet, consectetur adipiscing elit placerat."; + char databuf[64]; + + mCircleBufferInit(&buffer, 64); + + assert_int_equal(mCircleBufferWrite(&buffer, data, 64), 64); + assert_int_equal(mCircleBufferSize(&buffer), 64); + assert_int_equal(mCircleBufferRead(&buffer, databuf, 48), 48); + assert_memory_equal(data, databuf, 48); + assert_int_equal(mCircleBufferSize(&buffer), 16); + assert_int_equal(mCircleBufferWrite(&buffer, data, 16), 16); + assert_int_equal(mCircleBufferSize(&buffer), 32); + + assert_int_equal(mCircleBufferDump(&buffer, databuf, 64, 0), 32); + assert_memory_equal(&data[48], databuf, 16); + assert_memory_equal(data, &databuf[16], 16); + + assert_int_equal(mCircleBufferDump(&buffer, databuf, 64, 8), 24); + assert_memory_equal(&data[56], databuf, 8); + assert_memory_equal(data, &databuf[8], 16); + + assert_int_equal(mCircleBufferDump(&buffer, databuf, 64, 16), 16); + assert_memory_equal(data, databuf, 16); + + assert_int_equal(mCircleBufferDump(&buffer, databuf, 64, 24), 8); + assert_memory_equal(&data[8], databuf, 8); + + mCircleBufferDeinit(&buffer); +} + +M_TEST_SUITE_DEFINE(mCircleBuffer, + cmocka_unit_test(basicCircle), + cmocka_unit_test(basicAlignment16), + cmocka_unit_test(basicAlignment32), + cmocka_unit_test(capacity), + cmocka_unit_test(overflowWrap8), + cmocka_unit_test(overflowWrap16), + cmocka_unit_test(overflowWrap16_1), + cmocka_unit_test(overflowWrap32), + cmocka_unit_test(overflowWrap32_1), + cmocka_unit_test(overflowWrap32_2), + cmocka_unit_test(overflowWrap32_3), + cmocka_unit_test(weirdSize16), + cmocka_unit_test(weirdSize32_1), + cmocka_unit_test(weirdSize32_2), + cmocka_unit_test(weirdSize32_3), + cmocka_unit_test(overCapacity16), + cmocka_unit_test(writeLenCapacity), + cmocka_unit_test(writeTruncate), + cmocka_unit_test(dumpBasic), + cmocka_unit_test(dumpOffset), + cmocka_unit_test(dumpOffsetWrap), +) diff --git a/src/util/test/hash.c b/src/util/test/hash.c new file mode 100644 index 000000000..6d014435b --- /dev/null +++ b/src/util/test/hash.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2013-2022 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/. */ +#include "util/test/suite.h" + +#include +#include + +M_TEST_DEFINE(emptyCrc32) { + uint8_t buffer[1] = {0}; + assert_int_equal(doCrc32(buffer, 0), 0); +} + +M_TEST_DEFINE(newlineCrc32) { +uint8_t buffer[1] = { '\n' }; + assert_int_equal(doCrc32(buffer, 1), 0x32D70693); +} + +M_TEST_DEFINE(helloWorldCrc32) { + const char* buffer = "Hello, world!"; + assert_int_equal(doCrc32(buffer, strlen(buffer)), 0xEBE6C6E6); +} + +#ifndef HAVE_CRC32 +M_TEST_DEFINE(stagedCrc32) { + uint8_t buffer[1] = { '\n\n' }; + assert_int_equal(crc32(0, buffer, 1), 0x32D70693); + assert_int_equal(crc32(0, buffer, 2), 0x09304EBD); + assert_int_equal(crc32(0x32D70693, buffer, 1), 0x09304EBD); +} +#endif + +M_TEST_DEFINE(emptyMd5) { + uint8_t buffer[1] = {0}; + uint8_t digest[0x10] = {0}; + md5Buffer(buffer, 0, digest); + assert_memory_equal(digest, ((uint8_t[]) { + 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E + }), 16); +} + +M_TEST_DEFINE(newlineMd5) { + uint8_t buffer[1] = { '\n' }; + uint8_t digest[0x10] = {0}; + md5Buffer(buffer, 1, digest); + assert_memory_equal(digest, ((uint8_t[]) { + 0x68, 0xB3, 0x29, 0xDA, 0x98, 0x93, 0xE3, 0x40, + 0x99, 0xC7, 0xD8, 0xAD, 0x5C, 0xB9, 0xC9, 0x40 + }), 16); +} + +M_TEST_DEFINE(fullBlockMd5) { + uint8_t buffer[56] = { + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + }; + uint8_t digest[0x10] = {0}; + md5Buffer(buffer, 56, digest); + assert_memory_equal(digest, ((uint8_t[]) { + 0xA3, 0x31, 0x42, 0x53, 0x78, 0x54, 0xFE, 0xE2, + 0xAF, 0xD6, 0xCF, 0xF4, 0xC5, 0xA1, 0xDD, 0x39 + }), 16); +} + +M_TEST_DEFINE(overflowBlockMd5) { + uint8_t buffer[57] = { + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x0a, + }; + uint8_t digest[0x10] = {0}; + md5Buffer(buffer, 57, digest); + assert_memory_equal(digest, ((uint8_t[]) { + 0xBA, 0x49, 0x77, 0x29, 0x15, 0x5B, 0x13, 0x5D, + 0xBA, 0x27, 0xF3, 0xD8, 0x53, 0xCF, 0xD2, 0x1A + }), 16); +} + +M_TEST_DEFINE(twoBlockMd5) { + uint8_t buffer[120] = { + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + }; + uint8_t digest[0x10] = {0}; + md5Buffer(buffer, 120, digest); + assert_memory_equal(digest, ((uint8_t[]) { + 0xB5, 0x68, 0xA7, 0x7E, 0xD4, 0xC2, 0x39, 0xFB, + 0x4B, 0x74, 0xD7, 0x5B, 0xDB, 0xFD, 0x94, 0x93 + }), 16); +} + +M_TEST_SUITE_DEFINE(Hashes, + cmocka_unit_test(emptyCrc32), + cmocka_unit_test(newlineCrc32), + cmocka_unit_test(helloWorldCrc32), +#ifndef HAVE_CRC32 + cmocka_unit_test(stagedCrc32), +#endif + cmocka_unit_test(emptyMd5), + cmocka_unit_test(newlineMd5), + cmocka_unit_test(fullBlockMd5), + cmocka_unit_test(overflowBlockMd5), + cmocka_unit_test(twoBlockMd5), +) diff --git a/src/util/test/image.c b/src/util/test/image.c index a27e53d5c..e3ea16e24 100644 --- a/src/util/test/image.c +++ b/src/util/test/image.c @@ -2038,6 +2038,97 @@ M_TEST_DEFINE(painterDrawCircleInvalid) { mImageDestroy(image); } +M_TEST_DEFINE(painterDrawMask) { + struct mImage* image; + struct mImage* mask; + struct mPainter painter; + + image = mImageCreate(4, 4, mCOLOR_XRGB8); + mPainterInit(&painter, image); + painter.blend = false; + painter.fill = true; + + mask = mImageCreate(2, 2, mCOLOR_XRGB8); + mImageSetPixel(mask, 0, 0, 0xFFFFFFFF); + mImageSetPixel(mask, 1, 0, 0xFFFF0000); + mImageSetPixel(mask, 0, 1, 0xFF00FF00); + mImageSetPixel(mask, 1, 1, 0xFF0000FF); + + painter.fillColor = 0xFFFFFFFF; + mPainterDrawMask(&painter, mask, 0, 0); + painter.fillColor = 0xFFFF0000; + mPainterDrawMask(&painter, mask, 2, 0); + painter.fillColor = 0xFF00FF00; + mPainterDrawMask(&painter, mask, 0, 2); + painter.fillColor = 0xFF0000FF; + mPainterDrawMask(&painter, mask, 2, 2); + + COMPARE4X(0xFFFFFF, 0xFF0000, 0xFF0000, 0xFF0000, + 0x00FF00, 0x0000FF, 0x000000, 0x000000, + 0x00FF00, 0x000000, 0x0000FF, 0x000000, + 0x00FF00, 0x000000, 0x000000, 0x0000FF); + + painter.fillColor = 0xFF808080; + mPainterDrawMask(&painter, mask, 0, 0); + painter.fillColor = 0xFFFFFF00; + mPainterDrawMask(&painter, mask, 2, 0); + painter.fillColor = 0xFF00FFFF; + mPainterDrawMask(&painter, mask, 0, 2); + painter.fillColor = 0xFFFF00FF; + mPainterDrawMask(&painter, mask, 2, 2); + + COMPARE4X(0x808080, 0x800000, 0xFFFF00, 0xFF0000, + 0x008000, 0x000080, 0x00FF00, 0x000000, + 0x00FFFF, 0x000000, 0xFF00FF, 0xFF0000, + 0x00FF00, 0x0000FF, 0x000000, 0x0000FF); + + painter.fillColor = 0xFFFFFFFF; + mPainterDrawMask(&painter, mask, -1, -1); + mPainterDrawMask(&painter, mask, 3, 3); + assert_int_equal(0xFF0000FF, mImageGetPixel(image, 0, 0)); + assert_int_equal(0xFFFFFFFF, mImageGetPixel(image, 3, 3)); + + mImageDestroy(image); + mImageDestroy(mask); +} + +M_TEST_DEFINE(painterDrawMaskBlend) { + struct mImage* image; + struct mImage* mask; + struct mPainter painter; + const uint8_t lut[4] = { 0x00, 0x55, 0xAA, 0xFF }; + int x, y; + + image = mImageCreate(4, 4, mCOLOR_XRGB8); + mPainterInit(&painter, image); + painter.blend = true; + painter.fill = true; + painter.fillColor = 0xFFFF8000; + + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + mImageSetPixel(image, x, y, 0xFF808080); + } + } + + mask = mImageCreate(4, 4, mCOLOR_ARGB8); + for (y = 0; y < 4; ++y) { + for (x = 0; x < 4; ++x) { + mImageSetPixel(mask, x, y, (lut[x] << 24) | (lut[y] * 0x010101)); + } + } + + mPainterDrawMask(&painter, mask, 0, 0); + + COMPARE4X(0x808080, 0x555555, 0x2A2A2A, 0x000000, + 0x808080, 0x716355, 0x63462A, 0x552A00, + 0x808080, 0x8E7155, 0x9C632A, 0xAA5500, + 0x808080, 0xAA8055, 0xD4802A, 0xFF8000); + + mImageDestroy(image); + mImageDestroy(mask); +} + #undef COMPARE3X #undef COMPARE3 #undef COMPARE4X @@ -2083,4 +2174,6 @@ M_TEST_SUITE_DEFINE(Image, cmocka_unit_test(painterDrawCircleOffset), cmocka_unit_test(painterDrawCircleBlend), cmocka_unit_test(painterDrawCircleInvalid), + cmocka_unit_test(painterDrawMask), + cmocka_unit_test(painterDrawMaskBlend), ) diff --git a/src/util/test/vfs.c b/src/util/test/vfs.c index 4fd995275..2d1cfd56a 100644 --- a/src/util/test/vfs.c +++ b/src/util/test/vfs.c @@ -7,7 +7,7 @@ #include -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#ifdef ENABLE_VFS M_TEST_DEFINE(openNullPathR) { struct VFile* vf = VFileOpen(NULL, O_RDONLY); assert_null(vf); @@ -146,7 +146,7 @@ M_TEST_DEFINE(mapMemChunk) { } M_TEST_SUITE_DEFINE(VFS, -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#ifdef ENABLE_VFS cmocka_unit_test(openNullPathR), cmocka_unit_test(openNullPathW), cmocka_unit_test(openNullPathCreate), diff --git a/src/util/vector.c b/src/util/vector.c index 28750a1b4..f84838a16 100644 --- a/src/util/vector.c +++ b/src/util/vector.c @@ -6,6 +6,7 @@ #include DEFINE_VECTOR(IntList, int); +DEFINE_VECTOR(UIntList, unsigned); DEFINE_VECTOR(SInt8List, int8_t); DEFINE_VECTOR(SInt16List, int16_t); DEFINE_VECTOR(SInt32List, int32_t); diff --git a/src/util/vfs.c b/src/util/vfs.c index d99f5020f..a14100bbf 100644 --- a/src/util/vfs.c +++ b/src/util/vfs.c @@ -18,8 +18,9 @@ #include #endif +#ifdef ENABLE_VFS struct VFile* VFileOpen(const char* path, int flags) { -#ifdef USE_VFS_FILE +#ifdef ENABLE_VFS_FILE const char* chflags; switch (flags & O_ACCMODE) { case O_WRONLY: @@ -67,7 +68,7 @@ struct VFile* VFileOpen(const char* path, int flags) { sceFlags |= SCE_O_CREAT; } return VFileOpenSce(path, sceFlags, 0666); -#elif defined(USE_VFS_3DS) +#elif defined(ENABLE_VFS_3DS) int ctrFlags = FS_OPEN_READ; switch (flags & O_ACCMODE) { case O_WRONLY: @@ -95,8 +96,10 @@ struct VFile* VFileOpen(const char* path, int flags) { vf->seek(vf, vf->size(vf), SEEK_SET); } return vf; -#else +#elif defined(ENABLE_VFS_FD) return VFileOpenFD(path, flags); +#else +#error "Can't build VFS subsystem without a VFile backend" #endif } @@ -115,6 +118,7 @@ struct VDir* VDirOpenArchive(const char* path) { #endif return dir; } +#endif ssize_t VFileReadline(struct VFile* vf, char* buffer, size_t size) { size_t bytesRead = 0; @@ -246,6 +250,7 @@ void makeAbsolute(const char* path, const char* base, char* out) { strncpy(out, buf, PATH_MAX); } +#ifdef ENABLE_VFS struct VFile* VDirFindFirst(struct VDir* dir, bool (*filter)(struct VFile*)) { dir->rewind(dir); struct VDirEntry* dirent = dir->listNext(dir); @@ -310,3 +315,4 @@ struct VFile* VDirFindNextAvailable(struct VDir* dir, const char* basename, cons path[PATH_MAX - 1] = '\0'; return dir->openFile(dir, path, mode); } +#endif diff --git a/src/util/vfs/vfs-devlist.c b/src/util/vfs/vfs-devlist.c index 667ffd193..8f61d49c8 100644 --- a/src/util/vfs/vfs-devlist.c +++ b/src/util/vfs/vfs-devlist.c @@ -20,7 +20,7 @@ static enum VFSType _vdleType(struct VDirEntry* vde); struct VDirEntryDevList { struct VDirEntry d; size_t index; - char* name; + char name[PATH_MAX + 1]; }; struct VDirDevList { @@ -31,7 +31,7 @@ struct VDirDevList { struct VDir* VDeviceList() { struct VDirDevList* vd = malloc(sizeof(struct VDirDevList)); if (!vd) { - return 0; + return NULL; } vd->d.close = _vdlClose; @@ -44,50 +44,42 @@ struct VDir* VDeviceList() { vd->vde.d.name = _vdleName; vd->vde.d.type = _vdleType; vd->vde.index = 0; - vd->vde.name = 0; + vd->vde.name[0] = '\0'; return &vd->d; } static bool _vdlClose(struct VDir* vd) { struct VDirDevList* vdl = (struct VDirDevList*) vd; - free(vdl->vde.name); free(vdl); return true; } static void _vdlRewind(struct VDir* vd) { struct VDirDevList* vdl = (struct VDirDevList*) vd; - free(vdl->vde.name); - vdl->vde.name = 0; - vdl->vde.index = 3; + vdl->vde.name[0] = '\0'; + vdl->vde.index = 0; } static struct VDirEntry* _vdlListNext(struct VDir* vd) { struct VDirDevList* vdl = (struct VDirDevList*) vd; - if (vdl->vde.name) { - ++vdl->vde.index; - free(vdl->vde.name); - vdl->vde.name = 0; - } while (vdl->vde.index < STD_MAX) { const devoptab_t *devops = devoptab_list[vdl->vde.index]; - if (devops->dirStateSize > 0) { - vdl->vde.name = malloc(strlen(devops->name) + 3); - sprintf(vdl->vde.name, "%s:", devops->name); - return &vdl->vde.d; - } - ++vdl->vde.index; + if (!devops || !devops->name || devops->dirStateSize <= 0) { + continue; + } + snprintf(vdl->vde.name, sizeof(vdl->vde.name), "%s:", devops->name); + return &vdl->vde.d; } - return 0; + return NULL; } static struct VFile* _vdlOpenFile(struct VDir* vd, const char* path, int mode) { UNUSED(vd); UNUSED(path); UNUSED(mode); - return 0; + return NULL; } static struct VDir* _vdlOpenDir(struct VDir* vd, const char* path) { diff --git a/src/util/vfs/vfs-fifo.c b/src/util/vfs/vfs-fifo.c index 5b6af5760..c7bb5be04 100644 --- a/src/util/vfs/vfs-fifo.c +++ b/src/util/vfs/vfs-fifo.c @@ -8,7 +8,7 @@ struct VFileFIFO { struct VFile d; - struct CircleBuffer* backing; + struct mCircleBuffer* backing; }; static bool _vffClose(struct VFile* vf); @@ -21,7 +21,7 @@ static void _vffTruncate(struct VFile* vf, size_t size); static ssize_t _vffSize(struct VFile* vf); static bool _vffSync(struct VFile* vf, void* buffer, size_t size); -struct VFile* VFileFIFO(struct CircleBuffer* backing) { +struct VFile* VFileFIFO(struct mCircleBuffer* backing) { if (!backing) { return NULL; } @@ -61,12 +61,12 @@ static off_t _vffSeek(struct VFile* vf, off_t offset, int whence) { static ssize_t _vffRead(struct VFile* vf, void* buffer, size_t size) { struct VFileFIFO* vff = (struct VFileFIFO*) vf; - return CircleBufferRead(vff->backing, buffer, size); + return mCircleBufferRead(vff->backing, buffer, size); } static ssize_t _vffWrite(struct VFile* vf, const void* buffer, size_t size) { struct VFileFIFO* vff = (struct VFileFIFO*) vf; - return CircleBufferWrite(vff->backing, buffer, size); + return mCircleBufferWrite(vff->backing, buffer, size); } static void* _vffMap(struct VFile* vf, size_t size, int flags) { @@ -85,13 +85,13 @@ static void _vffUnmap(struct VFile* vf, void* memory, size_t size) { static void _vffTruncate(struct VFile* vf, size_t size) { struct VFileFIFO* vff = (struct VFileFIFO*) vf; if (!size) { - CircleBufferClear(vff->backing); + mCircleBufferClear(vff->backing); } } static ssize_t _vffSize(struct VFile* vf) { struct VFileFIFO* vff = (struct VFileFIFO*) vf; - return CircleBufferSize(vff->backing); + return mCircleBufferSize(vff->backing); } static bool _vffSync(struct VFile* vf, void* buffer, size_t size) { diff --git a/src/util/vfs/vfs-lzma.c b/src/util/vfs/vfs-lzma.c index a094c187a..c9f88411d 100644 --- a/src/util/vfs/vfs-lzma.c +++ b/src/util/vfs/vfs-lzma.c @@ -7,7 +7,9 @@ #ifdef USE_LZMA +#include #include +#include #include "third-party/lzma/7z.h" #include "third-party/lzma/7zAlloc.h" @@ -26,15 +28,19 @@ struct VDirEntry7z { char* utf8; }; +struct VDir7zAlloc { + ISzAlloc d; + struct Table allocs; +}; + struct VDir7z { struct VDir d; struct VDirEntry7z dirent; - // What is all this garbage? CFileInStream archiveStream; CLookToRead2 lookStream; CSzArEx db; - ISzAlloc allocImp; + struct VDir7zAlloc allocImp; ISzAlloc allocTempImp; }; @@ -70,6 +76,43 @@ static bool _vd7zDeleteFile(struct VDir* vd, const char* path); static const char* _vde7zName(struct VDirEntry* vde); static enum VFSType _vde7zType(struct VDirEntry* vde); +static void* _vd7zAlloc(ISzAllocPtr p, size_t size) { + struct VDir7zAlloc* alloc = (struct VDir7zAlloc*) p; + void* address; + if (size >= 0x10000) { + address = anonymousMemoryMap(size); + } else { + address = malloc(size); + } + if (address) { + TableInsert(&alloc->allocs, (uintptr_t) address >> 2, (void*) size); + } + return address; +} + +static void _vd7zFree(ISzAllocPtr p, void* address) { + struct VDir7zAlloc* alloc = (struct VDir7zAlloc*) p; + size_t size = (size_t) TableLookup(&alloc->allocs, (uintptr_t) address >> 2); + if (size) { + TableRemove(&alloc->allocs, (uintptr_t) address >> 2); + if (size >= 0x10000) { + mappedMemoryFree(address, size); + } else { + free(address); + } + } +} + +static void* _vd7zAllocTemp(ISzAllocPtr p, size_t size) { + UNUSED(p); + return malloc(size); +} + +static void _vd7zFreeTemp(ISzAllocPtr p, void* address) { + UNUSED(p); + free(address); +} + struct VDir* VDirOpen7z(const char* path, int flags) { if (flags & O_WRONLY || flags & O_CREAT) { return 0; @@ -83,11 +126,12 @@ struct VDir* VDirOpen7z(const char* path, int flags) { return 0; } - vd->allocImp.Alloc = SzAlloc; - vd->allocImp.Free = SzFree; + vd->allocImp.d.Alloc = _vd7zAlloc; + vd->allocImp.d.Free = _vd7zFree; + TableInit(&vd->allocImp.allocs, 0, NULL); - vd->allocTempImp.Alloc = SzAllocTemp; - vd->allocTempImp.Free = SzFreeTemp; + vd->allocTempImp.Alloc = _vd7zAllocTemp; + vd->allocTempImp.Free = _vd7zFreeTemp; FileInStream_CreateVTable(&vd->archiveStream); LookToRead2_CreateVTable(&vd->lookStream, False); @@ -101,11 +145,12 @@ struct VDir* VDirOpen7z(const char* path, int flags) { CrcGenerateTable(); SzArEx_Init(&vd->db); - SRes res = SzArEx_Open(&vd->db, &vd->lookStream.vt, &vd->allocImp, &vd->allocTempImp); + SRes res = SzArEx_Open(&vd->db, &vd->lookStream.vt, &vd->allocImp.d, &vd->allocTempImp); if (res != SZ_OK) { - SzArEx_Free(&vd->db, &vd->allocImp); + SzArEx_Free(&vd->db, &vd->allocImp.d); File_Close(&vd->archiveStream.file); free(vd->lookStream.buf); + TableDeinit(&vd->allocImp.allocs); free(vd); return 0; } @@ -128,7 +173,7 @@ struct VDir* VDirOpen7z(const char* path, int flags) { bool _vf7zClose(struct VFile* vf) { struct VFile7z* vf7z = (struct VFile7z*) vf; - IAlloc_Free(&vf7z->vd->allocImp, vf7z->outBuffer); + IAlloc_Free(&vf7z->vd->allocImp.d, vf7z->outBuffer); free(vf7z); return true; } @@ -215,12 +260,13 @@ ssize_t _vf7zSize(struct VFile* vf) { bool _vd7zClose(struct VDir* vd) { struct VDir7z* vd7z = (struct VDir7z*) vd; - SzArEx_Free(&vd7z->db, &vd7z->allocImp); + SzArEx_Free(&vd7z->db, &vd7z->allocImp.d); File_Close(&vd7z->archiveStream.file); free(vd7z->lookStream.buf); free(vd7z->dirent.utf8); vd7z->dirent.utf8 = 0; + TableDeinit(&vd7z->allocImp.allocs); free(vd7z); return true; @@ -292,7 +338,7 @@ struct VFile* _vd7zOpenFile(struct VDir* vd, const char* path, int mode) { SRes res = SzArEx_Extract(&vd7z->db, &vd7z->lookStream.vt, i, &blockIndex, &vf->outBuffer, &outBufferSize, &vf->bufferOffset, &vf->size, - &vd7z->allocImp, &vd7z->allocTempImp); + &vd7z->allocImp.d, &vd7z->allocTempImp); if (res != SZ_OK) { free(vf); diff --git a/src/util/vfs/vfs-zip.c b/src/util/vfs/vfs-zip.c index 65e1c1e32..bd803d7bb 100644 --- a/src/util/vfs/vfs-zip.c +++ b/src/util/vfs/vfs-zip.c @@ -309,9 +309,7 @@ ssize_t _vfzRead(struct VFile* vf, void* buffer, size_t size) { if (!vfz->buffer) { vfz->bufferSize = BLOCK_SIZE; vfz->buffer = malloc(BLOCK_SIZE); - if (vfz->readSize) { - abort(); - } + mASSERT(!vfz->readSize); } while (bytesRead < size) { diff --git a/tools/deploy-mac.py b/tools/deploy-mac.py index 82b8df4f2..89369d163 100755 --- a/tools/deploy-mac.py +++ b/tools/deploy-mac.py @@ -130,6 +130,8 @@ if __name__ == '__main__': parser.add_argument('-I', '--install-name-tool', metavar='INSTALL_NAME_TOOL', default='install_name_tool', help='path to install_name_tool') parser.add_argument('-O', '--otool', metavar='OTOOL', default='otool', help='path to otool') parser.add_argument('-p', '--qt-plugins', metavar='PLUGINS', default='', help='Qt plugins to include (comma-separated)') + parser.add_argument('-s', '--sign', metavar='IDENTITY', help='sign with a given identity') + parser.add_argument('-E', '--entitlements', metavar='ENTITLEMENTS', help='use a given file for entitlements when signing') parser.add_argument('-v', '--verbose', action='store_true', default=False, help='output more information') parser.add_argument('bundle', help='application bundle to deploy') args = parser.parse_args() @@ -168,3 +170,9 @@ if __name__ == '__main__': newPath = os.path.join(newDir, plug) shutil.copy2(os.path.join(qtPath, 'plugins', plugin), newPath) updateMachO(newPath, splitPath(os.path.join(args.bundle, 'Contents/MacOS')), splitPath(args.root)) + if args.sign: + args = ['codesign', '-s', args.sign, '-vf', '-o', 'runtime'] + if args.entitlements: + args.extend(['--entitlements', args.entitlements]) + args.append(args.bundle) + subprocess.check_call(args)