diff --git a/CHANGES b/CHANGES
index 10677d6ea..aa28a7c30 100644
--- a/CHANGES
+++ b/CHANGES
@@ -21,17 +21,72 @@ Misc:
0.7.0: (Future)
Features:
- ELF support
+ - Game Boy Camera support
+ - Qt: Set default Game Boy colors
+ - Game Boy Printer support
+ - Super Game Boy support
+ - Customizable autofire speed
+ - Ability to set default Game Boy model
+ - Map viewer
Bugfixes:
- GB Audio: Make audio unsigned with bias (fixes mgba.io/i/749)
- - Python: Fix importing .gb or .gba before .core
- - GBA: Reset active region as needed when loading a ROM
- - Qt: Fix command line debugger closing second game
+ - GB Serialize: Fix audio state loading
+ - GB Video: Fix dot clock timing being slightly wrong
+ - Qt: Fix GL display when loading a game from CLI (fixes mgba.io/i/843)
+ - ARM: Fix MSR when T bit is set
+ - GB Serialize: Fix game title check
+ - GB: Revamp IRQ handling based on new information
Misc:
- GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
- All: Make FIXED_ROM_BUFFER an option instead of 3DS-only
- - Qt: Don't rebuild library view if style hasn't changed
- Qt: Redo GameController into multiple classes
+ - Test: Restructure test suite into multiple executables
+ - Python: Integrate tests from cinema test suite
+ - Util: Don't build crc32 if the function already exists
+
+0.6.1: (2017-10-01)
+Bugfixes:
+ - GB, GBA: Fix crashes when attempting to identify null VFiles
+ - GB, GBA: Fix sync to video with frameskip
+ - GB, GBA Savedata: Fix savestate-related save overwriting (fixes mgba.io/i/834)
+ - GB Audio: Fix NRx2 writes while active (fixes mgba.io/i/866)
+ - GB Core: Fix palette loading when loading a foreign config
+ - GB MBC: Pocket Cam memory should be accessible without enabling
+ - GB MBC: Fix SRAM sizes 4 and 5
+ - GB MBC: Fix RTC initialization (fixes mgba.io/i/825)
+ - GB MBC: Fix RTC loading when file size is off
+ - GB Memory: Initialize peripheral pointers
+ - GB Memory: Prevent accessing empty SRAM (fixes mgba.io/i/831)
+ - GB Memory: Fix HDMA count starting in mode 0 (fixes mgba.io/i/855)
+ - GB Memory: Actually load latch time from savestate
+ - GB Serialize: Fix deserializing video STAT
+ - GB Video: Fix 16-bit screenshots (fixes mgba.io/i/826)
+ - GB Video: Fix potential hang when ending mode 0
+ - GB Video: Fix read mode when enabling LCD
+ - GBA: Reset active region as needed when loading a ROM
+ - GBA: Fix keypad IRQs not firing when extra buttons are pressed
+ - GBA BIOS: Use core's VRAM variable instead of renderer's
+ - GBA Cheats: Fix PARv3 multiline blocks (fixes mgba.io/i/889)
+ - GBA I/O: Fix reading from a few invalid I/O registers (fixes mgba.io/i/876)
+ - GBA Savedata: Fix 512 byte EEPROM saving as 8kB (fixes mgba.io/i/877)
+ - GBA Savedata: Fix size of SRAM saves (fixes mgba.io/i/883)
+ - GBA Video: Fix broken sprite blending hack (fixes mgba.io/i/532)
+ - Python: Fix importing .gb or .gba before .core
+ - Qt: Fix command line debugger closing second game
+ - Qt: Fix LOG argument order
+ - Qt: Fix timezone issues with time overrides
+ - Qt: Fix sprite export pausing game indefinitely (fixes mgba.io/i/841)
+ - SDL: Fix potential race condition when pressing keys (fixes mgba.io/i/872)
+Misc:
+ - CMake: Fix CPack dependencies for libpng 1.6
+ - GBA: Detect hardware for Pokémon FireRed ROM hacks
+ - GBA Cheats: Improve detection of raw cheats
+ - Qt: Don't rebuild library view if style hasn't changed
+ - Qt: Allow overrides to be saved before a game is loaded
+ - Qt: Hide mouse immediately when loading
+ - SDL: Fix 2.0.5 build on macOS under some circumstances
+ - VFS: Make VFile.truncate work growing files on PSV (fixes mgba.io/i/885)
0.6.0: (2017-07-16)
Features:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2f35e04c4..9dfecec0e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,7 +59,7 @@ file(GLOB GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/gui/*.c ${CMAKE_CURRENT_S
file(GLOB GBA_RENDERER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/renderers/*.c)
file(GLOB GBA_SIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/sio/lockstep.c)
file(GLOB GBA_EXTRA_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/extra/*.c)
-file(GLOB GB_SIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/sio/lockstep.c)
+file(GLOB GB_SIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/sio/*.c)
file(GLOB GB_RENDERER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/renderers/*.c)
file(GLOB GB_EXTRA_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/extra/*.c)
file(GLOB DS_RENDERER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/renderers/*.c ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/gx/*.c)
@@ -129,6 +129,7 @@ function(find_feature FEATURE_NAME FEATURE_REQUIRES)
set(${UREQUIRE}_CFLAGS_OTHER ${${REQUIRE}_CFLAGS_OTHER} PARENT_SCOPE)
set(${UREQUIRE}_FOUND ${${REQUIRE}_FOUND} PARENT_SCOPE)
set(${UREQUIRE}_INCLUDE_DIRS ${${REQUIRE}_INCLUDE_DIRS} PARENT_SCOPE)
+ set(${UREQUIRE}_VERSION_STRING ${${REQUIRE}_VERSION_STRING} PARENT_SCOPE)
if (APPLE)
set(IS_FRAMEWORK OFF)
set(LIBS)
@@ -518,6 +519,14 @@ if(USE_ZLIB)
include_directories(AFTER ${ZLIB_INCLUDE_DIRS})
list(APPEND DEPENDENCY_LIB ${ZLIB_LIBRARIES})
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},zlib1g")
+ set(HAVE_CRC32 ON)
+else()
+ # zlib pulls in crc32
+ check_function_exists(crc32 HAVE_CRC32)
+endif()
+
+if(HAVE_CRC32)
+ list(APPEND FUNCTION_DEFINES HAVE_CRC32)
endif()
if(WANT_PNG AND USE_ZLIB AND NOT USE_PNG)
@@ -536,7 +545,15 @@ if(USE_PNG)
list(APPEND FEATURES PNG)
include_directories(AFTER ${PNG_INCLUDE_DIRS})
list(APPEND DEPENDENCY_LIB ${PNG_LIBRARIES} ${ZLIB_LIBRARIES})
- set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libpng12-0")
+ if(PNG_VERSION_STRING)
+ string(REGEX MATCH "^[0-9]+\\.[0-9]+" PNG_VERSION_PARTIAL ${PNG_VERSION_STRING})
+ if(${PNG_VERSION_PARTIAL} STREQUAL "1.6")
+ set(PNG_DEB_VERSION "16-16")
+ else()
+ set(PNG_DEB_VERSION "12-0")
+ endif()
+ set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libpng${PNG_DEB_VERSION}")
+ endif()
endif()
if(WANT_SQLITE3 AND NOT USE_SQLITE3)
@@ -625,10 +642,6 @@ endif()
if(USE_ELF)
list(APPEND FEATURES ELF)
include_directories(AFTER ${LIBELF_INCLUDE_DIRS})
- find_file(ELF_REPL_H elf_repl.h PATHS ${LIBELF_INCLUDE_DIRS} NO_CMAKE_FIND_ROOT_PATH)
- if (ELF_REPL_H)
- add_definitions(-DUSE_ELF_REPL)
- endif()
list(APPEND DEPENDENCY_LIB ${LIBELF_LIBRARIES})
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libelfg0")
endif()
@@ -637,8 +650,7 @@ if(ENABLE_SCRIPTING)
list(APPEND ENABLES SCRIPTING)
if(BUILD_PYTHON)
- find_program(PYTHON python)
- include(FindPythonLibs)
+ find_package(PythonLibs ${USE_PYTHON_VERSION})
list(APPEND DEPENDENCY_LIB ${PYTHON_LIBRARIES})
include_directories(AFTER ${PYTHON_INCLUDE_DIRS})
list(APPEND ENABLES PYTHON)
@@ -892,10 +904,16 @@ if(BUILD_SUITE)
include_directories(AFTER ${CMOCKA_INCLUDE_DIRS})
link_directories(${CMOCKA_LIBRARY_DIRS})
- add_executable(${BINARY_NAME}-suite ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/test/suite-main.c ${TEST_SRC})
- target_link_libraries(${BINARY_NAME}-suite ${BINARY_NAME} ${PLATFORM_LIBRARY} cmocka)
- set_target_properties(${BINARY_NAME}-suite PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
- add_test(${BINARY_NAME}-suite ${BINARY_NAME}-suite)
+ foreach(TEST IN LISTS TEST_SRC)
+ string(REPLACE "${CMAKE_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}")
+ add_executable(test-${TEST_NAME} ${TEST})
+ target_link_libraries(test-${TEST_NAME} ${BINARY_NAME} ${PLATFORM_LIBRARY} cmocka)
+ set_target_properties(test-${TEST_NAME} PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
+ add_test(${TEST_NAME} test-${TEST_NAME})
+ endforeach()
endif()
if(BUILD_EXAMPLE)
diff --git a/README.md b/README.md
index bd1a176dd..f756ebdf7 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ Features
- Save type detection, even for flash memory size[[3]](#flashdetect).
- Support for cartridges with motion sensors and rumble (only usable with game controllers)[[2]](#dscaveat).
- Real-time clock support, even without configuration.
+- Game Boy Camera and Game Boy Printer support.
- A built-in GBA BIOS implementation, and ability to load external BIOS files. DS currently requires BIOS and firmware dumps[[2]](#dscaveat).
- Turbo/fast-forward support by holding Tab.
- Rewind by holding Backquote.
@@ -46,7 +47,6 @@ Features
- A comprehensive debug suite.
- e-Reader support.
- Wireless adapter support.
-- Game Boy Printer support.
- OpenGL renderer.
- HLE support for DS BIOS and DS ARM7 processor.
- Synthesizing a customizable DS firmware to avoid needing a dump.
diff --git a/include/mgba-util/arm-algo.h b/include/mgba-util/arm-algo.h
index 1c603ab5b..2c80b78dc 100644
--- a/include/mgba-util/arm-algo.h
+++ b/include/mgba-util/arm-algo.h
@@ -7,12 +7,10 @@
#define ARM_ALGO_H
#ifdef __arm__
-void _to16Bit(uint16_t* dest, uint32_t* src, size_t words);
-
#if defined(__ARM_NEON)
void _neon2x(void* dest, void* src, int width, int height);
void _neon4x(void* dest, void* src, int width, int height);
#endif
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/include/mgba-util/crc32.h b/include/mgba-util/crc32.h
index 225998bb9..ba5e694fd 100644
--- a/include/mgba-util/crc32.h
+++ b/include/mgba-util/crc32.h
@@ -12,8 +12,13 @@ CXX_GUARD_START
struct VFile;
+#ifndef HAVE_CRC32
+uint32_t crc32(uint32_t crc, const void* buf, size_t size);
+#else
+#include
+#endif
+
uint32_t doCrc32(const void* buf, size_t size);
-uint32_t updateCrc32(uint32_t crc, const void* buf, size_t size);
uint32_t fileCrc32(struct VFile* file, size_t endOffset);
CXX_GUARD_END
diff --git a/include/mgba-util/elf-read.h b/include/mgba-util/elf-read.h
index e3886ac64..86683ea82 100644
--- a/include/mgba-util/elf-read.h
+++ b/include/mgba-util/elf-read.h
@@ -14,12 +14,6 @@ CXX_GUARD_START
#include
-#if USE_ELF_REPL
-#include
-#else
-#include
-#endif
-
#include
struct ELF;
diff --git a/include/mgba-util/png-io.h b/include/mgba-util/png-io.h
index 983992856..7156d67cb 100644
--- a/include/mgba-util/png-io.h
+++ b/include/mgba-util/png-io.h
@@ -26,9 +26,11 @@ enum {
png_structp PNGWriteOpen(struct VFile* source);
png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height);
+png_infop PNGWriteHeaderA(png_structp png, unsigned width, unsigned height);
png_infop PNGWriteHeader8(png_structp png, unsigned width, unsigned height);
bool PNGWritePalette(png_structp png, png_infop info, const uint32_t* palette, unsigned entries);
bool PNGWritePixels(png_structp png, unsigned width, unsigned height, unsigned stride, const void* pixels);
+bool PNGWritePixelsA(png_structp png, unsigned width, unsigned height, unsigned stride, const void* pixels);
bool PNGWritePixels8(png_structp png, unsigned width, unsigned height, unsigned stride, const void* pixels);
bool PNGWriteCustomChunk(png_structp png, const char* name, size_t size, void* data);
void PNGWriteClose(png_structp png, png_infop info);
diff --git a/include/mgba/core/cache-set.h b/include/mgba/core/cache-set.h
new file mode 100644
index 000000000..8fed166a9
--- /dev/null
+++ b/include/mgba/core/cache-set.h
@@ -0,0 +1,35 @@
+/* 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 M_CACHE_SET_H
+#define M_CACHE_SET_H
+
+#include
+
+CXX_GUARD_START
+
+#include
+#include
+#include
+
+DECLARE_VECTOR(mMapCacheSet, struct mMapCache);
+DECLARE_VECTOR(mTileCacheSet, struct mTileCache);
+
+struct mCacheSet {
+ struct mMapCacheSet maps;
+ struct mTileCacheSet tiles;
+};
+
+void mCacheSetInit(struct mCacheSet*, size_t nMaps, size_t nTiles);
+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);
+
+CXX_GUARD_END
+
+#endif
diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h
index f726cfcae..fcf76111b 100644
--- a/include/mgba/core/interface.h
+++ b/include/mgba/core/interface.h
@@ -35,8 +35,50 @@ typedef uint32_t color_t;
#define M_RGB8_TO_BGR5(X) ((((X) & 0xF8) >> 3) | (((X) & 0xF800) >> 6) | (((X) & 0xF80000) >> 9))
#define M_RGB8_TO_RGB5(X) ((((X) & 0xF8) << 7) | (((X) & 0xF800) >> 6) | (((X) & 0xF80000) >> 19))
+#ifndef PYCPARSE
+static inline color_t mColorFrom555(uint16_t value) {
+#ifdef COLOR_16_BIT
+#ifdef COLOR_5_6_5
+ color_t color = 0;
+ color |= (value & 0x001F) << 11;
+ color |= (value & 0x03E0) << 1;
+ color |= (value & 0x7C00) >> 10;
+#else
+ color_t color = value;
+#endif
+#else
+ color_t color = M_RGB5_TO_BGR8(value);
+ color |= (color >> 5) & 0x070707;
+#endif
+ return color;
+}
+#endif
+
struct blip_t;
+enum mColorFormat {
+ mCOLOR_XBGR8 = 0x00001,
+ mCOLOR_XRGB8 = 0x00002,
+ mCOLOR_BGRX8 = 0x00004,
+ mCOLOR_RGBX8 = 0x00008,
+ mCOLOR_ABGR8 = 0x00010,
+ mCOLOR_ARGB8 = 0x00020,
+ mCOLOR_BGRA8 = 0x00040,
+ mCOLOR_RGBA8 = 0x00080,
+ mCOLOR_RGB5 = 0x00100,
+ mCOLOR_BGR5 = 0x00200,
+ mCOLOR_RGB565 = 0x00400,
+ mCOLOR_BGR565 = 0x00800,
+ mCOLOR_ARGB5 = 0x01000,
+ mCOLOR_ABGR5 = 0x02000,
+ mCOLOR_RGBA5 = 0x04000,
+ mCOLOR_BGRA5 = 0x08000,
+ mCOLOR_RGB8 = 0x10000,
+ mCOLOR_BGR8 = 0x20000,
+
+ mCOLOR_ANY = -1
+};
+
struct mCoreCallbacks {
void* context;
void (*videoFrameStarted)(void* context);
@@ -62,6 +104,7 @@ struct mKeyCallback {
enum mPeripheral {
mPERIPH_ROTATION = 1,
mPERIPH_RUMBLE,
+ mPERIPH_IMAGE_SOURCE,
mPERIPH_CUSTOM = 0x1000
};
@@ -83,6 +126,12 @@ struct mRTCSource {
bool (*deserialize)(struct mRTCSource*, const struct mStateExtdataItem*);
};
+struct mImageSource {
+ void (*startRequestImage)(struct mImageSource*, unsigned w, unsigned h, int colorFormats);
+ void (*stopRequestImage)(struct mImageSource*);
+ void (*requestImage)(struct mImageSource*, const void** buffer, size_t* stride, enum mColorFormat* colorFormat);
+};
+
enum mRTCGenericType {
RTC_NO_OVERRIDE,
RTC_FIXED,
diff --git a/include/mgba/core/map-cache.h b/include/mgba/core/map-cache.h
new file mode 100644
index 000000000..6dc9e72f6
--- /dev/null
+++ b/include/mgba/core/map-cache.h
@@ -0,0 +1,79 @@
+/* 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 M_MAP_CACHE_H
+#define M_MAP_CACHE_H
+
+#include
+
+CXX_GUARD_START
+
+#include
+#include
+
+DECL_BITFIELD(mMapCacheConfiguration, uint32_t);
+DECL_BIT(mMapCacheConfiguration, ShouldStore, 0);
+
+DECL_BITFIELD(mMapCacheSystemInfo, uint32_t);
+DECL_BITS(mMapCacheSystemInfo, PaletteBPP, 0, 2);
+DECL_BITS(mMapCacheSystemInfo, PaletteCount, 2, 4);
+DECL_BITS(mMapCacheSystemInfo, TilesWide, 8, 4);
+DECL_BITS(mMapCacheSystemInfo, TilesHigh, 12, 4);
+DECL_BITS(mMapCacheSystemInfo, MacroTileSize, 16, 7);
+DECL_BITS(mMapCacheSystemInfo, MapAlign, 23, 2);
+
+DECL_BITFIELD(mMapCacheEntryFlags, uint16_t);
+DECL_BITS(mMapCacheEntryFlags, PaletteId, 0, 4);
+DECL_BIT(mMapCacheEntryFlags, VramClean, 4);
+DECL_BIT(mMapCacheEntryFlags, HMirror, 5);
+DECL_BIT(mMapCacheEntryFlags, VMirror, 6);
+DECL_BITS(mMapCacheEntryFlags, Mirror, 5, 2);
+
+struct mMapCacheEntry {
+ uint32_t vramVersion;
+ uint16_t tileId;
+ mMapCacheEntryFlags flags;
+ struct mTileCacheEntry tileStatus[16];
+};
+
+struct mTileCache;
+struct mTileCacheEntry;
+struct mMapCache {
+ color_t* cache;
+ struct mTileCache* tileCache;
+ struct mMapCacheEntry* status;
+
+ uint8_t* vram;
+
+ uint32_t mapStart;
+ uint32_t mapSize;
+
+ uint32_t tileStart;
+
+ mMapCacheConfiguration config;
+ mMapCacheSystemInfo sysConfig;
+
+ void (*mapParser)(struct mMapCache*, struct mMapCacheEntry* entry, void* vram);
+ void* context;
+};
+
+void mMapCacheInit(struct mMapCache* cache);
+void mMapCacheDeinit(struct mMapCache* cache);
+void mMapCacheConfigure(struct mMapCache* cache, mMapCacheConfiguration config);
+void mMapCacheConfigureSystem(struct mMapCache* cache, mMapCacheSystemInfo config);
+void mMapCacheConfigureMap(struct mMapCache* cache, uint32_t mapStart);
+void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address);
+
+uint32_t mMapCacheTileId(struct mMapCache* cache, unsigned x, unsigned y);
+
+bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* entry, unsigned x, unsigned y);
+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);
+
+CXX_GUARD_END
+
+#endif
diff --git a/include/mgba/core/thread.h b/include/mgba/core/thread.h
index 420533762..9e609bfe7 100644
--- a/include/mgba/core/thread.h
+++ b/include/mgba/core/thread.h
@@ -34,6 +34,8 @@ struct mCoreThread {
ThreadCallback cleanCallback;
ThreadCallback frameCallback;
ThreadCallback sleepCallback;
+ ThreadCallback pauseCallback;
+ ThreadCallback unpauseCallback;
void* userData;
void (*run)(struct mCoreThread*);
@@ -50,13 +52,19 @@ enum mCoreThreadState {
THREAD_RUNNING = 0,
THREAD_REWINDING,
THREAD_MAX_RUNNING = THREAD_REWINDING,
+
+ THREAD_WAITING,
THREAD_INTERRUPTED,
- THREAD_INTERRUPTING,
THREAD_PAUSED,
+ THREAD_MAX_WAITING = THREAD_PAUSED,
+
THREAD_PAUSING,
THREAD_RUN_ON,
- THREAD_WAITING,
THREAD_RESETING,
+ THREAD_MIN_DEFERRED = THREAD_PAUSING,
+ THREAD_MAX_DEFERRED = THREAD_RESETING,
+
+ THREAD_INTERRUPTING,
THREAD_EXITING,
THREAD_SHUTDOWN,
THREAD_CRASHED
diff --git a/include/mgba/core/tile-cache.h b/include/mgba/core/tile-cache.h
index 540705af9..f8600b3ad 100644
--- a/include/mgba/core/tile-cache.h
+++ b/include/mgba/core/tile-cache.h
@@ -10,14 +10,14 @@
CXX_GUARD_START
+#include
+
DECL_BITFIELD(mTileCacheConfiguration, uint32_t);
DECL_BIT(mTileCacheConfiguration, ShouldStore, 0);
DECL_BITFIELD(mTileCacheSystemInfo, uint32_t);
-DECL_BITS(mTileCacheSystemInfo, Palette0BPP, 0, 2);
-DECL_BITS(mTileCacheSystemInfo, Palette0Count, 2, 4);
-DECL_BITS(mTileCacheSystemInfo, Palette1BPP, 8, 2);
-DECL_BITS(mTileCacheSystemInfo, Palette1Count, 10, 4);
+DECL_BITS(mTileCacheSystemInfo, PaletteBPP, 0, 2);
+DECL_BITS(mTileCacheSystemInfo, PaletteCount, 2, 4);
DECL_BITS(mTileCacheSystemInfo, MaxTiles, 16, 13);
struct mTileCacheEntry {
@@ -25,24 +25,22 @@ struct mTileCacheEntry {
uint32_t vramVersion;
uint8_t vramClean;
uint8_t paletteId;
- uint8_t activePalette;
- uint8_t padding;
+ uint16_t padding;
};
struct mTileCache {
- uint16_t* cache;
+ color_t* cache;
struct mTileCacheEntry* status;
- uint32_t* globalPaletteVersion[2];
+ uint32_t* globalPaletteVersion;
- int activePalette;
- unsigned entries;
- unsigned count;
+ uint32_t tileBase;
+ uint32_t paletteBase;
unsigned entriesPerTile;
unsigned bpp;
uint16_t* vram;
- uint16_t* palette;
- uint16_t temporaryTile[64];
+ color_t* palette;
+ color_t temporaryTile[64];
mTileCacheConfiguration config;
mTileCacheSystemInfo sysConfig;
@@ -51,15 +49,14 @@ struct mTileCache {
void mTileCacheInit(struct mTileCache* cache);
void mTileCacheDeinit(struct mTileCache* cache);
void mTileCacheConfigure(struct mTileCache* cache, mTileCacheConfiguration config);
-void mTileCacheConfigureSystem(struct mTileCache* cache, mTileCacheSystemInfo 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 address);
-void mTileCacheSetPalette(struct mTileCache* cache, int palette);
+void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, color_t color);
-const uint16_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId);
-const uint16_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId);
-const uint8_t* mTileCacheGetRawTile(struct mTileCache* cache, unsigned tileId);
-const uint16_t* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId);
+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 uint16_t* mTileCacheGetVRAM(struct mTileCache* cache, unsigned tileId);
CXX_GUARD_END
diff --git a/include/mgba/core/timing.h b/include/mgba/core/timing.h
index 634631bed..16154ba9c 100644
--- a/include/mgba/core/timing.h
+++ b/include/mgba/core/timing.h
@@ -23,6 +23,7 @@ struct mTimingEvent {
struct mTiming {
struct mTimingEvent* root;
+ struct mTimingEvent* reroot;
uint32_t masterCycles;
int32_t* relativeCycles;
diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h
index ef0771bca..809c0ca36 100644
--- a/include/mgba/gb/interface.h
+++ b/include/mgba/gb/interface.h
@@ -12,10 +12,12 @@ CXX_GUARD_START
enum GBModel {
GB_MODEL_AUTODETECT = 0xFF,
- GB_MODEL_DMG = 0x00,
- GB_MODEL_SGB = 0x40,
- GB_MODEL_CGB = 0x80,
- GB_MODEL_AGB = 0xC0
+ GB_MODEL_DMG = 0x00,
+ GB_MODEL_SGB = 0x20,
+ GB_MODEL_MGB = 0x40,
+ GB_MODEL_SGB2 = 0x60,
+ GB_MODEL_CGB = 0x80,
+ GB_MODEL_AGB = 0xC0
};
enum GBMemoryBankControllerType {
@@ -31,6 +33,7 @@ enum GBMemoryBankControllerType {
GB_HuC1 = 0x11,
GB_HuC3 = 0x12,
GB_POCKETCAM = 0x13,
+ GB_TAMA5 = 0x14,
GB_MBC3_RTC = 0x103,
GB_MBC5_RUMBLE = 0x105
};
@@ -44,6 +47,9 @@ struct GBSIODriver {
uint8_t (*writeSC)(struct GBSIODriver* driver, uint8_t value);
};
+enum GBModel GBNameToModel(const char*);
+const char* GBModelToName(enum GBModel);
+
CXX_GUARD_END
#endif
diff --git a/include/mgba/internal/gb/audio.h b/include/mgba/internal/gb/audio.h
index b1e86e299..6165f6f4c 100644
--- a/include/mgba/internal/gb/audio.h
+++ b/include/mgba/internal/gb/audio.h
@@ -142,6 +142,7 @@ struct GBAudioNoiseChannel {
enum GBAudioStyle {
GB_AUDIO_DMG,
+ GB_AUDIO_MGB = GB_AUDIO_DMG, // TODO
GB_AUDIO_CGB,
GB_AUDIO_AGB, // GB in GBA
GB_AUDIO_GBA, // GBA PSG
diff --git a/include/mgba/internal/gb/gb.h b/include/mgba/internal/gb/gb.h
index 37050e613..1d222211a 100644
--- a/include/mgba/internal/gb/gb.h
+++ b/include/mgba/internal/gb/gb.h
@@ -44,6 +44,34 @@ enum GBIRQVector {
GB_VECTOR_KEYPAD = 0x60,
};
+enum GBSGBCommand {
+ SGB_PAL01 = 0,
+ SGB_PAL23,
+ SGB_PAL03,
+ SGB_PAL12,
+ SGB_ATTR_BLK,
+ SGB_ATTR_LIN,
+ SGB_ATTR_DIV,
+ SGB_ATTR_CHR,
+ SGB_SOUND,
+ SGB_SOU_TRN,
+ SGB_PAL_SET,
+ SGB_PAL_TRN,
+ SGB_ATRC_EN,
+ SGB_TEST_EN,
+ SGB_PICON_EN,
+ SGB_DATA_SND,
+ SGB_DATA_TRN,
+ SGB_MLT_REG,
+ SGB_JUMP,
+ SGB_CHR_TRN,
+ SGB_PCT_TRN,
+ SGB_ATTR_TRN,
+ SGB_ATTR_SET,
+ SGB_MASK_EN,
+ SGB_OBJ_TRN
+};
+
struct LR35902Core;
struct mCoreSync;
struct mAVStream;
@@ -76,6 +104,10 @@ struct GB {
int32_t sramDirtAge;
bool sramMaskWriteback;
+ int sgbBit;
+ int currentSgbBits;
+ uint8_t sgbPacket[16];
+
struct mCoreCallbacksList coreCallbacks;
struct mAVStream* stream;
diff --git a/include/mgba/internal/gb/mbc.h b/include/mgba/internal/gb/mbc.h
index 96a27ddc9..2269e5af7 100644
--- a/include/mgba/internal/gb/mbc.h
+++ b/include/mgba/internal/gb/mbc.h
@@ -19,8 +19,14 @@ struct GBMemory;
void GBMBCInit(struct GB* gb);
void GBMBCSwitchBank(struct GB* gb, int bank);
void GBMBCSwitchBank0(struct GB* gb, int bank);
+void GBMBCSwitchHalfBank(struct GB* gb, int half, int bank);
void GBMBCSwitchSramBank(struct GB* gb, int bank);
+enum GBCam {
+ GBCAM_WIDTH = 128,
+ GBCAM_HEIGHT = 112
+};
+
struct GBMBCRTCSaveBuffer {
uint32_t sec;
uint32_t min;
@@ -37,8 +43,6 @@ struct GBMBCRTCSaveBuffer {
void GBMBCRTCRead(struct GB* gb);
void GBMBCRTCWrite(struct GB* gb);
-void GBMBC7Write(struct GBMemory*, uint16_t address, uint8_t value);
-
CXX_GUARD_END
#endif
diff --git a/include/mgba/internal/gb/memory.h b/include/mgba/internal/gb/memory.h
index d28338cff..f971c353e 100644
--- a/include/mgba/internal/gb/memory.h
+++ b/include/mgba/internal/gb/memory.h
@@ -22,6 +22,8 @@ struct GB;
enum {
GB_BASE_CART_BANK0 = 0x0000,
GB_BASE_CART_BANK1 = 0x4000,
+ GB_BASE_CART_HALFBANK1 = 0x4000,
+ GB_BASE_CART_HALFBANK2 = 0x6000,
GB_BASE_VRAM = 0x8000,
GB_BASE_EXTERNAL_RAM = 0xA000,
GB_BASE_WORKING_RAM_BANK0 = 0xC000,
@@ -46,6 +48,7 @@ enum {
enum {
GB_SIZE_CART_BANK0 = 0x4000,
+ GB_SIZE_CART_HALFBANK = 0x2000,
GB_SIZE_CART_MAX = 0x800000,
GB_SIZE_VRAM = 0x4000,
GB_SIZE_VRAM_BANK0 = 0x2000,
@@ -86,11 +89,29 @@ enum GBMBC7MachineState {
GBMBC7_STATE_EEPROM_ERASE = 0x1C,
};
+enum GBTAMA5Register {
+ GBTAMA5_BANK_LO = 0x0,
+ GBTAMA5_BANK_HI = 0x1,
+ GBTAMA5_WRITE_LO = 0x4,
+ GBTAMA5_WRITE_HI = 0x5,
+ GBTAMA5_CS = 0x6,
+ GBTAMA5_ADDR_LO = 0x7,
+ GBTAMA5_MAX = 0x8,
+ GBTAMA5_ACTIVE = 0xA,
+ GBTAMA5_READ_LO = 0xC,
+ GBTAMA5_READ_HI = 0xD,
+};
+
struct GBMBC1State {
int mode;
int multicartStride;
};
+struct GBMBC6State {
+ int currentBank1;
+ uint8_t* romBank1;
+};
+
struct GBMBC7State {
enum GBMBC7MachineState state;
uint16_t sr;
@@ -104,12 +125,20 @@ struct GBMBC7State {
struct GBPocketCamState {
bool registersActive;
+ uint8_t registers[0x36];
+};
+
+struct GBTAMA5State {
+ uint8_t reg;
+ uint8_t registers[GBTAMA5_MAX];
};
union GBMBCState {
struct GBMBC1State mbc1;
+ struct GBMBC6State mbc6;
struct GBMBC7State mbc7;
struct GBPocketCamState pocketCam;
+ struct GBTAMA5State tama5;
};
struct mRotationSource;
@@ -160,6 +189,7 @@ struct GBMemory {
struct mRTCSource* rtc;
struct mRotationSource* rotation;
struct mRumble* rumble;
+ struct mImageSource* cam;
};
struct LR35902Core;
diff --git a/include/mgba/internal/gb/overrides.h b/include/mgba/internal/gb/overrides.h
index 44d012183..f138ee9c8 100644
--- a/include/mgba/internal/gb/overrides.h
+++ b/include/mgba/internal/gb/overrides.h
@@ -17,7 +17,7 @@ struct GBCartridgeOverride {
enum GBModel model;
enum GBMemoryBankControllerType mbc;
- uint32_t gbColors[4];
+ uint32_t gbColors[12];
};
struct Configuration;
diff --git a/include/mgba/internal/gb/renderers/tile-cache.h b/include/mgba/internal/gb/renderers/cache-set.h
similarity index 61%
rename from include/mgba/internal/gb/renderers/tile-cache.h
rename to include/mgba/internal/gb/renderers/cache-set.h
index 1b739ca46..f11bdf45f 100644
--- a/include/mgba/internal/gb/renderers/tile-cache.h
+++ b/include/mgba/internal/gb/renderers/cache-set.h
@@ -11,10 +11,12 @@
CXX_GUARD_START
struct GBVideo;
-struct mTileCache;
+struct mCacheSet;
-void GBVideoTileCacheInit(struct mTileCache* cache);
-void GBVideoTileCacheAssociate(struct mTileCache* cache, struct GBVideo* video);
+void GBVideoCacheInit(struct mCacheSet* cache);
+void GBVideoCacheAssociate(struct mCacheSet* cache, struct GBVideo* video);
+
+void GBVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint16_t address, uint8_t value);
CXX_GUARD_END
diff --git a/include/mgba/internal/gb/renderers/software.h b/include/mgba/internal/gb/renderers/software.h
index 038c660b8..a5bbcb80f 100644
--- a/include/mgba/internal/gb/renderers/software.h
+++ b/include/mgba/internal/gb/renderers/software.h
@@ -23,6 +23,7 @@ struct GBVideoSoftwareRenderer {
uint8_t row[GB_VIDEO_HORIZONTAL_PIXELS + 8];
color_t palette[128];
+ uint8_t lookup[64];
uint32_t* temporaryBuffer;
@@ -34,6 +35,14 @@ struct GBVideoSoftwareRenderer {
GBRegisterLCDC lcdc;
enum GBModel model;
+
+ int sgbTransfer;
+ uint8_t sgbPacket[16];
+ uint8_t sgbCommandHeader;
+ int sgbPacketId;
+ int sgbDataSets;
+ uint8_t sgbPartialDataSet[15];
+ bool sgbBorders;
};
void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer*);
diff --git a/include/mgba/internal/gb/serialize.h b/include/mgba/internal/gb/serialize.h
index dcdb400a7..2acf592d4 100644
--- a/include/mgba/internal/gb/serialize.h
+++ b/include/mgba/internal/gb/serialize.h
@@ -19,7 +19,7 @@ extern const uint32_t GB_SAVESTATE_VERSION;
mLOG_DECLARE_CATEGORY(GB_STATE);
/* Savestate format:
- * 0x00000 - 0x00003: Version Magic (0x01000001)
+ * 0x00000 - 0x00003: Version Magic (0x01000002)
* 0x00004 - 0x00007: ROM CRC32
* 0x00008: Game Boy model
* 0x00009 - 0x0000B: Reserved (leave zero)
@@ -42,7 +42,7 @@ mLOG_DECLARE_CATEGORY(GB_STATE);
* | 0x00036 - 0x00037: Index address
* | 0x00038: Bus value
* | 0x00039: Execution state
- * | 0x0003A - 0x0003B: IRQ vector
+ * | 0x0003A - 0x0003B: Reserved
* | 0x0003C - 0x0003F: EI pending cycles
* | 0x00040 - 0x00043: Reserved (DI pending cycles)
* | 0x00044 - 0x00047: Flags
@@ -161,7 +161,22 @@ mLOG_DECLARE_CATEGORY(GB_STATE);
* 0x003FF: Interrupts enabled
* 0x00400 - 0x043FF: VRAM
* 0x04400 - 0x0C3FF: WRAM
- * Total size: 0xC400 (50,176) bytes
+ * 0x0C400 - 0x0C77F: Reserved
+ * 0x0C780 - 0x117FF: Super Game Boy
+ * | 0x0C780 - 0x0C7D9: Current attributes
+ * | 0x0C7DA: Current command
+ * | 0x0C7DB: Current bit count
+ * | 0x0C7DC - 0x0C7DF: Flags
+ * | bits 0 - 1: Current P1 bits
+ * | bits 2 - 3: Current render mode
+ * | bits 4 - 31: Reserved (leave 0)
+ * | 0x0C7E0 - 0x0C7EF: Current packet
+ * | 0x0C7F0 - 0x0C7FF: Reserved
+ * | 0x0C800 - 0x0E7FF: Character VRAM
+ * | 0x0E800 - 0x0F7FF: Tile map VRAM
+ * | 0x0F800 - 0x107FF: Palette VRAM
+ * | 0x10800 - 0x117FF: Attribute file
+ * Total size: 0x11800 (71,680) bytes
*/
DECL_BITFIELD(GBSerializedAudioFlags, uint32_t);
@@ -238,6 +253,10 @@ DECL_BIT(GBSerializedMemoryFlags, Ime, 3);
DECL_BIT(GBSerializedMemoryFlags, IsHdma, 4);
DECL_BITS(GBSerializedMemoryFlags, ActiveRtcReg, 5, 3);
+DECL_BITFIELD(GBSerializedSGBFlags, uint32_t);
+DECL_BITS(GBSerializedSGBFlags, P1Bits, 0, 2);
+DECL_BITS(GBSerializedSGBFlags, RenderMode, 2, 2);
+
#pragma pack(push, 1)
struct GBSerializedState {
uint32_t versionMagic;
@@ -268,7 +287,7 @@ struct GBSerializedState {
uint8_t bus;
uint8_t executionState;
- uint16_t irqVector;
+ uint16_t reserved;
uint32_t eiPending;
int32_t reservedDiPending;
@@ -366,6 +385,21 @@ struct GBSerializedState {
uint8_t vram[GB_SIZE_VRAM];
uint8_t wram[GB_SIZE_WORKING_RAM];
+
+ uint32_t reserved2[0xE0];
+
+ struct {
+ uint8_t attributes[90];
+ uint8_t command;
+ uint8_t bits;
+ GBSerializedSGBFlags flags;
+ uint8_t packet[16];
+ uint32_t reserved[4];
+ uint8_t charRam[SGB_SIZE_CHAR_RAM];
+ uint8_t mapRam[SGB_SIZE_MAP_RAM];
+ uint8_t palRam[SGB_SIZE_PAL_RAM];
+ uint8_t atfRam[SGB_SIZE_ATF_RAM];
+ } sgb;
};
#pragma pack(pop)
diff --git a/include/mgba/internal/gb/sio/printer.h b/include/mgba/internal/gb/sio/printer.h
new file mode 100644
index 000000000..a5b42a83d
--- /dev/null
+++ b/include/mgba/internal/gb/sio/printer.h
@@ -0,0 +1,74 @@
+/* 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 GB_PRINTER_H
+#define GB_PRINTER_H
+
+#include
+
+CXX_GUARD_START
+
+#include
+
+enum GBPrinterPacketByte {
+ GB_PRINTER_BYTE_MAGIC_0,
+ GB_PRINTER_BYTE_MAGIC_1,
+ GB_PRINTER_BYTE_COMMAND,
+ GB_PRINTER_BYTE_COMPRESSION,
+ GB_PRINTER_BYTE_LENGTH_0,
+ GB_PRINTER_BYTE_LENGTH_1,
+ GB_PRINTER_BYTE_DATA,
+ GB_PRINTER_BYTE_CHECKSUM_0,
+ GB_PRINTER_BYTE_CHECKSUM_1,
+ GB_PRINTER_BYTE_KEEPALIVE,
+ GB_PRINTER_BYTE_STATUS,
+
+ GB_PRINTER_BYTE_COMPRESSED_DATUM,
+ GB_PRINTER_BYTE_UNCOMPRESSED_DATA
+};
+
+enum GBPrinterStatus {
+ GB_PRINTER_STATUS_CHECKSUM_ERROR = 0x01,
+ GB_PRINTER_STATUS_PRINTING = 0x02,
+ GB_PRINTER_STATUS_PRINT_REQ = 0x04,
+ GB_PRINTER_STATUS_READY = 0x08,
+ GB_PRINTER_STATUS_LOW_BATTERY = 0x10,
+ GB_PRINTER_STATUS_TIMEOUT = 0x20,
+ GB_PRINTER_STATUS_PAPER_JAM = 0x40,
+ GB_PRINTER_STATUS_TEMPERATURE_ISSUE = 0x80
+};
+
+enum GBPrinterCommand {
+ GB_PRINTER_COMMAND_INIT = 0x1,
+ GB_PRINTER_COMMAND_PRINT = 0x2,
+ GB_PRINTER_COMMAND_DATA = 0x4,
+ GB_PRINTER_COMMAND_STATUS = 0xF,
+};
+
+struct GBPrinter {
+ struct GBSIODriver d;
+
+ void (*print)(struct GBPrinter*, int height, const uint8_t* data);
+
+ uint8_t* buffer;
+ uint16_t checksum;
+ enum GBPrinterCommand command;
+ uint16_t remainingBytes;
+ uint8_t remainingCmpBytes;
+ unsigned currentIndex;
+ bool compression;
+
+ uint8_t byte;
+ enum GBPrinterPacketByte next;
+ uint8_t status;
+ int printWait;
+};
+
+void GBPrinterCreate(struct GBPrinter* printer);
+void GBPrinterDonePrinting(struct GBPrinter* printer);
+
+CXX_GUARD_END
+
+#endif
diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h
index 440a90ccf..a19fa928e 100644
--- a/include/mgba/internal/gb/video.h
+++ b/include/mgba/internal/gb/video.h
@@ -30,7 +30,12 @@ enum {
GB_VIDEO_TOTAL_LENGTH = 70224,
GB_BASE_MAP = 0x1800,
- GB_SIZE_MAP = 0x0400
+ GB_SIZE_MAP = 0x0400,
+
+ SGB_SIZE_CHAR_RAM = 0x2000,
+ SGB_SIZE_MAP_RAM = 0x1000,
+ SGB_SIZE_PAL_RAM = 0x1000,
+ SGB_SIZE_ATF_RAM = 0x1000
};
DECL_BITFIELD(GBObjAttributes, uint8_t);
@@ -41,6 +46,13 @@ DECL_BIT(GBObjAttributes, XFlip, 5);
DECL_BIT(GBObjAttributes, YFlip, 6);
DECL_BIT(GBObjAttributes, Priority, 7);
+DECL_BITFIELD(SGBBgAttributes, uint16_t);
+DECL_BITS(SGBBgAttributes, Tile, 0, 10);
+DECL_BITS(SGBBgAttributes, Palette, 10, 3);
+DECL_BIT(SGBBgAttributes, Priority, 13);
+DECL_BIT(SGBBgAttributes, XFlip, 14);
+DECL_BIT(SGBBgAttributes, YFlip, 15);
+
struct GBObj {
uint8_t y;
uint8_t x;
@@ -53,12 +65,13 @@ union GBOAM {
uint8_t raw[160];
};
-struct mTileCache;
+struct mCacheSet;
struct GBVideoRenderer {
- void (*init)(struct GBVideoRenderer* renderer, enum GBModel model);
+ void (*init)(struct GBVideoRenderer* renderer, enum GBModel model, bool borders);
void (*deinit)(struct GBVideoRenderer* renderer);
uint8_t (*writeVideoRegister)(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
+ void (*writeSGBPacket)(struct GBVideoRenderer* renderer, uint8_t* data);
void (*writeVRAM)(struct GBVideoRenderer* renderer, uint16_t address);
void (*writePalette)(struct GBVideoRenderer* renderer, int index, uint16_t value);
void (*writeOAM)(struct GBVideoRenderer* renderer, uint16_t oam);
@@ -71,7 +84,14 @@ struct GBVideoRenderer {
uint8_t* vram;
union GBOAM* oam;
- struct mTileCache* cache;
+ struct mCacheSet* cache;
+
+ uint8_t* sgbCharRam;
+ uint8_t* sgbMapRam;
+ uint8_t* sgbPalRam;
+ int sgbRenderMode;
+ uint8_t* sgbAttributes;
+ uint8_t* sgbAttributeFiles;
bool disableBG;
bool disableOBJ;
@@ -123,10 +143,13 @@ struct GBVideo {
bool bcpIncrement;
int ocpIndex;
bool ocpIncrement;
+ uint8_t sgbCommandHeader;
- uint16_t dmgPalette[4];
+ uint16_t dmgPalette[12];
uint16_t palette[64];
+ bool sgbBorders;
+
int32_t frameCounter;
int frameskip;
int frameskipCounter;
@@ -144,8 +167,11 @@ void GBVideoWriteLYC(struct GBVideo* video, uint8_t value);
void GBVideoWritePalette(struct GBVideo* video, uint16_t address, uint8_t value);
void GBVideoSwitchBank(struct GBVideo* video, uint8_t value);
+void GBVideoDisableCGB(struct GBVideo* video);
void GBVideoSetPalette(struct GBVideo* video, unsigned index, uint32_t color);
+void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data);
+
struct GBSerializedState;
void GBVideoSerialize(const struct GBVideo* video, struct GBSerializedState* state);
void GBVideoDeserialize(struct GBVideo* video, const struct GBSerializedState* state);
diff --git a/include/mgba/internal/gba/memory.h b/include/mgba/internal/gba/memory.h
index d227be16e..08e9ef673 100644
--- a/include/mgba/internal/gba/memory.h
+++ b/include/mgba/internal/gba/memory.h
@@ -67,10 +67,11 @@ enum {
SIZE_CART0 = 0x02000000,
SIZE_CART1 = 0x02000000,
SIZE_CART2 = 0x02000000,
- SIZE_CART_SRAM = 0x00010000,
+ SIZE_CART_SRAM = 0x00008000,
SIZE_CART_FLASH512 = 0x00010000,
SIZE_CART_FLASH1M = 0x00020000,
- SIZE_CART_EEPROM = 0x00002000
+ SIZE_CART_EEPROM = 0x00002000,
+ SIZE_CART_EEPROM512 = 0x00000200
};
enum {
diff --git a/include/mgba/internal/gba/overrides.h b/include/mgba/internal/gba/overrides.h
index 4240fea2e..c20e1f8e1 100644
--- a/include/mgba/internal/gba/overrides.h
+++ b/include/mgba/internal/gba/overrides.h
@@ -28,7 +28,7 @@ void GBAOverrideSave(struct Configuration*, const struct GBACartridgeOverride* o
struct GBA;
void GBAOverrideApply(struct GBA*, const struct GBACartridgeOverride*);
-void GBAOverrideApplyDefaults(struct GBA*);
+void GBAOverrideApplyDefaults(struct GBA*, const struct Configuration*);
CXX_GUARD_END
diff --git a/include/mgba/internal/gba/renderers/tile-cache.h b/include/mgba/internal/gba/renderers/cache-set.h
similarity index 53%
rename from include/mgba/internal/gba/renderers/tile-cache.h
rename to include/mgba/internal/gba/renderers/cache-set.h
index 3e2143f35..3ad4f6196 100644
--- a/include/mgba/internal/gba/renderers/tile-cache.h
+++ b/include/mgba/internal/gba/renderers/cache-set.h
@@ -3,18 +3,19 @@
* 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_TILE_CACHE_H
-#define GBA_TILE_CACHE_H
+#ifndef GBA_CACHE_SET_H
+#define GBA_CACHE_SET_H
#include
CXX_GUARD_START
struct GBAVideo;
-struct mTileCache;
+struct mCacheSet;
-void GBAVideoTileCacheInit(struct mTileCache* cache);
-void GBAVideoTileCacheAssociate(struct mTileCache* cache, struct GBAVideo* video);
+void GBAVideoCacheInit(struct mCacheSet* cache);
+void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video);
+void GBAVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint32_t address, uint16_t value);
CXX_GUARD_END
diff --git a/include/mgba/internal/gba/renderers/video-software.h b/include/mgba/internal/gba/renderers/video-software.h
index 02298ee79..63893c0fe 100644
--- a/include/mgba/internal/gba/renderers/video-software.h
+++ b/include/mgba/internal/gba/renderers/video-software.h
@@ -11,6 +11,7 @@
CXX_GUARD_START
#include
+#include
#include
struct GBAVideoSoftwareSprite {
@@ -167,6 +168,14 @@ struct GBAVideoSoftwareRenderer {
int bitmapStride;
bool combinedObjSort;
+ uint32_t scanlineDirty[5];
+ uint16_t nextIo[REG_SOUND1CNT_LO];
+ struct ScanlineCache {
+ uint16_t io[REG_SOUND1CNT_LO];
+ int32_t scale[2][2];
+ } cache[VIDEO_VERTICAL_PIXELS];
+ int nextY;
+
int start;
int end;
int masterEnd;
diff --git a/include/mgba/internal/gba/video.h b/include/mgba/internal/gba/video.h
index 69316b51e..eb700c23d 100644
--- a/include/mgba/internal/gba/video.h
+++ b/include/mgba/internal/gba/video.h
@@ -169,7 +169,7 @@ struct GBAVideoRenderer {
uint16_t* vramBG[32];
uint16_t* vramOBJ[32];
union GBAOAM* oam;
- struct mTileCache* cache;
+ struct mCacheSet* cache;
bool disableBG[4];
bool disableOBJ;
diff --git a/include/mgba/internal/lr35902/lr35902.h b/include/mgba/internal/lr35902/lr35902.h
index 3e586f0ed..c5bfd1381 100644
--- a/include/mgba/internal/lr35902/lr35902.h
+++ b/include/mgba/internal/lr35902/lr35902.h
@@ -66,6 +66,7 @@ struct LR35902InterruptHandler {
void (*reset)(struct LR35902Core* cpu);
void (*processEvents)(struct LR35902Core* cpu);
void (*setInterrupts)(struct LR35902Core* cpu, bool enable);
+ uint16_t (*irqVector)(struct LR35902Core* cpu);
void (*halt)(struct LR35902Core* cpu);
void (*stop)(struct LR35902Core* cpu);
@@ -118,7 +119,6 @@ struct LR35902Core {
LR35902Instruction instruction;
bool irqPending;
- uint16_t irqVector;
struct LR35902Memory memory;
struct LR35902InterruptHandler irqh;
@@ -136,7 +136,7 @@ void LR35902HotplugAttach(struct LR35902Core* cpu, size_t slot);
void LR35902HotplugDetach(struct LR35902Core* cpu, size_t slot);
void LR35902Reset(struct LR35902Core* cpu);
-void LR35902RaiseIRQ(struct LR35902Core* cpu, uint8_t vector);
+void LR35902RaiseIRQ(struct LR35902Core* cpu);
void LR35902Tick(struct LR35902Core* cpu);
void LR35902Run(struct LR35902Core* cpu);
diff --git a/res/no-cam.png b/res/no-cam.png
new file mode 100644
index 000000000..2070f21cc
Binary files /dev/null and b/res/no-cam.png differ
diff --git a/res/patrons.txt b/res/patrons.txt
index 3ec04c2b9..a92093f30 100644
--- a/res/patrons.txt
+++ b/res/patrons.txt
@@ -2,8 +2,8 @@ Jaime J. Denizard
Fog
Reilly Grant
Philip Horton
-Jordan Jorgensen
mars
+pr1ntf
Rohit Nirmal
Rhys Powell
rootfather
diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c
index db8bf2252..e08eebd64 100644
--- a/src/arm/isa-arm.c
+++ b/src/arm/isa-arm.c
@@ -817,8 +817,9 @@ DEFINE_INSTRUCTION_ARM(MSR,
}
_ARMReadCPSR(cpu);
if (cpu->executionMode == MODE_THUMB) {
- LOAD_16(cpu->prefetch[0], (cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & cpu->memory.activeMask, cpu->memory.activeRegion);
- LOAD_16(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
+ cpu->prefetch[0] = 0x46C0; // nop
+ cpu->prefetch[1] &= 0xFFFF;
+ cpu->gprs[ARM_PC] += WORD_SIZE_THUMB;
} else {
LOAD_32(cpu->prefetch[0], (cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & cpu->memory.activeMask, cpu->memory.activeRegion);
LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
@@ -858,8 +859,9 @@ DEFINE_INSTRUCTION_ARM(MSRI,
}
_ARMReadCPSR(cpu);
if (cpu->executionMode == MODE_THUMB) {
- LOAD_16(cpu->prefetch[0], (cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & cpu->memory.activeMask, cpu->memory.activeRegion);
- LOAD_16(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
+ cpu->prefetch[0] = 0x46C0; // nop
+ cpu->prefetch[1] &= 0xFFFF;
+ cpu->gprs[ARM_PC] += WORD_SIZE_THUMB;
} else {
LOAD_32(cpu->prefetch[0], (cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & cpu->memory.activeMask, cpu->memory.activeRegion);
LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
diff --git a/src/core/cache-set.c b/src/core/cache-set.c
new file mode 100644
index 000000000..7561981e3
--- /dev/null
+++ b/src/core/cache-set.c
@@ -0,0 +1,62 @@
+/* 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_VECTOR(mMapCacheSet, struct mMapCache);
+DEFINE_VECTOR(mTileCacheSet, struct mTileCache);
+
+void mCacheSetInit(struct mCacheSet* cache, size_t nMaps, size_t nTiles) {
+ mMapCacheSetInit(&cache->maps, nMaps);
+ mMapCacheSetResize(&cache->maps, nMaps);
+ mTileCacheSetInit(&cache->tiles, nTiles);
+ mTileCacheSetResize(&cache->tiles, nTiles);
+
+ size_t i;
+ for (i = 0; i < nMaps; ++i) {
+ mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, i));
+ }
+ for (i = 0; i < nTiles; ++i) {
+ mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, i));
+ }
+}
+
+void mCacheSetDeinit(struct mCacheSet* cache) {
+ size_t i;
+ for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) {
+ mMapCacheDeinit(mMapCacheSetGetPointer(&cache->maps, i));
+ }
+ for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
+ mTileCacheDeinit(mTileCacheSetGetPointer(&cache->tiles, i));
+ }
+}
+
+void mCacheSetAssignVRAM(struct mCacheSet* cache, void* vram) {
+ size_t i;
+ for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) {
+ mMapCacheSetGetPointer(&cache->maps, i)->vram = vram;
+ }
+ for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
+ struct mTileCache* tileCache = mTileCacheSetGetPointer(&cache->tiles, i);
+ tileCache->vram = (void*) ((uintptr_t) vram + tileCache->tileBase);
+ }
+}
+
+void mCacheSetWriteVRAM(struct mCacheSet* cache, uint32_t address) {
+ size_t i;
+ for (i = 0; i < mMapCacheSetSize(&cache->maps); ++i) {
+ mMapCacheWriteVRAM(mMapCacheSetGetPointer(&cache->maps, i), address);
+ }
+ for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
+ mTileCacheWriteVRAM(mTileCacheSetGetPointer(&cache->tiles, i), address);
+ }
+}
+
+void mCacheSetWritePalette(struct mCacheSet* cache, uint32_t entry, color_t color) {
+ size_t i;
+ for (i = 0; i < mTileCacheSetSize(&cache->tiles); ++i) {
+ mTileCacheWritePalette(mTileCacheSetGetPointer(&cache->tiles, i), entry, color);
+ }
+}
diff --git a/src/core/cheats.c b/src/core/cheats.c
index 5085a3d67..21a7b8a7b 100644
--- a/src/core/cheats.c
+++ b/src/core/cheats.c
@@ -256,35 +256,23 @@ void mCheatRefresh(struct mCheatDevice* device, struct mCheatSet* cheats) {
if (!cheats->enabled) {
return;
}
- bool condition = true;
- int conditionRemaining = 0;
- int negativeConditionRemaining = 0;
cheats->refresh(cheats, device);
+ size_t elseLoc = 0;
+ size_t endLoc = 0;
size_t nCodes = mCheatListSize(&cheats->list);
size_t i;
for (i = 0; i < nCodes; ++i) {
- if (conditionRemaining > 0) {
- --conditionRemaining;
- if (!condition) {
- continue;
- }
- } else if (negativeConditionRemaining > 0) {
- conditionRemaining = negativeConditionRemaining - 1;
- negativeConditionRemaining = 0;
- condition = !condition;
- if (!condition) {
- continue;
- }
- } else {
- condition = true;
- }
struct mCheat* cheat = mCheatListGetPointer(&cheats->list, i);
int32_t value = 0;
int32_t operand = cheat->operand;
uint32_t operationsRemaining = cheat->repeat;
uint32_t address = cheat->address;
bool performAssignment = false;
+ bool condition = true;
+ int conditionRemaining = 0;
+ int negativeConditionRemaining = 0;
+
for (; operationsRemaining; --operationsRemaining) {
switch (cheat->type) {
case CHEAT_ASSIGN:
@@ -312,46 +300,55 @@ void mCheatRefresh(struct mCheatDevice* device, struct mCheatSet* cheats) {
condition = _readMem(device->p, address, cheat->width) == operand;
conditionRemaining = cheat->repeat;
negativeConditionRemaining = cheat->negativeRepeat;
+ operationsRemaining = 1;
break;
case CHEAT_IF_NE:
condition = _readMem(device->p, address, cheat->width) != operand;
conditionRemaining = cheat->repeat;
negativeConditionRemaining = cheat->negativeRepeat;
+ operationsRemaining = 1;
break;
case CHEAT_IF_LT:
condition = _readMem(device->p, address, cheat->width) < operand;
conditionRemaining = cheat->repeat;
negativeConditionRemaining = cheat->negativeRepeat;
+ operationsRemaining = 1;
break;
case CHEAT_IF_GT:
condition = _readMem(device->p, address, cheat->width) > operand;
conditionRemaining = cheat->repeat;
negativeConditionRemaining = cheat->negativeRepeat;
+ operationsRemaining = 1;
break;
case CHEAT_IF_ULT:
condition = (uint32_t) _readMem(device->p, address, cheat->width) < (uint32_t) operand;
conditionRemaining = cheat->repeat;
negativeConditionRemaining = cheat->negativeRepeat;
+ operationsRemaining = 1;
break;
case CHEAT_IF_UGT:
condition = (uint32_t) _readMem(device->p, address, cheat->width) > (uint32_t) operand;
conditionRemaining = cheat->repeat;
negativeConditionRemaining = cheat->negativeRepeat;
+ operationsRemaining = 1;
break;
case CHEAT_IF_AND:
condition = _readMem(device->p, address, cheat->width) & operand;
conditionRemaining = cheat->repeat;
negativeConditionRemaining = cheat->negativeRepeat;
+ operationsRemaining = 1;
break;
case CHEAT_IF_LAND:
condition = _readMem(device->p, address, cheat->width) && operand;
conditionRemaining = cheat->repeat;
negativeConditionRemaining = cheat->negativeRepeat;
+ operationsRemaining = 1;
break;
case CHEAT_IF_NAND:
condition = !(_readMem(device->p, address, cheat->width) & operand);
conditionRemaining = cheat->repeat;
negativeConditionRemaining = cheat->negativeRepeat;
+ operationsRemaining = 1;
break;
}
@@ -362,6 +359,18 @@ void mCheatRefresh(struct mCheatDevice* device, struct mCheatSet* cheats) {
address += cheat->addressOffset;
operand += cheat->operandOffset;
}
+
+
+ if (elseLoc && i == elseLoc) {
+ i = endLoc;
+ endLoc = 0;
+ }
+ if (conditionRemaining > 0 && !condition) {
+ i += conditionRemaining;
+ } else if (negativeConditionRemaining > 0) {
+ elseLoc = i + conditionRemaining;
+ endLoc = elseLoc + negativeConditionRemaining;
+ }
}
}
diff --git a/src/core/map-cache.c b/src/core/map-cache.c
new file mode 100644
index 000000000..495978672
--- /dev/null
+++ b/src/core/map-cache.c
@@ -0,0 +1,205 @@
+/* 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
+
+void mMapCacheInit(struct mMapCache* cache) {
+ // TODO: Reconfigurable cache for space savings
+ cache->cache = NULL;
+ cache->config = mMapCacheConfigurationFillShouldStore(0);
+ cache->status = NULL;
+}
+
+static void _freeCache(struct mMapCache* cache) {
+ size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig));
+ mappedMemoryFree(cache->cache, 8 * 8 * sizeof(color_t) * tiles);
+ mappedMemoryFree(cache->status, tiles * sizeof(*cache->status));
+ cache->cache = NULL;
+ cache->status = NULL;
+}
+
+static void _redoCacheSize(struct mMapCache* cache) {
+ if (!mMapCacheConfigurationIsShouldStore(cache->config)) {
+ return;
+ }
+
+ size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig));
+ cache->cache = anonymousMemoryMap(8 * 8 * sizeof(color_t) * tiles);
+ cache->status = anonymousMemoryMap(tiles * sizeof(*cache->status));
+}
+
+void mMapCacheConfigure(struct mMapCache* cache, mMapCacheConfiguration config) {
+ if (config == cache->config) {
+ return;
+ }
+ _freeCache(cache);
+ cache->config = config;
+ _redoCacheSize(cache);
+}
+
+void mMapCacheConfigureSystem(struct mMapCache* cache, mMapCacheSystemInfo config) {
+ if (config == cache->sysConfig) {
+ return;
+ }
+ _freeCache(cache);
+ cache->sysConfig = config;
+ _redoCacheSize(cache);
+
+ size_t mapSize = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig));
+ cache->mapSize = mapSize << mMapCacheSystemInfoGetMapAlign(cache->sysConfig);
+}
+
+void mMapCacheConfigureMap(struct mMapCache* cache, uint32_t mapStart) {
+ size_t tiles = (1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig)) * (1 << mMapCacheSystemInfoGetTilesHigh(cache->sysConfig));
+ memset(cache->status, 0, tiles * sizeof(*cache->status));
+ cache->mapStart = mapStart;
+}
+
+void mMapCacheDeinit(struct mMapCache* cache) {
+ _freeCache(cache);
+}
+
+void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address) {
+ if (address >= cache->mapStart && address < cache->mapStart + cache->mapSize) {
+ address -= cache->mapStart;
+ struct mMapCacheEntry* status = &cache->status[address >> mMapCacheSystemInfoGetMapAlign(cache->sysConfig)];
+ ++status->vramVersion;
+ status->flags = mMapCacheEntryFlagsClearVramClean(status->flags);
+ status->tileStatus[mMapCacheEntryFlagsGetPaletteId(status->flags)].vramClean = 0;
+ }
+}
+
+static inline void _cleanTile(struct mMapCache* cache, const color_t* tile, color_t* 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);
+ break;
+ case 1:
+ for (y = 0; y < 8; ++y) {
+ for (x = 0; x < 8; ++x) {
+ mapOut[y * stride + (7 - x)] = tile[y * 8 + x];
+ }
+ }
+ 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);
+ break;
+ case 3:
+ for (y = 0; y < 8; ++y) {
+ for (x = 0; x < 8; ++x) {
+ mapOut[(7 - y) * stride + (7 - x)] = tile[y * 8 + x];
+ }
+ }
+ break;
+ }
+}
+
+uint32_t mMapCacheTileId(struct mMapCache* cache, unsigned x, unsigned y) {
+ int tilesWide = mMapCacheSystemInfoGetTilesWide(cache->sysConfig);
+ int tilesHigh = mMapCacheSystemInfoGetTilesHigh(cache->sysConfig);
+ int stride = 1 << mMapCacheSystemInfoGetMacroTileSize(cache->sysConfig);
+ x &= (1 << tilesWide) - 1;
+ y &= (1 << tilesHigh) - 1;
+ unsigned xMajor = x & ~(stride - 1);
+ unsigned yMajor = y >> mMapCacheSystemInfoGetMacroTileSize(cache->sysConfig);
+ x &= stride - 1;
+ y &= stride - 1;
+ yMajor <<= tilesWide;
+ y += xMajor + yMajor;
+ return stride * y + x;
+}
+
+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;
+ if (!mMapCacheEntryFlagsIsVramClean(status->flags)) {
+ status->flags = mMapCacheEntryFlagsFillVramClean(status->flags);
+ cache->mapParser(cache, status, &cache->vram[cache->mapStart + (location << mMapCacheSystemInfoGetMapAlign(cache->sysConfig))]);
+ }
+ unsigned tileId = status->tileId + cache->tileStart;
+ if (tileId >= mTileCacheSystemInfoGetMaxTiles(cache->tileCache->sysConfig)) {
+ tileId = 0;
+ }
+ tile = mTileCacheGetTileIfDirty(cache->tileCache, status->tileStatus, tileId, mMapCacheEntryFlagsGetPaletteId(status->flags));
+ if (!tile) {
+ if (mMapCacheEntryFlagsIsVramClean(status->flags) && memcmp(status, &entry[location], sizeof(*entry)) == 0) {
+ return;
+ }
+ tile = mTileCacheGetTile(cache->tileCache, tileId, mMapCacheEntryFlagsGetPaletteId(status->flags));
+ }
+
+ size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig);
+ color_t* mapOut = &cache->cache[(y * stride + x) * 8];
+ _cleanTile(cache, tile, mapOut, status);
+ entry[location] = *status;
+}
+
+bool mMapCacheCheckTile(struct mMapCache* cache, const struct mMapCacheEntry* entry, unsigned x, unsigned y) {
+ size_t location = mMapCacheTileId(cache, x, y);
+ struct mMapCacheEntry* status = &cache->status[location];
+ int paletteId = mMapCacheEntryFlagsGetPaletteId(status->flags);
+ const color_t* 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)) {
+ tileId = 0;
+ }
+ tile = mTileCacheGetTileIfDirty(cache->tileCache, &status->tileStatus[paletteId], tileId, mMapCacheEntryFlagsGetPaletteId(status->flags));
+ return !tile;
+ }
+ return false;
+}
+
+void mMapCacheCleanRow(struct mMapCache* cache, unsigned y) {
+ // TODO: Cache
+ int tilesWide = 1 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig);
+ int macroTile = (1 << mMapCacheSystemInfoGetMacroTileSize(cache->sysConfig)) - 1;
+ size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig);
+ int location = 0;
+ int x;
+ for (x = 0; x < tilesWide; ++x) {
+ if (!(x & macroTile)) {
+ location = mMapCacheTileId(cache, x, y);
+ } else {
+ ++location;
+ }
+ struct mMapCacheEntry* status = &cache->status[location];
+ if (!mMapCacheEntryFlagsIsVramClean(status->flags)) {
+ status->flags = mMapCacheEntryFlagsFillVramClean(status->flags);
+ cache->mapParser(cache, status, &cache->vram[cache->mapStart + (location << mMapCacheSystemInfoGetMapAlign(cache->sysConfig))]);
+ }
+ unsigned tileId = status->tileId + cache->tileStart;
+ 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];
+ _cleanTile(cache, tile, mapOut, status);
+ }
+}
+
+const color_t* mMapCacheGetRow(struct mMapCache* cache, unsigned y) {
+ size_t stride = 8 << mMapCacheSystemInfoGetTilesWide(cache->sysConfig);
+ return &cache->cache[y * stride];
+}
diff --git a/src/core/serialize.c b/src/core/serialize.c
index 399a8b006..125309fc1 100644
--- a/src/core/serialize.c
+++ b/src/core/serialize.c
@@ -407,11 +407,8 @@ void* mCoreExtractState(struct mCore* core, struct VFile* vf, struct mStateExtda
}
#endif
ssize_t stateSize = core->stateSize(core);
- vf->seek(vf, 0, SEEK_SET);
- if (vf->size(vf) < stateSize) {
- return false;
- }
void* state = anonymousMemoryMap(stateSize);
+ vf->seek(vf, 0, SEEK_SET);
if (vf->read(vf, state, stateSize) != stateSize) {
mappedMemoryFree(state, stateSize);
return 0;
diff --git a/src/core/test/core.c b/src/core/test/core.c
index 3fcebaf31..10c566b2c 100644
--- a/src/core/test/core.c
+++ b/src/core/test/core.c
@@ -34,9 +34,3 @@ M_TEST_SUITE_DEFINE(mCore,
#endif
cmocka_unit_test(findNullVF),
cmocka_unit_test(findEmpty))
-
-int TestRunCore(void) {
- int failures = 0;
- failures += M_TEST_SUITE_RUN(mCore);
- return failures;
-}
diff --git a/src/core/thread.c b/src/core/thread.c
index 782b573df..3a0c802ea 100644
--- a/src/core/thread.c
+++ b/src/core/thread.c
@@ -158,7 +158,6 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
};
core->addCoreCallbacks(core, &callbacks);
core->setSync(core, &threadContext->impl->sync);
- core->reset(core);
struct mLogFilter filter;
if (!threadContext->logger.d.filter) {
@@ -168,12 +167,13 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
}
mCoreThreadRewindParamsChanged(threadContext);
-
- _changeState(threadContext->impl, THREAD_RUNNING, true);
-
if (threadContext->startCallback) {
threadContext->startCallback(threadContext);
}
+
+ core->reset(core);
+ _changeState(threadContext->impl, THREAD_RUNNING, true);
+
if (threadContext->resetCallback) {
threadContext->resetCallback(threadContext);
}
@@ -195,38 +195,58 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
}
}
- int resetScheduled = 0;
+ enum mCoreThreadState deferred = THREAD_RUNNING;
MutexLock(&impl->stateMutex);
while (impl->state > THREAD_MAX_RUNNING && impl->state < THREAD_EXITING) {
- if (impl->state == THREAD_PAUSING) {
- impl->state = THREAD_PAUSED;
- ConditionWake(&impl->stateCond);
- }
+ deferred = impl->state;
+
if (impl->state == THREAD_INTERRUPTING) {
impl->state = THREAD_INTERRUPTED;
ConditionWake(&impl->stateCond);
}
- if (impl->state == THREAD_RUN_ON) {
- if (threadContext->run) {
- threadContext->run(threadContext);
- }
- impl->state = impl->savedState;
- ConditionWake(&impl->stateCond);
+
+ if (impl->state == THREAD_PAUSING) {
+ impl->state = THREAD_PAUSED;
}
if (impl->state == THREAD_RESETING) {
impl->state = THREAD_RUNNING;
- resetScheduled = 1;
}
- while (impl->state == THREAD_PAUSED || impl->state == THREAD_INTERRUPTED || impl->state == THREAD_WAITING) {
+
+ if (deferred >= THREAD_MIN_DEFERRED && deferred <= THREAD_MAX_DEFERRED) {
+ break;
+ }
+
+ deferred = impl->state;
+ while (impl->state >= THREAD_WAITING && impl->state <= THREAD_MAX_WAITING) {
ConditionWait(&impl->stateCond, &impl->stateMutex);
}
}
MutexUnlock(&impl->stateMutex);
- if (resetScheduled) {
+ switch (deferred) {
+ case THREAD_PAUSING:
+ if (threadContext->pauseCallback) {
+ threadContext->pauseCallback(threadContext);
+ }
+ break;
+ case THREAD_PAUSED:
+ if (threadContext->unpauseCallback) {
+ threadContext->unpauseCallback(threadContext);
+ }
+ break;
+ case THREAD_RUN_ON:
+ if (threadContext->run) {
+ threadContext->run(threadContext);
+ }
+ threadContext->impl->state = threadContext->impl->savedState;
+ break;
+ case THREAD_RESETING:
core->reset(core);
if (threadContext->resetCallback) {
threadContext->resetCallback(threadContext);
}
+ break;
+ default:
+ break;
}
}
diff --git a/src/core/tile-cache.c b/src/core/tile-cache.c
index 3c34a8d86..2a7c8cf3a 100644
--- a/src/core/tile-cache.c
+++ b/src/core/tile-cache.c
@@ -12,60 +12,42 @@ void mTileCacheInit(struct mTileCache* cache) {
cache->cache = NULL;
cache->config = mTileCacheConfigurationFillShouldStore(0);
cache->status = NULL;
- cache->activePalette = 0;
- memset(cache->globalPaletteVersion, 0, sizeof(cache->globalPaletteVersion));
+ cache->globalPaletteVersion = NULL;
+ cache->palette = NULL;
}
static void _freeCache(struct mTileCache* cache) {
- unsigned count0;
- count0 = 1 << mTileCacheSystemInfoGetPalette0Count(cache->sysConfig);
- unsigned count1;
- count1 = 1 << mTileCacheSystemInfoGetPalette1Count(cache->sysConfig);
+ unsigned size = 1 << mTileCacheSystemInfoGetPaletteCount(cache->sysConfig);
unsigned tiles = mTileCacheSystemInfoGetMaxTiles(cache->sysConfig);
- unsigned size = count0 > count1 ? count0 : count1;
if (cache->cache) {
- mappedMemoryFree(cache->cache, 8 * 8 * 2 * tiles * size);
+ mappedMemoryFree(cache->cache, 8 * 8 * sizeof(color_t) * tiles * size);
cache->cache = NULL;
}
if (cache->status) {
mappedMemoryFree(cache->status, tiles * size * sizeof(*cache->status));
cache->status = NULL;
}
- free(cache->globalPaletteVersion[0]);
- free(cache->globalPaletteVersion[1]);
- memset(cache->globalPaletteVersion, 0, sizeof(cache->globalPaletteVersion));
+ free(cache->globalPaletteVersion);
+ cache->globalPaletteVersion = NULL;
+ free(cache->palette);
+ cache->palette = NULL;
}
static void _redoCacheSize(struct mTileCache* cache) {
if (!mTileCacheConfigurationIsShouldStore(cache->config)) {
return;
}
- unsigned count0 = mTileCacheSystemInfoGetPalette0Count(cache->sysConfig);
- unsigned bpp0 = mTileCacheSystemInfoGetPalette0BPP(cache->sysConfig);
- bpp0 = 1 << (1 << bpp0);
- if (count0) {
- count0 = 1 << count0;
- }
- unsigned count1 = mTileCacheSystemInfoGetPalette1Count(cache->sysConfig);
- unsigned bpp1 = mTileCacheSystemInfoGetPalette1BPP(cache->sysConfig);
- bpp1 = 1 << (1 << bpp1);
- if (count1) {
- count1 = 1 << count1;
- }
- unsigned size = count0 > count1 ? count0 : count1;
- if (!size) {
- return;
- }
+ unsigned size = mTileCacheSystemInfoGetPaletteCount(cache->sysConfig);
+ unsigned bpp = mTileCacheSystemInfoGetPaletteBPP(cache->sysConfig);
+ cache->bpp = bpp;
+ bpp = 1 << (1 << bpp);
+ size = 1 << size;
cache->entriesPerTile = size;
unsigned tiles = mTileCacheSystemInfoGetMaxTiles(cache->sysConfig);
- cache->cache = anonymousMemoryMap(8 * 8 * 2 * tiles * size);
+ cache->cache = anonymousMemoryMap(8 * 8 * sizeof(color_t) * tiles * size);
cache->status = anonymousMemoryMap(tiles * size * sizeof(*cache->status));
- if (count0) {
- cache->globalPaletteVersion[0] = malloc(count0 * bpp0 * sizeof(*cache->globalPaletteVersion[0]));
- }
- if (count1) {
- cache->globalPaletteVersion[1] = malloc(count1 * bpp1 * sizeof(*cache->globalPaletteVersion[1]));
- }
+ cache->globalPaletteVersion = malloc(size * sizeof(*cache->globalPaletteVersion));
+ cache->palette = malloc(size * bpp * sizeof(*cache->palette));
}
void mTileCacheConfigure(struct mTileCache* cache, mTileCacheConfiguration config) {
@@ -74,9 +56,11 @@ void mTileCacheConfigure(struct mTileCache* cache, mTileCacheConfiguration confi
_redoCacheSize(cache);
}
-void mTileCacheConfigureSystem(struct mTileCache* cache, mTileCacheSystemInfo config) {
+void mTileCacheConfigureSystem(struct mTileCache* cache, mTileCacheSystemInfo config, uint32_t tileBase, uint32_t paletteBase) {
_freeCache(cache);
cache->sysConfig = config;
+ cache->tileBase = tileBase;
+ cache->paletteBase = paletteBase;
_redoCacheSize(cache);
}
@@ -85,40 +69,41 @@ void mTileCacheDeinit(struct mTileCache* cache) {
}
void mTileCacheWriteVRAM(struct mTileCache* cache, uint32_t address) {
+ if (address < cache->tileBase) {
+ return;
+ }
+ address -= cache->tileBase;
unsigned bpp = cache->bpp + 3;
unsigned count = cache->entriesPerTile;
+ address >>= bpp;
+ if (address >= mTileCacheSystemInfoGetMaxTiles(cache->sysConfig)) {
+ return;
+ }
size_t i;
for (i = 0; i < count; ++i) {
- cache->status[(address >> bpp) * count + i].vramClean = 0;
- ++cache->status[(address >> bpp) * count + i].vramVersion;
+ cache->status[address * count + i].vramClean = 0;
+ ++cache->status[address * count + i].vramVersion;
}
}
-void mTileCacheWritePalette(struct mTileCache* cache, uint32_t address) {
- if (cache->globalPaletteVersion[0]) {
- ++cache->globalPaletteVersion[0][address >> 1];
+void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, color_t color) {
+ if (entry < cache->paletteBase) {
+ return;
}
- if (cache->globalPaletteVersion[1]) {
- ++cache->globalPaletteVersion[1][address >> 1];
+ entry -= cache->paletteBase;
+ unsigned maxEntry = (1 << (1 << cache->bpp)) * cache->entriesPerTile;
+ if (entry >= maxEntry) {
+ return;
}
+ cache->palette[entry] = color;
+ entry >>= (1 << mTileCacheSystemInfoGetPaletteBPP(cache->sysConfig));
+ ++cache->globalPaletteVersion[entry];
}
-void mTileCacheSetPalette(struct mTileCache* cache, int palette) {
- cache->activePalette = palette;
- if (palette == 0) {
- cache->bpp = mTileCacheSystemInfoGetPalette0BPP(cache->sysConfig);
- cache->count = 1 << mTileCacheSystemInfoGetPalette0Count(cache->sysConfig);
- } else {
- cache->bpp = mTileCacheSystemInfoGetPalette1BPP(cache->sysConfig);
- cache->count = 1 << mTileCacheSystemInfoGetPalette1Count(cache->sysConfig);
- }
- cache->entries = 1 << (1 << cache->bpp);
-}
-
-static void _regenerateTile4(struct mTileCache* cache, uint16_t* tile, unsigned tileId, unsigned paletteId) {
+static void _regenerateTile4(struct mTileCache* cache, color_t* tile, unsigned tileId, unsigned paletteId) {
uint8_t* start = (uint8_t*) &cache->vram[tileId << 3];
paletteId <<= 2;
- uint16_t* palette = &cache->palette[paletteId];
+ color_t* palette = &cache->palette[paletteId];
int i;
for (i = 0; i < 8; ++i) {
uint8_t tileDataLower = start[0];
@@ -126,108 +111,114 @@ static void _regenerateTile4(struct mTileCache* cache, uint16_t* tile, unsigned
start += 2;
int pixel;
pixel = ((tileDataUpper & 128) >> 6) | ((tileDataLower & 128) >> 7);
- tile[0] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[0] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = ((tileDataUpper & 64) >> 5) | ((tileDataLower & 64) >> 6);
- tile[1] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[1] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = ((tileDataUpper & 32) >> 4) | ((tileDataLower & 32) >> 5);
- tile[2] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[2] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = ((tileDataUpper & 16) >> 3) | ((tileDataLower & 16) >> 4);
- tile[3] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[3] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = ((tileDataUpper & 8) >> 2) | ((tileDataLower & 8) >> 3);
- tile[4] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[4] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = ((tileDataUpper & 4) >> 1) | ((tileDataLower & 4) >> 2);
- tile[5] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[5] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (tileDataUpper & 2) | ((tileDataLower & 2) >> 1);
- tile[6] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[6] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = ((tileDataUpper & 1) << 1) | (tileDataLower & 1);
- tile[7] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[7] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
tile += 8;
}
}
-static void _regenerateTile16(struct mTileCache* cache, uint16_t* tile, unsigned tileId, unsigned paletteId) {
+static void _regenerateTile16(struct mTileCache* cache, color_t* tile, unsigned tileId, unsigned paletteId) {
uint32_t* start = (uint32_t*) &cache->vram[tileId << 4];
paletteId <<= 4;
- uint16_t* palette = &cache->palette[paletteId];
+ color_t* palette = &cache->palette[paletteId];
int i;
for (i = 0; i < 8; ++i) {
uint32_t line = *start;
++start;
int pixel;
pixel = line & 0xF;
- tile[0] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[0] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 4) & 0xF;
- tile[1] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[1] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 8) & 0xF;
- tile[2] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[2] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 12) & 0xF;
- tile[3] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[3] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 16) & 0xF;
- tile[4] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[4] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 20) & 0xF;
- tile[5] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[5] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 24) & 0xF;
- tile[6] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[6] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 28) & 0xF;
- tile[7] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[7] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
tile += 8;
}
}
-static void _regenerateTile256(struct mTileCache* cache, uint16_t* tile, unsigned tileId, unsigned paletteId) {
+static void _regenerateTile256(struct mTileCache* cache, color_t* tile, unsigned tileId, unsigned paletteId) {
uint32_t* start = (uint32_t*) &cache->vram[tileId << 5];
paletteId <<= 8;
- uint16_t* palette = &cache->palette[paletteId];
+ color_t* palette = &cache->palette[paletteId];
int i;
for (i = 0; i < 8; ++i) {
uint32_t line = *start;
++start;
int pixel;
pixel = line & 0xFF;
- tile[0] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[0] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 8) & 0xFF;
- tile[1] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[1] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 16) & 0xFF;
- tile[2] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[2] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 24) & 0xFF;
- tile[3] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[3] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
line = *start;
++start;
pixel = line & 0xFF;
- tile[4] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[4] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 8) & 0xFF;
- tile[5] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[5] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 16) & 0xFF;
- tile[6] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[6] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
pixel = (line >> 24) & 0xFF;
- tile[7] = pixel ? palette[pixel] | 0x8000 : palette[pixel] & 0x7FFF;
+ tile[7] = pixel ? palette[pixel] | 0xFF000000 : palette[pixel];
tile += 8;
}
}
-static inline uint16_t* _tileLookup(struct mTileCache* cache, unsigned tileId, unsigned paletteId) {
+static inline color_t* _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 >= 1 << mTileCacheSystemInfoGetPaletteCount(cache->sysConfig)) {
+ abort();
+ }
+#endif
return &cache->cache[(tileId + paletteId * tiles) << 6];
} else {
return cache->temporaryTile;
}
}
-const uint16_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId) {
- unsigned cPaletteId = cache->activePalette;
+const color_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, unsigned paletteId) {
unsigned count = cache->entriesPerTile;
unsigned bpp = cache->bpp;
struct mTileCacheEntry* status = &cache->status[tileId * count + paletteId];
struct mTileCacheEntry desiredStatus = {
- .paletteVersion = cache->globalPaletteVersion[cPaletteId][paletteId],
+ .paletteVersion = cache->globalPaletteVersion[paletteId],
.vramVersion = status->vramVersion,
.vramClean = 1,
- .paletteId = paletteId,
- .activePalette = cPaletteId
+ .paletteId = paletteId
};
- uint16_t* tile = _tileLookup(cache, tileId, paletteId);
+ color_t* tile = _tileLookup(cache, tileId, paletteId);
if (!mTileCacheConfigurationIsShouldStore(cache->config) || memcmp(status, &desiredStatus, sizeof(*status))) {
switch (bpp) {
case 0:
@@ -247,19 +238,17 @@ const uint16_t* mTileCacheGetTile(struct mTileCache* cache, unsigned tileId, uns
return tile;
}
-const uint16_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileCacheEntry* entry, unsigned tileId, unsigned paletteId) {
- unsigned cPaletteId = cache->activePalette;
+const color_t* 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];
struct mTileCacheEntry desiredStatus = {
- .paletteVersion = cache->globalPaletteVersion[cPaletteId][paletteId],
+ .paletteVersion = cache->globalPaletteVersion[paletteId],
.vramVersion = status->vramVersion,
.vramClean = 1,
- .paletteId = paletteId,
- .activePalette = cPaletteId
+ .paletteId = paletteId
};
- uint16_t* tile = NULL;
+ color_t* tile = NULL;
if (memcmp(status, &desiredStatus, sizeof(*status))) {
tile = _tileLookup(cache, tileId, paletteId);
switch (bpp) {
@@ -284,26 +273,10 @@ const uint16_t* mTileCacheGetTileIfDirty(struct mTileCache* cache, struct mTileC
return tile;
}
-const uint8_t* mTileCacheGetRawTile(struct mTileCache* cache, unsigned tileId) {
- unsigned bpp = cache->bpp;
- switch (bpp) {
- case 0:
- return NULL;
- default:
- return (uint8_t*) &cache->vram[tileId << (2 + bpp)];
- }
+const color_t* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId) {
+ return &cache->palette[paletteId << (1 << cache->bpp)];
}
-const uint16_t* mTileCacheGetPalette(struct mTileCache* cache, unsigned paletteId) {
- unsigned bpp = cache->bpp;
- switch (bpp) {
- default:
- return NULL;
- case 1:
- return &cache->palette[paletteId << 2];
- case 2:
- return &cache->palette[paletteId << 4];
- case 3:
- return &cache->palette[paletteId << 8];
- }
+const uint16_t* mTileCacheGetVRAM(struct mTileCache* cache, unsigned tileId) {
+ return &cache->vram[tileId << (cache->bpp + 2)];
}
diff --git a/src/core/timing.c b/src/core/timing.c
index 1d22a93cb..adbbfbbf8 100644
--- a/src/core/timing.c
+++ b/src/core/timing.c
@@ -7,6 +7,7 @@
void mTimingInit(struct mTiming* timing, int32_t* relativeCycles, int32_t* nextEvent) {
timing->root = NULL;
+ timing->reroot = NULL;
timing->masterCycles = 0;
timing->relativeCycles = relativeCycles;
timing->nextEvent = nextEvent;
@@ -17,6 +18,7 @@ void mTimingDeinit(struct mTiming* timing) {
void mTimingClear(struct mTiming* timing) {
timing->root = NULL;
+ timing->reroot = NULL;
timing->masterCycles = 0;
}
@@ -77,6 +79,11 @@ int32_t mTimingTick(struct mTiming* timing, int32_t cycles) {
timing->root = next->next;
next->callback(timing, next->context, -nextWhen);
}
+ if (timing->reroot) {
+ timing->root = timing->reroot;
+ timing->reroot = NULL;
+ *timing->nextEvent = mTimingNextEvent(timing);
+ }
return *timing->nextEvent;
}
diff --git a/src/feature/video-logger.c b/src/feature/video-logger.c
index ab071512d..6d9710872 100644
--- a/src/feature/video-logger.c
+++ b/src/feature/video-logger.c
@@ -687,8 +687,16 @@ void mVideoLogContextDestroy(struct mCore* core, struct mVideoLogContext* contex
void mVideoLogContextRewind(struct mVideoLogContext* context, struct mCore* core) {
_readHeader(context);
- if (core && core->stateSize(core) == context->initialStateSize) {
- core->loadState(core, context->initialState);
+ if (core) {
+ size_t size = core->stateSize(core);
+ if (size <= context->initialStateSize) {
+ core->loadState(core, context->initialState);
+ } else {
+ void* extendedState = anonymousMemoryMap(size);
+ memcpy(extendedState, context->initialState, context->initialStateSize);
+ core->loadState(core, extendedState);
+ mappedMemoryFree(extendedState, size);
+ }
}
off_t pointer = context->backing->seek(context->backing, 0, SEEK_CUR);
diff --git a/src/gb/audio.c b/src/gb/audio.c
index b8541b720..4a465a10e 100644
--- a/src/gb/audio.c
+++ b/src/gb/audio.c
@@ -25,7 +25,7 @@ const int GB_AUDIO_VOLUME_MAX = 0x100;
static bool _writeSweep(struct GBAudioSweep* sweep, uint8_t value);
static void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value);
-static bool _writeEnvelope(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);
@@ -153,6 +153,10 @@ void GBAudioReset(struct GBAudio* audio) {
audio->playingCh2 = false;
audio->playingCh3 = false;
audio->playingCh4 = false;
+ if (audio->p && (audio->p->model == GB_MODEL_DMG || audio->p->model == GB_MODEL_CGB)) {
+ audio->playingCh1 = true;
+ *audio->nr52 |= 0x01;
+ }
}
void GBAudioResizeBuffer(struct GBAudio* audio, size_t samples) {
@@ -178,7 +182,7 @@ void GBAudioWriteNR11(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) {
- if (!_writeEnvelope(&audio->ch1.envelope, value)) {
+ if (!_writeEnvelope(&audio->ch1.envelope, value, audio->style)) {
mTimingDeschedule(audio->timing, &audio->ch1Event);
audio->playingCh1 = false;
*audio->nr52 &= ~0x0001;
@@ -236,7 +240,7 @@ void GBAudioWriteNR21(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) {
- if (!_writeEnvelope(&audio->ch2.envelope, value)) {
+ if (!_writeEnvelope(&audio->ch2.envelope, value, audio->style)) {
mTimingDeschedule(audio->timing, &audio->ch2Event);
audio->playingCh2 = false;
*audio->nr52 &= ~0x0002;
@@ -354,7 +358,7 @@ void GBAudioWriteNR41(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) {
- if (!_writeEnvelope(&audio->ch4.envelope, value)) {
+ if (!_writeEnvelope(&audio->ch4.envelope, value, audio->style)) {
mTimingDeschedule(audio->timing, &audio->ch4Event);
audio->playingCh4 = false;
*audio->nr52 &= ~0x0008;
@@ -696,17 +700,16 @@ void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value) {
envelope->duty = GBAudioRegisterDutyGetDuty(value);
}
-bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value) {
+bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudioStyle style) {
envelope->stepTime = GBAudioRegisterSweepGetStepTime(value);
envelope->direction = GBAudioRegisterSweepGetDirection(value);
envelope->initialVolume = GBAudioRegisterSweepGetInitialVolume(value);
- if (!envelope->stepTime) {
+ if (style == GB_AUDIO_DMG && !envelope->stepTime) {
// TODO: Improve "zombie" mode
++envelope->currentVolume;
envelope->currentVolume &= 0xF;
}
_updateEnvelopeDead(envelope);
- envelope->nextStep = envelope->stepTime;
return (envelope->initialVolume || envelope->direction) && envelope->dead != 2;
}
@@ -960,6 +963,8 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt
mTimingSchedule(audio->timing, &audio->frameEvent, when);
LOAD_32LE(flags, 0, flagsIn);
+ audio->frame = GBSerializedAudioFlagsGetFrame(flags);
+
LOAD_32LE(ch1Flags, 0, &state->ch1.envelope);
audio->ch1.envelope.currentVolume = GBSerializedAudioFlagsGetCh1Volume(flags);
audio->ch1.envelope.dead = GBSerializedAudioFlagsGetCh1Dead(flags);
diff --git a/src/gb/core.c b/src/gb/core.c
index 397448fa9..8adffa633 100644
--- a/src/gb/core.c
+++ b/src/gb/core.c
@@ -31,8 +31,8 @@
static const struct mCoreChannelInfo _GBVideoLayers[] = {
{ 0, "bg", "Background", NULL },
- { 1, "obj", "Objects", NULL },
- { 2, "win", "Window", NULL },
+ { 1, "bgwin", "Window", NULL },
+ { 2, "obj", "Objects", NULL },
};
static const struct mCoreChannelInfo _GBAudioChannels[] = {
@@ -176,21 +176,50 @@ static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* conf
gb->video.frameskip = core->opts.frameskip;
int color;
- if (mCoreConfigGetIntValue(&core->config, "gb.pal[0]", &color)) {
- GBVideoSetPalette(&gb->video, 0, color);
+ if (mCoreConfigGetIntValue(config, "gb.pal[0]", &color)) {
+ GBVideoSetPalette(&gb->video, 0, color);
}
- if (mCoreConfigGetIntValue(&core->config, "gb.pal[1]", &color)) {
- GBVideoSetPalette(&gb->video, 1, color);
+ if (mCoreConfigGetIntValue(config, "gb.pal[1]", &color)) {
+ GBVideoSetPalette(&gb->video, 1, color);
}
- if (mCoreConfigGetIntValue(&core->config, "gb.pal[2]", &color)) {
- GBVideoSetPalette(&gb->video, 2, color);
+ if (mCoreConfigGetIntValue(config, "gb.pal[2]", &color)) {
+ GBVideoSetPalette(&gb->video, 2, color);
}
- if (mCoreConfigGetIntValue(&core->config, "gb.pal[3]", &color)) {
- GBVideoSetPalette(&gb->video, 3, color);
+ if (mCoreConfigGetIntValue(config, "gb.pal[3]", &color)) {
+ GBVideoSetPalette(&gb->video, 3, color);
+ }
+ if (mCoreConfigGetIntValue(config, "gb.pal[4]", &color)) {
+ GBVideoSetPalette(&gb->video, 4, color);
+ }
+ if (mCoreConfigGetIntValue(config, "gb.pal[5]", &color)) {
+ GBVideoSetPalette(&gb->video, 5, color);
+ }
+ if (mCoreConfigGetIntValue(config, "gb.pal[6]", &color)) {
+ GBVideoSetPalette(&gb->video, 6, color);
+ }
+ if (mCoreConfigGetIntValue(config, "gb.pal[7]", &color)) {
+ GBVideoSetPalette(&gb->video, 7, color);
+ }
+ if (mCoreConfigGetIntValue(config, "gb.pal[8]", &color)) {
+ GBVideoSetPalette(&gb->video, 8, color);
+ }
+ if (mCoreConfigGetIntValue(config, "gb.pal[9]", &color)) {
+ GBVideoSetPalette(&gb->video, 9, color);
+ }
+ if (mCoreConfigGetIntValue(config, "gb.pal[10]", &color)) {
+ GBVideoSetPalette(&gb->video, 10, color);
+ }
+ if (mCoreConfigGetIntValue(config, "gb.pal[11]", &color)) {
+ GBVideoSetPalette(&gb->video, 11, color);
}
mCoreConfigCopyValue(&core->config, config, "gb.bios");
+ mCoreConfigCopyValue(&core->config, config, "sgb.bios");
mCoreConfigCopyValue(&core->config, config, "gbc.bios");
+ mCoreConfigCopyValue(&core->config, config, "gb.model");
+ mCoreConfigCopyValue(&core->config, config, "sgb.model");
+ mCoreConfigCopyValue(&core->config, config, "cgb.model");
+ mCoreConfigCopyValue(&core->config, config, "sgb.borders");
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
struct GBCore* gbcore = (struct GBCore*) core;
@@ -199,9 +228,14 @@ static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* conf
}
static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
- UNUSED(core);
- *width = GB_VIDEO_HORIZONTAL_PIXELS;
- *height = GB_VIDEO_VERTICAL_PIXELS;
+ struct GB* gb = core->board;
+ if (gb && (gb->model != GB_MODEL_SGB || !gb->video.sgbBorders)) {
+ *width = GB_VIDEO_HORIZONTAL_PIXELS;
+ *height = GB_VIDEO_VERTICAL_PIXELS;
+ } else {
+ *width = 256;
+ *height = 224;
+ }
}
static void _GBCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
@@ -333,6 +367,25 @@ static void _GBCoreReset(struct mCore* core) {
}
}
+ const char* modelGB = mCoreConfigGetValue(&core->config, "gb.model");
+ const char* modelCGB = mCoreConfigGetValue(&core->config, "cgb.model");
+ const char* modelSGB = mCoreConfigGetValue(&core->config, "sgb.model");
+ if (modelGB || modelCGB || modelSGB) {
+ GBDetectModel(gb);
+ if (gb->model == GB_MODEL_DMG && modelGB) {
+ gb->model = GBNameToModel(modelGB);
+ } else if (gb->model == GB_MODEL_CGB && modelCGB) {
+ gb->model = GBNameToModel(modelCGB);
+ } else if (gb->model == GB_MODEL_SGB && modelSGB) {
+ gb->model = GBNameToModel(modelSGB);
+ }
+ }
+
+ int fakeBool;
+ if (mCoreConfigGetIntValue(&core->config, "sgb.borders", &fakeBool)) {
+ gb->video.sgbBorders = fakeBool;
+ }
+
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
if (!gb->biosVf && core->opts.useBios) {
struct VFile* bios = NULL;
@@ -352,9 +405,13 @@ static void _GBCoreReset(struct mCore* core) {
switch (gb->model) {
case GB_MODEL_DMG:
- case GB_MODEL_SGB: // TODO
+ case GB_MODEL_MGB: // TODO
configPath = mCoreConfigGetValue(&core->config, "gb.bios");
break;
+ case GB_MODEL_SGB:
+ case GB_MODEL_SGB2: // TODO
+ configPath = mCoreConfigGetValue(&core->config, "sgb.bios");
+ break;
case GB_MODEL_CGB:
case GB_MODEL_AGB:
configPath = mCoreConfigGetValue(&core->config, "gbc.bios");
@@ -377,9 +434,13 @@ static void _GBCoreReset(struct mCore* core) {
mCoreConfigDirectory(path, PATH_MAX);
switch (gb->model) {
case GB_MODEL_DMG:
- case GB_MODEL_SGB: // TODO
+ case GB_MODEL_MGB: // TODO
strncat(path, PATH_SEP "gb_bios.bin", PATH_MAX - strlen(path));
break;
+ case GB_MODEL_SGB:
+ case GB_MODEL_SGB2: // TODO
+ strncat(path, PATH_SEP "sgb_bios.bin", PATH_MAX - strlen(path));
+ break;
case GB_MODEL_CGB:
case GB_MODEL_AGB:
strncat(path, PATH_SEP "gbc_bios.bin", PATH_MAX - strlen(path));
@@ -502,6 +563,9 @@ static void _GBCoreSetPeripheral(struct mCore* core, int type, void* periph) {
case mPERIPH_RUMBLE:
gb->memory.rumble = periph;
break;
+ case mPERIPH_IMAGE_SOURCE:
+ gb->memory.cam = periph;
+ break;
default:
return;
}
@@ -581,7 +645,9 @@ size_t _GBListMemoryBlocks(const struct mCore* core, const struct mCoreMemoryBlo
const struct GB* gb = core->board;
switch (gb->model) {
case GB_MODEL_DMG:
+ case GB_MODEL_MGB:
case GB_MODEL_SGB:
+ case GB_MODEL_SGB2:
default:
*blocks = _GBMemoryBlocks;
return sizeof(_GBMemoryBlocks) / sizeof(*_GBMemoryBlocks);
diff --git a/src/gb/extra/proxy.c b/src/gb/extra/proxy.c
index 2b015ae6c..eb2c29e79 100644
--- a/src/gb/extra/proxy.c
+++ b/src/gb/extra/proxy.c
@@ -5,15 +5,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include
-#include
+#include
#include
#include
#define BUFFER_OAM 1
+#define BUFFER_SGB 2
-static void GBVideoProxyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model);
+static void GBVideoProxyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders);
static void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer);
static uint8_t GBVideoProxyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
+static void GBVideoProxyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data);
static void GBVideoProxyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address);
static void GBVideoProxyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam);
static void GBVideoProxyRendererWritePalette(struct GBVideoRenderer* renderer, int address, uint16_t value);
@@ -30,6 +32,7 @@ void GBVideoProxyRendererCreate(struct GBVideoProxyRenderer* renderer, struct GB
renderer->d.init = GBVideoProxyRendererInit;
renderer->d.deinit = GBVideoProxyRendererDeinit;
renderer->d.writeVideoRegister = GBVideoProxyRendererWriteVideoRegister;
+ renderer->d.writeSGBPacket = GBVideoProxyRendererWriteSGBPacket;
renderer->d.writeVRAM = GBVideoProxyRendererWriteVRAM;
renderer->d.writeOAM = GBVideoProxyRendererWriteOAM;
renderer->d.writePalette = GBVideoProxyRendererWritePalette;
@@ -93,12 +96,12 @@ void GBVideoProxyRendererUnshim(struct GBVideo* video, struct GBVideoProxyRender
mVideoLoggerRendererDeinit(renderer->logger);
}
-void GBVideoProxyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model) {
+void GBVideoProxyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders) {
struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer;
_init(proxyRenderer);
- proxyRenderer->backend->init(proxyRenderer->backend, model);
+ proxyRenderer->backend->init(proxyRenderer->backend, model, borders);
}
void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer) {
@@ -111,6 +114,7 @@ void GBVideoProxyRendererDeinit(struct GBVideoRenderer* renderer) {
static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) {
struct GBVideoProxyRenderer* proxyRenderer = logger->context;
+ uint8_t sgbPacket[16];
switch (item->type) {
case DIRTY_REGISTER:
proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, item->address, item->value);
@@ -154,6 +158,11 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
return false;
}
logger->readData(logger, &proxyRenderer->objThisLine, item->value2, true);
+ break;
+ case BUFFER_SGB:
+ logger->readData(logger, sgbPacket, 16, true);
+ proxyRenderer->backend->writeSGBPacket(proxyRenderer->backend, sgbPacket);
+ break;
}
break;
case DIRTY_FLUSH:
@@ -179,6 +188,14 @@ uint8_t GBVideoProxyRendererWriteVideoRegister(struct GBVideoRenderer* renderer,
return value;
}
+void GBVideoProxyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data) {
+ struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer;
+ if (!proxyRenderer->logger->block) {
+ proxyRenderer->backend->writeSGBPacket(proxyRenderer->backend, data);
+ }
+ mVideoLoggerWriteBuffer(proxyRenderer->logger, BUFFER_SGB, 0, 16, data);
+}
+
void GBVideoProxyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address) {
struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer;
mVideoLoggerRendererWriteVRAM(proxyRenderer->logger, address);
@@ -186,7 +203,7 @@ void GBVideoProxyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t ad
proxyRenderer->backend->writeVRAM(proxyRenderer->backend, address);
}
if (renderer->cache) {
- mTileCacheWriteVRAM(renderer->cache, address);
+ mCacheSetWriteVRAM(renderer->cache, address);
}
}
@@ -197,7 +214,7 @@ void GBVideoProxyRendererWritePalette(struct GBVideoRenderer* renderer, int addr
proxyRenderer->backend->writePalette(proxyRenderer->backend, address, value);
}
if (renderer->cache) {
- mTileCacheWritePalette(renderer->cache, address);
+ mCacheSetWritePalette(renderer->cache, address, mColorFrom555(value));
}
}
diff --git a/src/gb/gb.c b/src/gb/gb.c
index e6f620ce1..c75992461 100644
--- a/src/gb/gb.c
+++ b/src/gb/gb.c
@@ -28,6 +28,8 @@ static const uint8_t _knownHeader[4] = { 0xCE, 0xED, 0x66, 0x66};
#define DMG_BIOS_CHECKSUM 0xC2F5CC97
#define DMG_2_BIOS_CHECKSUM 0x59C8598E
+#define MGB_BIOS_CHECKSUM 0xE6920754
+#define SGB_BIOS_CHECKSUM 0xEC8A83B9
#define CGB_BIOS_CHECKSUM 0x41884E46
mLOG_DEFINE_CATEGORY(GB, "GB", "gb");
@@ -37,6 +39,7 @@ static void GBDeinit(struct mCPUComponent* component);
static void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh);
static void GBProcessEvents(struct LR35902Core* cpu);
static void GBSetInterrupts(struct LR35902Core* cpu, bool enable);
+static uint16_t GBIRQVector(struct LR35902Core* cpu);
static void GBIllegal(struct LR35902Core* cpu);
static void GBStop(struct LR35902Core* cpu);
@@ -162,7 +165,6 @@ void GBResizeSram(struct GB* gb, size_t size) {
if (gb->memory.sram && size <= gb->sramSize) {
return;
}
- mLOG(GB, INFO, "Resizing SRAM to %"PRIz"u bytes", size);
struct VFile* vf = gb->sramVf;
if (vf) {
if (vf == gb->sramRealVf) {
@@ -220,7 +222,7 @@ void GBResizeSram(struct GB* gb, size_t size) {
void GBSramClean(struct GB* gb, uint32_t frameCount) {
// TODO: Share with GBASavedataClean
- if (!gb->sramVf || gb->sramVf != gb->sramRealVf) {
+ if (!gb->sramVf) {
return;
}
if (gb->sramDirty & GB_SRAM_DIRT_NEW) {
@@ -230,6 +232,9 @@ void GBSramClean(struct GB* gb, uint32_t frameCount) {
gb->sramDirty |= GB_SRAM_DIRT_SEEN;
}
} else if ((gb->sramDirty & GB_SRAM_DIRT_SEEN) && frameCount - gb->sramDirtAge > CLEANUP_THRESHOLD) {
+ if (gb->sramMaskWriteback) {
+ GBSavedataUnmask(gb);
+ }
if (gb->memory.mbcType == GB_MBC3_RTC) {
GBMBCRTCWrite(gb);
}
@@ -259,7 +264,9 @@ void GBSavedataUnmask(struct GB* gb) {
gb->sramVf = gb->sramRealVf;
gb->memory.sram = gb->sramVf->map(gb->sramVf, gb->sramSize, MAP_WRITE);
if (gb->sramMaskWriteback) {
+ vf->seek(vf, 0, SEEK_SET);
vf->read(vf, gb->memory.sram, gb->sramSize);
+ gb->sramMaskWriteback = false;
}
vf->close(vf);
}
@@ -287,6 +294,7 @@ void GBUnloadROM(struct GB* gb) {
gb->memory.mbcType = GB_MBC_AUTODETECT;
gb->isPristine = false;
+ gb->sramMaskWriteback = false;
GBSavedataUnmask(gb);
GBSramDeinit(gb);
if (gb->sramRealVf) {
@@ -294,6 +302,9 @@ void GBUnloadROM(struct GB* gb) {
}
gb->sramRealVf = NULL;
gb->sramVf = NULL;
+ if (gb->memory.cam && gb->memory.cam->stopRequestImage) {
+ gb->memory.cam->stopRequestImage(gb->memory.cam);
+ }
}
void GBSynthesizeROM(struct VFile* vf) {
@@ -361,6 +372,7 @@ void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh) {
irqh->reset = GBReset;
irqh->processEvents = GBProcessEvents;
irqh->setInterrupts = GBSetInterrupts;
+ irqh->irqVector = GBIRQVector;
irqh->hitIllegal = GBIllegal;
irqh->stop = GBStop;
irqh->halt = GBHalt;
@@ -381,6 +393,8 @@ bool GBIsBIOS(struct VFile* vf) {
switch (_GBBiosCRC32(vf)) {
case DMG_BIOS_CHECKSUM:
case DMG_2_BIOS_CHECKSUM:
+ case MGB_BIOS_CHECKSUM:
+ case SGB_BIOS_CHECKSUM:
case CGB_BIOS_CHECKSUM:
return true;
default:
@@ -420,24 +434,63 @@ void GBReset(struct LR35902Core* cpu) {
cpu->b = 0;
cpu->d = 0;
+ gb->timer.internalDiv = 0;
+ int nextDiv = 0;
if (!gb->biosVf) {
switch (gb->model) {
- case GB_MODEL_DMG:
- // TODO: SGB
- case GB_MODEL_SGB:
case GB_MODEL_AUTODETECT: // Silence warnings
gb->model = GB_MODEL_DMG;
+ case GB_MODEL_DMG:
cpu->a = 1;
cpu->f.packed = 0xB0;
cpu->c = 0x13;
cpu->e = 0xD8;
cpu->h = 1;
cpu->l = 0x4D;
- gb->timer.internalDiv = 0x2AF3;
+ gb->timer.internalDiv = 0xABC;
+ nextDiv = 4;
+ break;
+ case GB_MODEL_SGB:
+ cpu->a = 1;
+ cpu->f.packed = 0x00;
+ cpu->c = 0x14;
+ cpu->e = 0x00;
+ cpu->h = 0xC0;
+ cpu->l = 0x60;
+ gb->timer.internalDiv = 0xABC;
+ nextDiv = 4;
+ break;
+ case GB_MODEL_MGB:
+ cpu->a = 0xFF;
+ cpu->f.packed = 0xB0;
+ cpu->c = 0x13;
+ cpu->e = 0xD8;
+ cpu->h = 1;
+ cpu->l = 0x4D;
+ gb->timer.internalDiv = 0xABC;
+ nextDiv = 4;
+ break;
+ case GB_MODEL_SGB2:
+ cpu->a = 0xFF;
+ cpu->f.packed = 0x00;
+ cpu->c = 0x14;
+ cpu->e = 0x00;
+ cpu->h = 0xC0;
+ cpu->l = 0x60;
+ gb->timer.internalDiv = 0xABC;
+ nextDiv = 4;
break;
case GB_MODEL_AGB:
+ cpu->a = 0x11;
cpu->b = 1;
- // Fall through
+ cpu->f.packed = 0x00;
+ cpu->c = 0;
+ cpu->e = 0x08;
+ cpu->h = 0;
+ cpu->l = 0x7C;
+ gb->timer.internalDiv = 0x1EA;
+ nextDiv = 0xC;
+ break;
case GB_MODEL_CGB:
cpu->a = 0x11;
cpu->f.packed = 0x80;
@@ -445,7 +498,8 @@ void GBReset(struct LR35902Core* cpu) {
cpu->e = 0x08;
cpu->h = 0;
cpu->l = 0x7C;
- gb->timer.internalDiv = 0x7A8;
+ gb->timer.internalDiv = 0x1EA;
+ nextDiv = 0xC;
break;
}
@@ -464,15 +518,19 @@ void GBReset(struct LR35902Core* cpu) {
gb->yankedRomSize = 0;
}
+ gb->sgbBit = -1;
+ gb->currentSgbBits = 0;
+ memset(gb->sgbPacket, 0, sizeof(gb->sgbPacket));
+
mTimingClear(&gb->timing);
GBMemoryReset(gb);
GBVideoReset(&gb->video);
GBTimerReset(&gb->timer);
- mTimingSchedule(&gb->timing, &gb->timer.event, GB_DMG_DIV_PERIOD);
+ mTimingSchedule(&gb->timing, &gb->timer.event, nextDiv);
- GBAudioReset(&gb->audio);
GBIOReset(gb);
+ GBAudioReset(&gb->audio);
GBSIOReset(&gb->sio);
GBSavedataUnmask(gb);
@@ -488,6 +546,12 @@ void GBDetectModel(struct GB* gb) {
case DMG_2_BIOS_CHECKSUM:
gb->model = GB_MODEL_DMG;
break;
+ case MGB_BIOS_CHECKSUM:
+ gb->model = GB_MODEL_MGB;
+ break;
+ case SGB_BIOS_CHECKSUM:
+ gb->model = GB_MODEL_SGB;
+ break;
case CGB_BIOS_CHECKSUM:
gb->model = GB_MODEL_CGB;
break;
@@ -500,6 +564,8 @@ void GBDetectModel(struct GB* gb) {
const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
if (cart->cgb & 0x80) {
gb->model = GB_MODEL_CGB;
+ } else if (cart->sgb == 0x03 && cart->oldLicensee == 0x33) {
+ gb->model = GB_MODEL_SGB;
} else {
gb->model = GB_MODEL_DMG;
}
@@ -511,6 +577,10 @@ void GBDetectModel(struct GB* gb) {
case GB_MODEL_AUTODETECT: //Silence warnings
gb->audio.style = GB_AUDIO_DMG;
break;
+ case GB_MODEL_MGB:
+ case GB_MODEL_SGB2:
+ gb->audio.style = GB_AUDIO_MGB;
+ break;
case GB_MODEL_AGB:
case GB_MODEL_CGB:
gb->audio.style = GB_AUDIO_CGB;
@@ -528,31 +598,7 @@ void GBUpdateIRQs(struct GB* gb) {
if (!gb->memory.ime || gb->cpu->irqPending) {
return;
}
-
- if (irqs & (1 << GB_IRQ_VBLANK)) {
- LR35902RaiseIRQ(gb->cpu, GB_VECTOR_VBLANK);
- gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_VBLANK);
- return;
- }
- if (irqs & (1 << GB_IRQ_LCDSTAT)) {
- LR35902RaiseIRQ(gb->cpu, GB_VECTOR_LCDSTAT);
- gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_LCDSTAT);
- return;
- }
- if (irqs & (1 << GB_IRQ_TIMER)) {
- LR35902RaiseIRQ(gb->cpu, GB_VECTOR_TIMER);
- gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_TIMER);
- return;
- }
- if (irqs & (1 << GB_IRQ_SIO)) {
- LR35902RaiseIRQ(gb->cpu, GB_VECTOR_SIO);
- gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_SIO);
- return;
- }
- if (irqs & (1 << GB_IRQ_KEYPAD)) {
- LR35902RaiseIRQ(gb->cpu, GB_VECTOR_KEYPAD);
- gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_KEYPAD);
- }
+ LR35902RaiseIRQ(gb->cpu);
}
void GBProcessEvents(struct LR35902Core* cpu) {
@@ -595,6 +641,33 @@ void GBSetInterrupts(struct LR35902Core* cpu, bool enable) {
}
}
+uint16_t GBIRQVector(struct LR35902Core* cpu) {
+ struct GB* gb = (struct GB*) cpu->master;
+ int irqs = gb->memory.ie & gb->memory.io[REG_IF];
+
+ if (irqs & (1 << GB_IRQ_VBLANK)) {
+ gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_VBLANK);
+ return GB_VECTOR_VBLANK;
+ }
+ if (irqs & (1 << GB_IRQ_LCDSTAT)) {
+ gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_LCDSTAT);
+ return GB_VECTOR_LCDSTAT;
+ }
+ if (irqs & (1 << GB_IRQ_TIMER)) {
+ gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_TIMER);
+ return GB_VECTOR_TIMER;
+ }
+ if (irqs & (1 << GB_IRQ_SIO)) {
+ gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_SIO);
+ return GB_VECTOR_SIO;
+ }
+ if (irqs & (1 << GB_IRQ_KEYPAD)) {
+ gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_KEYPAD);
+ return GB_VECTOR_KEYPAD;
+ }
+ return 0;
+}
+
static void _enableInterrupts(struct mTiming* timing, void* user, uint32_t cyclesLate) {
UNUSED(timing);
UNUSED(cyclesLate);
@@ -613,7 +686,7 @@ void GBHalt(struct LR35902Core* cpu) {
void GBStop(struct LR35902Core* cpu) {
struct GB* gb = (struct GB*) cpu->master;
if (cpu->bus) {
- mLOG(GB, GAME_ERROR, "Hit illegal stop at address %04X:%02X\n", cpu->pc, cpu->bus);
+ mLOG(GB, GAME_ERROR, "Hit illegal stop at address %04X:%02X", cpu->pc, cpu->bus);
}
if (gb->memory.io[REG_KEY1] & 1) {
gb->doubleSpeed ^= 1;
@@ -639,7 +712,7 @@ void GBStop(struct LR35902Core* cpu) {
void GBIllegal(struct LR35902Core* cpu) {
struct GB* gb = (struct GB*) cpu->master;
- mLOG(GB, GAME_ERROR, "Hit illegal opcode at address %04X:%02X\n", cpu->pc, cpu->bus);
+ mLOG(GB, GAME_ERROR, "Hit illegal opcode at address %04X:%02X", cpu->pc, cpu->bus);
#ifdef USE_DEBUGGERS
if (cpu->components && cpu->components[CPU_COMPONENT_DEBUGGER]) {
struct mDebuggerEntryInfo info = {
@@ -655,6 +728,9 @@ void GBIllegal(struct LR35902Core* cpu) {
}
bool GBIsROM(struct VFile* vf) {
+ if (!vf) {
+ return false;
+ }
vf->seek(vf, 0x104, SEEK_SET);
uint8_t header[4];
@@ -715,3 +791,40 @@ void GBFrameEnded(struct GB* gb) {
GBTestKeypadIRQ(gb);
}
+
+enum GBModel GBNameToModel(const char* model) {
+ if (strcasecmp(model, "DMG") == 0) {
+ return GB_MODEL_DMG;
+ } else if (strcasecmp(model, "CGB") == 0) {
+ return GB_MODEL_CGB;
+ } else if (strcasecmp(model, "AGB") == 0) {
+ return GB_MODEL_AGB;
+ } else if (strcasecmp(model, "SGB") == 0) {
+ return GB_MODEL_SGB;
+ } else if (strcasecmp(model, "MGB") == 0) {
+ return GB_MODEL_MGB;
+ } else if (strcasecmp(model, "SGB2") == 0) {
+ return GB_MODEL_SGB2;
+ }
+ return GB_MODEL_AUTODETECT;
+}
+
+const char* GBModelToName(enum GBModel model) {
+ switch (model) {
+ case GB_MODEL_DMG:
+ return "DMG";
+ case GB_MODEL_SGB:
+ return "SGB";
+ case GB_MODEL_MGB:
+ return "MGB";
+ case GB_MODEL_SGB2:
+ return "SGB2";
+ case GB_MODEL_CGB:
+ return "CGB";
+ case GB_MODEL_AGB:
+ return "AGB";
+ default:
+ case GB_MODEL_AUTODETECT:
+ return NULL;
+ }
+}
diff --git a/src/gb/io.c b/src/gb/io.c
index 3be656499..2db5d8c6e 100644
--- a/src/gb/io.c
+++ b/src/gb/io.c
@@ -105,6 +105,33 @@ static const uint8_t _registerMask[] = {
[REG_IE] = 0xE0,
};
+static void _writeSGBBits(struct GB* gb, int bits) {
+ if (!bits) {
+ gb->sgbBit = 0;
+ memset(gb->sgbPacket, 0, sizeof(gb->sgbPacket));
+ }
+ if (bits == gb->currentSgbBits) {
+ return;
+ }
+ gb->currentSgbBits = bits;
+ if (gb->sgbBit == 128 && bits == 2) {
+ GBVideoWriteSGBPacket(&gb->video, gb->sgbPacket);
+ ++gb->sgbBit;
+ }
+ if (gb->sgbBit >= 128) {
+ return;
+ }
+ switch (bits) {
+ case 1:
+ gb->sgbPacket[gb->sgbBit >> 3] |= 1 << (gb->sgbBit & 7);
+ // Fall through
+ case 2:
+ ++gb->sgbBit;
+ default:
+ break;
+ }
+}
+
void GBIOInit(struct GB* gb) {
memset(gb->memory.io, 0, sizeof(gb->memory.io));
}
@@ -117,19 +144,19 @@ void GBIOReset(struct GB* gb) {
GBIOWrite(gb, REG_TAC, 0);
GBIOWrite(gb, REG_IF, 1);
GBIOWrite(gb, REG_NR52, 0xF1);
- GBIOWrite(gb, REG_NR14, 0xBF);
+ GBIOWrite(gb, REG_NR14, 0x3F);
GBIOWrite(gb, REG_NR10, 0x80);
GBIOWrite(gb, REG_NR11, 0xBF);
GBIOWrite(gb, REG_NR12, 0xF3);
GBIOWrite(gb, REG_NR13, 0xF3);
- GBIOWrite(gb, REG_NR24, 0xBF);
+ GBIOWrite(gb, REG_NR24, 0x3F);
GBIOWrite(gb, REG_NR21, 0x3F);
GBIOWrite(gb, REG_NR22, 0x00);
- GBIOWrite(gb, REG_NR34, 0xBF);
+ GBIOWrite(gb, REG_NR34, 0x3F);
GBIOWrite(gb, REG_NR30, 0x7F);
GBIOWrite(gb, REG_NR31, 0xFF);
GBIOWrite(gb, REG_NR32, 0x9F);
- GBIOWrite(gb, REG_NR44, 0xBF);
+ GBIOWrite(gb, REG_NR44, 0x3F);
GBIOWrite(gb, REG_NR41, 0xFF);
GBIOWrite(gb, REG_NR42, 0x00);
GBIOWrite(gb, REG_NR43, 0x00);
@@ -140,19 +167,26 @@ void GBIOReset(struct GB* gb) {
GBIOWrite(gb, REG_SCX, 0x00);
GBIOWrite(gb, REG_LYC, 0x00);
GBIOWrite(gb, REG_BGP, 0xFC);
- GBIOWrite(gb, REG_OBP0, 0xFF);
- GBIOWrite(gb, REG_OBP1, 0xFF);
+ if (gb->model < GB_MODEL_CGB) {
+ GBIOWrite(gb, REG_OBP0, 0xFF);
+ GBIOWrite(gb, REG_OBP1, 0xFF);
+ }
GBIOWrite(gb, REG_WY, 0x00);
GBIOWrite(gb, REG_WX, 0x00);
- GBIOWrite(gb, REG_VBK, 0);
- GBIOWrite(gb, REG_BCPS, 0);
- GBIOWrite(gb, REG_OCPS, 0);
- GBIOWrite(gb, REG_SVBK, 1);
- GBIOWrite(gb, REG_HDMA1, 0xFF);
- GBIOWrite(gb, REG_HDMA2, 0xFF);
- GBIOWrite(gb, REG_HDMA3, 0xFF);
- GBIOWrite(gb, REG_HDMA4, 0xFF);
- gb->memory.io[REG_HDMA5] = 0xFF;
+ if (gb->model >= GB_MODEL_CGB) {
+ GBIOWrite(gb, REG_JOYP, 0xFF);
+ GBIOWrite(gb, REG_VBK, 0);
+ GBIOWrite(gb, REG_BCPS, 0);
+ GBIOWrite(gb, REG_OCPS, 0);
+ GBIOWrite(gb, REG_SVBK, 1);
+ GBIOWrite(gb, REG_HDMA1, 0xFF);
+ GBIOWrite(gb, REG_HDMA2, 0xFF);
+ GBIOWrite(gb, REG_HDMA3, 0xFF);
+ GBIOWrite(gb, REG_HDMA4, 0xFF);
+ gb->memory.io[REG_HDMA5] = 0xFF;
+ } else if (gb->model == GB_MODEL_SGB) {
+ GBIOWrite(gb, REG_JOYP, 0xFF);
+ }
GBIOWrite(gb, REG_IE, 0x00);
}
@@ -341,6 +375,10 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
}
break;
case REG_JOYP:
+ if (gb->model == GB_MODEL_SGB) {
+ _writeSGBBits(gb, (value >> 4) & 3);
+ }
+ break;
case REG_TIMA:
case REG_TMA:
// Handled transparently by the registers
@@ -386,6 +424,10 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
free(gb->memory.romBase);
gb->memory.romBase = gb->memory.rom;
}
+ if (gb->model >= GB_MODEL_CGB && gb->memory.io[0x6C]) {
+ gb->model = GB_MODEL_DMG;
+ GBVideoDisableCGB(&gb->video);
+ }
break;
case REG_IE:
gb->memory.ie = value;
@@ -453,7 +495,8 @@ static uint8_t _readKeys(struct GB* gb) {
uint8_t keys = *gb->keySource;
switch (gb->memory.io[REG_JOYP] & 0x30) {
case 0x30:
- keys = 0;
+ // TODO: Increment
+ keys = (gb->video.sgbCommandHeader >> 3) == SGB_MLT_REG ? 0xF : 0;
break;
case 0x20:
keys >>= 4;
@@ -553,6 +596,9 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {
case REG_SVBK:
// Handled transparently by the registers
goto success;
+ case REG_DMA:
+ mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
+ return 0;
default:
break;
}
@@ -580,9 +626,45 @@ void GBIOSerialize(const struct GB* gb, struct GBSerializedState* state) {
void GBIODeserialize(struct GB* gb, const struct GBSerializedState* state) {
memcpy(gb->memory.io, state->io, GB_SIZE_IO);
gb->memory.ie = state->ie;
+
+ if (GBAudioEnableGetEnable(*gb->audio.nr52)) {
+ GBIOWrite(gb, REG_NR10, gb->memory.io[REG_NR10]);
+ GBIOWrite(gb, REG_NR11, gb->memory.io[REG_NR11]);
+ GBIOWrite(gb, REG_NR12, gb->memory.io[REG_NR12]);
+ GBIOWrite(gb, REG_NR13, gb->memory.io[REG_NR13]);
+ gb->audio.ch1.control.frequency &= 0xFF;
+ gb->audio.ch1.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[REG_NR14] << 8);
+ gb->audio.ch1.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[REG_NR14] << 8);
+ GBIOWrite(gb, REG_NR21, gb->memory.io[REG_NR21]);
+ GBIOWrite(gb, REG_NR22, gb->memory.io[REG_NR22]);
+ GBIOWrite(gb, REG_NR22, gb->memory.io[REG_NR23]);
+ gb->audio.ch2.control.frequency &= 0xFF;
+ gb->audio.ch2.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[REG_NR24] << 8);
+ gb->audio.ch2.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[REG_NR24] << 8);
+ GBIOWrite(gb, REG_NR30, gb->memory.io[REG_NR30]);
+ GBIOWrite(gb, REG_NR31, gb->memory.io[REG_NR31]);
+ GBIOWrite(gb, REG_NR32, gb->memory.io[REG_NR32]);
+ GBIOWrite(gb, REG_NR32, gb->memory.io[REG_NR33]);
+ gb->audio.ch3.rate &= 0xFF;
+ gb->audio.ch3.rate |= GBAudioRegisterControlGetRate(gb->memory.io[REG_NR34] << 8);
+ gb->audio.ch3.stop = GBAudioRegisterControlGetStop(gb->memory.io[REG_NR34] << 8);
+ GBIOWrite(gb, REG_NR41, gb->memory.io[REG_NR41]);
+ GBIOWrite(gb, REG_NR42, gb->memory.io[REG_NR42]);
+ GBIOWrite(gb, REG_NR43, gb->memory.io[REG_NR43]);
+ gb->audio.ch4.stop = GBAudioRegisterNoiseControlGetStop(gb->memory.io[REG_NR44]);
+ GBIOWrite(gb, REG_NR50, gb->memory.io[REG_NR50]);
+ GBIOWrite(gb, REG_NR51, gb->memory.io[REG_NR51]);
+ }
+
gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_LCDC, state->io[REG_LCDC]);
gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_SCY, state->io[REG_SCY]);
gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_SCX, state->io[REG_SCX]);
gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_WY, state->io[REG_WY]);
gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_WX, state->io[REG_WX]);
+ if (gb->model == GB_MODEL_SGB) {
+ gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_BGP, state->io[REG_BGP]);
+ gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_OBP0, state->io[REG_OBP0]);
+ gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_OBP1, state->io[REG_OBP1]);
+ }
+ gb->video.stat = state->io[REG_STAT];
}
diff --git a/src/gb/mbc.c b/src/gb/mbc.c
index 559e3b2f9..83ac2f2fc 100644
--- a/src/gb/mbc.c
+++ b/src/gb/mbc.c
@@ -29,9 +29,15 @@ static void _GBMBC6(struct GB*, uint16_t address, uint8_t value);
static void _GBMBC7(struct GB*, uint16_t address, uint8_t value);
static void _GBHuC3(struct GB*, uint16_t address, uint8_t value);
static void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value);
+static void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value);
static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address);
+static void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value);
+
+static uint8_t _GBTAMA5Read(struct GBMemory*, uint16_t address);
+
static uint8_t _GBPocketCamRead(struct GBMemory*, uint16_t address);
+static void _GBPocketCamCapture(struct GBMemory*);
void GBMBCSwitchBank(struct GB* gb, int bank) {
size_t bankStart = bank * GB_SIZE_CART_BANK0;
@@ -62,6 +68,28 @@ void GBMBCSwitchBank0(struct GB* gb, int bank) {
}
}
+void GBMBCSwitchHalfBank(struct GB* gb, int half, int bank) {
+ size_t bankStart = bank * GB_SIZE_CART_HALFBANK;
+ if (bankStart + GB_SIZE_CART_HALFBANK > gb->memory.romSize) {
+ mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);
+ bankStart &= (gb->memory.romSize - 1);
+ bank = bankStart / GB_SIZE_CART_HALFBANK;
+ if (!bank) {
+ ++bank;
+ }
+ }
+ if (!half) {
+ gb->memory.romBank = &gb->memory.rom[bankStart];
+ gb->memory.currentBank = bank;
+ } else {
+ gb->memory.mbcState.mbc6.romBank1 = &gb->memory.rom[bankStart];
+ gb->memory.mbcState.mbc6.currentBank1 = bank;
+ }
+ if (gb->cpu->pc < GB_BASE_VRAM) {
+ gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
+ }
+}
+
static bool _isMulticart(const uint8_t* mem) {
bool success = true;
struct VFile* vf;
@@ -105,6 +133,12 @@ void GBMBCInit(struct GB* gb) {
case 3:
gb->sramSize = 0x8000;
break;
+ case 4:
+ gb->sramSize = 0x20000;
+ break;
+ case 5:
+ gb->sramSize = 0x10000;
+ break;
}
if (gb->memory.mbcType == GB_MBC_AUTODETECT) {
@@ -160,11 +194,14 @@ void GBMBCInit(struct GB* gb) {
gb->memory.mbcType = GB_POCKETCAM;
break;
case 0xFD:
- gb->memory.mbcType = GB_HuC1;
+ gb->memory.mbcType = GB_TAMA5;
break;
case 0xFE:
gb->memory.mbcType = GB_HuC3;
break;
+ case 0xFF:
+ gb->memory.mbcType = GB_HuC1;
+ break;
}
}
} else {
@@ -211,6 +248,13 @@ void GBMBCInit(struct GB* gb) {
case GB_HuC3:
gb->memory.mbcWrite = _GBHuC3;
break;
+ case GB_TAMA5:
+ mLOG(GB_MBC, WARN, "unimplemented MBC: TAMA5");
+ memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
+ gb->memory.mbcWrite = _GBTAMA5;
+ gb->memory.mbcRead = _GBTAMA5Read;
+ gb->sramSize = 0x20;
+ break;
case GB_MBC3_RTC:
memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
gb->memory.mbcWrite = _GBMBC3;
@@ -221,6 +265,9 @@ void GBMBCInit(struct GB* gb) {
case GB_POCKETCAM:
gb->memory.mbcWrite = _GBPocketCam;
gb->memory.mbcRead = _GBPocketCamRead;
+ if (gb->memory.cam && gb->memory.cam->startRequestImage) {
+ gb->memory.cam->startRequestImage(gb->memory.cam, GBCAM_WIDTH, GBCAM_HEIGHT, mCOLOR_ANY);
+ }
break;
}
@@ -230,6 +277,15 @@ void GBMBCInit(struct GB* gb) {
gb->memory.rtcAccess = false;
gb->memory.activeRtcReg = 0;
gb->memory.rtcLatched = false;
+ gb->memory.rtcLastLatch = 0;
+ if (gb->memory.rtc) {
+ if (gb->memory.rtc->sample) {
+ gb->memory.rtc->sample(gb->memory.rtc);
+ }
+ gb->memory.rtcLastLatch = gb->memory.rtc->unixTime(gb->memory.rtc);
+ } else {
+ gb->memory.rtcLastLatch = time(0);
+ }
memset(&gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
GBResizeSram(gb, gb->sramSize);
@@ -462,11 +518,34 @@ void _GBMBC5(struct GB* gb, uint16_t address, uint8_t value) {
}
void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) {
- // TODO
- mLOG(GB_MBC, STUB, "MBC6 unimplemented");
- UNUSED(gb);
- UNUSED(address);
- UNUSED(value);
+ struct GBMemory* memory = &gb->memory;
+ int bank = value & 0x7F;
+ switch (address >> 10) {
+ case 0:
+ switch (value) {
+ case 0:
+ memory->sramAccess = false;
+ break;
+ case 0xA:
+ memory->sramAccess = true;
+ GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
+ break;
+ default:
+ // TODO
+ mLOG(GB_MBC, STUB, "MBC6 unknown value %02X", value);
+ break;
+ }
+ break;
+ case 0x9:
+ GBMBCSwitchHalfBank(gb, 0, bank);
+ break;
+ case 0xD:
+ GBMBCSwitchHalfBank(gb, 1, bank);
+ break;
+ default:
+ mLOG(GB_MBC, STUB, "MBC6 unknown address: %04X:%02X", address, value);
+ break;
+ }
}
void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) {
@@ -493,6 +572,8 @@ void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) {
gb->memory.mbcState.mbc7.access &= ~2;
}
break;
+ case 0x5:
+ _GBMBC7Write(&gb->memory, address, value);
default:
// TODO
mLOG(GB_MBC, STUB, "MBC7 unknown address: %04X:%02X", address, value);
@@ -547,7 +628,7 @@ uint8_t _GBMBC7Read(struct GBMemory* memory, uint16_t address) {
}
}
-void GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value) {
+static void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value) {
struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
if (mbc7->access != 3) {
return;
@@ -734,6 +815,16 @@ void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value) {
memory->mbcState.pocketCam.registersActive = true;
}
break;
+ case 0x5:
+ address &= 0x7F;
+ if (address == 0 && value & 1) {
+ value &= 6; // TODO: Timing
+ _GBPocketCamCapture(memory);
+ }
+ if (address < sizeof(memory->mbcState.pocketCam.registers)) {
+ memory->mbcState.pocketCam.registers[address] = value;
+ }
+ break;
default:
mLOG(GB_MBC, STUB, "Pocket Cam unknown address: %04X:%02X", address, value);
break;
@@ -742,31 +833,182 @@ void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value) {
uint8_t _GBPocketCamRead(struct GBMemory* memory, uint16_t address) {
if (memory->mbcState.pocketCam.registersActive) {
+ if ((address & 0x7F) == 0) {
+ return memory->mbcState.pocketCam.registers[0];
+ }
return 0;
}
- if (!memory->sramAccess) {
- return 0xFF;
- }
return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
}
+void _GBPocketCamCapture(struct GBMemory* memory) {
+ if (!memory->cam) {
+ return;
+ }
+ const void* image = NULL;
+ size_t stride;
+ enum mColorFormat format;
+ memory->cam->requestImage(memory->cam, &image, &stride, &format);
+ if (!image) {
+ return;
+ }
+ memset(&memory->sram[0x100], 0, GBCAM_HEIGHT * GBCAM_WIDTH / 4);
+ struct GBPocketCamState* pocketCam = &memory->mbcState.pocketCam;
+ size_t x, y;
+ for (y = 0; y < GBCAM_HEIGHT; ++y) {
+ for (x = 0; x < GBCAM_WIDTH; ++x) {
+ uint32_t gray;
+ uint32_t color;
+ switch (format) {
+ case mCOLOR_XBGR8:
+ 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;
+ 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;
+ // TODO: Additional processing
+ int matrixEntry = 3 * ((x & 3) + 4 * (y & 3));
+ if (gray < pocketCam->registers[matrixEntry + 6]) {
+ gray = 0x101;
+ } else if (gray < pocketCam->registers[matrixEntry + 7]) {
+ gray = 0x100;
+ } else if (gray < pocketCam->registers[matrixEntry + 8]) {
+ gray = 0x001;
+ } else {
+ gray = 0;
+ }
+ int coord = (((x >> 3) & 0xF) * 8 + (y & 0x7)) * 2 + (y & ~0x7) * 0x20;
+ uint16_t existing;
+ LOAD_16LE(existing, coord + 0x100, memory->sram);
+ existing |= gray << (7 - (x & 7));
+ STORE_16LE(existing, coord + 0x100, memory->sram);
+ }
+ }
+}
+
+void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value) {
+ struct GBMemory* memory = &gb->memory;
+ struct GBTAMA5State* tama5 = &memory->mbcState.tama5;
+ switch (address >> 13) {
+ case 0x5:
+ if (address & 1) {
+ tama5->reg = value;
+ } else {
+ value &= 0xF;
+ if (tama5->reg < GBTAMA5_MAX) {
+ tama5->registers[tama5->reg] = value;
+ uint8_t address = ((tama5->registers[GBTAMA5_CS] << 4) & 0x10) | tama5->registers[GBTAMA5_ADDR_LO];
+ uint8_t out = (tama5->registers[GBTAMA5_WRITE_HI] << 4) | tama5->registers[GBTAMA5_WRITE_LO];
+ switch (tama5->reg) {
+ case GBTAMA5_BANK_LO:
+ case GBTAMA5_BANK_HI:
+ GBMBCSwitchBank(gb, tama5->registers[GBTAMA5_BANK_LO] | (tama5->registers[GBTAMA5_BANK_HI] << 4));
+ break;
+ case GBTAMA5_WRITE_LO:
+ case GBTAMA5_WRITE_HI:
+ case GBTAMA5_CS:
+ break;
+ case GBTAMA5_ADDR_LO:
+ switch (tama5->registers[GBTAMA5_CS] >> 1) {
+ case 0x0: // RAM write
+ memory->sram[address] = out;
+ break;
+ case 0x1: // RAM read
+ break;
+ default:
+ mLOG(GB_MBC, STUB, "TAMA5 unknown address: %X-%02X:%02X", tama5->registers[GBTAMA5_CS] >> 1, address, out);
+ }
+ break;
+ default:
+ mLOG(GB_MBC, STUB, "TAMA5 unknown write: %02X:%X", tama5->reg, value);
+ break;
+ }
+ } else {
+ mLOG(GB_MBC, STUB, "TAMA5 unknown write: %02X", tama5->reg);
+ }
+ }
+ break;
+ default:
+ mLOG(GB_MBC, STUB, "TAMA5 unknown address: %04X:%02X", address, value);
+ }
+}
+
+uint8_t _GBTAMA5Read(struct GBMemory* memory, uint16_t address) {
+ struct GBTAMA5State* tama5 = &memory->mbcState.tama5;
+ if ((address & 0x1FFF) > 1) {
+ mLOG(GB_MBC, STUB, "TAMA5 unknown address: %04X", address);
+ }
+ if (address & 1) {
+ return 0xFF;
+ } else {
+ uint8_t value = 0xF0;
+ uint8_t address = ((tama5->registers[GBTAMA5_CS] << 4) & 0x10) | tama5->registers[GBTAMA5_ADDR_LO];
+ switch (tama5->reg) {
+ case GBTAMA5_ACTIVE:
+ return 0xF1;
+ case GBTAMA5_READ_LO:
+ case GBTAMA5_READ_HI:
+ switch (tama5->registers[GBTAMA5_CS] >> 1) {
+ case 1:
+ value = memory->sram[address];
+ break;
+ default:
+ mLOG(GB_MBC, STUB, "TAMA5 unknown read: %02X", tama5->reg);
+ break;
+ }
+ if (tama5->reg == GBTAMA5_READ_HI) {
+ value >>= 4;
+ }
+ value |= 0xF0;
+ return value;
+ default:
+ mLOG(GB_MBC, STUB, "TAMA5 unknown read: %02X", tama5->reg);
+ return 0xF1;
+ }
+ }
+}
+
void GBMBCRTCRead(struct GB* gb) {
struct GBMBCRTCSaveBuffer rtcBuffer;
struct VFile* vf = gb->sramVf;
if (!vf) {
return;
}
- ssize_t end = vf->seek(vf, -sizeof(rtcBuffer), SEEK_END);
- switch (end & 0x1FFF) {
- case 0:
- break;
- case 0x1FFC:
- vf->seek(vf, -sizeof(rtcBuffer) - 4, SEEK_END);
- break;
- default:
+ vf->seek(vf, gb->sramSize, SEEK_SET);
+ if (vf->read(vf, &rtcBuffer, sizeof(rtcBuffer)) < (ssize_t) sizeof(rtcBuffer) - 4) {
return;
}
- vf->read(vf, &rtcBuffer, sizeof(rtcBuffer));
LOAD_32LE(gb->memory.rtcRegs[0], 0, &rtcBuffer.latchedSec);
LOAD_32LE(gb->memory.rtcRegs[1], 0, &rtcBuffer.latchedMin);
@@ -798,9 +1040,9 @@ void GBMBCRTCWrite(struct GB* gb) {
STORE_32LE(gb->memory.rtcRegs[2], 0, &rtcBuffer.latchedHour);
STORE_32LE(gb->memory.rtcRegs[3], 0, &rtcBuffer.latchedDays);
STORE_32LE(gb->memory.rtcRegs[4], 0, &rtcBuffer.latchedDaysHi);
- STORE_64LE(rtcLastLatch, 0, &rtcBuffer.unixTime);
+ STORE_64LE(gb->memory.rtcLastLatch, 0, &rtcBuffer.unixTime);
- if (vf->size(vf) == gb->sramSize) {
+ if ((size_t) vf->size(vf) < gb->sramSize + sizeof(rtcBuffer)) {
// Writing past the end of the file can invalidate the file mapping
vf->unmap(vf, gb->memory.sram, gb->sramSize);
gb->memory.sram = NULL;
diff --git a/src/gb/memory.c b/src/gb/memory.c
index f37f6ef73..25b562146 100644
--- a/src/gb/memory.c
+++ b/src/gb/memory.c
@@ -103,6 +103,9 @@ void GBMemoryInit(struct GB* gb) {
gb->memory.mbcWrite = NULL;
gb->memory.rtc = NULL;
+ gb->memory.rotation = NULL;
+ gb->memory.rumble = NULL;
+ gb->memory.cam = NULL;
GBIOInit(gb);
}
@@ -204,10 +207,14 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
case GB_REGION_CART_BANK0 + 2:
case GB_REGION_CART_BANK0 + 3:
return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)];
- case GB_REGION_CART_BANK1:
- case GB_REGION_CART_BANK1 + 1:
case GB_REGION_CART_BANK1 + 2:
case GB_REGION_CART_BANK1 + 3:
+ if (memory->mbcType == GB_MBC6) {
+ return memory->mbcState.mbc6.romBank1[address & (GB_SIZE_CART_HALFBANK - 1)];
+ }
+ // Fall through
+ case GB_REGION_CART_BANK1:
+ case GB_REGION_CART_BANK1 + 1:
return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
case GB_REGION_VRAM:
case GB_REGION_VRAM + 1:
@@ -218,7 +225,7 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
return memory->rtcRegs[memory->activeRtcReg];
} else if (memory->mbcRead) {
return memory->mbcRead(memory, address);
- } else if (memory->sramAccess) {
+ } else if (memory->sramAccess && memory->sram) {
return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
} else if (memory->mbcType == GB_HuC3) {
return 0x01; // TODO: Is this supposed to be the current SRAM bank?
@@ -287,10 +294,10 @@ void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
case GB_REGION_EXTERNAL_RAM + 1:
if (memory->rtcAccess) {
memory->rtcRegs[memory->activeRtcReg] = value;
- } else if (memory->sramAccess) {
+ } else if (memory->sramAccess && memory->sram) {
memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value;
- } else if (memory->mbcType == GB_MBC7) {
- GBMBC7Write(memory, address, value);
+ } else {
+ memory->mbcWrite(gb, address, value);
}
gb->sramDirty |= GB_SRAM_DIRT_NEW;
return;
@@ -385,7 +392,7 @@ uint8_t GBView8(struct LR35902Core* cpu, uint16_t address, int segment) {
if (memory->rtcAccess) {
return memory->rtcRegs[memory->activeRtcReg];
} else if (memory->sramAccess) {
- if (segment < 0) {
+ if (segment < 0 && memory->sram) {
return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
} else if ((size_t) segment * GB_SIZE_EXTERNAL_RAM < gb->sramSize) {
return memory->sram[(address & (GB_SIZE_EXTERNAL_RAM - 1)) + segment *GB_SIZE_EXTERNAL_RAM];
@@ -462,10 +469,13 @@ void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) {
bool wasHdma = gb->memory.isHdma;
gb->memory.isHdma = value & 0x80;
if ((!wasHdma && !gb->memory.isHdma) || gb->video.mode == 0) {
- gb->memory.hdmaRemaining = ((value & 0x7F) + 1) * 0x10;
+ if (gb->memory.isHdma) {
+ gb->memory.hdmaRemaining = 0x10;
+ } else {
+ gb->memory.hdmaRemaining = ((value & 0x7F) + 1) * 0x10;
+ }
gb->cpuBlocked = true;
mTimingSchedule(&gb->timing, &gb->memory.hdmaEvent, 0);
- gb->cpu->nextEvent = gb->cpu->cycles;
}
}
@@ -703,8 +713,7 @@ void GBMemoryDeserialize(struct GB* gb, const struct GBSerializedState* state) {
}
break;
case GB_MBC3_RTC:
- // TODO?
- //LOAD_64LE(gb->memory.rtcLastLatch, 0, &state->memory.rtc.lastLatch);
+ LOAD_64LE(gb->memory.rtcLastLatch, 0, &state->memory.rtc.lastLatch);
break;
case GB_MBC7:
memory->mbcState.mbc7.state = state->memory.mbc7.state;
diff --git a/src/gb/overrides.c b/src/gb/overrides.c
index d8265800b..4f598544c 100644
--- a/src/gb/overrides.c
+++ b/src/gb/overrides.c
@@ -19,6 +19,7 @@ static const struct GBCartridgeOverride _overrides[] = {
bool GBOverrideFind(const struct Configuration* config, struct GBCartridgeOverride* override) {
override->model = GB_MODEL_AUTODETECT;
override->mbc = GB_MBC_AUTODETECT;
+ memset(override->gbColors, 0, sizeof(override->gbColors));
bool found = false;
int i;
@@ -35,30 +36,24 @@ bool GBOverrideFind(const struct Configuration* config, struct GBCartridgeOverri
snprintf(sectionName, sizeof(sectionName), "gb.override.%08X", override->headerCrc32);
const char* model = ConfigurationGetValue(config, sectionName, "model");
const char* mbc = ConfigurationGetValue(config, sectionName, "mbc");
- const char* pal[4] = {
+ const char* pal[12] = {
ConfigurationGetValue(config, sectionName, "pal[0]"),
ConfigurationGetValue(config, sectionName, "pal[1]"),
ConfigurationGetValue(config, sectionName, "pal[2]"),
- ConfigurationGetValue(config, sectionName, "pal[3]")
+ ConfigurationGetValue(config, sectionName, "pal[3]"),
+ ConfigurationGetValue(config, sectionName, "pal[4]"),
+ ConfigurationGetValue(config, sectionName, "pal[5]"),
+ ConfigurationGetValue(config, sectionName, "pal[6]"),
+ ConfigurationGetValue(config, sectionName, "pal[7]"),
+ ConfigurationGetValue(config, sectionName, "pal[8]"),
+ ConfigurationGetValue(config, sectionName, "pal[9]"),
+ ConfigurationGetValue(config, sectionName, "pal[10]"),
+ ConfigurationGetValue(config, sectionName, "pal[11]")
};
if (model) {
- if (strcasecmp(model, "DMG") == 0) {
- found = true;
- override->model = GB_MODEL_DMG;
- } else if (strcasecmp(model, "CGB") == 0) {
- found = true;
- override->model = GB_MODEL_CGB;
- } else if (strcasecmp(model, "AGB") == 0) {
- found = true;
- override->model = GB_MODEL_AGB;
- } else if (strcasecmp(model, "SGB") == 0) {
- found = true;
- override->model = GB_MODEL_DMG; // TODO
- } else if (strcasecmp(model, "MGB") == 0) {
- found = true;
- override->model = GB_MODEL_DMG; // TODO
- }
+ override->model = GBNameToModel(model);
+ found = override->model != GB_MODEL_AUTODETECT;
}
if (mbc) {
@@ -70,18 +65,25 @@ bool GBOverrideFind(const struct Configuration* config, struct GBCartridgeOverri
}
}
- if (pal[0] && pal[1] && pal[2] && pal[3]) {
- int i;
- for (i = 0; i < 4; ++i) {
- char* end;
- unsigned long value = strtoul(pal[i], &end, 10);
- if (end == &pal[i][1] && *end == 'x') {
- value = strtoul(pal[i], &end, 16);
- }
- if (*end) {
- continue;
- }
- override->gbColors[i] = value;
+ for (i = 0; i < 12; ++i) {
+ if (!pal[i]) {
+ continue;
+ }
+ char* end;
+ unsigned long value = strtoul(pal[i], &end, 10);
+ if (end == &pal[i][1] && *end == 'x') {
+ value = strtoul(pal[i], &end, 16);
+ }
+ if (*end) {
+ continue;
+ }
+ value |= 0xFF000000;
+ override->gbColors[i] = value;
+ if (i < 8) {
+ override->gbColors[i + 4] = value;
+ }
+ if (i < 4) {
+ override->gbColors[i + 8] = value;
}
}
}
@@ -91,31 +93,46 @@ bool GBOverrideFind(const struct Configuration* config, struct GBCartridgeOverri
void GBOverrideSave(struct Configuration* config, const struct GBCartridgeOverride* override) {
char sectionName[24] = "";
snprintf(sectionName, sizeof(sectionName), "gb.override.%08X", override->headerCrc32);
- const char* model = 0;
- switch (override->model) {
- case GB_MODEL_DMG:
- model = "DMG";
- break;
- case GB_MODEL_SGB:
- model = "SGB";
- break;
- case GB_MODEL_CGB:
- model = "CGB";
- break;
- case GB_MODEL_AGB:
- model = "AGB";
- break;
- case GB_MODEL_AUTODETECT:
- break;
- }
+ const char* model = GBModelToName(override->model);
ConfigurationSetValue(config, sectionName, "model", model);
- if (override->gbColors[0] | override->gbColors[1] | override->gbColors[2] | override->gbColors[3]) {
- ConfigurationSetIntValue(config, sectionName, "pal[0]", override->gbColors[0]);
- ConfigurationSetIntValue(config, sectionName, "pal[1]", override->gbColors[1]);
- ConfigurationSetIntValue(config, sectionName, "pal[2]", override->gbColors[2]);
- ConfigurationSetIntValue(config, sectionName, "pal[3]", override->gbColors[3]);
+ if (override->gbColors[0] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[0]", override->gbColors[0] & ~0xFF000000);
}
+ if (override->gbColors[1] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[1]", override->gbColors[1] & ~0xFF000000);
+ }
+ if (override->gbColors[2] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[2]", override->gbColors[2] & ~0xFF000000);
+ }
+ if (override->gbColors[3] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[3]", override->gbColors[3] & ~0xFF000000);
+ }
+ if (override->gbColors[4] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[4]", override->gbColors[4] & ~0xFF000000);
+ }
+ if (override->gbColors[5] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[5]", override->gbColors[5] & ~0xFF000000);
+ }
+ if (override->gbColors[6] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[6]", override->gbColors[6] & ~0xFF000000);
+ }
+ if (override->gbColors[7] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[7]", override->gbColors[7] & ~0xFF000000);
+ }
+ if (override->gbColors[8] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[8]", override->gbColors[8] & ~0xFF000000);
+ }
+ if (override->gbColors[9] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[9]", override->gbColors[9] & ~0xFF000000);
+ }
+ if (override->gbColors[10] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[10]", override->gbColors[10] & ~0xFF000000);
+ }
+ if (override->gbColors[11] & 0xFF000000) {
+ ConfigurationSetIntValue(config, sectionName, "pal[11]", override->gbColors[11] & ~0xFF000000);
+ }
+
if (override->mbc != GB_MBC_AUTODETECT) {
ConfigurationSetIntValue(config, sectionName, "mbc", override->mbc);
} else {
@@ -133,11 +150,18 @@ void GBOverrideApply(struct GB* gb, const struct GBCartridgeOverride* override)
GBMBCInit(gb);
}
- if (override->gbColors[0] | override->gbColors[1] | override->gbColors[2] | override->gbColors[3]) {
- GBVideoSetPalette(&gb->video, 0, override->gbColors[0]);
- GBVideoSetPalette(&gb->video, 1, override->gbColors[1]);
- GBVideoSetPalette(&gb->video, 2, override->gbColors[2]);
- GBVideoSetPalette(&gb->video, 3, override->gbColors[3]);
+ int i;
+ for (i = 0; i < 12; ++i) {
+ if (!(override->gbColors[i] & 0xFF000000)) {
+ continue;
+ }
+ GBVideoSetPalette(&gb->video, i, override->gbColors[i]);
+ if (i < 8) {
+ GBVideoSetPalette(&gb->video, i + 4, override->gbColors[i]);
+ }
+ if (i < 4) {
+ GBVideoSetPalette(&gb->video, i + 8, override->gbColors[i]);
+ }
}
}
diff --git a/src/gb/renderers/cache-set.c b/src/gb/renderers/cache-set.c
new file mode 100644
index 000000000..741d043cd
--- /dev/null
+++ b/src/gb/renderers/cache-set.c
@@ -0,0 +1,129 @@
+/* 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
+#include
+
+void GBVideoCacheInit(struct mCacheSet* cache) {
+ mCacheSetInit(cache, 2, 1);
+ mTileCacheConfiguration config = 0;
+ config = mTileCacheSystemInfoSetPaletteBPP(config, 1); // 2^(2^1) = 4 entries
+ config = mTileCacheSystemInfoSetPaletteCount(config, 4); // 16 palettes
+ config = mTileCacheSystemInfoSetMaxTiles(config, 1024);
+ mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 0));
+ mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), config, 0, 0);
+
+ mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 0));
+ mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 1));
+ mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
+ mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
+}
+
+void GBVideoCacheAssociate(struct mCacheSet* cache, struct GBVideo* video) {
+ mCacheSetAssignVRAM(cache, video->vram);
+ video->renderer->cache = cache;
+ size_t i;
+ for (i = 0; i < 64; ++i) {
+ mCacheSetWritePalette(cache, i, mColorFrom555(video->palette[i]));
+ }
+ mMapCacheSystemInfo sysconfig = mMapCacheSystemInfoSetPaletteCount(0, 0);
+ if (video->p->model >= GB_MODEL_CGB) {
+ sysconfig = mMapCacheSystemInfoSetPaletteCount(0, 2);
+ }
+ mMapCacheConfigureSystem(mMapCacheSetGetPointer(&cache->maps, 0), sysconfig);
+ mMapCacheConfigureSystem(mMapCacheSetGetPointer(&cache->maps, 1), sysconfig);
+
+ GBVideoCacheWriteVideoRegister(cache, REG_LCDC, video->p->memory.io[REG_LCDC]);
+}
+
+static void mapParserDMG0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
+ UNUSED(cache);
+ int map = *(uint8_t*) vram;
+ entry->tileId = map;
+ entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags);
+ entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags);
+ entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, 0);
+}
+
+static void mapParserDMG1(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
+ UNUSED(cache);
+ int map = *(int8_t*) vram;
+ entry->tileId = map + 128;
+ entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags);
+ entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags);
+ entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, 0);
+}
+
+static void mapParserCGB0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
+ UNUSED(cache);
+ int map = *(uint8_t*) vram;
+ uint8_t attr = ((uint8_t*) vram)[0x2000];
+ entry->tileId = map + GBObjAttributesGetBank(attr) * 512;
+ entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBObjAttributesGetXFlip(attr));
+ entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, GBObjAttributesGetYFlip(attr));
+ entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBObjAttributesGetCGBPalette(attr));
+}
+
+static void mapParserCGB1(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
+ UNUSED(cache);
+ int map = *(int8_t*) vram;
+ uint8_t attr = ((uint8_t*) vram)[0x2000];
+ entry->tileId = map + 128 + GBObjAttributesGetBank(attr) * 512;
+ entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, GBObjAttributesGetXFlip(attr));
+ entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, GBObjAttributesGetYFlip(attr));
+ entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBObjAttributesGetCGBPalette(attr));
+}
+
+void GBVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint16_t address, uint8_t value) {
+ if (address != REG_LCDC) {
+ return;
+ }
+ struct mMapCache* map = mMapCacheSetGetPointer(&cache->maps, 0);
+ struct mMapCache* window = mMapCacheSetGetPointer(&cache->maps, 1);
+
+ mMapCacheSystemInfo sysconfig = mMapCacheSystemInfoIsPaletteCount(map->sysConfig);
+ int tileStart = 0;
+ int mapStart = GB_BASE_MAP;
+ int windowStart = GB_BASE_MAP;
+ if (GBRegisterLCDCIsTileMap(value)) {
+ mapStart += GB_SIZE_MAP;
+ }
+ if (GBRegisterLCDCIsWindowTileMap(value)) {
+ windowStart += GB_SIZE_MAP;
+ }
+ if (GBRegisterLCDCIsTileData(value)) {
+ if (!sysconfig) {
+ map->mapParser = mapParserDMG0;
+ window->mapParser = mapParserDMG0;
+ } else {
+ map->mapParser = mapParserCGB0;
+ window->mapParser = mapParserCGB0;
+ }
+ } else {
+ if (!sysconfig) {
+ map->mapParser = mapParserDMG1;
+ window->mapParser = mapParserDMG1;
+ } else {
+ map->mapParser = mapParserCGB1;
+ window->mapParser = mapParserCGB1;
+ }
+ tileStart = 0x80;
+ }
+ map->tileStart = tileStart;
+ window->tileStart = tileStart;
+ sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 5);
+ sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 1);
+ sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0);
+ sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, 5);
+ sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, 5);
+ mMapCacheConfigureSystem(map, sysconfig);
+ mMapCacheConfigureSystem(window, sysconfig);
+ mMapCacheConfigureMap(map, mapStart);
+ mMapCacheConfigureMap(window, windowStart);
+}
diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c
index 2d2dbe787..0c3526960 100644
--- a/src/gb/renderers/software.c
+++ b/src/gb/renderers/software.c
@@ -5,13 +5,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include
-#include
+#include
#include
+#include
+#include
#include
-static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum GBModel model);
+static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders);
static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer);
static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
+static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data);
static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value);
static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address);
static void GBVideoSoftwareRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam);
@@ -25,9 +28,13 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer
static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y);
static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) {
+ size_t sgbOffset = 0;
+ if (renderer->model == GB_MODEL_SGB && renderer->sgbBorders) {
+ sgbOffset = renderer->outputBufferStride * 40 + 48;
+ }
int y;
for (y = 0; y < GB_VIDEO_VERTICAL_PIXELS; ++y) {
- color_t* row = &renderer->outputBuffer[renderer->outputBufferStride * y];
+ color_t* 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];
@@ -38,10 +45,112 @@ static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) {
}
}
+static void _regenerateSGBBorder(struct GBVideoSoftwareRenderer* renderer) {
+ int i;
+ for (i = 0; i < 0x40; ++i) {
+ uint16_t color;
+ LOAD_16LE(color, 0x800 + i * 2, renderer->d.sgbMapRam);
+ renderer->d.writePalette(&renderer->d, i + 0x40, color);
+ }
+ int x, y;
+ for (y = 0; y < 224; ++y) {
+ for (x = 0; x < 256; x += 8) {
+ if (x >= 48 && x < 208 && y >= 40 && y < 104) {
+ continue;
+ }
+ uint16_t mapData;
+ LOAD_16LE(mapData, (x >> 2) + (y & ~7) * 8, renderer->d.sgbMapRam);
+ if (UNLIKELY(SGBBgAttributesGetTile(mapData) >= 0x100)) {
+ continue;
+ }
+
+ int localY = y & 0x7;
+ if (SGBBgAttributesIsYFlip(mapData)) {
+ localY = 7 - localY;
+ }
+ uint8_t tileData[4];
+ tileData[0] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x00];
+ tileData[1] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x01];
+ tileData[2] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x10];
+ tileData[3] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x11];
+
+ size_t base = y * renderer->outputBufferStride + x;
+ int p = SGBBgAttributesGetPalette(mapData) * 0x10;
+ if (SGBBgAttributesIsXFlip(mapData)) {
+ renderer->outputBuffer[base + 0] = renderer->palette[p | ((tileData[0] >> 0) & 0x1) | ((tileData[1] << 1) & 0x2) | ((tileData[2] << 2) & 0x4) | ((tileData[3] << 3) & 0x8)];
+ renderer->outputBuffer[base + 1] = renderer->palette[p | ((tileData[0] >> 1) & 0x1) | ((tileData[1] >> 0) & 0x2) | ((tileData[2] << 1) & 0x4) | ((tileData[3] << 2) & 0x8)];
+ renderer->outputBuffer[base + 2] = renderer->palette[p | ((tileData[0] >> 2) & 0x1) | ((tileData[1] >> 1) & 0x2) | ((tileData[2] >> 0) & 0x4) | ((tileData[3] << 1) & 0x8)];
+ renderer->outputBuffer[base + 3] = renderer->palette[p | ((tileData[0] >> 3) & 0x1) | ((tileData[1] >> 2) & 0x2) | ((tileData[2] >> 1) & 0x4) | ((tileData[3] >> 0) & 0x8)];
+ renderer->outputBuffer[base + 4] = renderer->palette[p | ((tileData[0] >> 4) & 0x1) | ((tileData[1] >> 3) & 0x2) | ((tileData[2] >> 2) & 0x4) | ((tileData[3] >> 1) & 0x8)];
+ renderer->outputBuffer[base + 5] = renderer->palette[p | ((tileData[0] >> 5) & 0x1) | ((tileData[1] >> 4) & 0x2) | ((tileData[2] >> 3) & 0x4) | ((tileData[3] >> 2) & 0x8)];
+ renderer->outputBuffer[base + 6] = renderer->palette[p | ((tileData[0] >> 6) & 0x1) | ((tileData[1] >> 5) & 0x2) | ((tileData[2] >> 4) & 0x4) | ((tileData[3] >> 3) & 0x8)];
+ renderer->outputBuffer[base + 7] = renderer->palette[p | ((tileData[0] >> 7) & 0x1) | ((tileData[1] >> 6) & 0x2) | ((tileData[2] >> 5) & 0x4) | ((tileData[3] >> 4) & 0x8)];
+ } else {
+ renderer->outputBuffer[base + 0] = renderer->palette[p | ((tileData[0] >> 7) & 0x1) | ((tileData[1] >> 6) & 0x2) | ((tileData[2] >> 5) & 0x4) | ((tileData[3] >> 4) & 0x8)];
+ renderer->outputBuffer[base + 1] = renderer->palette[p | ((tileData[0] >> 6) & 0x1) | ((tileData[1] >> 5) & 0x2) | ((tileData[2] >> 4) & 0x4) | ((tileData[3] >> 3) & 0x8)];
+ renderer->outputBuffer[base + 2] = renderer->palette[p | ((tileData[0] >> 5) & 0x1) | ((tileData[1] >> 4) & 0x2) | ((tileData[2] >> 3) & 0x4) | ((tileData[3] >> 2) & 0x8)];
+ renderer->outputBuffer[base + 3] = renderer->palette[p | ((tileData[0] >> 4) & 0x1) | ((tileData[1] >> 3) & 0x2) | ((tileData[2] >> 2) & 0x4) | ((tileData[3] >> 1) & 0x8)];
+ renderer->outputBuffer[base + 4] = renderer->palette[p | ((tileData[0] >> 3) & 0x1) | ((tileData[1] >> 2) & 0x2) | ((tileData[2] >> 1) & 0x4) | ((tileData[3] >> 0) & 0x8)];
+ renderer->outputBuffer[base + 5] = renderer->palette[p | ((tileData[0] >> 2) & 0x1) | ((tileData[1] >> 1) & 0x2) | ((tileData[2] >> 0) & 0x4) | ((tileData[3] << 1) & 0x8)];
+ renderer->outputBuffer[base + 6] = renderer->palette[p | ((tileData[0] >> 1) & 0x1) | ((tileData[1] >> 0) & 0x2) | ((tileData[2] << 1) & 0x4) | ((tileData[3] << 2) & 0x8)];
+ renderer->outputBuffer[base + 7] = renderer->palette[p | ((tileData[0] >> 0) & 0x1) | ((tileData[1] << 1) & 0x2) | ((tileData[2] << 2) & 0x4) | ((tileData[3] << 3) & 0x8)];
+ }
+ }
+ }
+}
+
+static inline void _setAttribute(uint8_t* sgbAttributes, unsigned x, unsigned y, int palette) {
+ int p = sgbAttributes[(x >> 2) + 5 * y];
+ p &= ~(3 << (2 * (3 - (x & 3))));
+ p |= palette << (2 * (3 - (x & 3)));
+ sgbAttributes[(x >> 2) + 5 * y] = p;
+}
+
+static void _parseAttrBlock(struct GBVideoSoftwareRenderer* renderer, int start) {
+ uint8_t block[6];
+ if (start < 0) {
+ memcpy(block, renderer->sgbPartialDataSet, -start);
+ memcpy(&block[-start], renderer->sgbPacket, 6 + start);
+ } else {
+ memcpy(block, &renderer->sgbPacket[start], 6);
+ }
+ unsigned x0 = block[2];
+ unsigned x1 = block[4];
+ unsigned y0 = block[3];
+ unsigned y1 = block[5];
+ unsigned x, y;
+ int pIn = block[1] & 3;
+ int pPerim = (block[1] >> 2) & 3;
+ int pOut = (block[1] >> 4) & 3;
+
+ for (y = 0; y < GB_VIDEO_VERTICAL_PIXELS / 8; ++y) {
+ for (x = 0; x < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++x) {
+ if (y > y0 && y < y1 && x > x0 && x < x1) {
+ if (block[0] & 1) {
+ _setAttribute(renderer->d.sgbAttributes, x, y, pIn);
+ }
+ } else if (y < y0 || y > y1 || x < x0 || x > x1) {
+ if (block[0] & 4) {
+ _setAttribute(renderer->d.sgbAttributes, x, y, pOut);
+ }
+ } else {
+ if (block[0] & 2) {
+ _setAttribute(renderer->d.sgbAttributes, x, y, pPerim);
+ } else if (block[0] & 1) {
+ _setAttribute(renderer->d.sgbAttributes, x, y, pIn);
+ } else if (block[0] & 4) {
+ _setAttribute(renderer->d.sgbAttributes, x, y, pOut);
+ }
+ }
+ }
+ }
+}
+
void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) {
renderer->d.init = GBVideoSoftwareRendererInit;
renderer->d.deinit = GBVideoSoftwareRendererDeinit;
renderer->d.writeVideoRegister = GBVideoSoftwareRendererWriteVideoRegister;
+ renderer->d.writeSGBPacket = GBVideoSoftwareRendererWriteSGBPacket;
renderer->d.writePalette = GBVideoSoftwareRendererWritePalette;
renderer->d.writeVRAM = GBVideoSoftwareRendererWriteVRAM;
renderer->d.writeOAM = GBVideoSoftwareRendererWriteOAM;
@@ -58,7 +167,7 @@ void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer* renderer) {
renderer->temporaryBuffer = 0;
}
-static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum GBModel model) {
+static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool sgbBorders) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
softwareRenderer->lcdc = 0;
softwareRenderer->scy = 0;
@@ -67,6 +176,16 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G
softwareRenderer->currentWy = 0;
softwareRenderer->wx = 0;
softwareRenderer->model = model;
+ softwareRenderer->sgbTransfer = 0;
+ softwareRenderer->sgbCommandHeader = 0;
+ softwareRenderer->sgbBorders = sgbBorders;
+ int i;
+ for (i = 0; i < 64; ++i) {
+ softwareRenderer->lookup[i] = i;
+ softwareRenderer->lookup[i] = i;
+ softwareRenderer->lookup[i] = i;
+ softwareRenderer->lookup[i] = i;
+ }
}
static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer) {
@@ -76,6 +195,9 @@ static void GBVideoSoftwareRendererDeinit(struct GBVideoRenderer* renderer) {
static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
+ if (renderer->cache) {
+ GBVideoCacheWriteVideoRegister(renderer->cache, address, value);
+ }
switch (address) {
case REG_LCDC:
softwareRenderer->lcdc = value;
@@ -92,37 +214,87 @@ static uint8_t GBVideoSoftwareRendererWriteVideoRegister(struct GBVideoRenderer*
case REG_WX:
softwareRenderer->wx = value;
break;
+ case REG_BGP:
+ softwareRenderer->lookup[0] = value & 3;
+ softwareRenderer->lookup[1] = (value >> 2) & 3;
+ softwareRenderer->lookup[2] = (value >> 4) & 3;
+ softwareRenderer->lookup[3] = (value >> 6) & 3;
+ break;
+ case REG_OBP0:
+ softwareRenderer->lookup[0x20 + 0] = value & 3;
+ softwareRenderer->lookup[0x20 + 1] = (value >> 2) & 3;
+ softwareRenderer->lookup[0x20 + 2] = (value >> 4) & 3;
+ softwareRenderer->lookup[0x20 + 3] = (value >> 6) & 3;
+ break;
+ case REG_OBP1:
+ softwareRenderer->lookup[0x24 + 0] = value & 3;
+ softwareRenderer->lookup[0x24 + 1] = (value >> 2) & 3;
+ softwareRenderer->lookup[0x24 + 2] = (value >> 4) & 3;
+ softwareRenderer->lookup[0x24 + 3] = (value >> 6) & 3;
+ break;
}
return value;
}
+static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data) {
+ struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
+ memcpy(softwareRenderer->sgbPacket, data, sizeof(softwareRenderer->sgbPacket));
+ int i;
+ if (!(softwareRenderer->sgbCommandHeader & 7)) {
+ softwareRenderer->sgbCommandHeader = data[0];
+ softwareRenderer->sgbPacketId = 0;
+ softwareRenderer->sgbTransfer = 0;
+ }
+ --softwareRenderer->sgbCommandHeader;
+ ++softwareRenderer->sgbPacketId;
+ int set;
+ switch (softwareRenderer->sgbCommandHeader >> 3) {
+ case SGB_PAL_SET:
+ softwareRenderer->sgbPacket[1] = data[9];
+ if (!(data[9] & 0x80)) {
+ break;
+ }
+ // Fall through
+ case SGB_ATTR_SET:
+ set = softwareRenderer->sgbPacket[1] & 0x3F;
+ if (set <= 0x2C) {
+ memcpy(renderer->sgbAttributes, &renderer->sgbAttributeFiles[set * 90], 90);
+ }
+ break;
+ case SGB_ATTR_BLK:
+ if (softwareRenderer->sgbPacketId == 1) {
+ softwareRenderer->sgbDataSets = softwareRenderer->sgbPacket[1];
+ i = 2;
+ } else {
+ i = (9 - softwareRenderer->sgbPacketId) % 3 * -2;
+ }
+ for (; i <= 10 && softwareRenderer->sgbDataSets; i += 6, --softwareRenderer->sgbDataSets) {
+ _parseAttrBlock(softwareRenderer, i);
+ }
+ if (i < 16 && softwareRenderer->sgbDataSets) {
+ memcpy(softwareRenderer->sgbPartialDataSet, &softwareRenderer->sgbPacket[i], 16 - i);
+ }
+ break;
+ case SGB_ATRC_EN:
+ if (softwareRenderer->sgbBorders) {
+ _regenerateSGBBorder(softwareRenderer);
+ }
+ break;
+ }
+}
+
static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
-#ifdef COLOR_16_BIT
-#ifdef COLOR_5_6_5
- color_t color = 0;
- color |= (value & 0x001F) << 11;
- color |= (value & 0x03E0) << 1;
- color |= (value & 0x7C00) >> 10;
-#else
- color_t color = value;
-#endif
-#else
- color_t color = 0;
- color |= (value << 3) & 0xF8;
- color |= (value << 6) & 0xF800;
- color |= (value << 9) & 0xF80000;
- color |= (color >> 5) & 0x070707;
-#endif
+ color_t color = mColorFrom555(value);
softwareRenderer->palette[index] = color;
if (renderer->cache) {
- mTileCacheWritePalette(renderer->cache, index << 1);
+ mCacheSetWritePalette(renderer->cache, index, color);
}
}
static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address) {
if (renderer->cache) {
- mTileCacheWriteVRAM(renderer->cache, address);
+ mCacheSetWriteVRAM(renderer->cache, address);
}
}
@@ -167,28 +339,149 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
GBVideoSoftwareRendererDrawObj(softwareRenderer, &obj[i], startX, endX, y);
}
}
- color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y];
- int x;
- for (x = startX; x + 7 < (endX & ~7); x += 8) {
- row[x] = softwareRenderer->palette[softwareRenderer->row[x] & 0x7F];
- row[x + 1] = softwareRenderer->palette[softwareRenderer->row[x + 1] & 0x7F];
- row[x + 2] = softwareRenderer->palette[softwareRenderer->row[x + 2] & 0x7F];
- row[x + 3] = softwareRenderer->palette[softwareRenderer->row[x + 3] & 0x7F];
- row[x + 4] = softwareRenderer->palette[softwareRenderer->row[x + 4] & 0x7F];
- row[x + 5] = softwareRenderer->palette[softwareRenderer->row[x + 5] & 0x7F];
- row[x + 6] = softwareRenderer->palette[softwareRenderer->row[x + 6] & 0x7F];
- row[x + 7] = softwareRenderer->palette[softwareRenderer->row[x + 7] & 0x7F];
+
+ size_t sgbOffset = 0;
+ if (softwareRenderer->model == GB_MODEL_SGB && softwareRenderer->sgbBorders) {
+ sgbOffset = softwareRenderer->outputBufferStride * 40 + 48;
}
- for (; x < endX; ++x) {
- row[x] = softwareRenderer->palette[softwareRenderer->row[x] & 0x7F];
+ color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y + sgbOffset];
+ int x = startX;
+ int p = 0;
+ switch (softwareRenderer->d.sgbRenderMode) {
+ case 0:
+ if (softwareRenderer->model == GB_MODEL_SGB) {
+ p = softwareRenderer->d.sgbAttributes[(startX >> 5) + 5 * (y >> 3)];
+ p >>= 6 - ((x / 4) & 0x6);
+ p &= 3;
+ p <<= 2;
+ }
+ for (; x < ((startX + 7) & ~7) && x < endX; ++x) {
+ row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & 0x7F]];
+ }
+ for (; x + 7 < (endX & ~7); x += 8) {
+ if (softwareRenderer->model == GB_MODEL_SGB) {
+ p = softwareRenderer->d.sgbAttributes[(x >> 5) + 5 * (y >> 3)];
+ p >>= 6 - ((x / 4) & 0x6);
+ p &= 3;
+ p <<= 2;
+ }
+ row[x + 0] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & 0x7F]];
+ row[x + 1] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 1] & 0x7F]];
+ row[x + 2] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 2] & 0x7F]];
+ row[x + 3] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 3] & 0x7F]];
+ row[x + 4] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 4] & 0x7F]];
+ row[x + 5] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 5] & 0x7F]];
+ row[x + 6] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 6] & 0x7F]];
+ row[x + 7] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 7] & 0x7F]];
+ }
+ if (softwareRenderer->model == GB_MODEL_SGB) {
+ p = softwareRenderer->d.sgbAttributes[(x >> 5) + 5 * (y >> 3)];
+ p >>= 6 - ((x / 4) & 0x6);
+ p &= 3;
+ p <<= 2;
+ }
+ for (; x < endX; ++x) {
+ row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & 0x7F]];
+ }
+ break;
+ case 1:
+ break;
+ case 2:
+ for (; x < ((startX + 7) & ~7) && x < endX; ++x) {
+ row[x] = 0;
+ }
+ for (; x + 7 < (endX & ~7); x += 8) {
+ row[x] = 0;
+ row[x + 1] = 0;
+ row[x + 2] = 0;
+ row[x + 3] = 0;
+ row[x + 4] = 0;
+ row[x + 5] = 0;
+ row[x + 6] = 0;
+ row[x + 7] = 0;
+ }
+ for (; x < endX; ++x) {
+ row[x] = 0;
+ }
+ break;
+ case 3:
+ for (; x < ((startX + 7) & ~7) && x < endX; ++x) {
+ row[x] = softwareRenderer->palette[0];
+ }
+ for (; x + 7 < (endX & ~7); x += 8) {
+ row[x] = softwareRenderer->palette[0];
+ row[x + 1] = softwareRenderer->palette[0];
+ row[x + 2] = softwareRenderer->palette[0];
+ row[x + 3] = softwareRenderer->palette[0];
+ row[x + 4] = softwareRenderer->palette[0];
+ row[x + 5] = softwareRenderer->palette[0];
+ row[x + 6] = softwareRenderer->palette[0];
+ row[x + 7] = softwareRenderer->palette[0];
+ }
+ for (; x < endX; ++x) {
+ row[x] = softwareRenderer->palette[0];
+ }
+ break;
}
}
static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
+
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && softwareRenderer->wy <= y && softwareRenderer->wx - 7 < GB_VIDEO_HORIZONTAL_PIXELS) {
++softwareRenderer->currentWy;
}
+ if (softwareRenderer->sgbTransfer == 1) {
+ size_t offset = 2 * ((y & 7) + (y >> 3) * GB_VIDEO_HORIZONTAL_PIXELS);
+ if (offset >= 0x1000) {
+ return;
+ }
+ uint8_t* buffer = NULL;
+ switch (softwareRenderer->sgbCommandHeader >> 3) {
+ case SGB_PAL_TRN:
+ buffer = renderer->sgbPalRam;
+ break;
+ case SGB_CHR_TRN:
+ buffer = &renderer->sgbCharRam[SGB_SIZE_CHAR_RAM / 2 * (softwareRenderer->sgbPacket[1] & 1)];
+ break;
+ case SGB_PCT_TRN:
+ buffer = renderer->sgbMapRam;
+ break;
+ case SGB_ATTR_TRN:
+ buffer = renderer->sgbAttributeFiles;
+ break;
+ default:
+ break;
+ }
+ if (buffer) {
+ int i;
+ for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS; i += 8) {
+ if (UNLIKELY(offset + (i << 1) + 1 >= 0x1000)) {
+ break;
+ }
+ uint8_t hi = 0;
+ uint8_t lo = 0;
+ hi |= (softwareRenderer->row[i + 0] & 0x2) << 6;
+ lo |= (softwareRenderer->row[i + 0] & 0x1) << 7;
+ hi |= (softwareRenderer->row[i + 1] & 0x2) << 5;
+ lo |= (softwareRenderer->row[i + 1] & 0x1) << 6;
+ hi |= (softwareRenderer->row[i + 2] & 0x2) << 4;
+ lo |= (softwareRenderer->row[i + 2] & 0x1) << 5;
+ hi |= (softwareRenderer->row[i + 3] & 0x2) << 3;
+ lo |= (softwareRenderer->row[i + 3] & 0x1) << 4;
+ hi |= (softwareRenderer->row[i + 4] & 0x2) << 2;
+ lo |= (softwareRenderer->row[i + 4] & 0x1) << 3;
+ hi |= (softwareRenderer->row[i + 5] & 0x2) << 1;
+ lo |= (softwareRenderer->row[i + 5] & 0x1) << 2;
+ hi |= (softwareRenderer->row[i + 6] & 0x2) << 0;
+ lo |= (softwareRenderer->row[i + 6] & 0x1) << 1;
+ hi |= (softwareRenderer->row[i + 7] & 0x2) >> 1;
+ lo |= (softwareRenderer->row[i + 7] & 0x1) >> 0;
+ buffer[offset + (i << 1) + 0] = lo;
+ buffer[offset + (i << 1) + 1] = hi;
+ }
+ }
+ }
}
static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer) {
@@ -201,6 +494,32 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer)
if (!GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) {
_clearScreen(softwareRenderer);
}
+ if (softwareRenderer->model == GB_MODEL_SGB) {
+ switch (softwareRenderer->sgbCommandHeader >> 3) {
+ case SGB_PAL_SET:
+ case SGB_ATTR_SET:
+ if (softwareRenderer->sgbPacket[1] & 0x40) {
+ renderer->sgbRenderMode = 0;
+ }
+ break;
+ case SGB_PAL_TRN:
+ case SGB_CHR_TRN:
+ case SGB_PCT_TRN:
+ if (softwareRenderer->sgbTransfer > 0 && softwareRenderer->sgbBorders) {
+ // Make sure every buffer sees this if we're multibuffering
+ _regenerateSGBBorder(softwareRenderer);
+ }
+ // Fall through
+ case SGB_ATTR_TRN:
+ ++softwareRenderer->sgbTransfer;
+ if (softwareRenderer->sgbTransfer == 5) {
+ softwareRenderer->sgbCommandHeader = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ }
softwareRenderer->currentWy = 0;
}
@@ -448,37 +767,10 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende
static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
- // TODO: Share with GBAVideoSoftwareRendererGetPixels
-#ifdef COLOR_16_BIT
- *stride = GB_VIDEO_HORIZONTAL_PIXELS;
- if (!softwareRenderer->temporaryBuffer) {
- softwareRenderer->temporaryBuffer = anonymousMemoryMap(GB_VIDEO_HORIZONTAL_PIXELS * GB_VIDEO_VERTICAL_PIXELS * 4);
- }
- *pixels = softwareRenderer->temporaryBuffer;
- unsigned y, x;
- for (y = 0; y < GB_VIDEO_VERTICAL_PIXELS; ++y) {
- for (x = 0; x < GB_VIDEO_HORIZONTAL_PIXELS; ++x) {
- color_t inColor = softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y + x];
- uint32_t outColor;
-#ifdef COLOR_5_6_5
- outColor = (inColor & 0x1F) << 19;
- outColor |= (inColor & 0x7C0) << 5;
- outColor |= (inColor & 0xF800) >> 8;
-#else
- outColor = (inColor & 0x1F) << 3;
- outColor |= (inColor & 0x3E0) << 6;
- outColor |= (inColor & 0x7C00) << 9;
-#endif
- softwareRenderer->temporaryBuffer[GB_VIDEO_HORIZONTAL_PIXELS * y + x] = outColor;
- }
- }
-#else
*stride = softwareRenderer->outputBufferStride;
*pixels = softwareRenderer->outputBuffer;
-#endif
}
-
static void GBVideoSoftwareRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels) {
struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer;
// TODO: Share with GBAVideoSoftwareRendererGetPixels
diff --git a/src/gb/renderers/tile-cache.c b/src/gb/renderers/tile-cache.c
deleted file mode 100644
index 4780649b8..000000000
--- a/src/gb/renderers/tile-cache.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright (c) 2013-2016 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
-
-void GBVideoTileCacheInit(struct mTileCache* cache) {
- mTileCacheInit(cache);
- mTileCacheConfiguration config = 0;
- config = mTileCacheSystemInfoSetPalette0BPP(config, 1); // 2^(2^2) = 4 entries
- config = mTileCacheSystemInfoSetPalette0Count(config, 4); // 16 palettes
- config = mTileCacheSystemInfoSetPalette1BPP(config, 0); // Disable
- config = mTileCacheSystemInfoSetPalette1Count(config, 0); // Disable
- config = mTileCacheSystemInfoSetMaxTiles(config, 1024);
- mTileCacheConfigureSystem(cache, config);
-}
-
-void GBVideoTileCacheAssociate(struct mTileCache* cache, struct GBVideo* video) {
- cache->vram = (uint16_t*) video->vram;
- cache->palette = video->palette;
- video->renderer->cache = cache;
-}
diff --git a/src/gb/serialize.c b/src/gb/serialize.c
index d9f192092..c37b3872b 100644
--- a/src/gb/serialize.c
+++ b/src/gb/serialize.c
@@ -12,7 +12,10 @@
mLOG_DEFINE_CATEGORY(GB_STATE, "GB Savestate", "gb.serialize");
const uint32_t GB_SAVESTATE_MAGIC = 0x00400000;
-const uint32_t GB_SAVESTATE_VERSION = 0x00000001;
+const uint32_t GB_SAVESTATE_VERSION = 0x00000002;
+
+static void GBSGBSerialize(struct GB* gb, struct GBSerializedState* state);
+static void GBSGBDeserialize(struct GB* gb, const struct GBSerializedState* state);
void GBSerialize(struct GB* gb, struct GBSerializedState* state) {
STORE_32LE(GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, 0, &state->versionMagic);
@@ -20,7 +23,7 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* state) {
STORE_32LE(gb->timing.masterCycles, 0, &state->masterCycles);
if (gb->memory.rom) {
- memcpy(state->title, ((struct GBCartridge*) gb->memory.rom)->titleLong, sizeof(state->title));
+ memcpy(state->title, ((struct GBCartridge*) &gb->memory.rom[0x100])->titleLong, sizeof(state->title));
} else {
memset(state->title, 0, sizeof(state->title));
}
@@ -44,7 +47,6 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* state) {
STORE_16LE(gb->cpu->index, 0, &state->cpu.index);
state->cpu.bus = gb->cpu->bus;
state->cpu.executionState = gb->cpu->executionState;
- STORE_16LE(gb->cpu->irqVector, 0, &state->cpu.irqVector);
GBSerializedCpuFlags flags = 0;
flags = GBSerializedCpuFlagsSetCondition(flags, gb->cpu->condition);
@@ -59,6 +61,10 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* state) {
GBVideoSerialize(&gb->video, state);
GBTimerSerialize(&gb->timer, state);
GBAudioSerialize(&gb->audio, state);
+
+ if (gb->model == GB_MODEL_SGB) {
+ GBSGBSerialize(gb, state);
+ }
}
bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
@@ -77,10 +83,15 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
} else if (ucheck < GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION) {
mLOG(GB_STATE, WARN, "Old savestate: expected %08X, got %08X, continuing anyway", GB_SAVESTATE_MAGIC + GB_SAVESTATE_VERSION, ucheck);
}
+ bool canSgb = ucheck >= GB_SAVESTATE_MAGIC + 2;
- if (gb->memory.rom && memcmp(state->title, ((struct GBCartridge*) gb->memory.rom)->titleLong, sizeof(state->title))) {
- mLOG(GB_STATE, WARN, "Savestate is for a different game");
- error = true;
+ if (gb->memory.rom && memcmp(state->title, ((struct GBCartridge*) &gb->memory.rom[0x100])->titleLong, sizeof(state->title))) {
+ LOAD_32LE(ucheck, 0, &state->versionMagic);
+ if (ucheck > GB_SAVESTATE_MAGIC + 2 || memcmp(state->title, ((struct GBCartridge*) gb->memory.rom)->titleLong, sizeof(state->title))) {
+ // There was a bug in previous versions where the memory address being compared was wrong
+ mLOG(GB_STATE, WARN, "Savestate is for a different game");
+ error = true;
+ }
}
LOAD_32LE(ucheck, 0, &state->romCrc32);
if (ucheck != gb->romCrc32) {
@@ -126,6 +137,7 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
return false;
}
gb->timing.root = NULL;
+ LOAD_32LE(gb->timing.masterCycles, 0, &state->masterCycles);
gb->cpu->a = state->cpu.a;
gb->cpu->f.packed = state->cpu.f;
@@ -141,7 +153,6 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
LOAD_16LE(gb->cpu->index, 0, &state->cpu.index);
gb->cpu->bus = state->cpu.bus;
gb->cpu->executionState = state->cpu.executionState;
- LOAD_16LE(gb->cpu->irqVector, 0, &state->cpu.irqVector);
GBSerializedCpuFlags flags;
LOAD_32LE(flags, 0, &state->cpu.flags);
@@ -150,16 +161,16 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
gb->doubleSpeed = GBSerializedCpuFlagsGetDoubleSpeed(flags);
gb->audio.timingFactor = gb->doubleSpeed + 1;
+ LOAD_32LE(gb->cpu->cycles, 0, &state->cpu.cycles);
+ LOAD_32LE(gb->cpu->nextEvent, 0, &state->cpu.nextEvent);
+ gb->timing.root = NULL;
+
uint32_t when;
LOAD_32LE(when, 0, &state->cpu.eiPending);
if (GBSerializedCpuFlagsIsEiPending(flags)) {
mTimingSchedule(&gb->timing, &gb->eiPending, when);
}
- LOAD_32LE(gb->cpu->cycles, 0, &state->cpu.cycles);
- LOAD_32LE(gb->cpu->nextEvent, 0, &state->cpu.nextEvent);
- gb->timing.root = NULL;
-
gb->model = state->model;
if (gb->model < GB_MODEL_CGB) {
@@ -174,7 +185,74 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
GBTimerDeserialize(&gb->timer, state);
GBAudioDeserialize(&gb->audio, state);
+ if (gb->model == GB_MODEL_SGB && canSgb) {
+ GBSGBDeserialize(gb, state);
+ }
+
gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
+ gb->timing.reroot = gb->timing.root;
+ gb->timing.root = NULL;
+
return true;
}
+
+// TODO: Reorganize SGB into its own file
+void GBSGBSerialize(struct GB* gb, struct GBSerializedState* state) {
+ state->sgb.command = gb->video.sgbCommandHeader;
+ state->sgb.bits = gb->sgbBit;
+
+ GBSerializedSGBFlags flags = 0;
+ flags = GBSerializedSGBFlagsSetP1Bits(flags, gb->currentSgbBits);
+ flags = GBSerializedSGBFlagsSetRenderMode(flags, gb->video.renderer->sgbRenderMode);
+ STORE_32LE(flags, 0, &state->sgb.flags);
+
+ memcpy(state->sgb.packet, gb->sgbPacket, sizeof(state->sgb.packet));
+
+ if (gb->video.renderer->sgbCharRam) {
+ memcpy(state->sgb.charRam, gb->video.renderer->sgbCharRam, sizeof(state->sgb.charRam));
+ }
+ if (gb->video.renderer->sgbMapRam) {
+ memcpy(state->sgb.mapRam, gb->video.renderer->sgbMapRam, sizeof(state->sgb.mapRam));
+ }
+ if (gb->video.renderer->sgbPalRam) {
+ memcpy(state->sgb.palRam, gb->video.renderer->sgbPalRam, sizeof(state->sgb.palRam));
+ }
+ if (gb->video.renderer->sgbAttributeFiles) {
+ memcpy(state->sgb.atfRam, gb->video.renderer->sgbAttributeFiles, sizeof(state->sgb.atfRam));
+ }
+ if (gb->video.renderer->sgbAttributes) {
+ memcpy(state->sgb.attributes, gb->video.renderer->sgbAttributes, sizeof(state->sgb.attributes));
+ }
+}
+
+void GBSGBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
+ gb->video.sgbCommandHeader = state->sgb.command;
+ gb->sgbBit = state->sgb.bits;
+
+ GBSerializedSGBFlags flags;
+ LOAD_32LE(flags, 0, &state->sgb.flags);
+ gb->currentSgbBits = GBSerializedSGBFlagsGetP1Bits(flags);
+ gb->video.renderer->sgbRenderMode = GBSerializedSGBFlagsGetRenderMode(flags);
+
+ memcpy(gb->sgbPacket, state->sgb.packet, sizeof(state->sgb.packet));
+
+ if (gb->video.renderer->sgbCharRam) {
+ memcpy(gb->video.renderer->sgbCharRam, state->sgb.charRam, sizeof(state->sgb.charRam));
+ }
+ if (gb->video.renderer->sgbMapRam) {
+ memcpy(gb->video.renderer->sgbMapRam, state->sgb.mapRam, sizeof(state->sgb.mapRam));
+ }
+ if (gb->video.renderer->sgbPalRam) {
+ memcpy(gb->video.renderer->sgbPalRam, state->sgb.palRam, sizeof(state->sgb.palRam));
+ }
+ if (gb->video.renderer->sgbAttributeFiles) {
+ memcpy(gb->video.renderer->sgbAttributeFiles, state->sgb.atfRam, sizeof(state->sgb.atfRam));
+ }
+ if (gb->video.renderer->sgbAttributes) {
+ memcpy(gb->video.renderer->sgbAttributes, state->sgb.attributes, sizeof(state->sgb.attributes));
+ }
+
+ GBVideoWriteSGBPacket(&gb->video, (uint8_t[16]) { (SGB_ATRC_EN << 3) | 1, 0 });
+ GBVideoWriteSGBPacket(&gb->video, gb->sgbPacket);
+}
diff --git a/src/gb/sio/printer.c b/src/gb/sio/printer.c
new file mode 100644
index 000000000..4bd1bf2ea
--- /dev/null
+++ b/src/gb/sio/printer.c
@@ -0,0 +1,233 @@
+/* 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 bool GBPrinterInit(struct GBSIODriver* driver);
+static void GBPrinterDeinit(struct GBSIODriver* driver);
+static void GBPrinterWriteSB(struct GBSIODriver* driver, uint8_t value);
+static uint8_t GBPrinterWriteSC(struct GBSIODriver* driver, uint8_t value);
+
+void GBPrinterCreate(struct GBPrinter* printer) {
+ printer->d.init = GBPrinterInit;
+ printer->d.deinit = GBPrinterDeinit;
+ printer->d.writeSB = GBPrinterWriteSB;
+ printer->d.writeSC = GBPrinterWriteSC;
+ printer->print = NULL;
+}
+
+bool GBPrinterInit(struct GBSIODriver* driver) {
+ struct GBPrinter* printer = (struct GBPrinter*) driver;
+
+ printer->checksum = 0;
+ printer->command = 0;
+ printer->remainingBytes = 0;
+ printer->currentIndex = 0;
+ printer->compression = false;
+ printer->byte = 0;
+ printer->next = GB_PRINTER_BYTE_MAGIC_0;
+ printer->status = 0;
+ printer->printWait = -1;
+
+ printer->buffer = malloc(GB_VIDEO_HORIZONTAL_PIXELS * GB_VIDEO_VERTICAL_PIXELS / 2);
+
+ return true;
+}
+
+void GBPrinterDeinit(struct GBSIODriver* driver) {
+ struct GBPrinter* printer = (struct GBPrinter*) driver;
+ free(printer->buffer);
+}
+
+static void GBPrinterWriteSB(struct GBSIODriver* driver, uint8_t value) {
+ struct GBPrinter* printer = (struct GBPrinter*) driver;
+ printer->byte = value;
+}
+
+static void _processByte(struct GBPrinter* printer) {
+ switch (printer->command) {
+ case GB_PRINTER_COMMAND_DATA:
+ if (printer->currentIndex < GB_VIDEO_VERTICAL_PIXELS * GB_VIDEO_HORIZONTAL_PIXELS / 2) {
+ printer->buffer[printer->currentIndex] = printer->byte;
+ ++printer->currentIndex;
+ }
+ break;
+ case GB_PRINTER_COMMAND_PRINT:
+ // TODO
+ break;
+ default:
+ break;
+ }
+}
+
+static uint8_t GBPrinterWriteSC(struct GBSIODriver* driver, uint8_t value) {
+ struct GBPrinter* printer = (struct GBPrinter*) driver;
+ if ((value & 0x81) == 0x81) {
+ switch (printer->next) {
+ driver->p->pendingSB = 0;
+ case GB_PRINTER_BYTE_MAGIC_0:
+ if (printer->byte == 0x88) {
+ printer->next = GB_PRINTER_BYTE_MAGIC_1;
+ } else {
+ printer->next = GB_PRINTER_BYTE_MAGIC_0;
+ }
+ break;
+ case GB_PRINTER_BYTE_MAGIC_1:
+ if (printer->byte == 0x33) {
+ printer->next = GB_PRINTER_BYTE_COMMAND;
+ } else {
+ printer->next = GB_PRINTER_BYTE_MAGIC_0;
+ }
+ break;
+ case GB_PRINTER_BYTE_COMMAND:
+ printer->checksum = printer->byte;
+ printer->command = printer->byte;
+ printer->next = GB_PRINTER_BYTE_COMPRESSION;
+ break;
+ case GB_PRINTER_BYTE_COMPRESSION:
+ printer->checksum += printer->byte;
+ printer->compression = printer->byte;
+ printer->next = GB_PRINTER_BYTE_LENGTH_0;
+ break;
+ case GB_PRINTER_BYTE_LENGTH_0:
+ printer->checksum += printer->byte;
+ printer->remainingBytes = printer->byte;
+ printer->next = GB_PRINTER_BYTE_LENGTH_1;
+ break;
+ case GB_PRINTER_BYTE_LENGTH_1:
+ printer->checksum += printer->byte;
+ printer->remainingBytes |= printer->byte << 8;
+ if (printer->remainingBytes) {
+ printer->next = GB_PRINTER_BYTE_DATA;
+ } else {
+ printer->next = GB_PRINTER_BYTE_CHECKSUM_0;
+ }
+ switch (printer->command) {
+ case GB_PRINTER_COMMAND_INIT:
+ printer->currentIndex = 0;
+ printer->status &= ~(GB_PRINTER_STATUS_PRINT_REQ | GB_PRINTER_STATUS_READY);
+ break;
+ default:
+ break;
+ }
+ break;
+ case GB_PRINTER_BYTE_DATA:
+ printer->checksum += printer->byte;
+ if (!printer->compression) {
+ _processByte(printer);
+ } else {
+ printer->next = printer->byte & 0x80 ? GB_PRINTER_BYTE_COMPRESSED_DATUM : GB_PRINTER_BYTE_UNCOMPRESSED_DATA;
+ printer->remainingCmpBytes = (printer->byte & 0x7F) + 1;
+ if (printer->byte & 0x80) {
+ ++printer->remainingCmpBytes;
+ }
+ }
+ --printer->remainingBytes;
+ if (!printer->remainingBytes) {
+ printer->next = GB_PRINTER_BYTE_CHECKSUM_0;
+ }
+ break;
+ case GB_PRINTER_BYTE_UNCOMPRESSED_DATA:
+ printer->checksum += printer->byte;
+ _processByte(printer);
+ --printer->remainingCmpBytes;
+ if (!printer->remainingCmpBytes) {
+ printer->next = GB_PRINTER_BYTE_DATA;
+ }
+ --printer->remainingBytes;
+ if (!printer->remainingBytes) {
+ printer->next = GB_PRINTER_BYTE_CHECKSUM_0;
+ }
+ break;
+ case GB_PRINTER_BYTE_COMPRESSED_DATUM:
+ printer->checksum += printer->byte;
+ while (printer->remainingCmpBytes) {
+ _processByte(printer);
+ --printer->remainingCmpBytes;
+ }
+ --printer->remainingBytes;
+ if (!printer->remainingBytes) {
+ printer->next = GB_PRINTER_BYTE_CHECKSUM_0;
+ } else {
+ printer->next = GB_PRINTER_BYTE_DATA;
+ }
+ break;
+ case GB_PRINTER_BYTE_CHECKSUM_0:
+ printer->checksum ^= printer->byte;
+ printer->next = GB_PRINTER_BYTE_CHECKSUM_1;
+ break;
+ case GB_PRINTER_BYTE_CHECKSUM_1:
+ printer->checksum ^= printer->byte << 8;
+ printer->next = GB_PRINTER_BYTE_KEEPALIVE;
+ break;
+ case GB_PRINTER_BYTE_KEEPALIVE:
+ driver->p->pendingSB = 0x81;
+ printer->next = GB_PRINTER_BYTE_STATUS;
+ break;
+ case GB_PRINTER_BYTE_STATUS:
+ switch (printer->command) {
+ case GB_PRINTER_COMMAND_DATA:
+ if (printer->currentIndex >= 0x280 && !(printer->status & GB_PRINTER_STATUS_CHECKSUM_ERROR)) {
+ printer->status |= GB_PRINTER_STATUS_READY;
+ }
+ break;
+ case GB_PRINTER_COMMAND_PRINT:
+ if (printer->currentIndex >= GB_VIDEO_HORIZONTAL_PIXELS * 2) {
+ printer->printWait = 0;
+ }
+ break;
+ case GB_PRINTER_COMMAND_STATUS:
+ if (!printer->printWait) {
+ printer->status &= ~GB_PRINTER_STATUS_READY;
+ printer->status |= GB_PRINTER_STATUS_PRINTING | GB_PRINTER_STATUS_PRINT_REQ;
+ if (printer->print) {
+ size_t y;
+ for (y = 0; y < printer->currentIndex / (2 * GB_VIDEO_HORIZONTAL_PIXELS); ++y) {
+ uint8_t lineBuffer[GB_VIDEO_HORIZONTAL_PIXELS * 2];
+ uint8_t* buffer = &printer->buffer[sizeof(lineBuffer) * y];
+ size_t i;
+ for (i = 0; i < sizeof(lineBuffer); i += 2) {
+ uint8_t ilo = buffer[i + 0x0];
+ uint8_t ihi = buffer[i + 0x1];
+ uint8_t olo = 0;
+ uint8_t ohi = 0;
+ olo |= ((ihi & 0x80) >> 0) | ((ilo & 0x80) >> 1);
+ olo |= ((ihi & 0x40) >> 1) | ((ilo & 0x40) >> 2);
+ olo |= ((ihi & 0x20) >> 2) | ((ilo & 0x20) >> 3);
+ olo |= ((ihi & 0x10) >> 3) | ((ilo & 0x10) >> 4);
+ ohi |= ((ihi & 0x08) << 4) | ((ilo & 0x08) << 3);
+ ohi |= ((ihi & 0x04) << 3) | ((ilo & 0x04) << 2);
+ ohi |= ((ihi & 0x02) << 2) | ((ilo & 0x02) << 1);
+ ohi |= ((ihi & 0x01) << 1) | ((ilo & 0x01) << 0);
+ lineBuffer[(((i >> 1) & 0x7) * GB_VIDEO_HORIZONTAL_PIXELS / 4) + ((i >> 3) & ~1)] = olo;
+ lineBuffer[(((i >> 1) & 0x7) * GB_VIDEO_HORIZONTAL_PIXELS / 4) + ((i >> 3) | 1)] = ohi;
+ }
+ memcpy(buffer, lineBuffer, sizeof(lineBuffer));
+ }
+ printer->print(printer, printer->currentIndex * 4 / GB_VIDEO_HORIZONTAL_PIXELS, printer->buffer);
+ }
+ }
+ if (printer->printWait >= 0) {
+ --printer->printWait;
+ }
+ default:
+ break;
+ }
+ driver->p->pendingSB = printer->status;
+ printer->next = GB_PRINTER_BYTE_MAGIC_0;
+ break;
+ }
+ printer->byte = 0;
+ }
+ return value;
+}
+
+void GBPrinterDonePrinting(struct GBPrinter* printer) {
+ printer->status &= ~GB_PRINTER_STATUS_PRINTING;
+}
diff --git a/src/gb/test/core.c b/src/gb/test/core.c
index 09f9ca25a..a8638012b 100644
--- a/src/gb/test/core.c
+++ b/src/gb/test/core.c
@@ -29,6 +29,7 @@ M_TEST_DEFINE(reset) {
struct mCore* core = GBCoreCreate();
assert_non_null(core);
assert_true(core->init(core));
+ mCoreInitConfig(core, NULL);
core->reset(core);
core->deinit(core);
}
@@ -37,6 +38,7 @@ M_TEST_DEFINE(loadNullROM) {
struct mCore* core = GBCoreCreate();
assert_non_null(core);
assert_true(core->init(core));
+ mCoreInitConfig(core, NULL);
assert_false(core->loadROM(core, NULL));
core->reset(core);
core->deinit(core);
diff --git a/src/gb/test/gb.c b/src/gb/test/gb.c
deleted file mode 100644
index 2a21b3228..000000000
--- a/src/gb/test/gb.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright (c) 2013-2016 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"
-
-M_TEST_SUITE_DECLARE(GBCore);
-M_TEST_SUITE_DECLARE(GBMBC);
-M_TEST_SUITE_DECLARE(GBMemory);
-M_TEST_SUITE_DECLARE(GBRTC);
-
-int TestRunGB(void) {
- int failures = 0;
- failures += M_TEST_SUITE_RUN(GBCore);
- failures += M_TEST_SUITE_RUN(GBMBC);
- failures += M_TEST_SUITE_RUN(GBMemory);
- failures += M_TEST_SUITE_RUN(GBRTC);
- return failures;
-}
diff --git a/src/gb/test/gb.h b/src/gb/test/gb.h
deleted file mode 100644
index 572a21466..000000000
--- a/src/gb/test/gb.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Copyright (c) 2013-2016 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 TEST_GB_H
-#define TEST_GB_H
-#include
-
-int TestRunGB(void);
-
-#endif
diff --git a/src/gb/test/mbc.c b/src/gb/test/mbc.c
index a9448892b..5498d004d 100644
--- a/src/gb/test/mbc.c
+++ b/src/gb/test/mbc.c
@@ -16,6 +16,7 @@ M_TEST_SUITE_SETUP(GBMBC) {
GBSynthesizeROM(vf);
struct mCore* core = GBCoreCreate();
core->init(core);
+ mCoreInitConfig(core, NULL);
core->loadROM(core, vf);
*state = core;
return 0;
diff --git a/src/gb/test/memory.c b/src/gb/test/memory.c
index f4e0ee642..01a4b398f 100644
--- a/src/gb/test/memory.c
+++ b/src/gb/test/memory.c
@@ -16,6 +16,7 @@ M_TEST_SUITE_SETUP(GBMemory) {
GBSynthesizeROM(vf);
struct mCore* core = GBCoreCreate();
core->init(core);
+ mCoreInitConfig(core, NULL);
core->loadROM(core, vf);
*state = core;
return 0;
diff --git a/src/gb/test/rtc.c b/src/gb/test/rtc.c
index 5ad393a64..71d06ced2 100644
--- a/src/gb/test/rtc.c
+++ b/src/gb/test/rtc.c
@@ -14,7 +14,7 @@
struct GBRTCTest {
struct mRTCSource d;
struct mCore* core;
- struct VFile* fakeROM;
+ struct VFile* fakeSave;
time_t nextTime;
};
@@ -48,13 +48,17 @@ M_TEST_SUITE_SETUP(GBRTC) {
return -1;
}
test->core->init(test->core);
+ mCoreInitConfig(test->core, NULL);
struct VFile* vf = VFileMemChunk(NULL, 2048);
GBSynthesizeROM(vf);
test->core->loadROM(test->core, vf);
- test->core->setRTC(test->core, &test->d);
+ mCoreSetRTC(test->core, &test->d);
+
+ test->fakeSave = VFileMemChunk(NULL, 0);
+ test->core->loadSave(test->core, test->fakeSave);
+
struct GB* gb = test->core->board;
- struct GBCartridge* cart = (struct GBCartridge*) &gb->memory.rom[0x100];
- cart->type = 0x0F;
+ gb->memory.mbcType = GB_MBC3_RTC;
*state = test;
return 0;
@@ -77,10 +81,12 @@ M_TEST_DEFINE(create) {
uint8_t expected[sizeof(gb->memory.rtcRegs)] = { 0, 0, 0, 0, 0 };
assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ assert_int_equal(gb->memory.mbcType, GB_MBC3_RTC);
}
M_TEST_DEFINE(tickSecond) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 1;
@@ -108,6 +114,7 @@ M_TEST_DEFINE(tickSecond) {
M_TEST_DEFINE(tick30Seconds) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 30;
@@ -142,6 +149,7 @@ M_TEST_DEFINE(tick30Seconds) {
M_TEST_DEFINE(tickMinute) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 60;
@@ -184,6 +192,7 @@ M_TEST_DEFINE(tickMinute) {
M_TEST_DEFINE(tick90Seconds) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 90;
@@ -240,6 +249,7 @@ M_TEST_DEFINE(tick90Seconds) {
M_TEST_DEFINE(tick30Minutes) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 1800;
@@ -282,6 +292,7 @@ M_TEST_DEFINE(tick30Minutes) {
M_TEST_DEFINE(tickHour) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 3600;
@@ -339,6 +350,7 @@ M_TEST_DEFINE(tickHour) {
M_TEST_DEFINE(tick12Hours) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 3600 * 12;
@@ -407,6 +419,7 @@ M_TEST_DEFINE(tick12Hours) {
M_TEST_DEFINE(tickDay) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 3600 * 24;
@@ -505,6 +518,7 @@ M_TEST_DEFINE(tickDay) {
M_TEST_DEFINE(wideTickDay) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 3600 * 24 * 2001;
@@ -611,6 +625,7 @@ M_TEST_DEFINE(wideTickDay) {
M_TEST_DEFINE(rolloverSecond) {
struct GBRTCTest* test = *state;
+ test->nextTime = 0;
test->core->reset(test->core);
struct GB* gb = test->core->board;
test->nextTime = 1;
@@ -672,6 +687,270 @@ M_TEST_DEFINE(rolloverSecond) {
assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
}
+M_TEST_DEFINE(roundtrip0) {
+ struct GBRTCTest* test = *state;
+ test->nextTime = 0;
+ test->fakeSave->truncate(test->fakeSave, 0);
+ test->core->reset(test->core);
+ struct GB* gb = test->core->board;
+
+ uint8_t expected[sizeof(gb->memory.rtcRegs)] = { 0, 0, 0, 0, 0 };
+ memset(gb->memory.rtcRegs, 0, sizeof(expected));
+ GBMBCRTCWrite(gb);
+
+ GBMBCRTCRead(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ GBMBCRTCWrite(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ GBMBCRTCRead(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 3600;
+ expected[2] = 1;
+ GBMBCRTCWrite(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ GBMBCRTCWrite(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 3600 * 2;
+ expected[2] = 2;
+ GBMBCRTCWrite(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+}
+
+M_TEST_DEFINE(roundtripSecond) {
+ struct GBRTCTest* test = *state;
+ test->nextTime = 0;
+ test->fakeSave->truncate(test->fakeSave, 0);
+ test->core->reset(test->core);
+ struct GB* gb = test->core->board;
+
+ uint8_t expected[sizeof(gb->memory.rtcRegs)] = { 0, 0, 0, 0, 0 };
+ memset(gb->memory.rtcRegs, 0, sizeof(expected));
+ GBMBCRTCWrite(gb);
+
+ test->nextTime = 1;
+ GBMBCRTCRead(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ expected[0] = 1;
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ GBMBCRTCWrite(gb);
+
+ test->nextTime = 2;
+ GBMBCRTCRead(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ _sampleRtcKeepLatch(gb);
+ expected[0] = 2;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->core->reset(test->core);
+ expected[0] = 1;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ _sampleRtcKeepLatch(gb);
+ expected[0] = 2;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->core->reset(test->core);
+ expected[0] = 1;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ expected[0] = 2;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 3;
+ test->core->reset(test->core);
+ expected[0] = 1;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ _sampleRtcKeepLatch(gb);
+ expected[0] = 3;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 1;
+ test->core->reset(test->core);
+ expected[0] = 1;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ test->nextTime = 4;
+ _sampleRtcKeepLatch(gb);
+ expected[0] = 4;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+}
+
+M_TEST_DEFINE(roundtripDay) {
+ struct GBRTCTest* test = *state;
+ test->nextTime = 0;
+ test->fakeSave->truncate(test->fakeSave, 0);
+ test->core->reset(test->core);
+ struct GB* gb = test->core->board;
+
+ uint8_t expected[sizeof(gb->memory.rtcRegs)] = { 0, 0, 0, 0, 0 };
+ memset(gb->memory.rtcRegs, 0, sizeof(expected));
+ GBMBCRTCWrite(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 3600 * 24;
+ GBMBCRTCRead(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 1;
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 3600 * 24 * 2;
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 2;
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ GBMBCRTCWrite(gb);
+
+ test->nextTime = 3600 * 24 * 2;
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 2;
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 3600 * 24 * 3;
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 3;
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 3600 * 24 * 2;
+ test->core->reset(test->core);
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 2;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 3600 * 24 * 3;
+ test->core->reset(test->core);
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 2;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 3;
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+}
+
+M_TEST_DEFINE(roundtripHuge) {
+ struct GBRTCTest* test = *state;
+ test->nextTime = 1500000000;
+ test->fakeSave->truncate(test->fakeSave, 0);
+ test->core->reset(test->core);
+ struct GB* gb = test->core->board;
+
+ uint8_t expected[sizeof(gb->memory.rtcRegs)] = { 0, 0, 0, 0, 0 };
+ memset(gb->memory.rtcRegs, 0, sizeof(expected));
+ GBMBCRTCWrite(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 1500000000 + 3600 * 24;
+ GBMBCRTCRead(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 1;
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 1500000000 + 3600 * 24 * 2;
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 2;
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ GBMBCRTCWrite(gb);
+
+ test->nextTime = 1500000000 + 3600 * 24 * 2;
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 2;
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 1500000000 + 3600 * 24 * 3;
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 3;
+ GBMBCRTCRead(gb);
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 1500000000 + 3600 * 24 * 2;
+ test->core->reset(test->core);
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 2;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+
+ test->nextTime = 1500000000 + 3600 * 24 * 3;
+ test->core->reset(test->core);
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 2;
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+ expected[0] = 0;
+ expected[1] = 0;
+ expected[2] = 0;
+ expected[3] = 3;
+ _sampleRtcKeepLatch(gb);
+ assert_memory_equal(gb->memory.rtcRegs, expected, sizeof(expected));
+}
+
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(GBRTC,
cmocka_unit_test(create),
cmocka_unit_test(tickSecond),
@@ -683,4 +962,8 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(GBRTC,
cmocka_unit_test(tick12Hours),
cmocka_unit_test(tickDay),
cmocka_unit_test(wideTickDay),
- cmocka_unit_test(rolloverSecond))
+ cmocka_unit_test(rolloverSecond),
+ cmocka_unit_test(roundtrip0),
+ cmocka_unit_test(roundtripSecond),
+ cmocka_unit_test(roundtripDay),
+ cmocka_unit_test(roundtripHuge))
diff --git a/src/gb/timer.c b/src/gb/timer.c
index 0e587410d..061fc8f2e 100644
--- a/src/gb/timer.c
+++ b/src/gb/timer.c
@@ -64,7 +64,6 @@ void GBTimerReset(struct GBTimer* timer) {
timer->nextDiv = GB_DMG_DIV_PERIOD; // TODO: GBC differences
timer->timaPeriod = 1024 >> 4;
- timer->internalDiv = 0;
}
void GBTimerDivReset(struct GBTimer* timer) {
diff --git a/src/gb/video.c b/src/gb/video.c
index 605fcdd7f..4478b079e 100644
--- a/src/gb/video.c
+++ b/src/gb/video.c
@@ -7,17 +7,19 @@
#include
#include
-#include
+#include
#include
#include
+#include
#include
#include
#include
-static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model);
+static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders);
static void GBVideoDummyRendererDeinit(struct GBVideoRenderer* renderer);
static uint8_t GBVideoDummyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value);
+static void GBVideoDummyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data);
static void GBVideoDummyRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value);
static void GBVideoDummyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address);
static void GBVideoDummyRendererWriteOAM(struct GBVideoRenderer* renderer, uint16_t oam);
@@ -39,6 +41,7 @@ static struct GBVideoRenderer dummyRenderer = {
.init = GBVideoDummyRendererInit,
.deinit = GBVideoDummyRendererDeinit,
.writeVideoRegister = GBVideoDummyRendererWriteVideoRegister,
+ .writeSGBPacket = GBVideoDummyRendererWriteSGBPacket,
.writeVRAM = GBVideoDummyRendererWriteVRAM,
.writeOAM = GBVideoDummyRendererWriteOAM,
.writePalette = GBVideoDummyRendererWritePalette,
@@ -52,6 +55,7 @@ static struct GBVideoRenderer dummyRenderer = {
void GBVideoInit(struct GBVideo* video) {
video->renderer = &dummyRenderer;
video->renderer->cache = NULL;
+ video->renderer->sgbRenderMode = 0;
video->vram = 0;
video->frameskip = 0;
@@ -68,6 +72,22 @@ void GBVideoInit(struct GBVideo* video) {
video->dmgPalette[1] = 0x56B5;
video->dmgPalette[2] = 0x294A;
video->dmgPalette[3] = 0x0000;
+ video->dmgPalette[4] = 0x7FFF;
+ video->dmgPalette[5] = 0x56B5;
+ video->dmgPalette[6] = 0x294A;
+ video->dmgPalette[7] = 0x0000;
+ video->dmgPalette[8] = 0x7FFF;
+ video->dmgPalette[9] = 0x56B5;
+ video->dmgPalette[10] = 0x294A;
+ video->dmgPalette[11] = 0x0000;
+
+ video->sgbBorders = true;
+
+ video->renderer->sgbCharRam = NULL;
+ video->renderer->sgbMapRam = NULL;
+ video->renderer->sgbPalRam = NULL;
+ video->renderer->sgbAttributes = NULL;
+ video->renderer->sgbAttributeFiles = NULL;
}
void GBVideoReset(struct GBVideo* video) {
@@ -89,21 +109,83 @@ void GBVideoReset(struct GBVideo* video) {
video->renderer->oam = &video->oam;
memset(&video->palette, 0, sizeof(video->palette));
+ if (video->p->model == GB_MODEL_SGB) {
+ video->renderer->sgbCharRam = anonymousMemoryMap(SGB_SIZE_CHAR_RAM);
+ video->renderer->sgbMapRam = anonymousMemoryMap(SGB_SIZE_MAP_RAM);
+ video->renderer->sgbPalRam = anonymousMemoryMap(SGB_SIZE_PAL_RAM);
+ video->renderer->sgbAttributeFiles = anonymousMemoryMap(SGB_SIZE_ATF_RAM);
+ video->renderer->sgbAttributes = malloc(90 * 45);
+ memset(video->renderer->sgbAttributes, 0, 90 * 45);
+ video->sgbCommandHeader = 0;
+ }
+
+ video->palette[0] = video->dmgPalette[0];
+ video->palette[1] = video->dmgPalette[1];
+ video->palette[2] = video->dmgPalette[2];
+ video->palette[3] = video->dmgPalette[3];
+ video->palette[8 * 4 + 0] = video->dmgPalette[4];
+ video->palette[8 * 4 + 1] = video->dmgPalette[5];
+ video->palette[8 * 4 + 2] = video->dmgPalette[6];
+ video->palette[8 * 4 + 3] = video->dmgPalette[7];
+ video->palette[9 * 4 + 0] = video->dmgPalette[8];
+ video->palette[9 * 4 + 1] = video->dmgPalette[9];
+ video->palette[9 * 4 + 2] = video->dmgPalette[10];
+ video->palette[9 * 4 + 3] = video->dmgPalette[11];
+
video->renderer->deinit(video->renderer);
- video->renderer->init(video->renderer, video->p->model);
+ video->renderer->init(video->renderer, video->p->model, video->sgbBorders);
+
+ video->renderer->writePalette(video->renderer, 0, video->palette[0]);
+ video->renderer->writePalette(video->renderer, 1, video->palette[1]);
+ video->renderer->writePalette(video->renderer, 2, video->palette[2]);
+ video->renderer->writePalette(video->renderer, 3, video->palette[3]);
+ video->renderer->writePalette(video->renderer, 8 * 4 + 0, video->palette[8 * 4 + 0]);
+ video->renderer->writePalette(video->renderer, 8 * 4 + 1, video->palette[8 * 4 + 1]);
+ video->renderer->writePalette(video->renderer, 8 * 4 + 2, video->palette[8 * 4 + 2]);
+ video->renderer->writePalette(video->renderer, 8 * 4 + 3, video->palette[8 * 4 + 3]);
+ video->renderer->writePalette(video->renderer, 9 * 4 + 0, video->palette[9 * 4 + 0]);
+ video->renderer->writePalette(video->renderer, 9 * 4 + 1, video->palette[9 * 4 + 1]);
+ video->renderer->writePalette(video->renderer, 9 * 4 + 2, video->palette[9 * 4 + 2]);
+ video->renderer->writePalette(video->renderer, 9 * 4 + 3, video->palette[9 * 4 + 3]);
}
void GBVideoDeinit(struct GBVideo* video) {
GBVideoAssociateRenderer(video, &dummyRenderer);
mappedMemoryFree(video->vram, GB_SIZE_VRAM);
+ if (video->renderer->sgbCharRam) {
+ mappedMemoryFree(video->renderer->sgbCharRam, SGB_SIZE_CHAR_RAM);
+ video->renderer->sgbCharRam = NULL;
+ }
+ if (video->renderer->sgbMapRam) {
+ mappedMemoryFree(video->renderer->sgbMapRam, SGB_SIZE_MAP_RAM);
+ video->renderer->sgbMapRam = NULL;
+ }
+ if (video->renderer->sgbPalRam) {
+ mappedMemoryFree(video->renderer->sgbPalRam, SGB_SIZE_PAL_RAM);
+ video->renderer->sgbPalRam = NULL;
+ }
+ if (video->renderer->sgbAttributeFiles) {
+ mappedMemoryFree(video->renderer->sgbAttributeFiles, SGB_SIZE_ATF_RAM);
+ video->renderer->sgbAttributeFiles = NULL;
+ }
+ if (video->renderer->sgbAttributes) {
+ free(video->renderer->sgbAttributes);
+ video->renderer->sgbAttributes = NULL;
+ }
}
void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer) {
video->renderer->deinit(video->renderer);
renderer->cache = video->renderer->cache;
+ renderer->sgbRenderMode = video->renderer->sgbRenderMode;
+ renderer->sgbCharRam = video->renderer->sgbCharRam;
+ renderer->sgbMapRam = video->renderer->sgbMapRam;
+ renderer->sgbPalRam = video->renderer->sgbPalRam;
+ renderer->sgbAttributeFiles = video->renderer->sgbAttributeFiles;
+ renderer->sgbAttributes = video->renderer->sgbAttributes;
video->renderer = renderer;
renderer->vram = video->vram;
- video->renderer->init(video->renderer, video->p->model);
+ video->renderer->init(video->renderer, video->p->model, video->sgbBorders);
}
static bool _statIRQAsserted(struct GBVideo* video, GBRegisterSTAT stat) {
@@ -154,6 +236,7 @@ void _endMode0(struct mTiming* timing, void* context, uint32_t cyclesLate) {
video->mode = 1;
video->modeEvent.callback = _endMode1;
+ mTimingDeschedule(&video->p->timing, &video->frameEvent);
mTimingSchedule(&video->p->timing, &video->frameEvent, -cyclesLate);
if (!_statIRQAsserted(video, oldStat) && GBRegisterSTATIsOAMIRQ(video->stat)) {
@@ -211,7 +294,7 @@ void _endMode2(struct mTiming* timing, void* context, uint32_t cyclesLate) {
struct GBVideo* video = context;
_cleanOAM(video, video->ly);
video->x = 0;
- video->dotClock = timing->masterCycles - cyclesLate;
+ video->dotClock = mTimingCurrentTime(timing) - cyclesLate;
int32_t next = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 6 - (video->p->memory.io[REG_SCX] & 7);
video->mode = 3;
video->modeEvent.callback = _endMode3;
@@ -230,6 +313,7 @@ void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate) {
GBVideoProcessDots(video);
if (video->ly < GB_VIDEO_VERTICAL_PIXELS && video->p->memory.isHdma && video->p->memory.io[REG_HDMA5] != 0xFF) {
video->p->memory.hdmaRemaining = 0x10;
+ video->p->cpuBlocked = true;
mTimingDeschedule(timing, &video->p->memory.hdmaEvent);
mTimingSchedule(timing, &video->p->memory.hdmaEvent, 0);
}
@@ -263,10 +347,10 @@ void _updateFrameCount(struct mTiming* timing, void* context, uint32_t cyclesLat
}
GBFrameEnded(video->p);
+ mCoreSyncPostFrame(video->p->sync);
--video->frameskipCounter;
if (video->frameskipCounter < 0) {
video->renderer->finishFrame(video->renderer);
- mCoreSyncPostFrame(video->p->sync);
video->frameskipCounter = video->frameskip;
}
++video->frameCounter;
@@ -342,9 +426,8 @@ void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) {
video->ly = 0;
video->p->memory.io[REG_LY] = 0;
- // TODO: Does this read as 0 for 4 T-cycles?
GBRegisterSTAT oldStat = video->stat;
- video->stat = GBRegisterSTATSetMode(video->stat, 2);
+ video->stat = GBRegisterSTATSetMode(video->stat, 0);
video->stat = GBRegisterSTATSetLYC(video->stat, video->ly == video->p->memory.io[REG_LYC]);
if (!_statIRQAsserted(video, oldStat) && _statIRQAsserted(video, video->stat)) {
video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT);
@@ -372,7 +455,7 @@ void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value) {
void GBVideoWriteSTAT(struct GBVideo* video, GBRegisterSTAT value) {
GBRegisterSTAT oldStat = video->stat;
video->stat = (video->stat & 0x7) | (value & 0x78);
- if (video->p->model == GB_MODEL_DMG && !_statIRQAsserted(video, oldStat) && video->mode < 3) {
+ if (video->p->model < GB_MODEL_CGB && !_statIRQAsserted(video, oldStat) && video->mode < 3) {
// TODO: variable for the IRQ line value?
video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT);
GBUpdateIRQs(video->p);
@@ -390,7 +473,7 @@ void GBVideoWriteLYC(struct GBVideo* video, uint8_t value) {
}
void GBVideoWritePalette(struct GBVideo* video, uint16_t address, uint8_t value) {
- if (video->p->model < GB_MODEL_CGB) {
+ if (video->p->model < GB_MODEL_SGB) {
switch (address) {
case REG_BGP:
video->palette[0] = video->dmgPalette[value & 3];
@@ -403,26 +486,28 @@ void GBVideoWritePalette(struct GBVideo* video, uint16_t address, uint8_t value)
video->renderer->writePalette(video->renderer, 3, video->palette[3]);
break;
case REG_OBP0:
- video->palette[8 * 4 + 0] = video->dmgPalette[value & 3];
- video->palette[8 * 4 + 1] = video->dmgPalette[(value >> 2) & 3];
- video->palette[8 * 4 + 2] = video->dmgPalette[(value >> 4) & 3];
- video->palette[8 * 4 + 3] = video->dmgPalette[(value >> 6) & 3];
+ video->palette[8 * 4 + 0] = video->dmgPalette[(value & 3) + 4];
+ video->palette[8 * 4 + 1] = video->dmgPalette[((value >> 2) & 3) + 4];
+ video->palette[8 * 4 + 2] = video->dmgPalette[((value >> 4) & 3) + 4];
+ video->palette[8 * 4 + 3] = video->dmgPalette[((value >> 6) & 3) + 4];
video->renderer->writePalette(video->renderer, 8 * 4 + 0, video->palette[8 * 4 + 0]);
video->renderer->writePalette(video->renderer, 8 * 4 + 1, video->palette[8 * 4 + 1]);
video->renderer->writePalette(video->renderer, 8 * 4 + 2, video->palette[8 * 4 + 2]);
video->renderer->writePalette(video->renderer, 8 * 4 + 3, video->palette[8 * 4 + 3]);
break;
case REG_OBP1:
- video->palette[9 * 4 + 0] = video->dmgPalette[value & 3];
- video->palette[9 * 4 + 1] = video->dmgPalette[(value >> 2) & 3];
- video->palette[9 * 4 + 2] = video->dmgPalette[(value >> 4) & 3];
- video->palette[9 * 4 + 3] = video->dmgPalette[(value >> 6) & 3];
+ video->palette[9 * 4 + 0] = video->dmgPalette[(value & 3) + 8];
+ video->palette[9 * 4 + 1] = video->dmgPalette[((value >> 2) & 3) + 8];
+ video->palette[9 * 4 + 2] = video->dmgPalette[((value >> 4) & 3) + 8];
+ video->palette[9 * 4 + 3] = video->dmgPalette[((value >> 6) & 3) + 8];
video->renderer->writePalette(video->renderer, 9 * 4 + 0, video->palette[9 * 4 + 0]);
video->renderer->writePalette(video->renderer, 9 * 4 + 1, video->palette[9 * 4 + 1]);
video->renderer->writePalette(video->renderer, 9 * 4 + 2, video->palette[9 * 4 + 2]);
video->renderer->writePalette(video->renderer, 9 * 4 + 3, video->palette[9 * 4 + 3]);
break;
}
+ } else if (video->p->model == GB_MODEL_SGB) {
+ video->renderer->writeVideoRegister(video->renderer, address, value);
} else {
switch (address) {
case REG_BCPD:
@@ -470,15 +555,160 @@ void GBVideoSwitchBank(struct GBVideo* video, uint8_t value) {
}
void GBVideoSetPalette(struct GBVideo* video, unsigned index, uint32_t color) {
- if (index >= 4) {
+ if (index >= 12) {
return;
}
video->dmgPalette[index] = M_RGB8_TO_RGB5(color);
}
-static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model) {
+void GBVideoDisableCGB(struct GBVideo* video) {
+ video->dmgPalette[0] = video->palette[0];
+ video->dmgPalette[1] = video->palette[1];
+ video->dmgPalette[2] = video->palette[2];
+ video->dmgPalette[3] = video->palette[3];
+ video->dmgPalette[4] = video->palette[8 * 4 + 0];
+ video->dmgPalette[5] = video->palette[8 * 4 + 1];
+ video->dmgPalette[6] = video->palette[8 * 4 + 2];
+ video->dmgPalette[7] = video->palette[8 * 4 + 3];
+ video->dmgPalette[8] = video->palette[9 * 4 + 0];
+ video->dmgPalette[9] = video->palette[9 * 4 + 1];
+ video->dmgPalette[10] = video->palette[9 * 4 + 2];
+ video->dmgPalette[11] = video->palette[9 * 4 + 3];
+ video->renderer->deinit(video->renderer);
+ video->renderer->init(video->renderer, video->p->model, video->sgbBorders);
+}
+
+void GBVideoWriteSGBPacket(struct GBVideo* video, uint8_t* data) {
+ int i;
+ if (!(video->sgbCommandHeader & 7)) {
+ if ((data[0] >> 3) > SGB_OBJ_TRN) {
+ video->sgbCommandHeader = 0;
+ return;
+ }
+ video->sgbCommandHeader = data[0];
+ }
+ --video->sgbCommandHeader;
+ switch (video->sgbCommandHeader >> 3) {
+ case SGB_PAL01:
+ video->palette[0] = data[1] | (data[2] << 8);
+ video->palette[1] = data[3] | (data[4] << 8);
+ video->palette[2] = data[5] | (data[6] << 8);
+ video->palette[3] = data[7] | (data[8] << 8);
+
+ video->palette[16] = data[1] | (data[2] << 8);
+ video->palette[17] = data[9] | (data[10] << 8);
+ video->palette[18] = data[11] | (data[12] << 8);
+ video->palette[19] = data[13] | (data[14] << 8);
+
+ video->palette[32] = data[1] | (data[2] << 8);
+ video->palette[48] = data[1] | (data[2] << 8);
+
+ video->renderer->writePalette(video->renderer, 0, video->palette[0]);
+ video->renderer->writePalette(video->renderer, 1, video->palette[1]);
+ video->renderer->writePalette(video->renderer, 2, video->palette[2]);
+ video->renderer->writePalette(video->renderer, 3, video->palette[3]);
+ video->renderer->writePalette(video->renderer, 16, video->palette[0]);
+ video->renderer->writePalette(video->renderer, 17, video->palette[17]);
+ video->renderer->writePalette(video->renderer, 18, video->palette[18]);
+ video->renderer->writePalette(video->renderer, 19, video->palette[19]);
+ video->renderer->writePalette(video->renderer, 32, video->palette[0]);
+ video->renderer->writePalette(video->renderer, 48, video->palette[0]);
+ break;
+ case SGB_PAL23:
+ video->palette[33] = data[3] | (data[4] << 8);
+ video->palette[34] = data[5] | (data[6] << 8);
+ video->palette[35] = data[7] | (data[8] << 8);
+
+ video->palette[49] = data[9] | (data[10] << 8);
+ video->palette[50] = data[11] | (data[12] << 8);
+ video->palette[51] = data[13] | (data[14] << 8);
+ video->renderer->writePalette(video->renderer, 33, video->palette[33]);
+ video->renderer->writePalette(video->renderer, 34, video->palette[34]);
+ video->renderer->writePalette(video->renderer, 35, video->palette[35]);
+ video->renderer->writePalette(video->renderer, 49, video->palette[49]);
+ video->renderer->writePalette(video->renderer, 50, video->palette[50]);
+ video->renderer->writePalette(video->renderer, 51, video->palette[51]);
+ break;
+ case SGB_PAL03:
+ video->palette[0] = data[1] | (data[2] << 8);
+ video->palette[1] = data[3] | (data[4] << 8);
+ video->palette[2] = data[5] | (data[6] << 8);
+ video->palette[3] = data[7] | (data[8] << 8);
+
+ video->palette[16] = data[1] | (data[2] << 8);
+ video->palette[32] = data[1] | (data[2] << 8);
+
+ video->palette[48] = data[1] | (data[2] << 8);
+ video->palette[49] = data[9] | (data[10] << 8);
+ video->palette[50] = data[11] | (data[12] << 8);
+ video->palette[51] = data[13] | (data[14] << 8);
+ video->renderer->writePalette(video->renderer, 0, video->palette[0]);
+ video->renderer->writePalette(video->renderer, 1, video->palette[1]);
+ video->renderer->writePalette(video->renderer, 2, video->palette[2]);
+ video->renderer->writePalette(video->renderer, 3, video->palette[3]);
+ video->renderer->writePalette(video->renderer, 16, video->palette[0]);
+ video->renderer->writePalette(video->renderer, 32, video->palette[0]);
+ video->renderer->writePalette(video->renderer, 48, video->palette[0]);
+ video->renderer->writePalette(video->renderer, 49, video->palette[49]);
+ video->renderer->writePalette(video->renderer, 50, video->palette[50]);
+ video->renderer->writePalette(video->renderer, 51, video->palette[51]);
+ break;
+ case SGB_PAL12:
+ video->palette[17] = data[3] | (data[4] << 8);
+ video->palette[18] = data[5] | (data[6] << 8);
+ video->palette[19] = data[7] | (data[8] << 8);
+
+ video->palette[33] = data[9] | (data[10] << 8);
+ video->palette[34] = data[11] | (data[12] << 8);
+ video->palette[35] = data[13] | (data[14] << 8);
+ video->renderer->writePalette(video->renderer, 17, video->palette[17]);
+ video->renderer->writePalette(video->renderer, 18, video->palette[18]);
+ video->renderer->writePalette(video->renderer, 19, video->palette[19]);
+ video->renderer->writePalette(video->renderer, 33, video->palette[33]);
+ video->renderer->writePalette(video->renderer, 34, video->palette[34]);
+ video->renderer->writePalette(video->renderer, 35, video->palette[35]);
+ break;
+ case SGB_PAL_SET:
+ for (i = 0; i < 4; ++i) {
+ uint16_t entry = (data[2 + (i * 2)] << 8) | data[1 + (i * 2)];
+ if (entry >= 0x200) {
+ mLOG(GB, STUB, "Unimplemented SGB palette overflow: %03X", entry);
+ continue;
+ }
+ LOAD_16LE(video->palette[i * 4 + 0], entry * 8 + 0, video->renderer->sgbPalRam);
+ video->renderer->writePalette(video->renderer, i * 4 + 0, video->palette[0]);
+ LOAD_16LE(video->palette[i * 4 + 1], entry * 8 + 2, video->renderer->sgbPalRam);
+ video->renderer->writePalette(video->renderer, i * 4 + 1, video->palette[i * 4 + 1]);
+ LOAD_16LE(video->palette[i * 4 + 2], entry * 8 + 4, video->renderer->sgbPalRam);
+ video->renderer->writePalette(video->renderer, i * 4 + 2, video->palette[i * 4 + 2]);
+ LOAD_16LE(video->palette[i * 4 + 3], entry * 8 + 6, video->renderer->sgbPalRam);
+ video->renderer->writePalette(video->renderer, i * 4 + 3, video->palette[i * 4 + 3]);
+ }
+ break;
+ case SGB_ATTR_BLK:
+ case SGB_PAL_TRN:
+ case SGB_ATRC_EN:
+ case SGB_CHR_TRN:
+ case SGB_PCT_TRN:
+ case SGB_ATTR_TRN:
+ case SGB_ATTR_SET:
+ break;
+ case SGB_MLT_REG:
+ return;
+ case SGB_MASK_EN:
+ video->renderer->sgbRenderMode = data[1] & 0x3;
+ break;
+ default:
+ mLOG(GB, STUB, "Unimplemented SGB command: %02X", data[0] >> 3);
+ return;
+ }
+ video->renderer->writeSGBPacket(video->renderer, data);
+}
+
+static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders) {
UNUSED(renderer);
UNUSED(model);
+ UNUSED(borders);
// Nothing to do
}
@@ -488,14 +718,20 @@ static void GBVideoDummyRendererDeinit(struct GBVideoRenderer* renderer) {
}
static uint8_t GBVideoDummyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value) {
- UNUSED(renderer);
- UNUSED(address);
+ if (renderer->cache) {
+ GBVideoCacheWriteVideoRegister(renderer->cache, address, value);
+ }
return value;
}
+static void GBVideoDummyRendererWriteSGBPacket(struct GBVideoRenderer* renderer, uint8_t* data) {
+ UNUSED(renderer);
+ UNUSED(data);
+}
+
static void GBVideoDummyRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address) {
if (renderer->cache) {
- mTileCacheWriteVRAM(renderer->cache, address);
+ mCacheSetWriteVRAM(renderer->cache, address);
}
}
@@ -506,9 +742,8 @@ static void GBVideoDummyRendererWriteOAM(struct GBVideoRenderer* renderer, uint1
}
static void GBVideoDummyRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value) {
- UNUSED(value);
if (renderer->cache) {
- mTileCacheWritePalette(renderer->cache, index << 1);
+ mCacheSetWritePalette(renderer->cache, index, mColorFrom555(value));
}
}
@@ -628,5 +863,5 @@ void GBVideoDeserialize(struct GBVideo* video, const struct GBSerializedState* s
GBVideoSwitchBank(video, video->vramCurrentBank);
video->renderer->deinit(video->renderer);
- video->renderer->init(video->renderer, video->p->model);
+ video->renderer->init(video->renderer, video->p->model, video->sgbBorders);
}
diff --git a/src/gba/cheats.c b/src/gba/cheats.c
index 2e1a30b54..b17244c76 100644
--- a/src/gba/cheats.c
+++ b/src/gba/cheats.c
@@ -139,7 +139,8 @@ static bool GBACheatAddAutodetect(struct GBACheatSet* set, uint32_t op1, uint32_
char line[18] = "XXXXXXXX XXXXXXXX";
snprintf(line, sizeof(line), "%08X %08X", op1, op2);
- int gsaP, parP;
+ int gsaP, rgsaP, parP, rparP;
+ int maxProbability = INT_MIN;
switch (set->gsaVersion) {
case 0:
// Try to detect GameShark version
@@ -147,27 +148,42 @@ static bool GBACheatAddAutodetect(struct GBACheatSet* set, uint32_t op1, uint32_
gsaP = GBACheatGameSharkProbability(o1, o2);
o1 = op1;
o2 = op2;
+ if (gsaP > maxProbability) {
+ maxProbability = gsaP;
+ GBACheatSetGameSharkVersion(set, GBA_GS_GSAV1);
+ }
+
GBACheatDecryptGameShark(&o1, &o2, GBACheatProActionReplaySeeds);
parP = GBACheatProActionReplayProbability(o1, o2);
- o1 = op1;
- o2 = op2;
- if (gsaP > parP) {
- GBACheatSetGameSharkVersion(set, 1);
- GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds);
- return GBACheatAddGameSharkRaw(set, o1, o2);
+ if (parP > maxProbability) {
+ maxProbability = parP;
+ GBACheatSetGameSharkVersion(set, GBA_GS_PARV3);
+ }
+
+ rgsaP = GBACheatGameSharkProbability(op1, op1);
+ if (rgsaP > maxProbability) {
+ maxProbability = rgsaP;
+ GBACheatSetGameSharkVersion(set, GBA_GS_GSAV1_RAW);
+ }
+
+ rparP = GBACheatProActionReplayProbability(op1, op1);
+ if (rparP > maxProbability) {
+ maxProbability = rparP;
+ GBACheatSetGameSharkVersion(set, GBA_GS_PARV3_RAW);
+ }
+
+ if (set->gsaVersion < 3) {
+ return GBACheatAddGameShark(set, op1, op2);
} else {
- // If probabilities are equal, assume PARv3
- GBACheatSetGameSharkVersion(set, 3);
- GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds);
- return GBACheatAddProActionReplayRaw(set, o1, o2);
+ return GBACheatAddProActionReplay(set, op1, op2);
}
break;
case 1:
- GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds);
- return GBACheatAddGameSharkRaw(set, o1, o2);
+ case 2:
+ return GBACheatAddGameShark(set, o1, o2);
case 3:
- GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds);
- return GBACheatAddProActionReplayRaw(set, o1, o2);
+ case 4:
+ return GBACheatAddProActionReplay(set, o1, o2);
}
return false;
}
@@ -288,11 +304,19 @@ static void GBACheatParseDirectives(struct mCheatSet* set, const struct StringLi
for (d = 0; d < StringListSize(directives); ++d) {
const char* directive = *StringListGetConstPointer(directives, d);
if (strcmp(directive, "GSAv1") == 0) {
- GBACheatSetGameSharkVersion(cheats, 1);
+ GBACheatSetGameSharkVersion(cheats, GBA_GS_GSAV1);
+ continue;
+ }
+ if (strcmp(directive, "GSAv1 raw") == 0) {
+ GBACheatSetGameSharkVersion(cheats, GBA_GS_GSAV1_RAW);
continue;
}
if (strcmp(directive, "PARv3") == 0) {
- GBACheatSetGameSharkVersion(cheats, 3);
+ GBACheatSetGameSharkVersion(cheats, GBA_GS_PARV3);
+ continue;
+ }
+ if (strcmp(directive, "PARv3 raw") == 0) {
+ GBACheatSetGameSharkVersion(cheats, GBA_GS_PARV3_RAW);
continue;
}
}
@@ -311,15 +335,21 @@ static void GBACheatDumpDirectives(struct mCheatSet* set, struct StringList* dir
char** directive;
switch (cheats->gsaVersion) {
case 1:
- case 2:
directive = StringListAppend(directives);
*directive = strdup("GSAv1");
break;
+ case 2:
+ directive = StringListAppend(directives);
+ *directive = strdup("GSAv1 raw");
+ break;
case 3:
- case 4:
directive = StringListAppend(directives);
*directive = strdup("PARv3");
break;
+ case 4:
+ directive = StringListAppend(directives);
+ *directive = strdup("PARv3 raw");
+ break;
}
}
@@ -367,7 +397,7 @@ int GBACheatAddressIsReal(uint32_t address) {
return -0x8;
case REGION_CART_SRAM:
case REGION_CART_SRAM_MIRROR:
- if ((address & OFFSET_MASK) > SIZE_CART_SRAM) {
+ if ((address & OFFSET_MASK) > SIZE_CART_FLASH512) {
return -0x80;
}
return -0x8;
diff --git a/src/gba/cheats/gameshark.c b/src/gba/cheats/gameshark.c
index 1fc476aff..e95b23b54 100644
--- a/src/gba/cheats/gameshark.c
+++ b/src/gba/cheats/gameshark.c
@@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include
+#include "gba/cheats/gameshark.h"
#include "gba/cheats/parv3.h"
#include
#include
@@ -73,17 +74,19 @@ void GBACheatReseedGameShark(uint32_t* seeds, uint16_t params, const uint8_t* t1
}
}
-void GBACheatSetGameSharkVersion(struct GBACheatSet* cheats, int version) {
+void GBACheatSetGameSharkVersion(struct GBACheatSet* cheats, enum GBACheatGameSharkVersion version) {
cheats->gsaVersion = version;
switch (version) {
- case 1:
- case 2:
+ case GBA_GS_GSAV1:
+ case GBA_GS_GSAV1_RAW:
memcpy(cheats->gsaSeeds, GBACheatGameSharkSeeds, 4 * sizeof(uint32_t));
break;
- case 3:
- case 4:
+ case GBA_GS_PARV3:
+ case GBA_GS_PARV3_RAW:
memcpy(cheats->gsaSeeds, GBACheatProActionReplaySeeds, 4 * sizeof(uint32_t));
break;
+ default:
+ break;
}
}
@@ -197,14 +200,13 @@ bool GBACheatAddGameShark(struct GBACheatSet* set, uint32_t op1, uint32_t op2) {
snprintf(line, sizeof(line), "%08X %08X", op1, op2);
switch (set->gsaVersion) {
- case 0:
- case 3:
- case 4:
- GBACheatSetGameSharkVersion(set, 1);
+ default:
+ GBACheatSetGameSharkVersion(set, GBA_GS_GSAV1);
// Fall through
- case 1:
- case 2:
+ case GBA_GS_GSAV1:
GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds);
+ // Fall through
+ case GBA_GS_GSAV1_RAW:
return GBACheatAddGameSharkRaw(set, o1, o2);
}
return false;
diff --git a/src/gba/cheats/gameshark.h b/src/gba/cheats/gameshark.h
index af4d10469..a4130714b 100644
--- a/src/gba/cheats/gameshark.h
+++ b/src/gba/cheats/gameshark.h
@@ -12,10 +12,18 @@ CXX_GUARD_START
extern const uint32_t GBACheatGameSharkSeeds[4];
+enum GBACheatGameSharkVersion {
+ GBA_GS_NOT_SET = 0,
+ GBA_GS_GSAV1 = 1,
+ GBA_GS_GSAV1_RAW = 2,
+ GBA_GS_PARV3 = 3,
+ GBA_GS_PARV3_RAW = 4
+};
+
struct GBACheatSet;
void GBACheatDecryptGameShark(uint32_t* op1, uint32_t* op2, const uint32_t* seeds);
void GBACheatReseedGameShark(uint32_t* seeds, uint16_t params, const uint8_t* t1, const uint8_t* t2);
-void GBACheatSetGameSharkVersion(struct GBACheatSet* cheats, int version);
+void GBACheatSetGameSharkVersion(struct GBACheatSet* cheats, enum GBACheatGameSharkVersion version);
bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t op2);
int GBACheatGameSharkProbability(uint32_t op1, uint32_t op2);
diff --git a/src/gba/cheats/parv3.c b/src/gba/cheats/parv3.c
index ccd6c34b0..087294d0f 100644
--- a/src/gba/cheats/parv3.c
+++ b/src/gba/cheats/parv3.c
@@ -53,7 +53,7 @@ static uint32_t _parAddr(uint32_t x) {
}
static void _parEndBlock(struct GBACheatSet* cheats) {
- size_t size = mCheatListSize(&cheats->d.list) - cheats->currentBlock;
+ size_t size = mCheatListSize(&cheats->d.list) - cheats->currentBlock - 1;
struct mCheat* currentBlock = mCheatListGetPointer(&cheats->d.list, cheats->currentBlock);
if (currentBlock->repeat) {
currentBlock->negativeRepeat = size - currentBlock->repeat;
@@ -64,7 +64,7 @@ static void _parEndBlock(struct GBACheatSet* cheats) {
}
static void _parElseBlock(struct GBACheatSet* cheats) {
- size_t size = mCheatListSize(&cheats->d.list) - cheats->currentBlock;
+ size_t size = mCheatListSize(&cheats->d.list) - cheats->currentBlock - 1;
struct mCheat* currentBlock = mCheatListGetPointer(&cheats->d.list, cheats->currentBlock);
currentBlock->repeat = size;
}
@@ -284,6 +284,10 @@ bool GBACheatAddProActionReplayRaw(struct GBACheatSet* cheats, uint32_t op1, uin
cheat->address = BASE_IO | (op1 & OFFSET_MASK);
break;
}
+ if (op1 & 0x01000000 && (op1 & 0xFE000000) != 0xC6000000) {
+ return false;
+ }
+
cheat->width = width;
cheat->operand = op2 & (0xFFFFFFFFU >> ((4 - width) * 8));
@@ -297,14 +301,13 @@ bool GBACheatAddProActionReplay(struct GBACheatSet* set, uint32_t op1, uint32_t
snprintf(line, sizeof(line), "%08X %08X", op1, op2);
switch (set->gsaVersion) {
- case 0:
- case 1:
- case 2:
- GBACheatSetGameSharkVersion(set, 3);
+ default:
+ GBACheatSetGameSharkVersion(set, GBA_GS_PARV3);
// Fall through
- case 3:
- case 4:
+ case GBA_GS_PARV3:
GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds);
+ // Fall through
+ case GBA_GS_PARV3_RAW:
return GBACheatAddProActionReplayRaw(set, o1, o2);
}
return false;
@@ -370,7 +373,7 @@ int GBACheatProActionReplayProbability(uint32_t op1, uint32_t op2) {
int width = ((op1 & PAR3_WIDTH) >> (PAR3_WIDTH_BASE - 3));
if (op1 & PAR3_COND) {
probability += 0x20;
- if (width == 32) {
+ if (width >= 24) {
return 0;
}
if (op2 & ~((1 << width) - 1)) {
@@ -384,10 +387,13 @@ int GBACheatProActionReplayProbability(uint32_t op1, uint32_t op2) {
if (op2 & ~((1 << width) - 1)) {
probability -= 0x10;
}
+ // Fall through
case PAR3_BASE_ASSIGN:
case PAR3_BASE_INDIRECT:
probability += GBACheatAddressIsReal(address);
- // Fall through
+ if (op1 & 0x01000000) {
+ return 0;
+ }
break;
case PAR3_BASE_OTHER:
break;
diff --git a/src/gba/core.c b/src/gba/core.c
index e943aae76..6f493fe5b 100644
--- a/src/gba/core.c
+++ b/src/gba/core.c
@@ -266,6 +266,7 @@ static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t s
struct GBACore* gbacore = (struct GBACore*) core;
gbacore->renderer.outputBuffer = buffer;
gbacore->renderer.outputBufferStride = stride;
+ memset(gbacore->renderer.scanlineDirty, 0xFFFFFFFF, sizeof(gbacore->renderer.scanlineDirty));
}
static void _GBACoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) {
@@ -405,14 +406,7 @@ static void _GBACoreReset(struct mCore* core) {
GBAVideoAssociateRenderer(&gba->video, renderer);
}
- struct GBACartridgeOverride override;
- const struct GBACartridge* cart = (const struct GBACartridge*) gba->memory.rom;
- if (cart) {
- memcpy(override.id, &cart->id, sizeof(override.id));
- if (GBAOverrideFind(gbacore->overrides, &override)) {
- GBAOverrideApply(gba, &override);
- }
- }
+ GBAOverrideApplyDefaults(gba, gbacore->overrides);
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
if (!gba->biosVf && core->opts.useBios) {
@@ -508,7 +502,6 @@ static void _GBACoreAddKeys(struct mCore* core, uint32_t keys) {
static void _GBACoreClearKeys(struct mCore* core, uint32_t keys) {
struct GBACore* gbacore = (struct GBACore*) core;
gbacore->keys &= ~keys;
- GBATestKeypadIRQ(core->board);
}
static void _GBACoreSetCursorLocation(struct mCore* core, int x, int y) {
diff --git a/src/gba/extra/proxy.c b/src/gba/extra/proxy.c
index 1fc3ecf3c..a54f68a8a 100644
--- a/src/gba/extra/proxy.c
+++ b/src/gba/extra/proxy.c
@@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include
-#include
+#include
#include
#include
@@ -224,7 +224,7 @@ void GBAVideoProxyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t
proxyRenderer->backend->writeVRAM(proxyRenderer->backend, address);
}
if (renderer->cache) {
- mTileCacheWriteVRAM(renderer->cache, address);
+ mCacheSetWriteVRAM(renderer->cache, address);
}
}
@@ -235,7 +235,7 @@ void GBAVideoProxyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32
proxyRenderer->backend->writePalette(proxyRenderer->backend, address, value);
}
if (renderer->cache) {
- mTileCacheWritePalette(renderer->cache, address);
+ mCacheSetWritePalette(renderer->cache, address >> 1, mColorFrom555(value));
}
}
diff --git a/src/gba/gba.c b/src/gba/gba.c
index df1625e75..c5c83ada0 100644
--- a/src/gba/gba.c
+++ b/src/gba/gba.c
@@ -526,6 +526,9 @@ bool GBAIsROM(struct VFile* vf) {
return isGBA;
}
#endif
+ if (!vf) {
+ return false;
+ }
if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) {
return false;
}
@@ -751,19 +754,17 @@ void GBATestKeypadIRQ(struct GBA* gba) {
return;
}
int isAnd = keycnt & 0x8000;
- uint16_t keyInput;
-
if (!gba->keySource) {
// TODO?
return;
}
keycnt &= 0x3FF;
- keyInput = *gba->keySource;
+ uint16_t keyInput = *gba->keySource & keycnt;
if (isAnd && keycnt == keyInput) {
GBARaiseIRQ(gba, IRQ_KEYPAD);
- } else if (!isAnd && keycnt & keyInput) {
+ } else if (!isAnd && keyInput) {
GBARaiseIRQ(gba, IRQ_KEYPAD);
}
}
diff --git a/src/gba/io.c b/src/gba/io.c
index 49036f516..629c4b687 100644
--- a/src/gba/io.c
+++ b/src/gba/io.c
@@ -890,14 +890,17 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
break;
case REG_MAX:
// Some bad interrupt libraries will read from this
- break;
- case 0x66:
- case 0x6E:
- case 0x76:
- case 0x7A:
- case 0x7E:
- case 0x86:
- case 0x8A:
+ case 0x066:
+ case 0x06E:
+ case 0x076:
+ case 0x07A:
+ case 0x07E:
+ case 0x086:
+ case 0x08A:
+ case 0x136:
+ case 0x142:
+ case 0x15A:
+ case 0x206:
mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
return 0;
case REG_DEBUG_ENABLE:
diff --git a/src/gba/memory.c b/src/gba/memory.c
index b05cbd2b9..d51354704 100644
--- a/src/gba/memory.c
+++ b/src/gba/memory.c
@@ -92,6 +92,7 @@ void GBAMemoryDeinit(struct GBA* gba) {
if (gba->memory.rom) {
mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
}
+ gba->memory.savedata.maskWriteback = false;
GBASavedataUnmask(&gba->memory.savedata);
GBASavedataDeinit(&gba->memory.savedata);
if (gba->memory.savedata.realVf) {
@@ -683,27 +684,39 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
GBAIOWrite32(gba, address & (OFFSET_MASK - 3), value);
#define STORE_PALETTE_RAM \
- STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
- gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16); \
- wait += waitstatesRegion[REGION_PALETTE_RAM]; \
- gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
+ LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
+ if (oldValue != value) { \
+ STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
+ gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16); \
+ gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value); \
+ } \
+ wait += waitstatesRegion[REGION_PALETTE_RAM];
#define STORE_VRAM \
if ((address & 0x0001FFFF) < SIZE_VRAM) { \
- STORE_32(value, address & 0x0001FFFC, gba->video.vram); \
- gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \
- gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \
+ LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram); \
+ if (oldValue != value) { \
+ STORE_32(value, address & 0x0001FFFC, gba->video.vram); \
+ gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \
+ gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \
+ } \
} else { \
- STORE_32(value, address & 0x00017FFC, gba->video.vram); \
- gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) + 2); \
- gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC)); \
+ LOAD_32(oldValue, address & 0x00017FFC, gba->video.vram); \
+ if (oldValue != value) { \
+ STORE_32(value, address & 0x00017FFC, gba->video.vram); \
+ gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) + 2); \
+ gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC)); \
+ } \
} \
wait += waitstatesRegion[REGION_VRAM];
#define STORE_OAM \
- STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); \
- gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \
- gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
+ LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw); \
+ if (oldValue != value) { \
+ STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); \
+ gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \
+ gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1); \
+ }
#define STORE_CART \
wait += waitstatesRegion[address >> BASE_OFFSET]; \
@@ -726,6 +739,7 @@ void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle
struct GBA* gba = (struct GBA*) cpu->master;
struct GBAMemory* memory = &gba->memory;
int wait = 0;
+ int32_t oldValue;
char* waitstatesRegion = memory->waitstatesNonseq32;
switch (address >> BASE_OFFSET) {
@@ -777,6 +791,7 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
struct GBA* gba = (struct GBA*) cpu->master;
struct GBAMemory* memory = &gba->memory;
int wait = 0;
+ int16_t oldValue;
switch (address >> BASE_OFFSET) {
case REGION_WORKING_RAM:
@@ -790,21 +805,33 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
GBAIOWrite(gba, address & (OFFSET_MASK - 1), value);
break;
case REGION_PALETTE_RAM:
- STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
- gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
+ LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
+ if (oldValue != value) {
+ STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
+ gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
+ }
break;
case REGION_VRAM:
if ((address & 0x0001FFFF) < SIZE_VRAM) {
- STORE_16(value, address & 0x0001FFFE, gba->video.vram);
- gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
+ LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram);
+ if (value != oldValue) {
+ STORE_16(value, address & 0x0001FFFE, gba->video.vram);
+ gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
+ }
} else {
- STORE_16(value, address & 0x00017FFE, gba->video.vram);
- gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE);
+ LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram);
+ if (value != oldValue) {
+ STORE_16(value, address & 0x00017FFE, gba->video.vram);
+ gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE);
+ }
}
break;
case REGION_OAM:
- STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
- gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
+ LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw);
+ if (value != oldValue) {
+ STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
+ gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
+ }
break;
case REGION_CART0:
if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFE)) {
@@ -844,6 +871,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
struct GBA* gba = (struct GBA*) cpu->master;
struct GBAMemory* memory = &gba->memory;
int wait = 0;
+ uint16_t oldValue;
switch (address >> BASE_OFFSET) {
case REGION_WORKING_RAM:
@@ -865,8 +893,11 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
break;
}
- gba->video.vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8);
- gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
+ oldValue = gba->video.vram[(address & 0x1FFFE) >> 1];
+ if (oldValue != (((uint8_t) value) | (value << 8))) {
+ gba->video.vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8);
+ gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
+ }
break;
case REGION_OAM:
mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
@@ -1369,6 +1400,7 @@ uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum
struct GBA* gba = (struct GBA*) cpu->master;
struct GBAMemory* memory = &gba->memory;
uint32_t value;
+ uint32_t oldValue;
char* waitstatesRegion = memory->waitstatesSeq32;
int i;
diff --git a/src/gba/overrides.c b/src/gba/overrides.c
index 787690945..915d220e3 100644
--- a/src/gba/overrides.c
+++ b/src/gba/overrides.c
@@ -338,11 +338,19 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* overri
}
}
-void GBAOverrideApplyDefaults(struct GBA* gba) {
- struct GBACartridgeOverride override;
+void GBAOverrideApplyDefaults(struct GBA* gba, const struct Configuration* overrides) {
+ struct GBACartridgeOverride override = { .idleLoop = IDLE_LOOP_NONE };
const struct GBACartridge* cart = (const struct GBACartridge*) gba->memory.rom;
- memcpy(override.id, &cart->id, sizeof(override.id));
- if (GBAOverrideFind(0, &override)) {
- GBAOverrideApply(gba, &override);
+ if (cart) {
+ memcpy(override.id, &cart->id, sizeof(override.id));
+
+ if (!strncmp("pokemon red version", &((const char*) gba->memory.rom)[0x108], 20) && gba->romCrc32 != 0xDD88761C) {
+ // Enable FLASH1M and RTC on Pokémon FireRed ROM hacks
+ override.savetype = SAVEDATA_FLASH1M;
+ override.hardware = HW_RTC;
+ GBAOverrideApply(gba, &override);
+ } else if (GBAOverrideFind(overrides, &override)) {
+ GBAOverrideApply(gba, &override);
+ }
}
}
diff --git a/src/gba/renderers/cache-set.c b/src/gba/renderers/cache-set.c
new file mode 100644
index 000000000..ce28d7e20
--- /dev/null
+++ b/src/gba/renderers/cache-set.c
@@ -0,0 +1,168 @@
+/* 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
+#include
+
+void GBAVideoCacheInit(struct mCacheSet* cache) {
+ mCacheSetInit(cache, 4, 4);
+ mTileCacheSystemInfo sysconfig = 0;
+ mTileCacheConfiguration config = mTileCacheConfigurationFillShouldStore(0);
+ sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 2); // 2^(2^2) = 16 entries
+ sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 4); // 16 palettes
+ sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048);
+ mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 0));
+ mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 0), config);
+ mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 0), sysconfig, 0, 0);
+ sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
+ mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 2));
+ mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 2), config);
+ mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 2), sysconfig, 0x10000, 0x100);
+
+ sysconfig = mTileCacheSystemInfoSetPaletteBPP(sysconfig, 3); // 2^(2^3) = 256 entries
+ sysconfig = mTileCacheSystemInfoSetPaletteCount(sysconfig, 0); // 1 palettes
+ sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 2048);
+ mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 1));
+ mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 1), config);
+ mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 1), sysconfig, 0, 0);
+ sysconfig = mTileCacheSystemInfoSetMaxTiles(sysconfig, 1024);
+ mTileCacheInit(mTileCacheSetGetPointer(&cache->tiles, 3));
+ mTileCacheConfigure(mTileCacheSetGetPointer(&cache->tiles, 3), config);
+ mTileCacheConfigureSystem(mTileCacheSetGetPointer(&cache->tiles, 3), sysconfig, 0x10000, 0x100);
+
+ mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 0));
+ mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 1));
+ mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 2));
+ mMapCacheInit(mMapCacheSetGetPointer(&cache->maps, 3));
+}
+
+void GBAVideoCacheAssociate(struct mCacheSet* cache, struct GBAVideo* video) {
+ mCacheSetAssignVRAM(cache, video->vram);
+ video->renderer->cache = cache;
+ size_t i;
+ for (i = 0; i < SIZE_PALETTE_RAM / 2; ++i) {
+ mCacheSetWritePalette(cache, i, mColorFrom555(video->palette[i]));
+ }
+ GBAVideoCacheWriteVideoRegister(cache, REG_DISPCNT, video->p->memory.io[REG_DISPCNT >> 1]);
+ GBAVideoCacheWriteVideoRegister(cache, REG_BG0CNT, video->p->memory.io[REG_BG0CNT >> 1]);
+ GBAVideoCacheWriteVideoRegister(cache, REG_BG1CNT, video->p->memory.io[REG_BG1CNT >> 1]);
+ GBAVideoCacheWriteVideoRegister(cache, REG_BG2CNT, video->p->memory.io[REG_BG2CNT >> 1]);
+ GBAVideoCacheWriteVideoRegister(cache, REG_BG3CNT, video->p->memory.io[REG_BG3CNT >> 1]);
+}
+
+static void mapParser0(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
+ UNUSED(cache);
+ uint16_t map = *(uint16_t*) vram;
+ entry->tileId = GBA_TEXT_MAP_TILE(map);
+ entry->flags = mMapCacheEntryFlagsSetHMirror(entry->flags, !!GBA_TEXT_MAP_HFLIP(map));
+ entry->flags = mMapCacheEntryFlagsSetVMirror(entry->flags, !!GBA_TEXT_MAP_VFLIP(map));
+ entry->flags = mMapCacheEntryFlagsSetPaletteId(entry->flags, GBA_TEXT_MAP_PALETTE(map));
+}
+
+static void mapParser2(struct mMapCache* cache, struct mMapCacheEntry* entry, void* vram) {
+ UNUSED(cache);
+ entry->tileId = *(uint8_t*) vram;
+ entry->flags = mMapCacheEntryFlagsClearHMirror(entry->flags);
+ entry->flags = mMapCacheEntryFlagsClearVMirror(entry->flags);
+ entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags);
+}
+
+static void GBAVideoCacheWriteDISPCNT(struct mCacheSet* cache, uint16_t value) {
+ switch (GBARegisterDISPCNTGetMode(value)) {
+ case 0:
+ default:
+ mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0;
+ mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0;
+ mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser0;
+ mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser0;
+
+ mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
+ mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
+ mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
+ mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
+ break;
+ case 1:
+ case 2:
+ mMapCacheSetGetPointer(&cache->maps, 0)->mapParser = mapParser0;
+ mMapCacheSetGetPointer(&cache->maps, 1)->mapParser = mapParser0;
+ mMapCacheSetGetPointer(&cache->maps, 2)->mapParser = mapParser2;
+ mMapCacheSetGetPointer(&cache->maps, 3)->mapParser = mapParser2;
+
+ mMapCacheSetGetPointer(&cache->maps, 0)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
+ mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 0);
+ mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
+ mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1);
+ break;
+ }
+}
+
+static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t value) {
+ struct mMapCache* map = mMapCacheSetGetPointer(&cache->maps, bg);
+ map->context = (void*) (uintptr_t) value;
+
+ int tileStart = GBARegisterBGCNTGetCharBase(value) * 256;
+ bool p = GBARegisterBGCNTGet256Color(value);
+ int size = GBARegisterBGCNTGetSize(value);
+ int tilesWide = 0;
+ int tilesHigh = 0;
+ mMapCacheSystemInfo sysconfig = 0;
+ if (map->mapParser == mapParser0) {
+ sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 2 + p);
+ sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 4 * !p);
+ sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 5);
+ sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 1);
+ tilesWide = 5;
+ tilesHigh = 5;
+ if (size & 1) {
+ ++tilesWide;
+ }
+ if (size & 2) {
+ ++tilesHigh;
+ }
+ map->tileStart = tileStart * 2;
+ } else if (map->mapParser == mapParser2) {
+ sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 3);
+ sysconfig = mMapCacheSystemInfoSetPaletteCount(sysconfig, 0);
+ sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 4 + size);
+ sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0);
+
+ tilesHigh = 4 + size;
+ tilesWide = 4 + size;
+ map->tileStart = tileStart;
+ }
+ sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, tilesHigh);
+ sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, tilesWide);
+ mMapCacheConfigureSystem(map, sysconfig);
+ mMapCacheConfigureMap(map, GBARegisterBGCNTGetScreenBase(value) << 11);
+}
+
+void GBAVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint32_t address, uint16_t value) {
+ switch (address) {
+ case REG_DISPCNT:
+ GBAVideoCacheWriteDISPCNT(cache, value);
+ GBAVideoCacheWriteBGCNT(cache, 0, (uint16_t) mMapCacheSetGetPointer(&cache->maps, 0)->context);
+ GBAVideoCacheWriteBGCNT(cache, 1, (uint16_t) mMapCacheSetGetPointer(&cache->maps, 1)->context);
+ GBAVideoCacheWriteBGCNT(cache, 2, (uint16_t) mMapCacheSetGetPointer(&cache->maps, 2)->context);
+ GBAVideoCacheWriteBGCNT(cache, 3, (uint16_t) mMapCacheSetGetPointer(&cache->maps, 3)->context);
+ break;
+ case REG_BG0CNT:
+ GBAVideoCacheWriteBGCNT(cache, 0, value);
+ break;
+ case REG_BG1CNT:
+ GBAVideoCacheWriteBGCNT(cache, 1, value);
+ break;
+ case REG_BG2CNT:
+ GBAVideoCacheWriteBGCNT(cache, 2, value);
+ break;
+ case REG_BG3CNT:
+ GBAVideoCacheWriteBGCNT(cache, 3, value);
+ break;
+
+ }
+}
diff --git a/src/gba/renderers/software-bg.c b/src/gba/renderers/software-bg.c
index 7c78e436e..9386b2d20 100644
--- a/src/gba/renderers/software-bg.c
+++ b/src/gba/renderers/software-bg.c
@@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gba/renderers/software-private.h"
+#include
#include
#define MODE_2_COORD_OVERFLOW \
@@ -96,21 +97,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode3(struct GBAVideoSoftwareRenderer
if (!mosaicWait) {
LOAD_16(color, ((localX >> 8) + (localY >> 8) * renderer->masterEnd) << 1, renderer->d.vramBG[0]);
-#ifndef COLOR_16_BIT
- unsigned color32;
- color32 = 0;
- color32 |= (color << 3) & 0xF8;
- color32 |= (color << 6) & 0xF800;
- color32 |= (color << 9) & 0xF80000;
- color32 |= (color32 >> 5) & 0x070707;
- color = color32;
-#elif COLOR_5_6_5
- uint16_t color16 = 0;
- color16 |= (color & 0x001F) << 11;
- color16 |= (color & 0x03E0) << 1;
- color16 |= (color & 0x7C00) >> 10;
- color = color16;
-#endif
+ color = mColorFrom555(color);
mosaicWait = mosaicH;
} else {
--mosaicWait;
@@ -185,20 +172,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode5(struct GBAVideoSoftwareRenderer
if (!mosaicWait) {
LOAD_16(color, offset + (localX >> 8) * 2 + (localY >> 8) * 320, renderer->d.vramBG[0]);
-#ifndef COLOR_16_BIT
- unsigned color32 = 0;
- color32 |= (color << 9) & 0xF80000;
- color32 |= (color << 3) & 0xF8;
- color32 |= (color << 6) & 0xF800;
- color32 |= (color32 >> 5) & 0x070707;
- color = color32;
-#elif COLOR_5_6_5
- uint16_t color16 = 0;
- color16 |= (color & 0x001F) << 11;
- color16 |= (color & 0x03E0) << 1;
- color16 |= (color & 0x7C00) >> 10;
- color = color16;
-#endif
+ color = mColorFrom555(color);
mosaicWait = mosaicH;
} else {
--mosaicWait;
diff --git a/src/gba/renderers/software-obj.c b/src/gba/renderers/software-obj.c
index 9d1ab3871..da0128ca0 100644
--- a/src/gba/renderers/software-obj.c
+++ b/src/gba/renderers/software-obj.c
@@ -255,9 +255,13 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
target2 |= renderer->bg[2].target2 << (renderer->bg[2].priority);
target2 |= renderer->bg[3].target2 << (renderer->bg[3].priority);
if ((1 << GBAObjAttributesCGetPriority(sprite->c)) <= target2) {
+ flags |= FLAG_REBLEND;
variant = 0;
+ } else if (!target2) {
+ flags &= ~FLAG_TARGET_1;
}
}
+
color_t* palette = &renderer->normalPalette[0x100];
color_t* objwinPalette = palette;
int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlGetBlendEnable(renderer->objwin.packed) != GBAWindowControlIsBlendEnable(renderer->currentWindow.packed);
diff --git a/src/gba/renderers/software-private.h b/src/gba/renderers/software-private.h
index 5c73903b5..2119d3c76 100644
--- a/src/gba/renderers/software-private.h
+++ b/src/gba/renderers/software-private.h
@@ -47,7 +47,7 @@ static inline void _compositeBlendObjwin(struct GBAVideoSoftwareRenderer* render
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->alphaA[x], current, renderer->alphaB[x], color);
} else {
- color = (current & 0x00FFFFFF) | ((current << 1) & FLAG_REBLEND);
+ color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND);
}
} else {
color = (color & ~FLAG_TARGET_2) | (current & FLAG_OBJWIN);
@@ -63,7 +63,7 @@ static inline void _compositeBlendNoObjwin(struct GBAVideoSoftwareRenderer* rend
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->alphaA[x], current, renderer->alphaB[x], color);
} else {
- color = (current & 0x00FFFFFF) | ((current << 1) & FLAG_REBLEND);
+ color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND);
}
} else {
color = color & ~FLAG_TARGET_2;
@@ -77,7 +77,7 @@ static inline void _compositeNoBlendObjwin(struct GBAVideoSoftwareRenderer* rend
if (color < current) {
color |= (current & FLAG_OBJWIN);
} else {
- color = (current & 0x00FFFFFF) | ((current << 1) & FLAG_REBLEND);
+ color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND);
}
renderer->row[x] = color;
}
@@ -86,7 +86,7 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re
uint32_t current) {
UNUSED(renderer);
if (color >= current) {
- color = (current & 0x00FFFFFF) | ((current << 1) & FLAG_REBLEND);
+ color = (current & 0x00FFFFFF) | (current & FLAG_REBLEND);
}
renderer->row[x] = color;
}
diff --git a/src/gba/renderers/tile-cache.c b/src/gba/renderers/tile-cache.c
deleted file mode 100644
index 20e24849a..000000000
--- a/src/gba/renderers/tile-cache.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright (c) 2013-2016 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 GBAVideoTileCacheInit(struct mTileCache* cache) {
- mTileCacheInit(cache);
- mTileCacheConfiguration config = 0;
- config = mTileCacheSystemInfoSetPalette0BPP(config, 2); // 2^(2^2) = 16 entries
- config = mTileCacheSystemInfoSetPalette0Count(config, 5); // 32 palettes
- config = mTileCacheSystemInfoSetPalette1BPP(config, 3); // 2^(2^3) = 256 entries
- config = mTileCacheSystemInfoSetPalette1Count(config, 1); // 2 palettes
- config = mTileCacheSystemInfoSetMaxTiles(config, 3072);
- mTileCacheConfigureSystem(cache, config);
-}
-
-void GBAVideoTileCacheAssociate(struct mTileCache* cache, struct GBAVideo* video) {
- cache->vram = video->vram;
- cache->palette = video->palette;
- video->renderer->cache = cache;
-}
diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c
index d633d61a0..b8d49ba80 100644
--- a/src/gba/renderers/video-software.c
+++ b/src/gba/renderers/video-software.c
@@ -5,13 +5,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gba/renderers/software-private.h"
-#include
+#include
#include
#include
+#include
#include
#include
+#define DIRTY_SCANLINE(R, Y) R->scanlineDirty[Y >> 5] |= (1 << (Y & 0x1F))
+#define CLEAN_SCANLINE(R, Y) R->scanlineDirty[Y >> 5] &= ~(1 << (Y & 0x1F))
+
static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer);
static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer);
static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer);
@@ -26,10 +30,6 @@ static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer,
static void GBAVideoSoftwareRendererUpdateDISPCNT(struct GBAVideoSoftwareRenderer* renderer);
static void GBAVideoSoftwareRendererWriteBGCNT(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* bg, uint16_t value);
-static void GBAVideoSoftwareRendererWriteBGPA(struct GBAVideoSoftwareBackground* bg, uint16_t value);
-static void GBAVideoSoftwareRendererWriteBGPB(struct GBAVideoSoftwareBackground* bg, uint16_t value);
-static void GBAVideoSoftwareRendererWriteBGPC(struct GBAVideoSoftwareBackground* bg, uint16_t value);
-static void GBAVideoSoftwareRendererWriteBGPD(struct GBAVideoSoftwareBackground* bg, uint16_t value);
static void GBAVideoSoftwareRendererWriteBGX_LO(struct GBAVideoSoftwareBackground* bg, uint16_t value);
static void GBAVideoSoftwareRendererWriteBGX_HI(struct GBAVideoSoftwareBackground* bg, uint16_t value);
static void GBAVideoSoftwareRendererWriteBGY_LO(struct GBAVideoSoftwareBackground* bg, uint16_t value);
@@ -120,6 +120,11 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) {
softwareRenderer->oamMax = 0;
softwareRenderer->mosaic = 0;
+ softwareRenderer->nextY = 0;
+
+ memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty));
+ memset(softwareRenderer->cache, 0, sizeof(softwareRenderer->cache));
+ memset(softwareRenderer->nextIo, 0, sizeof(softwareRenderer->nextIo));
for (i = 0; i < 4; ++i) {
struct GBAVideoSoftwareBackground* bg = &softwareRenderer->bg[i];
@@ -156,6 +161,10 @@ static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer) {
static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
+ if (renderer->cache) {
+ GBAVideoCacheWriteVideoRegister(renderer->cache, address, value);
+ }
+
switch (address) {
case REG_DISPCNT:
softwareRenderer->dispcnt = value;
@@ -210,52 +219,76 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
softwareRenderer->bg[3].y = value;
break;
case REG_BG2PA:
- GBAVideoSoftwareRendererWriteBGPA(&softwareRenderer->bg[2], value);
+ softwareRenderer->bg[2].dx = value;
break;
case REG_BG2PB:
- GBAVideoSoftwareRendererWriteBGPB(&softwareRenderer->bg[2], value);
+ softwareRenderer->bg[2].dmx = value;
break;
case REG_BG2PC:
- GBAVideoSoftwareRendererWriteBGPC(&softwareRenderer->bg[2], value);
+ softwareRenderer->bg[2].dy = value;
break;
case REG_BG2PD:
- GBAVideoSoftwareRendererWriteBGPD(&softwareRenderer->bg[2], value);
+ softwareRenderer->bg[2].dmy = value;
break;
case REG_BG2X_LO:
GBAVideoSoftwareRendererWriteBGX_LO(&softwareRenderer->bg[2], value);
+ if (softwareRenderer->bg[2].sx != softwareRenderer->cache[softwareRenderer->nextY].scale[0][0]) {
+ DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
+ }
break;
case REG_BG2X_HI:
GBAVideoSoftwareRendererWriteBGX_HI(&softwareRenderer->bg[2], value);
+ if (softwareRenderer->bg[2].sx != softwareRenderer->cache[softwareRenderer->nextY].scale[0][0]) {
+ DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
+ }
break;
case REG_BG2Y_LO:
GBAVideoSoftwareRendererWriteBGY_LO(&softwareRenderer->bg[2], value);
+ if (softwareRenderer->bg[2].sy != softwareRenderer->cache[softwareRenderer->nextY].scale[0][1]) {
+ DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
+ }
break;
case REG_BG2Y_HI:
GBAVideoSoftwareRendererWriteBGY_HI(&softwareRenderer->bg[2], value);
+ if (softwareRenderer->bg[2].sy != softwareRenderer->cache[softwareRenderer->nextY].scale[0][1]) {
+ DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
+ }
break;
case REG_BG3PA:
- GBAVideoSoftwareRendererWriteBGPA(&softwareRenderer->bg[3], value);
+ softwareRenderer->bg[3].dx = value;
break;
case REG_BG3PB:
- GBAVideoSoftwareRendererWriteBGPB(&softwareRenderer->bg[3], value);
+ softwareRenderer->bg[3].dmx = value;
break;
case REG_BG3PC:
- GBAVideoSoftwareRendererWriteBGPC(&softwareRenderer->bg[3], value);
+ softwareRenderer->bg[3].dy = value;
break;
case REG_BG3PD:
- GBAVideoSoftwareRendererWriteBGPD(&softwareRenderer->bg[3], value);
+ softwareRenderer->bg[3].dmy = value;
break;
case REG_BG3X_LO:
GBAVideoSoftwareRendererWriteBGX_LO(&softwareRenderer->bg[3], value);
+ if (softwareRenderer->bg[3].sx != softwareRenderer->cache[softwareRenderer->nextY].scale[1][0]) {
+ DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
+ }
break;
case REG_BG3X_HI:
GBAVideoSoftwareRendererWriteBGX_HI(&softwareRenderer->bg[3], value);
+ if (softwareRenderer->bg[3].sx != softwareRenderer->cache[softwareRenderer->nextY].scale[1][0]) {
+ DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
+ }
break;
case REG_BG3Y_LO:
GBAVideoSoftwareRendererWriteBGY_LO(&softwareRenderer->bg[3], value);
+ if (softwareRenderer->bg[3].sy != softwareRenderer->cache[softwareRenderer->nextY].scale[1][1]) {
+ DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
+ }
break;
case REG_BG3Y_HI:
GBAVideoSoftwareRendererWriteBGY_HI(&softwareRenderer->bg[3], value);
+ if (softwareRenderer->bg[3].sy != softwareRenderer->cache[softwareRenderer->nextY].scale[1][1]) {
+ DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
+ }
break;
case REG_BLDCNT:
GBAVideoSoftwareRendererWriteBLDCNT(softwareRenderer, value);
@@ -360,39 +393,32 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
default:
mLOG(GBA_VIDEO, GAME_ERROR, "Invalid video register: 0x%03X", address);
}
+ softwareRenderer->nextIo[address >> 1] = value;
+ if (softwareRenderer->cache[softwareRenderer->nextY].io[address >> 1] != value) {
+ softwareRenderer->cache[softwareRenderer->nextY].io[address >> 1] = value;
+ DIRTY_SCANLINE(softwareRenderer, softwareRenderer->nextY);
+ }
return value;
}
static void GBAVideoSoftwareRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) {
+ struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
if (renderer->cache) {
- mTileCacheWriteVRAM(renderer->cache, address);
+ mCacheSetWriteVRAM(renderer->cache, address);
}
+ memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty));
}
static void GBAVideoSoftwareRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam) {
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
- softwareRenderer->oamDirty = 1;
UNUSED(oam);
+ softwareRenderer->oamDirty = 1;
+ memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty));
}
static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
-#ifdef COLOR_16_BIT
-#ifdef COLOR_5_6_5
- unsigned color = 0;
- color |= (value & 0x001F) << 11;
- color |= (value & 0x03E0) << 1;
- color |= (value & 0x7C00) >> 10;
-#else
- unsigned color = value;
-#endif
-#else
- unsigned color = 0;
- color |= (value << 3) & 0xF8;
- color |= (value << 6) & 0xF800;
- color |= (value << 9) & 0xF80000;
- color |= (color >> 5) & 0x070707;
-#endif
+ color_t color = mColorFrom555(value);
softwareRenderer->normalPalette[address >> 1] = color;
if (softwareRenderer->blendEffect == BLEND_BRIGHTEN) {
softwareRenderer->variantPalette[address >> 1] = _brighten(color, softwareRenderer->bldy);
@@ -400,8 +426,9 @@ static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* render
softwareRenderer->variantPalette[address >> 1] = _darken(color, softwareRenderer->bldy);
}
if (renderer->cache) {
- mTileCacheWritePalette(renderer->cache, address);
+ mCacheSetWritePalette(renderer->cache, address >> 1, color);
}
+ memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty));
}
static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win, int y) {
@@ -515,6 +542,33 @@ static void _cleanOAM(struct GBAVideoSoftwareRenderer* renderer) {
static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
+ if (y == VIDEO_VERTICAL_PIXELS - 1) {
+ softwareRenderer->nextY = 0;
+ } else {
+ softwareRenderer->nextY = y + 1;
+ }
+
+ bool dirty = softwareRenderer->scanlineDirty[y >> 5] & (1 << (y & 0x1F));
+ if (memcmp(softwareRenderer->nextIo, softwareRenderer->cache[y].io, sizeof(softwareRenderer->nextIo))) {
+ memcpy(softwareRenderer->cache[y].io, softwareRenderer->nextIo, sizeof(softwareRenderer->nextIo));
+ dirty = true;
+ }
+
+ softwareRenderer->cache[y].scale[0][0] = softwareRenderer->bg[2].sx;
+ softwareRenderer->cache[y].scale[0][1] = softwareRenderer->bg[2].sy;
+ softwareRenderer->cache[y].scale[1][0] = softwareRenderer->bg[3].sx;
+ softwareRenderer->cache[y].scale[1][1] = softwareRenderer->bg[3].sy;
+
+ if (!dirty) {
+ if (GBARegisterDISPCNTGetMode(softwareRenderer->dispcnt) != 0) {
+ softwareRenderer->bg[2].sx += softwareRenderer->bg[2].dmx;
+ softwareRenderer->bg[2].sy += softwareRenderer->bg[2].dmy;
+ softwareRenderer->bg[3].sx += softwareRenderer->bg[3].dmx;
+ softwareRenderer->bg[3].sy += softwareRenderer->bg[3].dmy;
+ }
+ return;
+ }
+
color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y];
if (GBARegisterDISPCNTIsForcedBlank(softwareRenderer->dispcnt)) {
int x;
@@ -592,21 +646,23 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
GBAVideoSoftwareRendererPostprocessBuffer(softwareRenderer);
#ifdef COLOR_16_BIT
-#if defined(__ARM_NEON) && !defined(__APPLE__)
- _to16Bit(row, softwareRenderer->row, softwareRenderer->masterEnd);
-#else
+ size_t x;
for (x = 0; x < softwareRenderer->masterEnd; ++x) {
row[x] = softwareRenderer->row[x];
+ row[x + 1] = softwareRenderer->row[x + 1];
+ row[x + 2] = softwareRenderer->row[x + 2];
+ row[x + 3] = softwareRenderer->row[x + 3];
}
-#endif
#else
memcpy(row, softwareRenderer->row, softwareRenderer->masterEnd * sizeof(*row));
#endif
+ CLEAN_SCANLINE(softwareRenderer, y);
}
static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer) {
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
+ softwareRenderer->nextY = 0;
if (softwareRenderer->temporaryBuffer) {
mappedMemoryFree(softwareRenderer->temporaryBuffer, softwareRenderer->masterEnd * softwareRenderer->masterHeight * 4);
softwareRenderer->temporaryBuffer = 0;
@@ -654,22 +710,6 @@ static void GBAVideoSoftwareRendererWriteBGCNT(struct GBAVideoSoftwareRenderer*
bg->control = value;
}
-static void GBAVideoSoftwareRendererWriteBGPA(struct GBAVideoSoftwareBackground* bg, uint16_t value) {
- bg->dx = value;
-}
-
-static void GBAVideoSoftwareRendererWriteBGPB(struct GBAVideoSoftwareBackground* bg, uint16_t value) {
- bg->dmx = value;
-}
-
-static void GBAVideoSoftwareRendererWriteBGPC(struct GBAVideoSoftwareBackground* bg, uint16_t value) {
- bg->dy = value;
-}
-
-static void GBAVideoSoftwareRendererWriteBGPD(struct GBAVideoSoftwareBackground* bg, uint16_t value) {
- bg->dmy = value;
-}
-
static void GBAVideoSoftwareRendererWriteBGX_LO(struct GBAVideoSoftwareBackground* bg, uint16_t value) {
bg->refx = (bg->refx & 0xFFFF0000) | value;
bg->sx = bg->refx;
diff --git a/src/gba/savedata.c b/src/gba/savedata.c
index 08eab40aa..3008b9428 100644
--- a/src/gba/savedata.c
+++ b/src/gba/savedata.c
@@ -147,7 +147,7 @@ size_t GBASavedataSize(struct GBASavedata* savedata) {
case SAVEDATA_FLASH1M:
return SIZE_CART_FLASH1M;
case SAVEDATA_EEPROM:
- return SIZE_CART_EEPROM;
+ return (savedata->vf && savedata->vf->size(savedata->vf) == SIZE_CART_EEPROM512) ? SIZE_CART_EEPROM512 : SIZE_CART_EEPROM;
case SAVEDATA_FORCE_NONE:
return 0;
case SAVEDATA_AUTODETECT:
@@ -257,20 +257,23 @@ void GBASavedataInitEEPROM(struct GBASavedata* savedata, bool realisticTiming) {
mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
return;
}
+ int32_t eepromSize = SIZE_CART_EEPROM512;
off_t end;
if (!savedata->vf) {
end = 0;
savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
} else {
end = savedata->vf->size(savedata->vf);
- if (end < SIZE_CART_EEPROM) {
- savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);
+ if (end < SIZE_CART_EEPROM512) {
+ savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM512);
+ } else if (end > SIZE_CART_EEPROM512) {
+ eepromSize = SIZE_CART_EEPROM;
}
- savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
+ savedata->data = savedata->vf->map(savedata->vf, eepromSize, savedata->mapMode);
}
savedata->realisticTiming = realisticTiming;
- if (end < SIZE_CART_EEPROM) {
- memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end);
+ if (end < SIZE_CART_EEPROM512) {
+ memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM512 - end);
}
}
@@ -405,6 +408,19 @@ void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8
}
}
+static void _ensureEeprom(struct GBASavedata* savedata, uint32_t size) {
+ if (size < SIZE_CART_EEPROM512) {
+ return;
+ }
+ if (!savedata->vf || savedata->vf->size(savedata->vf) > SIZE_CART_EEPROM512) {
+ return;
+ }
+ savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_EEPROM512);
+ savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);
+ savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
+ memset(&savedata->data[SIZE_CART_EEPROM512], 0xFF, SIZE_CART_EEPROM - SIZE_CART_EEPROM512);
+}
+
void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32_t writeSize) {
switch (savedata->command) {
// Read header
@@ -430,6 +446,7 @@ void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32
} else if (writeSize == 1) {
savedata->command = EEPROM_COMMAND_NULL;
} else if ((savedata->writeAddress >> 3) < SIZE_CART_EEPROM) {
+ _ensureEeprom(savedata, savedata->writeAddress >> 3);
uint8_t current = savedata->data[savedata->writeAddress >> 3];
current &= ~(1 << (0x7 - (savedata->writeAddress & 0x7)));
current |= (value & 0x1) << (0x7 - (savedata->writeAddress & 0x7));
@@ -471,6 +488,7 @@ uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) {
if (savedata->readBitsRemaining < 64) {
int step = 63 - savedata->readBitsRemaining;
uint32_t address = (savedata->readAddress + step) >> 3;
+ _ensureEeprom(savedata, address);
if (address >= SIZE_CART_EEPROM) {
mLOG(GBA_SAVE, GAME_ERROR, "Reading beyond end of EEPROM: %08X", address);
return 0xFF;
diff --git a/src/gba/serialize.c b/src/gba/serialize.c
index 5917fa5f1..0f1820833 100644
--- a/src/gba/serialize.c
+++ b/src/gba/serialize.c
@@ -128,6 +128,8 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
return false;
}
gba->timing.root = NULL;
+ LOAD_32(gba->timing.masterCycles, 0, &state->masterCycles);
+
size_t i;
for (i = 0; i < 16; ++i) {
LOAD_32(gba->cpu->gprs[i], i * sizeof(gba->cpu->gprs[0]), state->cpu.gprs);
@@ -185,5 +187,9 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
if (gba->rr) {
gba->rr->stateLoaded(gba->rr, state);
}
+
+ gba->timing.reroot = gba->timing.root;
+ gba->timing.root = NULL;
+
return true;
}
diff --git a/src/gba/test/cheats.c b/src/gba/test/cheats.c
new file mode 100644
index 000000000..f3fb80b00
--- /dev/null
+++ b/src/gba/test/cheats.c
@@ -0,0 +1,943 @@
+/* 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 "util/test/suite.h"
+
+#include
+#include
+#include
+#include
+
+#include "gba/cheats/parv3.h"
+#include "gba/cheats/gameshark.h"
+
+M_TEST_SUITE_SETUP(GBACheats) {
+ struct mCore* core = GBACoreCreate();
+ core->init(core);
+ core->cheatDevice(core);
+ *state = core;
+ return 0;
+}
+
+M_TEST_SUITE_TEARDOWN(GBACheats) {
+ if (!*state) {
+ return 0;
+ }
+ struct mCore* core = *state;
+ core->deinit(core);
+ return 0;
+}
+
+M_TEST_DEFINE(createSet) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ set->deinit(set);
+}
+
+M_TEST_DEFINE(addRawPARv3) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "80000000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_false(set->addLine(set, "43000000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ set->deinit(set);
+}
+
+M_TEST_DEFINE(doPARv3Assign) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300000 00000078", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "02300002 00005678", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "04300004 12345678", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead16(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead32(core, 0x03000004, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x78);
+ assert_int_equal(core->rawRead16(core, 0x03000002, -1), 0x5678);
+ assert_int_equal(core->rawRead32(core, 0x03000004, -1), 0x12345678);
+
+ set->deinit(set);
+}
+
+M_TEST_DEFINE(doPARv3If1) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300001 00000011", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "08300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300001 00000012", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x12);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x11);
+
+ set->deinit(set);
+}
+
+M_TEST_DEFINE(doPARv3If1x1) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000031", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "08300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "08300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000032", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+
+ set->deinit(set);
+}
+
+M_TEST_DEFINE(doPARv3If2) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300001 00000011", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "48300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300001 00000012", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x12);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x11);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+
+ set->deinit(set);
+}
+
+M_TEST_DEFINE(doPARv3If2x2) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000031", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000041", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000051", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "48300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000032", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "48300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000042", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000052", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+ set->deinit(set);
+}
+
+M_TEST_DEFINE(doPARv3If2Contain1) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "48300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "08300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ set->deinit(set);
+}
+
+M_TEST_DEFINE(doPARv3IfX) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300001 00000011", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300001 00000012", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x12);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x11);
+}
+
+M_TEST_DEFINE(doPARv3IfXxX) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000031", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000041", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000032", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000042", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+}
+
+M_TEST_DEFINE(doPARv3IfXElse) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300001 00000011", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300001 00000012", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 60000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x12);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x11);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+}
+
+M_TEST_DEFINE(doPARv3IfXElsexX) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000031", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000041", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000051", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 60000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000032", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000042", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000052", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+}
+
+M_TEST_DEFINE(doPARv3IfXElsexXElse) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000031", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000041", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000051", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300006 00000061", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 60000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000032", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000042", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000052", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 60000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300006 00000062", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x61);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x62);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x62);
+}
+
+M_TEST_DEFINE(doPARv3IfXContain1) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000031", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000041", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "08300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000032", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000042", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+}
+
+M_TEST_DEFINE(doPARv3IfXContain1Else) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000031", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000041", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000051", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "08300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000032", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000042", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 60000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000052", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+}
+
+M_TEST_DEFINE(doPARv3IfXElseContain1) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300002 00000021", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000031", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000041", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000051", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300002 00000022", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 60000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000032", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "08300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000042", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000052", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x22);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x21);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+}
+
+M_TEST_DEFINE(doPARv3IfXContain1ElseContain1) {
+ struct mCore* core = *state;
+ struct mCheatDevice* device = core->cheatDevice(core);
+ assert_non_null(device);
+ struct mCheatSet* set = device->createSet(device, NULL);
+ assert_non_null(set);
+ GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW);
+ assert_true(set->addLine(set, "00300003 00000031", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000041", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000051", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300006 00000061", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300007 00000071", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300008 00000081", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "88300000 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300003 00000032", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "08300001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300004 00000042", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300005 00000052", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 60000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300006 00000062", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "08300002 00000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300007 00000072", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300008 00000082", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00000000 40000000", GBA_CHEAT_PRO_ACTION_REPLAY));
+ assert_true(set->addLine(set, "00300000 00000001", GBA_CHEAT_PRO_ACTION_REPLAY));
+
+ core->reset(core);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000007, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000008, -1), 0);
+
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x61);
+ assert_int_equal(core->rawRead8(core, 0x03000007, -1), 0x71);
+ assert_int_equal(core->rawRead8(core, 0x03000008, -1), 0x81);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x62);
+ assert_int_equal(core->rawRead8(core, 0x03000007, -1), 0x72);
+ assert_int_equal(core->rawRead8(core, 0x03000008, -1), 0x82);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x61);
+ assert_int_equal(core->rawRead8(core, 0x03000007, -1), 0x71);
+ assert_int_equal(core->rawRead8(core, 0x03000008, -1), 0x81);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000002, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x42);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x61);
+ assert_int_equal(core->rawRead8(core, 0x03000007, -1), 0x71);
+ assert_int_equal(core->rawRead8(core, 0x03000008, -1), 0x81);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x62);
+ assert_int_equal(core->rawRead8(core, 0x03000007, -1), 0x72);
+ assert_int_equal(core->rawRead8(core, 0x03000008, -1), 0x82);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000002, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x62);
+ assert_int_equal(core->rawRead8(core, 0x03000007, -1), 0x71);
+ assert_int_equal(core->rawRead8(core, 0x03000008, -1), 0x82);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ core->rawWrite8(core, 0x03000002, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x32);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x52);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x61);
+ assert_int_equal(core->rawRead8(core, 0x03000007, -1), 0x71);
+ assert_int_equal(core->rawRead8(core, 0x03000008, -1), 0x81);
+
+ core->reset(core);
+ core->rawWrite8(core, 0x03000000, -1, 0x1);
+ core->rawWrite8(core, 0x03000001, -1, 0x1);
+ core->rawWrite8(core, 0x03000002, -1, 0x1);
+ mCheatRefresh(device, set);
+ assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000001, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000002, -1), 0x1);
+ assert_int_equal(core->rawRead8(core, 0x03000003, -1), 0x31);
+ assert_int_equal(core->rawRead8(core, 0x03000004, -1), 0x41);
+ assert_int_equal(core->rawRead8(core, 0x03000005, -1), 0x51);
+ assert_int_equal(core->rawRead8(core, 0x03000006, -1), 0x62);
+ assert_int_equal(core->rawRead8(core, 0x03000007, -1), 0x71);
+ assert_int_equal(core->rawRead8(core, 0x03000008, -1), 0x82);
+}
+
+M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(GBACheats,
+ cmocka_unit_test(createSet),
+ cmocka_unit_test(addRawPARv3),
+ cmocka_unit_test(doPARv3Assign),
+ cmocka_unit_test(doPARv3If1),
+ cmocka_unit_test(doPARv3If1x1),
+ cmocka_unit_test(doPARv3If2),
+ cmocka_unit_test(doPARv3If2x2),
+ cmocka_unit_test(doPARv3If2Contain1),
+ cmocka_unit_test(doPARv3IfX),
+ cmocka_unit_test(doPARv3IfXxX),
+ cmocka_unit_test(doPARv3IfXElse),
+ cmocka_unit_test(doPARv3IfXElsexX),
+ cmocka_unit_test(doPARv3IfXElsexXElse),
+ cmocka_unit_test(doPARv3IfXContain1),
+ cmocka_unit_test(doPARv3IfXContain1Else),
+ cmocka_unit_test(doPARv3IfXElseContain1),
+ cmocka_unit_test(doPARv3IfXContain1ElseContain1))
diff --git a/src/gba/test/gba.c b/src/gba/test/gba.c
deleted file mode 100644
index 58186cd00..000000000
--- a/src/gba/test/gba.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/* Copyright (c) 2013-2016 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"
-
-M_TEST_SUITE_DECLARE(GBACore);
-
-int TestRunGBA(void) {
- int failures = 0;
- failures += M_TEST_SUITE_RUN(GBACore);
- return failures;
-}
diff --git a/src/gba/test/gba.h b/src/gba/test/gba.h
deleted file mode 100644
index 1e50b1d39..000000000
--- a/src/gba/test/gba.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Copyright (c) 2013-2016 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 TEST_GBA_H
-#define TEST_GBA_H
-#include
-
-int TestRunGBA(void);
-
-#endif
diff --git a/src/gba/video.c b/src/gba/video.c
index 285b8018c..377aafb15 100644
--- a/src/gba/video.c
+++ b/src/gba/video.c
@@ -6,11 +6,12 @@
#include
#include
-#include
+#include
#include
#include
#include
#include
+#include
#include
#include
@@ -177,9 +178,9 @@ void _startHdraw(struct mTiming* timing, void* context, uint32_t cyclesLate) {
GBARaiseIRQ(video->p, IRQ_VBLANK);
}
GBAFrameEnded(video->p);
+ mCoreSyncPostFrame(video->p->sync);
--video->frameskipCounter;
if (video->frameskipCounter < 0) {
- mCoreSyncPostFrame(video->p->sync);
video->frameskipCounter = video->frameskip;
}
++video->frameCounter;
@@ -234,7 +235,9 @@ static void GBAVideoDummyRendererDeinit(struct GBAVideoRenderer* renderer) {
}
static uint16_t GBAVideoDummyRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
- UNUSED(renderer);
+ if (renderer->cache) {
+ GBAVideoCacheWriteVideoRegister(renderer->cache, address, value);
+ }
switch (address) {
case REG_BG0CNT:
case REG_BG1CNT:
@@ -272,14 +275,13 @@ static uint16_t GBAVideoDummyRendererWriteVideoRegister(struct GBAVideoRenderer*
static void GBAVideoDummyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) {
if (renderer->cache) {
- mTileCacheWriteVRAM(renderer->cache, address);
+ mCacheSetWriteVRAM(renderer->cache, address);
}
}
static void GBAVideoDummyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
- UNUSED(value);
if (renderer->cache) {
- mTileCacheWritePalette(renderer->cache, address);
+ mCacheSetWritePalette(renderer->cache, address >> 1, mColorFrom555(value));
}
}
diff --git a/src/lr35902/lr35902.c b/src/lr35902/lr35902.c
index e4100a84a..6dd9db9ef 100644
--- a/src/lr35902/lr35902.c
+++ b/src/lr35902/lr35902.c
@@ -70,9 +70,8 @@ void LR35902Reset(struct LR35902Core* cpu) {
cpu->irqh.reset(cpu);
}
-void LR35902RaiseIRQ(struct LR35902Core* cpu, uint8_t vector) {
+void LR35902RaiseIRQ(struct LR35902Core* cpu) {
cpu->irqPending = true;
- cpu->irqVector = vector;
}
static void _LR35902InstructionIRQStall(struct LR35902Core* cpu) {
@@ -85,18 +84,19 @@ static void _LR35902InstructionIRQFinish(struct LR35902Core* cpu) {
}
static void _LR35902InstructionIRQDelay(struct LR35902Core* cpu) {
- cpu->index = cpu->sp + 1;
- cpu->bus = cpu->pc >> 8;
+ --cpu->sp;
+ cpu->index = cpu->sp;
+ cpu->bus = cpu->pc;
cpu->executionState = LR35902_CORE_MEMORY_STORE;
cpu->instruction = _LR35902InstructionIRQFinish;
- cpu->pc = cpu->irqVector;
+ cpu->pc = cpu->irqh.irqVector(cpu);
cpu->memory.setActiveRegion(cpu, cpu->pc);
}
static void _LR35902InstructionIRQ(struct LR35902Core* cpu) {
- cpu->sp -= 2; /* TODO: Atomic incrementing? */
+ --cpu->sp;
cpu->index = cpu->sp;
- cpu->bus = cpu->pc;
+ cpu->bus = cpu->pc >> 8;
cpu->executionState = LR35902_CORE_MEMORY_STORE;
cpu->instruction = _LR35902InstructionIRQDelay;
}
diff --git a/src/platform/3ds/CMakeLists.txt b/src/platform/3ds/CMakeLists.txt
index 5d0cbcf9e..bea542412 100644
--- a/src/platform/3ds/CMakeLists.txt
+++ b/src/platform/3ds/CMakeLists.txt
@@ -13,7 +13,11 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format" PARENT_SCOPE)
set(OS_DEFINES COLOR_16_BIT COLOR_5_6_5 IOAPI_NO_64)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
-list(APPEND OS_LIB citro3d ctru)
+if(${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo)
+ list(APPEND OS_LIB citro3dd ctrud)
+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_LIB ${OS_LIB} PARENT_SCOPE)
diff --git a/src/platform/3ds/ctr-gpu.c b/src/platform/3ds/ctr-gpu.c
index 4f446e649..02810e221 100644
--- a/src/platform/3ds/ctr-gpu.c
+++ b/src/platform/3ds/ctr-gpu.c
@@ -26,21 +26,21 @@ struct ctrUIVertex {
float rotate[2];
};
-#define MAX_NUM_QUADS 256
+#define MAX_NUM_QUADS 4096
#define VERTEX_BUFFER_SIZE MAX_NUM_QUADS * sizeof(struct ctrUIVertex)
static struct ctrUIVertex* ctrVertexBuffer = NULL;
static int ctrNumVerts = 0;
static int ctrVertStart = 0;
-static C3D_Tex* activeTexture = NULL;
+static const C3D_Tex* activeTexture = NULL;
static shaderProgram_s uiProgram;
static DVLB_s* uiShader = NULL;
static int GSH_FVEC_projectionMtx;
static int GSH_FVEC_textureMtx;
-bool ctrInitGpu() {
+bool ctrInitGpu(void) {
// Load vertex shader binary
uiShader = DVLB_ParseFile((u32*) uishader, uishader_size);
if (uiShader == NULL) {
@@ -83,7 +83,7 @@ bool ctrInitGpu() {
return true;
}
-void ctrDeinitGpu() {
+void ctrDeinitGpu(void) {
if (ctrVertexBuffer) {
linearFree(ctrVertexBuffer);
ctrVertexBuffer = NULL;
@@ -108,10 +108,23 @@ void ctrSetViewportSize(s16 w, s16 h, bool tilt) {
C3D_FVUnifMtx4x4(GPU_GEOMETRY_SHADER, GSH_FVEC_projectionMtx, &projectionMtx);
}
-void ctrActivateTexture(C3D_Tex* texture) {
+void ctrFlushBatch(void) {
+ int thisBatch = ctrNumVerts - ctrVertStart;
+ if (!thisBatch) {
+ return;
+ }
+ if (thisBatch < 0) {
+ svcBreak(USERBREAK_PANIC);
+ }
+ C3D_DrawArrays(GPU_GEOMETRY_PRIM, ctrVertStart, thisBatch);
+ ctrVertStart = ctrNumVerts;
+}
+
+void ctrActivateTexture(const C3D_Tex* texture) {
if (texture == activeTexture) {
return;
}
+
if (activeTexture) {
ctrFlushBatch();
}
@@ -172,14 +185,11 @@ void ctrAddRectEx(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s
return;
}
- if (ctrNumVerts + ctrVertStart == MAX_NUM_QUADS) {
- ctrFlushBatch();
- C3D_Flush();
- ctrNumVerts = 0;
- ctrVertStart = 0;
+ if (ctrNumVerts == MAX_NUM_QUADS) {
+ abort();
}
- struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrVertStart + ctrNumVerts];
+ struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrNumVerts];
vtx->x = x;
vtx->y = y;
vtx->w = w;
@@ -199,25 +209,17 @@ void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h) {
ctrAddRectEx(color, x, y, w, h, u, v, w, h, 0);
}
-void ctrFlushBatch(void) {
- if (ctrNumVerts == 0) {
- return;
- }
+void ctrStartFrame(void) {
+ ctrNumVerts = 0;
+ ctrVertStart = 0;
+ activeTexture = NULL;
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo);
- BufInfo_Add(bufInfo, &ctrVertexBuffer[ctrVertStart], sizeof(struct ctrUIVertex), 4, 0x3210);
-
- GSPGPU_FlushDataCache(&ctrVertexBuffer[ctrVertStart], sizeof(struct ctrUIVertex) * ctrNumVerts);
- C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, ctrNumVerts);
-
- ctrVertStart += ctrNumVerts;
- ctrNumVerts = 0;
+ BufInfo_Add(bufInfo, ctrVertexBuffer, sizeof(struct ctrUIVertex), 4, 0x3210);
}
-void ctrFinalize(void) {
+void ctrEndFrame(void) {
ctrFlushBatch();
- C3D_Flush();
- ctrNumVerts = 0;
- ctrVertStart = 0;
+ GSPGPU_FlushDataCache(ctrVertexBuffer, sizeof(struct ctrUIVertex) * ctrNumVerts);
}
diff --git a/src/platform/3ds/ctr-gpu.h b/src/platform/3ds/ctr-gpu.h
index e4d30965f..b271636f9 100644
--- a/src/platform/3ds/ctr-gpu.h
+++ b/src/platform/3ds/ctr-gpu.h
@@ -16,12 +16,13 @@ void ctrDeinitGpu(void);
void ctrSetViewportSize(s16 w, s16 h, bool tilt);
-void ctrActivateTexture(C3D_Tex* texture);
+void ctrActivateTexture(const C3D_Tex* texture);
void ctrTextureMultiply(void);
void ctrTextureBias(u32 color);
void ctrAddRectEx(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s16 vh, float rotate);
void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h);
void ctrFlushBatch(void);
-void ctrFinalize(void);
+void ctrStartFrame(void);
+void ctrEndFrame(void);
#endif
diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c
index 056f792cd..7c54d1bae 100644
--- a/src/platform/3ds/main.c
+++ b/src/platform/3ds/main.c
@@ -27,6 +27,9 @@
#include <3ds.h>
#include <3ds/gpu/gx.h>
+mLOG_DECLARE_CATEGORY(GUI_3DS);
+mLOG_DEFINE_CATEGORY(GUI_3DS, "3DS", "gui.3ds");
+
static enum ScreenMode {
SM_PA_BOTTOM,
SM_AF_BOTTOM,
@@ -58,12 +61,21 @@ static enum DarkenMode {
#define AUDIO_SAMPLE_BUFFER (AUDIO_SAMPLES * 16)
#define DSP_BUFFERS 4
-static struct GBA3DSRotationSource {
+static struct m3DSRotationSource {
struct mRotationSource d;
accelVector accel;
angularRate gyro;
} rotation;
+static struct m3DSImageSource {
+ struct mImageSource d;
+ Handle handles[2];
+ u32 bufferSize;
+ u32 transferSize;
+ void* buffer;
+ unsigned cam;
+} camera;
+
static enum {
NO_SOUND,
DSP_SUPPORTED,
@@ -80,10 +92,15 @@ static C3D_Tex outputTexture;
static ndspWaveBuf dspBuffer[DSP_BUFFERS];
static int bufferId = 0;
static bool frameLimiter = true;
+static u64 tickCounter;
-static C3D_RenderBuf bottomScreen;
-static C3D_RenderBuf topScreen;
-static C3D_RenderBuf upscaleBuffer;
+static C3D_RenderTarget* topScreen[2];
+static C3D_RenderTarget* bottomScreen[2];
+static int doubleBuffer = 0;
+static bool frameStarted = false;
+
+static C3D_RenderTarget* upscaleBuffer;
+static C3D_Tex upscaleBufferTex;
static aptHookCookie cookie;
@@ -94,10 +111,24 @@ static bool _initGpu(void) {
return false;
}
- if (!C3D_RenderBufInit(&topScreen, 240, 400, GPU_RB_RGB8, 0) || !C3D_RenderBufInit(&bottomScreen, 240, 320, GPU_RB_RGB8, 0) || !C3D_RenderBufInit(&upscaleBuffer, 512, 512, GPU_RB_RGB8, 0)) {
+ topScreen[0] = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, 0);
+ topScreen[1] = 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]) {
return false;
}
+ if (!C3D_TexInitVRAM(&upscaleBufferTex, 512, 512, GPU_RB_RGB8)) {
+ return false;
+ }
+ upscaleBuffer = C3D_RenderTargetCreateFromTex(&upscaleBufferTex, GPU_TEXFACE_2D, 0, 0);
+ if (!upscaleBuffer) {
+ return false;
+ }
+
+ C3D_RenderTargetSetClear(upscaleBuffer, C3D_CLEAR_COLOR, 0, 0);
+
return ctrInitGpu();
}
@@ -108,9 +139,13 @@ static void _cleanup(void) {
linearFree(outputBuffer);
}
- C3D_RenderBufDelete(&topScreen);
- C3D_RenderBufDelete(&bottomScreen);
- C3D_RenderBufDelete(&upscaleBuffer);
+ C3D_RenderTargetDelete(topScreen[0]);
+ C3D_RenderTargetDelete(topScreen[1]);
+ C3D_RenderTargetDelete(bottomScreen[0]);
+ C3D_RenderTargetDelete(bottomScreen[1]);
+ C3D_RenderTargetDelete(upscaleBuffer);
+ C3D_TexDelete(&upscaleBufferTex);
+ C3D_TexDelete(&outputTexture);
C3D_Fini();
gfxExit();
@@ -128,6 +163,7 @@ static void _cleanup(void) {
ndspExit();
}
+ camExit();
csndExit();
ptmuExit();
}
@@ -191,18 +227,41 @@ static void _csndPlaySound(u32 flags, u32 sampleRate, float vol, void* left, voi
static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right);
static void _drawStart(void) {
- C3D_RenderBufClear(&bottomScreen);
- C3D_RenderBufClear(&topScreen);
+}
+
+static void _frameStart(void) {
+ if (frameStarted) {
+ return;
+ }
+ frameStarted = true;
+ u8 flags = 0;
+ if (!frameLimiter) {
+ if (tickCounter + 4481000 > svcGetSystemTick()) {
+ flags = C3D_FRAME_NONBLOCK;
+ } else {
+ tickCounter = svcGetSystemTick();
+ }
+ }
+ C3D_FrameBegin(flags);
+ // Mark both buffers used to make sure they get cleared
+ C3D_FrameDrawOn(topScreen[doubleBuffer]);
+ C3D_FrameDrawOn(bottomScreen[doubleBuffer]);
+ ctrStartFrame();
}
static void _drawEnd(void) {
- ctrFinalize();
- C3D_RenderBufTransfer(&topScreen, (u32*) gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8));
- C3D_RenderBufTransfer(&bottomScreen, (u32*) gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8));
- gfxSwapBuffersGpu();
- if (frameLimiter) {
- gspWaitForEvent(GSPGPU_EVENT_VBlank0, false);
+ if (!frameStarted) {
+ 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_FrameEnd(GX_CMDLIST_FLUSH);
+ frameStarted = false;
+
+ doubleBuffer ^= 1;
+ C3D_FrameBufClear(&bottomScreen[doubleBuffer]->frameBuf, C3D_CLEAR_COLOR, 0, 0);
+ C3D_FrameBufClear(&topScreen[doubleBuffer]->frameBuf, C3D_CLEAR_COLOR, 0, 0);
}
static int _batteryState(void) {
@@ -221,12 +280,8 @@ static int _batteryState(void) {
}
static void _guiPrepare(void) {
- int screen = screenMode < SM_PA_TOP ? GFX_BOTTOM : GFX_TOP;
- if (screen == GFX_BOTTOM) {
- return;
- }
-
- C3D_RenderBufBind(&bottomScreen);
+ _frameStart();
+ C3D_FrameDrawOn(bottomScreen[doubleBuffer]);
ctrSetViewportSize(320, 240, true);
}
@@ -234,15 +289,29 @@ static void _guiFinish(void) {
ctrFlushBatch();
}
+static void _resetCamera(struct m3DSImageSource* imageSource) {
+ if (!imageSource->cam) {
+ return;
+ }
+ CAMU_SetSize(imageSource->cam, SIZE_QCIF, CONTEXT_A);
+ CAMU_SetOutputFormat(imageSource->cam, OUTPUT_RGB_565, CONTEXT_A);
+ CAMU_SetFrameRate(imageSource->cam, FRAME_RATE_30);
+ CAMU_FlipImage(imageSource->cam, FLIP_NONE, CONTEXT_A);
+
+ CAMU_SetNoiseFilter(imageSource->cam, true);
+ CAMU_SetAutoExposure(imageSource->cam, false);
+ CAMU_SetAutoWhiteBalance(imageSource->cam, false);
+}
+
static void _setup(struct mGUIRunner* runner) {
- bool isNew3DS = false;
- APT_CheckNew3DS(&isNew3DS);
- if (isNew3DS && !envIsHomebrew()) {
+ uint8_t mask;
+ if (R_SUCCEEDED(svcGetProcessAffinityMask(&mask, CUR_PROCESS_HANDLE, 4)) && mask >= 4) {
mCoreConfigSetDefaultIntValue(&runner->config, "threadedVideo", 1);
mCoreLoadForeignConfig(runner->core, &runner->config);
}
runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation.d);
+ runner->core->setPeripheral(runner->core, mPERIPH_IMAGE_SOURCE, &camera.d);
if (hasSound != NO_SOUND) {
runner->core->setAVStream(runner->core, &stream);
}
@@ -258,7 +327,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);
- outputBuffer = linearMemAlign(256 * VIDEO_VERTICAL_PIXELS * 2, 0x80);
+ outputBuffer = linearMemAlign(256 * 224 * 2, 0x80);
runner->core->setVideoBuffer(runner->core, outputBuffer, 256);
unsigned mode;
@@ -268,9 +337,9 @@ static void _setup(struct mGUIRunner* runner) {
if (mCoreConfigGetUIntValue(&runner->config, "filterMode", &mode) && mode < FM_MAX) {
filterMode = mode;
if (filterMode == FM_NEAREST) {
- C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_NEAREST, GPU_NEAREST);
+ C3D_TexSetFilter(&upscaleBufferTex, GPU_NEAREST, GPU_NEAREST);
} else {
- C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_LINEAR, GPU_LINEAR);
+ C3D_TexSetFilter(&upscaleBufferTex, GPU_LINEAR, GPU_LINEAR);
}
}
if (mCoreConfigGetUIntValue(&runner->config, "darkenMode", &mode) && mode < DM_MAX) {
@@ -284,6 +353,7 @@ static void _setup(struct mGUIRunner* runner) {
static void _gameLoaded(struct mGUIRunner* runner) {
switch (runner->core->platform(runner->core)) {
#ifdef M_CORE_GBA
+ // TODO: Move these to callbacks
case PLATFORM_GBA:
if (((struct GBA*) runner->core->board)->memory.hw.devices & HW_TILT) {
HIDUSER_EnableAccelerometer();
@@ -326,14 +396,35 @@ static void _gameLoaded(struct mGUIRunner* runner) {
if (mCoreConfigGetUIntValue(&runner->config, "filterMode", &mode) && mode < FM_MAX) {
filterMode = mode;
if (filterMode == FM_NEAREST) {
- C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_NEAREST, GPU_NEAREST);
+ C3D_TexSetFilter(&upscaleBufferTex, GPU_NEAREST, GPU_NEAREST);
} else {
- C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_LINEAR, GPU_LINEAR);
+ C3D_TexSetFilter(&upscaleBufferTex, GPU_LINEAR, GPU_LINEAR);
}
}
if (mCoreConfigGetUIntValue(&runner->config, "darkenMode", &mode) && mode < DM_MAX) {
darkenMode = mode;
}
+ if (mCoreConfigGetUIntValue(&runner->config, "camera", &mode)) {
+ switch (mode) {
+ case 0:
+ default:
+ mode = SELECT_NONE;
+ break;
+ case 1:
+ mode = SELECT_IN1;
+ break;
+ case 2:
+ mode = SELECT_OUT1;
+ break;
+ }
+ if (mode != camera.cam) {
+ camera.cam = mode;
+ if (camera.buffer) {
+ _resetCamera(&camera);
+ CAMU_Activate(camera.cam);
+ }
+ }
+ }
}
static void _gameUnloaded(struct mGUIRunner* runner) {
@@ -347,6 +438,7 @@ static void _gameUnloaded(struct mGUIRunner* runner) {
switch (runner->core->platform(runner->core)) {
#ifdef M_CORE_GBA
+ // TODO: Move these to callbacks
case PLATFORM_GBA:
if (((struct GBA*) runner->core->board)->memory.hw.devices & HW_TILT) {
HIDUSER_DisableAccelerometer();
@@ -369,22 +461,23 @@ static void _gameUnloaded(struct mGUIRunner* runner) {
}
static void _drawTex(struct mCore* core, bool faded) {
+ _frameStart();
unsigned screen_w, screen_h;
switch (screenMode) {
case SM_PA_BOTTOM:
- C3D_RenderBufBind(&bottomScreen);
+ C3D_FrameDrawOn(bottomScreen[doubleBuffer]);
screen_w = 320;
screen_h = 240;
break;
case SM_PA_TOP:
- C3D_RenderBufBind(&topScreen);
+ C3D_FrameDrawOn(topScreen[doubleBuffer]);
screen_w = 400;
screen_h = 240;
break;
default:
- C3D_RenderBufBind(&upscaleBuffer);
- screen_w = upscaleBuffer.colorBuf.width;
- screen_h = upscaleBuffer.colorBuf.height;
+ C3D_FrameDrawOn(upscaleBuffer);
+ screen_w = 512;
+ screen_h = 512;
break;
}
@@ -473,10 +566,10 @@ static void _drawTex(struct mCore* core, bool faded) {
coreh = h;
screen_h = 240;
if (screenMode < SM_PA_TOP) {
- C3D_RenderBufBind(&bottomScreen);
+ C3D_FrameDrawOn(bottomScreen[doubleBuffer]);
screen_w = 320;
} else {
- C3D_RenderBufBind(&topScreen);
+ C3D_FrameDrawOn(topScreen[doubleBuffer]);
screen_w = 400;
}
ctrSetViewportSize(screen_w, screen_h, true);
@@ -505,7 +598,7 @@ static void _drawTex(struct mCore* core, bool faded) {
x = (screen_w - w) / 2;
y = (screen_h - h) / 2;
- ctrActivateTexture(&upscaleBuffer.colorBuf);
+ ctrActivateTexture(&upscaleBufferTex);
ctrAddRectEx(0xFFFFFFFF, x, y, w, h, 0, 0, corew, coreh, 0);
ctrFlushBatch();
}
@@ -572,13 +665,17 @@ static void _incrementScreenMode(struct mGUIRunner* runner) {
screenMode = (screenMode + 1) % SM_MAX;
mCoreConfigSetUIntValue(&runner->config, "screenMode", screenMode);
- C3D_RenderBufClear(&bottomScreen);
- C3D_RenderBufClear(&topScreen);
+ C3D_FrameBufClear(&bottomScreen[doubleBuffer]->frameBuf, C3D_CLEAR_COLOR, 0, 0);
+ C3D_FrameBufClear(&topScreen[doubleBuffer]->frameBuf, C3D_CLEAR_COLOR, 0, 0);
}
static void _setFrameLimiter(struct mGUIRunner* runner, bool limit) {
UNUSED(runner);
+ if (frameLimiter == limit) {
+ return;
+ }
frameLimiter = limit;
+ tickCounter = svcGetSystemTick();
}
static uint32_t _pollInput(const struct mInputMap* map) {
@@ -600,27 +697,96 @@ static enum GUICursorState _pollCursor(unsigned* x, unsigned* y) {
}
static void _sampleRotation(struct mRotationSource* source) {
- struct GBA3DSRotationSource* rotation = (struct GBA3DSRotationSource*) source;
+ struct m3DSRotationSource* rotation = (struct m3DSRotationSource*) source;
// Work around ctrulib getting the entries wrong
rotation->accel = *(accelVector*) &hidSharedMem[0x48];
rotation->gyro = *(angularRate*) &hidSharedMem[0x5C];
}
static int32_t _readTiltX(struct mRotationSource* source) {
- struct GBA3DSRotationSource* rotation = (struct GBA3DSRotationSource*) source;
+ struct m3DSRotationSource* rotation = (struct m3DSRotationSource*) source;
return rotation->accel.x << 18L;
}
static int32_t _readTiltY(struct mRotationSource* source) {
- struct GBA3DSRotationSource* rotation = (struct GBA3DSRotationSource*) source;
+ struct m3DSRotationSource* rotation = (struct m3DSRotationSource*) source;
return rotation->accel.y << 18L;
}
static int32_t _readGyroZ(struct mRotationSource* source) {
- struct GBA3DSRotationSource* rotation = (struct GBA3DSRotationSource*) source;
+ struct m3DSRotationSource* rotation = (struct m3DSRotationSource*) source;
return rotation->gyro.y << 18L; // Yes, y
}
+static void _startRequestImage(struct mImageSource* source, unsigned w, unsigned h, int colorFormats) {
+ UNUSED(colorFormats);
+ struct m3DSImageSource* imageSource = (struct m3DSImageSource*) source;
+
+ _resetCamera(imageSource);
+
+ CAMU_SetTrimming(PORT_CAM1, true);
+ CAMU_SetTrimmingParamsCenter(PORT_CAM1, w, h, 176, 144);
+ CAMU_GetBufferErrorInterruptEvent(&imageSource->handles[1], PORT_CAM1);
+
+ if (imageSource->bufferSize != w * h * 2 && imageSource->buffer) {
+ free(imageSource->buffer);
+ imageSource->buffer = NULL;
+ }
+ imageSource->bufferSize = w * h * 2;
+ if (!imageSource->buffer) {
+ imageSource->buffer = malloc(imageSource->bufferSize);
+ }
+ CAMU_GetMaxBytes(&imageSource->transferSize, w, h);
+ CAMU_SetTransferBytes(PORT_CAM1, imageSource->transferSize, w, h);
+ CAMU_Activate(imageSource->cam);
+ CAMU_ClearBuffer(PORT_CAM1);
+ CAMU_StartCapture(PORT_CAM1);
+
+ if (imageSource->cam) {
+ CAMU_SetReceiving(&imageSource->handles[0], imageSource->buffer, PORT_CAM1, imageSource->bufferSize, imageSource->transferSize);
+ }
+}
+
+static void _stopRequestImage(struct mImageSource* source) {
+ struct m3DSImageSource* imageSource = (struct m3DSImageSource*) source;
+
+ free(imageSource->buffer);
+ imageSource->buffer = NULL;
+ svcCloseHandle(imageSource->handles[0]);
+ svcCloseHandle(imageSource->handles[1]);
+
+ CAMU_StopCapture(PORT_CAM1);
+ CAMU_Activate(SELECT_NONE);
+}
+
+
+static void _requestImage(struct mImageSource* source, const void** buffer, size_t* stride, enum mColorFormat* colorFormat) {
+ struct m3DSImageSource* imageSource = (struct m3DSImageSource*) source;
+
+ if (!imageSource->cam) {
+ memset(imageSource->buffer, 0, imageSource->bufferSize);
+ *buffer = imageSource->buffer;
+ *stride = 128;
+ *colorFormat = mCOLOR_RGB565;
+ return;
+ }
+
+ s32 i;
+ svcWaitSynchronizationN(&i, imageSource->handles, 2, false, U64_MAX);
+
+ if (i == 0) {
+ *buffer = imageSource->buffer;
+ *stride = 128;
+ *colorFormat = mCOLOR_RGB565;
+ } else {
+ CAMU_ClearBuffer(PORT_CAM1);
+ CAMU_StartCapture(PORT_CAM1);
+ }
+
+ svcCloseHandle(imageSource->handles[0]);
+ 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) {
UNUSED(stream);
if (hasSound == CSND_SUPPORTED) {
@@ -671,6 +837,13 @@ int main() {
stream.postAudioBuffer = _postAudioBuffer;
stream.videoFrameRateChanged = 0;
+ camera.d.startRequestImage = _startRequestImage;
+ camera.d.stopRequestImage = _stopRequestImage;
+ camera.d.requestImage = _requestImage;
+ camera.buffer = NULL;
+ camera.bufferSize = 0;
+ camera.cam = SELECT_IN1;
+
if (!allocateRomBuffer()) {
return 1;
}
@@ -678,6 +851,8 @@ int main() {
aptHook(&cookie, _aptHook, 0);
ptmuInit();
+ camInit();
+
hasSound = NO_SOUND;
if (!ndspInit()) {
hasSound = DSP_SUPPORTED;
@@ -717,7 +892,7 @@ int main() {
}
C3D_TexSetWrap(&outputTexture, GPU_CLAMP_TO_EDGE, GPU_CLAMP_TO_EDGE);
C3D_TexSetFilter(&outputTexture, GPU_NEAREST, GPU_NEAREST);
- C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_LINEAR, GPU_LINEAR);
+ C3D_TexSetFilter(&upscaleBufferTex, GPU_LINEAR, GPU_LINEAR);
void* outputTextureEnd = (u8*)outputTexture.data + 256 * 256 * 2;
// Zero texture data to make sure no garbage around the border interferes with filtering
@@ -820,9 +995,21 @@ int main() {
"Grayed",
},
.nStates = 4
+ },
+ {
+ .title = "Camera",
+ .data = "camera",
+ .submenu = 0,
+ .state = 1,
+ .validStates = (const char*[]) {
+ "None",
+ "Inner",
+ "Outer",
+ },
+ .nStates = 3
}
},
- .nConfigExtra = 3,
+ .nConfigExtra = 4,
.setup = _setup,
.teardown = 0,
.gameLoaded = _gameLoaded,
diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c
index cbdecf9e9..bafc88b9c 100644
--- a/src/platform/libretro/libretro.c
+++ b/src/platform/libretro/libretro.c
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
#ifdef M_CORE_GB
#include
@@ -101,8 +102,8 @@ void retro_set_environment(retro_environment_t env) {
struct retro_variable vars[] = {
{ "mgba_solar_sensor_level", "Solar sensor level; 0|1|2|3|4|5|6|7|8|9|10" },
{ "mgba_allow_opposing_directions", "Allow opposing directional input; OFF|ON" },
- { "mgba_use_bios", "Use BIOS file if found; ON|OFF" },
- { "mgba_skip_bios", "Skip BIOS intro; OFF|ON" },
+ { "mgba_use_bios", "Use BIOS file if found (requires restart); ON|OFF" },
+ { "mgba_skip_bios", "Skip BIOS intro (requires restart); OFF|ON" },
{ "mgba_idle_optimization", "Idle loop removal; Remove Known|Detect and Remove|Don't Remove" },
{ 0, 0 }
};
@@ -391,7 +392,7 @@ bool retro_load_game(const struct retro_game_info* game) {
core->init(core);
core->setAVStream(core, &stream);
- outputBuffer = malloc(256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
+ outputBuffer = malloc(256 * 224 * BYTES_PER_PIXEL);
core->setVideoBuffer(core, outputBuffer, 256);
core->setAudioBufferSize(core, SAMPLES);
@@ -528,16 +529,9 @@ size_t retro_get_memory_size(unsigned id) {
if (core->platform(core) == PLATFORM_GBA) {
switch (((struct GBA*) core->board)->memory.savedata.type) {
case SAVEDATA_AUTODETECT:
- case SAVEDATA_FLASH1M:
return SIZE_CART_FLASH1M;
- case SAVEDATA_FLASH512:
- return SIZE_CART_FLASH512;
- case SAVEDATA_EEPROM:
- return SIZE_CART_EEPROM;
- case SAVEDATA_SRAM:
- return SIZE_CART_SRAM;
- case SAVEDATA_FORCE_NONE:
- return 0;
+ default:
+ return GBASavedataSize(&((struct GBA*) core->board)->memory.savedata);
}
}
#endif
@@ -583,7 +577,12 @@ void GBARetroLog(struct mLogger* logger, int category, enum mLogLevel level, con
break;
}
#ifdef NDEBUG
- if (category == _mLOG_CAT_GBA_BIOS()) {
+ static int biosCat = -1;
+ if (biosCat < 0) {
+ biosCat = mLogCategoryById("gba.bios");
+ }
+
+ if (category == biosCat) {
return;
}
#endif
diff --git a/src/platform/openemu/mGBAGameCore.m b/src/platform/openemu/mGBAGameCore.m
index 1ddf5482f..9b2b93b05 100644
--- a/src/platform/openemu/mGBAGameCore.m
+++ b/src/platform/openemu/mGBAGameCore.m
@@ -65,13 +65,9 @@
};
mCoreConfigLoadDefaults(&core->config, &opts);
core->init(core);
+ outputBuffer = nil;
- unsigned width, height;
- core->desiredVideoDimensions(core, &width, &height);
- outputBuffer = malloc(width * height * BYTES_PER_PIXEL);
- core->setVideoBuffer(core, outputBuffer, width);
core->setAudioBufferSize(core, SAMPLES);
-
cheatSets = [[NSMutableDictionary alloc] init];
}
@@ -108,6 +104,15 @@
mCoreAutoloadSave(core);
core->reset(core);
+
+ unsigned width, height;
+ core->desiredVideoDimensions(core, &width, &height);
+ if (outputBuffer) {
+ free(outputBuffer);
+ }
+ outputBuffer = malloc(width * height * BYTES_PER_PIXEL);
+ core->setVideoBuffer(core, outputBuffer, width);
+
return YES;
}
diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c
index 2dfa7448b..84343e35f 100644
--- a/src/platform/opengl/gles2.c
+++ b/src/platform/opengl/gles2.c
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include
#include
@@ -190,13 +191,6 @@ static void mGLES2ContextClear(struct VideoBackend* v) {
void _drawShader(struct mGLES2Context* context, struct mGLES2Shader* shader) {
GLint viewport[4];
glBindFramebuffer(GL_FRAMEBUFFER, shader->fbo);
- if (shader->blend) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glDisable(GL_BLEND);
- glClear(GL_COLOR_BUFFER_BIT);
- }
glGetIntegerv(GL_VIEWPORT, viewport);
int drawW = shader->width;
@@ -222,6 +216,14 @@ void _drawShader(struct mGLES2Context* context, struct mGLES2Shader* shader) {
drawH -= drawH % context->d.height;
}
glViewport(padW, padH, drawW, drawH);
+ if (shader->blend) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glDisable(GL_BLEND);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
if (shader->tex && (shader->width <= 0 || shader->height <= 0)) {
GLint oldTex;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTex);
diff --git a/src/platform/psp2/CMakeLists.txt b/src/platform/psp2/CMakeLists.txt
index 8c127f735..eb8f31d75 100644
--- a/src/platform/psp2/CMakeLists.txt
+++ b/src/platform/psp2/CMakeLists.txt
@@ -13,7 +13,7 @@ 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)
-set(OS_LIB -lvita2d -lSceAppMgr_stub -lSceCtrl_stub -lScePgf_stub -lSceGxm_stub -lSceDisplay_stub -lSceAudio_stub -lSceCommonDialog_stub -lSceMotion_stub -lScePhotoExport_stub -lScePower_stub -lSceSysmodule_stub -lSceTouch_stub -l${M_LIBRARY})
+set(OS_LIB -lvita2d -lSceAppMgr_stub -lSceCtrl_stub -lSceAudio_stub -lSceCamera_stub -lSceCommonDialog_stub -lSceDisplay_stub -lSceGxm_stub -lSceMotion_stub -lScePgf_stub -lScePhotoExport_stub -lScePower_stub -lSceSysmodule_stub -lSceTouch_stub -l${M_LIBRARY})
set(OBJCOPY_CMD ${OBJCOPY} -I binary -O elf32-littlearm -B arm)
list(APPEND GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c)
diff --git a/src/platform/psp2/main.c b/src/platform/psp2/main.c
index d41ae49c6..40068e700 100644
--- a/src/platform/psp2/main.c
+++ b/src/platform/psp2/main.c
@@ -105,6 +105,18 @@ int main() {
"Fit Aspect Ratio",
},
.nStates = 4
+ },
+ {
+ .title = "Camera",
+ .data = "camera",
+ .submenu = 0,
+ .state = 1,
+ .validStates = (const char*[]) {
+ "None",
+ "Front",
+ "Back",
+ },
+ .nStates = 3
}
},
.keySources = (struct GUIInputKeys[]) {
@@ -133,7 +145,7 @@ int main() {
},
{ .id = 0 }
},
- .nConfigExtra = 1,
+ .nConfigExtra = 2,
.setup = mPSP2Setup,
.teardown = mPSP2Teardown,
.gameLoaded = mPSP2LoadROM,
diff --git a/src/platform/psp2/psp2-context.c b/src/platform/psp2/psp2-context.c
index b2bef2bae..278c7419d 100644
--- a/src/platform/psp2/psp2-context.c
+++ b/src/platform/psp2/psp2-context.c
@@ -27,6 +27,7 @@
#include
#include
+#include
#include
#include
#include
@@ -36,6 +37,7 @@
#include
#define RUMBLE_PWM 8
+#define CDRAM_ALIGN 0x40000
static enum ScreenMode {
SM_BACKDROP,
@@ -49,15 +51,26 @@ static void* outputBuffer;
static vita2d_texture* tex;
static vita2d_texture* screenshot;
static Thread audioThread;
+
static struct mSceRotationSource {
struct mRotationSource d;
struct SceMotionSensorState state;
} rotation;
+
static struct mSceRumble {
struct mRumble d;
struct CircleBuffer history;
int current;
} rumble;
+
+static struct mSceImageSource {
+ struct mImageSource d;
+ SceUID memblock;
+ void* buffer;
+ unsigned cam;
+ size_t bufferOffset;
+} camera;
+
bool frameLimiter = true;
extern const uint8_t _binary_backdrop_png_start[];
@@ -143,6 +156,79 @@ static void _setRumble(struct mRumble* source, int enable) {
sceCtrlSetActuator(1, &state);
}
+static void _resetCamera(struct mSceImageSource* imageSource) {
+ if (!imageSource->cam) {
+ return;
+ }
+
+ sceCameraOpen(imageSource->cam - 1, &(SceCameraInfo) {
+ .size = sizeof(SceCameraInfo),
+ .format = 5, // SCE_CAMERA_FORMAT_ABGR
+ .resolution = SCE_CAMERA_RESOLUTION_176_144,
+ .framerate = SCE_CAMERA_FRAMERATE_30_FPS,
+ .sizeIBase = 176 * 144 * 4,
+ .pitch = 0,
+ .pIBase = imageSource->buffer,
+ });
+ sceCameraStart(imageSource->cam - 1);
+}
+
+static void _startRequestImage(struct mImageSource* source, unsigned w, unsigned h, int colorFormats) {
+ UNUSED(colorFormats);
+ struct mSceImageSource* imageSource = (struct mSceImageSource*) source;
+
+ if (!imageSource->buffer) {
+ imageSource->memblock = sceKernelAllocMemBlock("camera", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, CDRAM_ALIGN, NULL);
+ sceKernelGetMemBlockBase(imageSource->memblock, &imageSource->buffer);
+ }
+
+ if (!imageSource->cam) {
+ return;
+ }
+
+ _resetCamera(imageSource);
+ imageSource->bufferOffset = (176 - w) / 2 + (144 - h) * 176 / 2;
+
+ SceCameraRead read = {
+ sizeof(SceCameraRead),
+ 1
+ };
+ sceCameraRead(imageSource->cam - 1, &read);
+}
+
+static void _stopRequestImage(struct mImageSource* source) {
+ struct mSceImageSource* imageSource = (struct mSceImageSource*) source;
+ if (imageSource->cam) {
+ sceCameraStop(imageSource->cam - 1);
+ sceCameraClose(imageSource->cam - 1);
+ }
+ sceKernelFreeMemBlock(imageSource->memblock);
+ imageSource->buffer = NULL;
+}
+
+
+static void _requestImage(struct mImageSource* source, const void** buffer, size_t* stride, enum mColorFormat* colorFormat) {
+ struct mSceImageSource* imageSource = (struct mSceImageSource*) source;
+
+ if (!imageSource->cam) {
+ memset(imageSource->buffer, 0, 176 * 144 * 4);
+ *buffer = (uint32_t*) imageSource->buffer;
+ *stride = 176;
+ *colorFormat = mCOLOR_XBGR8;
+ return;
+ }
+
+ *buffer = (uint32_t*) imageSource->buffer + imageSource->bufferOffset;
+ *stride = 176;
+ *colorFormat = mCOLOR_XBGR8;
+
+ SceCameraRead read = {
+ sizeof(SceCameraRead),
+ 1
+ };
+ sceCameraRead(imageSource->cam - 1, &read);
+}
+
uint16_t mPSP2PollInput(struct mGUIRunner* runner) {
SceCtrlData pad;
sceCtrlPeekBufferPositive(0, &pad, 1);
@@ -210,6 +296,13 @@ void mPSP2Setup(struct mGUIRunner* runner) {
CircleBufferInit(&rumble.history, RUMBLE_PWM);
runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble.d);
+ camera.d.startRequestImage = _startRequestImage;
+ camera.d.stopRequestImage = _stopRequestImage;
+ camera.d.requestImage = _requestImage;
+ camera.buffer = NULL;
+ camera.cam = 1;
+ runner->core->setPeripheral(runner->core, mPERIPH_IMAGE_SOURCE, &camera.d);
+
frameLimiter = true;
backdrop = vita2d_load_PNG_buffer(_binary_backdrop_png_start);
@@ -217,6 +310,9 @@ void mPSP2Setup(struct mGUIRunner* runner) {
if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) {
screenMode = mode;
}
+ if (mCoreConfigGetUIntValue(&runner->config, "camera", &mode)) {
+ camera.cam = mode;
+ }
}
void mPSP2LoadROM(struct mGUIRunner* runner) {
@@ -313,6 +409,19 @@ void mPSP2Unpaused(struct mGUIRunner* runner) {
if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode != screenMode) {
screenMode = mode;
}
+
+ if (mCoreConfigGetUIntValue(&runner->config, "camera", &mode)) {
+ if (mode != camera.cam) {
+ if (camera.buffer) {
+ sceCameraStop(camera.cam - 1);
+ sceCameraClose(camera.cam - 1);
+ }
+ camera.cam = mode;
+ if (camera.buffer) {
+ _resetCamera(&camera);
+ }
+ }
+ }
}
void mPSP2Teardown(struct mGUIRunner* runner) {
diff --git a/src/platform/psp2/sce-vfs.c b/src/platform/psp2/sce-vfs.c
index 4b6fdce52..284479660 100644
--- a/src/platform/psp2/sce-vfs.c
+++ b/src/platform/psp2/sce-vfs.c
@@ -120,7 +120,20 @@ static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size) {
static void _vfsceTruncate(struct VFile* vf, size_t size) {
struct VFileSce* vfsce = (struct VFileSce*) vf;
- // TODO
+ SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
+ SceOff end = sceIoLseek(vfsce->fd, 0, SEEK_END);
+ if (end < size) {
+ uint8_t buffer[2048] = {};
+ size_t write = size - end;
+ while (write >= sizeof(buffer)) {
+ sceIoWrite(vfsce->fd, buffer, sizeof(buffer));
+ write -= sizeof(buffer);
+ }
+ if (write) {
+ sceIoWrite(vfsce->fd, buffer, write);
+ }
+ } // TODO: Else
+ sceIoLseek(vfsce->fd, cur, SEEK_SET);
}
ssize_t _vfsceSize(struct VFile* vf) {
diff --git a/src/platform/python/.gitignore b/src/platform/python/.gitignore
new file mode 100644
index 000000000..c581b47ef
--- /dev/null
+++ b/src/platform/python/.gitignore
@@ -0,0 +1,5 @@
+/build
+/dist
+.eggs
+.cache
+*.egg-info*
diff --git a/src/platform/python/CMakeLists.txt b/src/platform/python/CMakeLists.txt
index 2c914eb51..a2c1a3568 100644
--- a/src/platform/python/CMakeLists.txt
+++ b/src/platform/python/CMakeLists.txt
@@ -1,4 +1,7 @@
-find_program(PYTHON python)
+find_package(PythonLibs ${USE_PYTHON_VERSION})
+find_package(PythonInterp ${USE_PYTHON_VERSION})
+list(APPEND DEPENDENCY_LIB ${PYTHON_LIBRARIES})
+include_directories(AFTER ${PYTHON_INCLUDE_DIRS})
get_property(INCLUDE_DIRECTORIES DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
set(INCLUDE_FLAGS)
@@ -6,24 +9,22 @@ foreach(DIR IN LISTS INCLUDE_DIRECTORIES)
list(APPEND INCLUDE_FLAGS "-I${DIR}")
endforeach()
-include(FindPythonLibs)
-list(APPEND DEPENDENCY_LIB ${PYTHON_LIBRARIES})
-include_directories(AFTER ${PYTHON_INCLUDE_DIRS})
-
file(GLOB PYTHON_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
+if(NOT GIT_TAG)
+ if(GIT_BRANCH STREQUAL "master" OR NOT GIT_BRANCH)
+ set(PYLIB_VERSION -b -${GIT_REV}-${GIT_COMMIT_SHORT})
+ else()
+ set(PYLIB_VERSION -b -${GIT_BRANCH}-${GIT_REV}-${GIT_COMMIT_SHORT})
+ endif()
+endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
-add_custom_command(OUTPUT build/lib/${BINARY_NAME}/__init__.py
- COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON} ${CMAKE_CURRENT_BINARY_DIR}/setup.py build --build-base ${CMAKE_CURRENT_BINARY_DIR}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- DEPENDS ${BINARY_NAME}
- DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/setup.py
- DEPENDS ${PYTHON_HEADERS}
- DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py)
-add_custom_command(OUTPUT lib.c
- COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lib.c
+ COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py
+ COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/lib.c
DEPENDS ${PYTHON_HEADERS}
+ DEPENDS ${BINARY_NAME}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/lib.c PROPERTIES GENERATED ON)
@@ -32,6 +33,29 @@ file(GLOB PYTHON_SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.c)
add_library(${BINARY_NAME}-pylib STATIC ${CMAKE_CURRENT_BINARY_DIR}/lib.c ${PYTHON_SRC})
set_target_properties(${BINARY_NAME}-pylib PROPERTIES INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR};${INCLUDE_DIRECTORIES}")
set_target_properties(${BINARY_NAME}-pylib PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
-set(PYTHON_LIBRARY ${BINARY_NAME}-pylib PARENT_SCOPE)
-add_custom_target(${BINARY_NAME}-py ALL DEPENDS ${BINARY_NAME}-pylib ${CMAKE_CURRENT_BINARY_DIR}/build/lib/${BINARY_NAME}/__init__.py)
+add_custom_target(${BINARY_NAME}-py ALL
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py egg_info -e ${CMAKE_CURRENT_BINARY_DIR} ${PYLIB_VERSION}
+ COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py build -b ${CMAKE_CURRENT_BINARY_DIR}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ DEPENDS ${BINARY_NAME}
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/setup.py
+ DEPENDS ${PYTHON_HEADERS}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py
+ DEPENDS ${BINARY_NAME}-pylib)
+
+file(GLOB BASE_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/test_*.py)
+file(GLOB SUBTESTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/*/test_*.py)
+foreach(TEST IN LISTS BASE_TESTS SUBTESTS)
+ if(APPLE)
+ set(PATH DYLD_LIBRARY_PATH)
+ elseif(WIN32)
+ set(PATH PATH)
+ else()
+ set(PATH LD_LIBRARY_PATH)
+ endif()
+ string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/(tests/.*/)?test_" "" TEST_NAME "${TEST}")
+ string(REPLACE ".py" "" TEST_NAME "${TEST_NAME}")
+ add_test(python-${TEST_NAME} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py build -b ${CMAKE_CURRENT_BINARY_DIR} pytest --extras --addopts ${TEST})
+ set_tests_properties(python-${TEST_NAME} PROPERTIES ENVIRONMENT "${PATH}=${CMAKE_CURRENT_BINARY_DIR}/..")
+endforeach()
diff --git a/src/platform/python/_builder.h b/src/platform/python/_builder.h
index 525937078..1c12bbf5c 100644
--- a/src/platform/python/_builder.h
+++ b/src/platform/python/_builder.h
@@ -7,14 +7,22 @@
#define _TIME_H_
#define ATTRIBUTE_FORMAT(X, Y, Z)
-#define DECL_BITFIELD(newtype, oldtype) typedef oldtype newtype
-#define DECL_BIT(type, name, bit)
-#define DECL_BITS(type, name, bit, nbits)
#define ATTRIBUTE_ALIGN(align)
+#define DECL_BITFIELD(newtype, oldtype) typedef oldtype newtype
+#define DECL_BIT(type, field, bit) DECL_BITS(type, field, bit, 1)
+#define DECL_BITS(TYPE, FIELD, START, SIZE) \
+ TYPE TYPE ## Is ## FIELD (TYPE); \
+ TYPE TYPE ## Get ## FIELD (TYPE); \
+ TYPE TYPE ## Clear ## FIELD (TYPE); \
+ TYPE TYPE ## Fill ## FIELD (TYPE); \
+ TYPE TYPE ## Set ## FIELD (TYPE, TYPE); \
+ TYPE TYPE ## TestFill ## FIELD (TYPE, bool);
#define CXX_GUARD_START
#define CXX_GUARD_END
+#define PYCPARSE
+
typedef int... time_t;
typedef int... off_t;
typedef ... va_list;
@@ -25,13 +33,13 @@ typedef ...* png_unknown_chunkp;
void free(void*);
#include
-#undef const
#include "flags.h"
+#include
#include
+#include
#include
-#include
#include
#include
@@ -49,13 +57,13 @@ void free(void*);
#include
#include
#include
-#include
+#include
#endif
#ifdef M_CORE_GB
#include
#include
#include
-#include
+#include
#endif
#ifdef M_CORE_DS
#include
diff --git a/src/platform/python/_builder.py b/src/platform/python/_builder.py
index e16903a40..2d44e3769 100644
--- a/src/platform/python/_builder.py
+++ b/src/platform/python/_builder.py
@@ -17,14 +17,17 @@ if __name__ == "__main__":
cppflags.extend(["-I" + incdir, "-I" + srcdir, "-I" + bindir])
ffi.set_source("mgba._pylib", """
+#define static
+#define inline
#include "flags.h"
#define OPAQUE_THREADING
+#include
#include
#include
+#include
#include
#include
#include
-#include
#include
#include
#include
@@ -33,10 +36,10 @@ ffi.set_source("mgba._pylib", """
#include
#include
#include
-#include
+#include
#include
#include
-#include
+#include
#include
#include
@@ -73,6 +76,11 @@ for line in preprocessed.splitlines():
ffi.embedding_api('\n'.join(lines))
ffi.embedding_init_code("""
+ import os, os.path
+ venv = os.getenv('VIRTUAL_ENV')
+ if venv:
+ activate = os.path.join(venv, 'bin', 'activate_this.py')
+ exec(compile(open(activate, "rb").read(), activate, 'exec'), dict(__file__=activate))
from mgba._pylib import ffi, lib
symbols = {}
globalSyms = {
diff --git a/src/platform/python/cinema/__init__.py b/src/platform/python/cinema/__init__.py
new file mode 100644
index 000000000..288aa3f0c
--- /dev/null
+++ b/src/platform/python/cinema/__init__.py
@@ -0,0 +1,23 @@
+from PIL.ImageChops import difference
+from PIL.ImageOps import autocontrast
+from PIL.Image import open as PIOpen
+
+class VideoFrame(object):
+ def __init__(self, pilImage):
+ self.image = pilImage.convert('RGB')
+
+ @staticmethod
+ def diff(a, b):
+ diff = difference(a.image, b.image)
+ diffNormalized = autocontrast(diff)
+ return (VideoFrame(diff), VideoFrame(diffNormalized))
+
+ @staticmethod
+ def load(path):
+ with open(path, 'rb') as f:
+ image = PIOpen(f)
+ image.load()
+ return VideoFrame(image)
+
+ def save(self, path):
+ return self.image.save(path)
diff --git a/src/platform/python/cinema/movie.py b/src/platform/python/cinema/movie.py
new file mode 100644
index 000000000..c71002626
--- /dev/null
+++ b/src/platform/python/cinema/movie.py
@@ -0,0 +1,47 @@
+from mgba.image import Image
+from collections import namedtuple
+from . import VideoFrame
+
+Output = namedtuple('Output', ['video'])
+
+class Tracer(object):
+ def __init__(self, core):
+ self.core = core
+ self.fb = Image(*core.desiredVideoDimensions())
+ self.core.setVideoBuffer(self.fb)
+ self._videoFifo = []
+
+ def yieldFrames(self, skip=0, limit=None):
+ self.core.reset()
+ skip = (skip or 0) + 1
+ while skip > 0:
+ frame = self.core.frameCounter
+ self.core.runFrame()
+ skip -= 1
+ while frame <= self.core.frameCounter and limit != 0:
+ self._videoFifo.append(VideoFrame(self.fb.toPIL()))
+ yield frame
+ frame = self.core.frameCounter
+ self.core.runFrame()
+ if limit is not None:
+ assert limit >= 0
+ limit -= 1
+
+ def video(self, generator=None, **kwargs):
+ if not generator:
+ generator = self.yieldFrames(**kwargs)
+ try:
+ while True:
+ if self._videoFifo:
+ result = self._videoFifo[0]
+ self._videoFifo = self._videoFifo[1:]
+ yield result
+ else:
+ next(generator)
+ except StopIteration:
+ return
+
+ def output(self, **kwargs):
+ generator = self.yieldFrames(**kwargs)
+
+ return mCoreOutput(video=self.video(generator=generator, **kwargs))
diff --git a/src/platform/python/cinema/test.py b/src/platform/python/cinema/test.py
new file mode 100644
index 000000000..833d493ed
--- /dev/null
+++ b/src/platform/python/cinema/test.py
@@ -0,0 +1,96 @@
+import os, os.path
+import mgba.core, mgba.image
+import cinema.movie
+import itertools
+import glob
+import re
+import yaml
+from copy import deepcopy
+from cinema import VideoFrame
+from cinema.util import dictMerge
+
+class CinemaTest(object):
+ TEST = 'test.(mvl|gb|gba|nds)'
+
+ def __init__(self, path, root, settings={}):
+ self.fullPath = path or []
+ self.path = os.path.abspath(os.path.join(root, *self.fullPath))
+ self.root = root
+ self.name = '.'.join(path)
+ self.settings = settings
+ try:
+ with open(os.path.join(self.path, 'manifest.yml'), 'r') as f:
+ dictMerge(self.settings, yaml.safe_load(f))
+ except IOError:
+ pass
+ self.tests = {}
+
+ def __repr__(self):
+ return '<%s %s>' % (self.__class__.__name__, self.name)
+
+ def setUp(self):
+ results = [f for f in glob.glob(os.path.join(self.path, 'test.*')) if re.search(self.TEST, f)]
+ self.core = mgba.core.loadPath(results[0])
+ if 'config' in self.settings:
+ self.config = mgba.core.Config(defaults=self.settings['config'])
+ self.core.loadConfig(self.config)
+ self.core.reset()
+
+ def addTest(self, name, cls=None, settings={}):
+ cls = cls or self.__class__
+ newSettings = deepcopy(self.settings)
+ dictMerge(newSettings, settings)
+ self.tests[name] = cls(self.fullPath + [name], self.root, newSettings)
+ return self.tests[name]
+
+ def outputSettings(self):
+ outputSettings = {}
+ if 'frames' in self.settings:
+ outputSettings['limit'] = self.settings['frames']
+ if 'skip' in self.settings:
+ outputSettings['skip'] = self.settings['skip']
+ return outputSettings
+
+ def __lt__(self, other):
+ return self.path < other.path
+
+class VideoTest(CinemaTest):
+ BASELINE = 'baseline_%04u.png'
+
+ def setUp(self):
+ super(VideoTest, self).setUp();
+ self.tracer = cinema.movie.Tracer(self.core)
+
+ def generateFrames(self):
+ for i, frame in zip(itertools.count(), self.tracer.video(**self.outputSettings())):
+ try:
+ baseline = VideoFrame.load(os.path.join(self.path, self.BASELINE % i))
+ yield baseline, frame, VideoFrame.diff(baseline, frame)
+ except IOError:
+ yield None, frame, (None, None)
+
+ def test(self):
+ self.baseline, self.frames, self.diffs = zip(*self.generateFrames())
+ assert not any(any(diffs[0].image.convert("L").point(bool).getdata()) for diffs in self.diffs)
+
+ def generateBaseline(self):
+ for i, frame in zip(itertools.count(), self.tracer.video(**self.outputSettings())):
+ frame.save(os.path.join(self.path, self.BASELINE % i))
+
+def gatherTests(root=os.getcwd()):
+ tests = CinemaTest([], root)
+ for path, _, files in os.walk(root):
+ test = [f for f in files if re.match(CinemaTest.TEST, f)]
+ if not test:
+ continue
+ prefix = os.path.commonprefix([path, root])
+ suffix = path[len(prefix)+1:]
+ testPath = suffix.split(os.sep)
+ testRoot = tests
+ for component in testPath[:-1]:
+ newTest = testRoot.tests.get(component)
+ if not newTest:
+ newTest = testRoot.addTest(component)
+ testRoot = newTest
+ testRoot.addTest(testPath[-1], VideoTest)
+ return tests
diff --git a/src/platform/python/cinema/util.py b/src/platform/python/cinema/util.py
new file mode 100644
index 000000000..3a8dccd40
--- /dev/null
+++ b/src/platform/python/cinema/util.py
@@ -0,0 +1,9 @@
+def dictMerge(a, b):
+ for key, value in b.items():
+ if isinstance(value, dict):
+ if key in a:
+ dictMerge(a[key], value)
+ else:
+ a[key] = dict(value)
+ else:
+ a[key] = value
diff --git a/src/platform/python/conftest.py b/src/platform/python/conftest.py
new file mode 100644
index 000000000..6690268a1
--- /dev/null
+++ b/src/platform/python/conftest.py
@@ -0,0 +1,49 @@
+import errno
+import itertools
+import os
+import os.path
+import pytest
+import yaml
+
+def pytest_addoption(parser):
+ parser.addoption("--rebaseline", action="store_true", help="output a new baseline instead of testing")
+ parser.addoption("--mark-failing", action="store_true", help="mark all failing tests as failing")
+ parser.addoption("--mark-succeeding", action="store_true", help="unmark all succeeding tests marked as failing")
+ parser.addoption("--output-diff", help="output diffs for failed tests to directory")
+
+EXPECTED = 'expected_%04u.png'
+RESULT = 'result_%04u.png'
+DIFF = 'diff_%04u.png'
+DIFF_NORM = 'diff_norm_%04u.png'
+
+def pytest_exception_interact(node, call, report):
+ outroot = node.config.getoption("--output-diff")
+ if report.failed and hasattr(node, 'funcargs'):
+ vtest = node.funcargs.get('vtest')
+ if outroot:
+ if not vtest:
+ return
+ outdir = os.path.join(outroot, *vtest.fullPath)
+ try:
+ os.makedirs(outdir)
+ except OSError as e:
+ if e.errno == errno.EEXIST and os.path.isdir(outdir):
+ pass
+ else:
+ raise
+ for i, expected, result, diff, diffNorm in zip(itertools.count(), vtest.baseline, vtest.frames, *zip(*vtest.diffs)):
+ result.save(os.path.join(outdir, RESULT % i))
+ if expected:
+ expected.save(os.path.join(outdir, EXPECTED % i))
+ diff.save(os.path.join(outdir, DIFF % i))
+ diffNorm.save(os.path.join(outdir, DIFF_NORM % i))
+
+ if node.config.getoption("--mark-failing"):
+ try:
+ with open(os.path.join(vtest.path, 'manifest.yml'), 'r') as f:
+ settings = yaml.safe_load(f)
+ except IOError:
+ settings = {}
+ settings['fail'] = True
+ with open(os.path.join(vtest.path, 'manifest.yml'), 'w') as f:
+ yaml.dump(settings, f, default_flow_style=False)
diff --git a/src/platform/python/engine.c b/src/platform/python/engine.c
index 19fe76c0c..6222039a0 100644
--- a/src/platform/python/engine.c
+++ b/src/platform/python/engine.c
@@ -105,6 +105,7 @@ void mPythonScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryR
return;
}
+ mPythonSetDebugger(debugger);
mPythonDebuggerEntered(reason, info);
}
#endif
diff --git a/src/platform/python/mgba/core.py b/src/platform/python/mgba/core.py
index b2272a4dd..1b9b0c113 100644
--- a/src/platform/python/mgba/core.py
+++ b/src/platform/python/mgba/core.py
@@ -106,10 +106,32 @@ class Core(object):
self._protected = False
self._callbacks = CoreCallbacks()
self._core.addCoreCallbacks(self._core, self._callbacks.context)
+ self.config = Config(ffi.addressof(native.config))
+
+ def __del__(self):
+ self._wasReset = False
+
+ @cached_property
+ def graphicsCache(self):
+ if not self._wasReset:
+ raise RuntimeError("Core must be reset first")
+ return tile.CacheSet(self)
@cached_property
def tiles(self):
- return tile.TileView(self)
+ t = []
+ ts = ffi.addressof(self.graphicsCache.cache.tiles)
+ for i in range(lib.mTileCacheSetSize(ts)):
+ t.append(tile.TileView(lib.mTileCacheSetGetPointer(ts, i)))
+ return t
+
+ @cached_property
+ def maps(self):
+ m = []
+ ms = ffi.addressof(self.graphicsCache.cache.maps)
+ for i in range(lib.mMapCacheSetSize(ms)):
+ m.append(tile.MapView(lib.mMapCacheSetGetPointer(ms, i)))
+ return m
@classmethod
def _init(cls, native):
@@ -154,6 +176,9 @@ class Core(object):
def loadPatch(self, vf):
return bool(self._core.loadPatch(self._core, vf.handle))
+ def loadConfig(self, config):
+ lib.mCoreLoadForeignConfig(self._core, config._native)
+
def autoloadSave(self):
return bool(lib.mCoreAutoloadSave(self._core))
@@ -267,3 +292,28 @@ class IRunner(object):
def isPaused(self):
raise NotImplementedError
+
+class Config(object):
+ def __init__(self, native=None, port=None, defaults={}):
+ if not native:
+ self._port = ffi.NULL
+ if port:
+ self._port = ffi.new("char[]", port.encode("UTF-8"))
+ native = ffi.gc(ffi.new("struct mCoreConfig*"), lib.mCoreConfigDeinit)
+ lib.mCoreConfigInit(native, self._port)
+ self._native = native
+ for key, value in defaults.items():
+ if isinstance(value, bool):
+ value = int(value)
+ lib.mCoreConfigSetDefaultValue(self._native, ffi.new("char[]", key.encode("UTF-8")), ffi.new("char[]", str(value).encode("UTF-8")))
+
+ def __getitem__(self, key):
+ string = lib.mCoreConfigGetValue(self._native, ffi.new("char[]", key.encode("UTF-8")))
+ if not string:
+ return None
+ return ffi.string(string)
+
+ def __setitem__(self, key, value):
+ if isinstance(value, bool):
+ value = int(value)
+ lib.mCoreConfigSetValue(self._native, ffi.new("char[]", key.encode("UTF-8")), ffi.new("char[]", str(value).encode("UTF-8")))
diff --git a/src/platform/python/mgba/gb.py b/src/platform/python/mgba/gb.py
index fdf7f78bd..f70f9173f 100644
--- a/src/platform/python/mgba/gb.py
+++ b/src/platform/python/mgba/gb.py
@@ -27,13 +27,14 @@ class GB(Core):
self.cpu = LR35902Core(self._core.cpu)
@needsReset
- def _initTileCache(self, cache):
- lib.GBVideoTileCacheInit(cache)
- lib.GBVideoTileCacheAssociate(cache, ffi.addressof(self._native.video))
+ def _initCache(self, cache):
+ lib.GBVideoCacheInit(cache)
+ lib.GBVideoCacheAssociate(cache, ffi.addressof(self._native.video))
- def _deinitTileCache(self, cache):
- self._native.video.renderer.cache = ffi.NULL
- lib.mTileCacheDeinit(cache)
+ def _deinitCache(self, cache):
+ lib.mCacheSetDeinit(cache)
+ if self._wasReset:
+ self._native.video.renderer.cache = ffi.NULL
def reset(self):
super(GB, self).reset()
@@ -135,6 +136,7 @@ class GBSprite(Sprite):
self.paletteId = self._attr & 7
else:
self.paletteId = (self._attr >> 4) & 1
+ self.paletteId += 8
class GBObjs:
@@ -149,5 +151,5 @@ class GBObjs:
if index >= len(self):
raise IndexError()
sprite = GBSprite(self._obj[index], self._core)
- sprite.constitute(self._core.tiles, 0, 0)
+ sprite.constitute(self._core.tiles[0], 0)
return sprite
diff --git a/src/platform/python/mgba/gba.py b/src/platform/python/mgba/gba.py
index 5ba050748..bbe544683 100644
--- a/src/platform/python/mgba/gba.py
+++ b/src/platform/python/mgba/gba.py
@@ -35,13 +35,14 @@ class GBA(Core):
self.cpu = ARMCore(self._core.cpu)
@needsReset
- def _initTileCache(self, cache):
- lib.GBAVideoTileCacheInit(cache)
- lib.GBAVideoTileCacheAssociate(cache, ffi.addressof(self._native.video))
+ def _initCache(self, cache):
+ lib.GBAVideoCacheInit(cache)
+ lib.GBAVideoCacheAssociate(cache, ffi.addressof(self._native.video))
- def _deinitTileCache(self, cache):
- self._native.video.renderer.cache = ffi.NULL
- lib.mTileCacheDeinit(cache)
+ def _deinitCache(self, cache):
+ lib.mCacheSetDeinit(cache)
+ if self._wasReset:
+ self._native.video.renderer.cache = ffi.NULL
def reset(self):
super(GBA, self).reset()
@@ -127,6 +128,7 @@ class GBAObjs:
if index >= len(self):
raise IndexError()
sprite = GBASprite(self._obj[index])
+ tiles = self._core.tiles[3 if sprite._256Color else 2]
map1D = bool(self._core._native.memory.io[0] & 0x40)
- sprite.constitute(self._core.tiles, 0 if map1D else 0x20, int(sprite._256Color))
+ sprite.constitute(tiles, 0 if map1D else 0x20)
return sprite
diff --git a/src/platform/python/mgba/image.py b/src/platform/python/mgba/image.py
index 948edeeb4..ac6407012 100644
--- a/src/platform/python/mgba/image.py
+++ b/src/platform/python/mgba/image.py
@@ -12,10 +12,11 @@ except ImportError:
pass
class Image:
- def __init__(self, width, height, stride=0):
+ def __init__(self, width, height, stride=0, alpha=False):
self.width = width
self.height = height
self.stride = stride
+ self.alpha = alpha
self.constitute()
def constitute(self):
@@ -24,7 +25,7 @@ class Image:
self.buffer = ffi.new("color_t[{}]".format(self.stride * self.height))
def savePNG(self, f):
- p = png.PNG(f)
+ p = png.PNG(f, mode=png.MODE_RGBA if self.alpha else png.MODE_RGB)
success = p.writeHeader(self)
success = success and p.writePixels(self)
p.writeClose()
@@ -32,8 +33,9 @@ class Image:
if 'PImage' in globals():
def toPIL(self):
- return PImage.frombytes("RGBX", (self.width, self.height), ffi.buffer(self.buffer), "raw",
- "RGBX", self.stride * 4)
+ type = "RGBA" if self.alpha else "RGBX"
+ return PImage.frombytes(type, (self.width, self.height), ffi.buffer(self.buffer), "raw",
+ type, self.stride * 4)
def u16ToU32(c):
r = c & 0x1F
diff --git a/src/platform/python/mgba/png.py b/src/platform/python/mgba/png.py
index bc1ff836c..e4156f13b 100644
--- a/src/platform/python/mgba/png.py
+++ b/src/platform/python/mgba/png.py
@@ -6,17 +6,32 @@
from ._pylib import ffi, lib
from . import vfs
+MODE_RGB = 0
+MODE_RGBA = 1
+MODE_INDEX = 2
+
class PNG:
- def __init__(self, f):
+ def __init__(self, f, mode=MODE_RGB):
self.vf = vfs.open(f)
+ self.mode = mode
def writeHeader(self, image):
self._png = lib.PNGWriteOpen(self.vf.handle)
- self._info = lib.PNGWriteHeader(self._png, image.width, image.height)
+ if self.mode == MODE_RGB:
+ self._info = lib.PNGWriteHeader(self._png, image.width, image.height)
+ if self.mode == MODE_RGBA:
+ self._info = lib.PNGWriteHeaderA(self._png, image.width, image.height)
+ if self.mode == MODE_INDEX:
+ self._info = lib.PNGWriteHeader8(self._png, image.width, image.height)
return self._info != ffi.NULL
def writePixels(self, image):
- return lib.PNGWritePixels(self._png, image.width, image.height, image.stride, image.buffer)
+ if self.mode == MODE_RGB:
+ return lib.PNGWritePixels(self._png, image.width, image.height, image.stride, image.buffer)
+ if self.mode == MODE_RGBA:
+ return lib.PNGWritePixelsA(self._png, image.width, image.height, image.stride, image.buffer)
+ if self.mode == MODE_INDEX:
+ return lib.PNGWritePixels8(self._png, image.width, image.height, image.stride, image.buffer)
def writeClose(self):
lib.PNGWriteClose(self._png, self._info)
diff --git a/src/platform/python/mgba/tile.py b/src/platform/python/mgba/tile.py
index 4d89f8869..3dbc060ad 100644
--- a/src/platform/python/mgba/tile.py
+++ b/src/platform/python/mgba/tile.py
@@ -17,41 +17,52 @@ class Tile:
def composite(self, i, x, y):
for iy in range(8):
- for ix in range(8):
- i.buffer[ix + x + (iy + y) * i.stride] = image.u16ToColor(self.buffer[ix + iy * 8])
+ ffi.memmove(ffi.addressof(i.buffer, x + (iy + y) * i.stride), ffi.addressof(self.buffer, iy * 8), 8 * ffi.sizeof("color_t"))
-class TileView:
+class CacheSet:
def __init__(self, core):
self.core = core
- self.cache = ffi.gc(ffi.new("struct mTileCache*"), core._deinitTileCache)
- core._initTileCache(self.cache)
- lib.mTileCacheSetPalette(self.cache, 0)
- self.paletteSet = 0
+ self.cache = ffi.gc(ffi.new("struct mCacheSet*"), core._deinitCache)
+ core._initCache(self.cache)
+
+class TileView:
+ def __init__(self, cache):
+ self.cache = cache
def getTile(self, tile, palette):
return Tile(lib.mTileCacheGetTile(self.cache, tile, palette))
- def setPalette(self, paletteSet):
- if paletteSet > 1 or paletteSet < 0:
- raise IndexError("Palette Set ID out of bounds")
- lib.mTileCacheSetPalette(self.cache, paletteSet)
- self.paletteSet = paletteSet
+class MapView:
+ def __init__(self, cache):
+ self.cache = cache
+
+ @property
+ def width(self):
+ return 1 << lib.mMapCacheSystemInfoGetTilesWide(self.cache.sysConfig)
+
+ @property
+ def height(self):
+ return 1 << lib.mMapCacheSystemInfoGetTilesHigh(self.cache.sysConfig)
+
+ @property
+ def image(self):
+ i = image.Image(self.width * 8, self.height * 8, alpha=True)
+ for y in range(self.height * 8):
+ 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"))
+ return i
class Sprite(object):
- TILE_BASE = 0, 0
- PALETTE_BASE = 0, 0
-
- def constitute(self, tileView, tilePitch, paletteSet):
- oldPaletteSet = tileView.paletteSet
- tileView.setPalette(paletteSet)
- i = image.Image(self.width, self.height)
- tileId = self.tile + self.TILE_BASE[paletteSet]
+ def constitute(self, tileView, tilePitch):
+ i = image.Image(self.width, self.height, alpha=True)
+ tileId = self.tile
for y in range(self.height // 8):
for x in range(self.width // 8):
- tile = tileView.getTile(tileId, self.paletteId + self.PALETTE_BASE[paletteSet])
+ tile = tileView.getTile(tileId, self.paletteId)
tile.composite(i, x * 8, y * 8)
tileId += 1
if tilePitch:
tileId += tilePitch - self.width // 8
self.image = i
- tileView.setPalette(oldPaletteSet)
diff --git a/src/platform/python/mgba/vfs.py b/src/platform/python/mgba/vfs.py
index 48d1e6794..dbb65b4f0 100644
--- a/src/platform/python/mgba/vfs.py
+++ b/src/platform/python/mgba/vfs.py
@@ -11,6 +11,7 @@ import os
def _vfpClose(vf):
vfp = ffi.cast("struct VFilePy*", vf)
ffi.from_handle(vfp.fileobj).close()
+ return True
@ffi.def_extern()
def _vfpSeek(vf, offset, whence):
@@ -93,14 +94,17 @@ def openPath(path, mode="r"):
if "x" in mode[1:]:
flags |= os.O_EXCL
- return VFile(lib.VFileOpen(path.encode("UTF-8"), flags))
+ vf = lib.VFileOpen(path.encode("UTF-8"), flags);
+ if vf == ffi.NULL:
+ return None
+ return VFile(vf)
class VFile:
def __init__(self, vf):
self.handle = vf
def close(self):
- return self.handle.close(self.handle)
+ return bool(self.handle.close(self.handle))
def seek(self, offset, whence):
return self.handle.seek(self.handle, offset, whence)
diff --git a/src/platform/python/setup.cfg b/src/platform/python/setup.cfg
new file mode 100644
index 000000000..b7e478982
--- /dev/null
+++ b/src/platform/python/setup.cfg
@@ -0,0 +1,2 @@
+[aliases]
+test=pytest
diff --git a/src/platform/python/setup.py.in b/src/platform/python/setup.py.in
index 04c1c0c29..040be3fdc 100644
--- a/src/platform/python/setup.py.in
+++ b/src/platform/python/setup.py.in
@@ -1,6 +1,7 @@
from setuptools import setup
import re
import os
+import sys
os.environ["BINDIR"] = "${CMAKE_BINARY_DIR}"
os.environ["CPPFLAGS"] = " ".join([d for d in "${INCLUDE_FLAGS}".split(";") if d])
@@ -16,14 +17,15 @@ classifiers = [
]
setup(name="${BINARY_NAME}",
- version=re.sub("/", "-", "${VERSION_STRING}"),
+ version="${LIB_VERSION_STRING}",
author="Jeffrey Pfau",
author_email="jeffrey@endrift.com",
url="http://github.com/mgba-emu/mgba/",
packages=["mgba"],
- setup_requires=['cffi>=1.6'],
+ setup_requires=['cffi>=1.6', 'pytest-runner'],
install_requires=['cffi>=1.6', 'cached-property'],
- extras_require={'pil': ['Pillow>=2.3']},
+ extras_require={'pil': ['Pillow>=2.3'], 'cinema': ['pyyaml', 'pytest']},
+ tests_require=['pytest'],
cffi_modules=["_builder.py:ffi"],
license="MPL 2.0",
classifiers=classifiers
diff --git a/src/platform/python/test_cinema.py b/src/platform/python/test_cinema.py
new file mode 100644
index 000000000..61c27bf7d
--- /dev/null
+++ b/src/platform/python/test_cinema.py
@@ -0,0 +1,61 @@
+import pytest
+import cinema.test
+import mgba.log
+import os.path
+import yaml
+
+mgba.log.installDefault(mgba.log.NullLogger())
+
+def flatten(d):
+ l = []
+ for k, v in d.tests.items():
+ if v.tests:
+ l.extend(flatten(v))
+ else:
+ l.append(v)
+ l.sort()
+ return l
+
+def pytest_generate_tests(metafunc):
+ if 'vtest' in metafunc.fixturenames:
+ tests = cinema.test.gatherTests(os.path.join(os.path.dirname(__file__), 'tests/cinema'))
+ testList = flatten(tests)
+ params = []
+ for test in testList:
+ marks = []
+ xfail = test.settings.get('fail')
+ if xfail:
+ marks = pytest.mark.xfail(reason=xfail if isinstance(xfail, str) else None)
+ params.append(pytest.param(test, id=test.name, marks=marks))
+ metafunc.parametrize('vtest', params, indirect=True)
+
+@pytest.fixture
+def vtest(request):
+ return request.param
+
+def test_video(vtest, pytestconfig):
+ vtest.setUp()
+ if pytestconfig.getoption('--rebaseline'):
+ vtest.generateBaseline()
+ else:
+ try:
+ vtest.test()
+ except IOError:
+ raise
+ if pytestconfig.getoption('--mark-succeeding') and 'fail' in vtest.settings:
+ # TODO: This can fail if an entire directory is marked as failing
+ settings = {}
+ try:
+ with open(os.path.join(vtest.path, 'manifest.yml'), 'r') as f:
+ settings = yaml.safe_load(f)
+ except IOError:
+ pass
+ if 'fail' in settings:
+ del settings['fail']
+ else:
+ settings['fail'] = False
+ if settings:
+ with open(os.path.join(vtest.path, 'manifest.yml'), 'w') as f:
+ yaml.dump(settings, f, default_flow_style=False)
+ else:
+ os.remove(os.path.join(vtest.path, 'manifest.yml'))
diff --git a/src/platform/python/tests/__init__.py b/src/platform/python/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/platform/python/tests/cinema/.gitignore b/src/platform/python/tests/cinema/.gitignore
new file mode 100644
index 000000000..ba0080f32
--- /dev/null
+++ b/src/platform/python/tests/cinema/.gitignore
@@ -0,0 +1 @@
+*.sav
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/LICENSE b/src/platform/python/tests/cinema/gb/mooneye-gb/LICENSE
new file mode 100644
index 000000000..2d7ffa2ea
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014-2017 Joonas Javanainen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/baseline_0000.png
new file mode 100644
index 000000000..ff29c9a76
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.gb
new file mode 100644
index 000000000..afb22740c
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.sym
new file mode 100644
index 000000000..71a70bfcd
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.sym
@@ -0,0 +1,206 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/add_sp_e_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 _wait_ly_4
+00:0156 _wait_ly_5
+00:0180 test_finish
+00:01c4 wram_test
+00:01d3 hiram_test
+00:01d3 test_round1
+00:01d5 _wait_ly_6
+00:01db _wait_ly_7
+00:01f0 finish_round1
+00:01ff test_round2
+00:0201 _wait_ly_8
+00:0207 _wait_ly_9
+00:021d finish_round2
+00:c014 result_tmp
+00:c016 result_round1
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.gb
new file mode 100644
index 000000000..9ad322193
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.sym
new file mode 100644
index 000000000..9cc9099d8
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.sym
@@ -0,0 +1,212 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/bits/mem_oam.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:016f test_finish
+00:0183 _wait_ly_4
+00:0189 _wait_ly_5
+00:019f _print_results_halt_1
+00:01a2 _test_ok_cb_0
+00:01aa _print_sl_data55
+00:01b2 _print_sl_out55
+00:01b5 fail_1
+00:01c9 _wait_ly_6
+00:01cf _wait_ly_7
+00:01e5 _print_results_halt_2
+00:01e8 _test_failure_cb_0
+00:01f0 _print_sl_data56
+00:01fd _print_sl_out56
+00:0200 fail_0
+00:0214 _wait_ly_8
+00:021a _wait_ly_9
+00:0230 _print_results_halt_3
+00:0233 _test_failure_cb_1
+00:023b _print_sl_data57
+00:0248 _print_sl_out57
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/reg_f/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/reg_f/baseline_0000.png
new file mode 100644
index 000000000..34b4c1a3f
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/reg_f/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.gb
new file mode 100644
index 000000000..4326468fe
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.sym
new file mode 100644
index 000000000..01b7077fc
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/bits/reg_f.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0160 test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.gb
new file mode 100644
index 000000000..70c39674c
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.sym
new file mode 100644
index 000000000..8407e6a43
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.sym
@@ -0,0 +1,535 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/bits/unused_hwio-GS.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c017 regs_save
+00:c017 regs_save.f
+00:c018 regs_save.a
+00:c019 regs_save.c
+00:c01a regs_save.b
+00:c01b regs_save.e
+00:c01c regs_save.d
+00:c01d regs_save.l
+00:c01e regs_save.h
+00:c01f regs_flags
+00:c020 regs_assert
+00:c020 regs_assert.f
+00:c021 regs_assert.a
+00:c022 regs_assert.c
+00:c023 regs_assert.b
+00:c024 regs_assert.e
+00:c025 regs_assert.d
+00:c026 regs_assert.l
+00:c027 regs_assert.h
+00:c028 memdump_len
+00:c029 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0161 _test_data_0
+00:0177 _finish_0
+00:0187 _test_data_1
+00:019d _finish_1
+00:01ad _test_data_2
+00:01c3 _finish_2
+00:01d3 _test_data_3
+00:01e9 _finish_3
+00:01f9 _test_data_4
+00:020f _finish_4
+00:021f _test_data_5
+00:0235 _finish_5
+00:0245 _test_data_6
+00:025b _finish_6
+00:026b _test_data_7
+00:0281 _finish_7
+00:0291 _test_data_8
+00:02a7 _finish_8
+00:02b7 _test_data_9
+00:02cd _finish_9
+00:02dd _test_data_10
+00:02f3 _finish_10
+00:0303 _test_data_11
+00:0319 _finish_11
+00:0329 _test_data_12
+00:033f _finish_12
+00:034f _test_data_13
+00:0365 _finish_13
+00:0375 _test_data_14
+00:038b _finish_14
+00:039b _test_data_15
+00:03b1 _finish_15
+00:03c1 _test_data_16
+00:03d7 _finish_16
+00:03e7 _test_data_17
+00:03fd _finish_17
+00:040d _test_data_18
+00:0423 _finish_18
+00:0433 _test_data_19
+00:0449 _finish_19
+00:0459 _test_data_20
+00:046f _finish_20
+00:047f _test_data_21
+00:0495 _finish_21
+00:04a5 _test_data_22
+00:04bb _finish_22
+00:04cb _test_data_23
+00:04e1 _finish_23
+00:04f1 _test_data_24
+00:0507 _finish_24
+00:0517 _test_data_25
+00:052d _finish_25
+00:053d _test_data_26
+00:0553 _finish_26
+00:0563 _test_data_27
+00:0579 _finish_27
+00:0589 _test_data_28
+00:059f _finish_28
+00:05af _test_data_29
+00:05c5 _finish_29
+00:05d5 _test_data_30
+00:05eb _finish_30
+00:05fb _test_data_31
+00:0611 _finish_31
+00:0621 _test_data_32
+00:0637 _finish_32
+00:0647 _test_data_33
+00:065d _finish_33
+00:066d _test_data_34
+00:0683 _finish_34
+00:0693 _test_data_35
+00:06a9 _finish_35
+00:06b9 _test_data_36
+00:06cf _finish_36
+00:06df _test_data_37
+00:06f5 _finish_37
+00:0705 _test_data_38
+00:071b _finish_38
+00:072b _test_data_39
+00:0741 _finish_39
+00:0751 _test_data_40
+00:0767 _finish_40
+00:0777 _test_data_41
+00:078d _finish_41
+00:079d _test_data_42
+00:07b3 _finish_42
+00:07c3 _test_data_43
+00:07d9 _finish_43
+00:07e9 _test_data_44
+00:07ff _finish_44
+00:080f _test_data_45
+00:0825 _finish_45
+00:0835 _test_data_46
+00:084b _finish_46
+00:085b _test_data_47
+00:0871 _finish_47
+00:0881 _test_data_48
+00:0897 _finish_48
+00:08a7 _test_data_49
+00:08bd _finish_49
+00:08cd _test_data_50
+00:08e3 _finish_50
+00:08f3 _test_data_51
+00:0909 _finish_51
+00:0919 _test_data_52
+00:092f _finish_52
+00:093f _test_data_53
+00:0955 _finish_53
+00:0965 _test_data_54
+00:097b _finish_54
+00:098b _test_data_55
+00:09a1 _finish_55
+00:09b1 _test_data_56
+00:09c7 _finish_56
+00:09d7 _test_data_57
+00:09ed _finish_57
+00:09fd _test_data_58
+00:0a13 _finish_58
+00:0a23 _test_data_59
+00:0a39 _finish_59
+00:0a49 _test_data_60
+00:0a5f _finish_60
+00:0a6f _test_data_61
+00:0a85 _finish_61
+00:0a95 _test_data_62
+00:0aab _finish_62
+00:0abb _test_data_63
+00:0ad1 _finish_63
+00:0ae1 _test_data_64
+00:0af7 _finish_64
+00:0b07 _test_data_65
+00:0b1d _finish_65
+00:0b2d _test_data_66
+00:0b43 _finish_66
+00:0b53 _test_data_67
+00:0b69 _finish_67
+00:0b79 _test_data_68
+00:0b8f _finish_68
+00:0b9f _test_data_69
+00:0bb5 _finish_69
+00:0bc5 _test_data_70
+00:0bdb _finish_70
+00:0beb _test_data_71
+00:0c01 _finish_71
+00:0c11 _test_data_72
+00:0c27 _finish_72
+00:0c37 _test_data_73
+00:0c4d _finish_73
+00:0c5d _test_data_74
+00:0c73 _finish_74
+00:0c83 _test_data_75
+00:0c99 _finish_75
+00:0ca9 _test_data_76
+00:0cbf _finish_76
+00:0ccf _test_data_77
+00:0ce5 _finish_77
+00:0cf5 _test_data_78
+00:0d0b _finish_78
+00:0d1b _test_data_79
+00:0d31 _finish_79
+00:0d41 _test_data_80
+00:0d57 _finish_80
+00:0d67 _test_data_81
+00:0d7d _finish_81
+00:0d8d _test_data_82
+00:0da3 _finish_82
+00:0db3 _test_data_83
+00:0dc9 _finish_83
+00:0dd9 _test_data_84
+00:0def _finish_84
+00:0dff _test_data_85
+00:0e15 _finish_85
+00:0e25 _test_data_86
+00:0e3b _finish_86
+00:0e4b _test_data_87
+00:0e61 _finish_87
+00:0e71 _test_data_88
+00:0e87 _finish_88
+00:0e97 _test_data_89
+00:0ead _finish_89
+00:0ebd _test_data_90
+00:0ed3 _finish_90
+00:0ee3 _test_data_91
+00:0ef9 _finish_91
+00:0f09 _test_data_92
+00:0f1f _finish_92
+00:0f2f _test_data_93
+00:0f45 _finish_93
+00:0f55 _test_data_94
+00:0f6b _finish_94
+00:0f7b _test_data_95
+00:0f91 _finish_95
+00:0fa1 _test_data_96
+00:0fb7 _finish_96
+00:0fc7 _test_data_97
+00:0fdd _finish_97
+00:0fed _test_data_98
+00:1003 _finish_98
+00:1013 _test_data_99
+00:1029 _finish_99
+00:1039 _test_data_100
+00:104f _finish_100
+00:105f _test_data_101
+00:1075 _finish_101
+00:1085 _test_data_102
+00:109b _finish_102
+00:10ab _test_data_103
+00:10c1 _finish_103
+00:10d1 _test_data_104
+00:10e7 _finish_104
+00:10f7 _test_data_105
+00:110d _finish_105
+00:111d _test_data_106
+00:1133 _finish_106
+00:1143 _test_data_107
+00:1159 _finish_107
+00:1169 _test_data_108
+00:117f _finish_108
+00:118f _test_data_109
+00:11a5 _finish_109
+00:11b5 _test_data_110
+00:11cb _finish_110
+00:11db _test_data_111
+00:11f1 _finish_111
+00:1201 _test_data_112
+00:1217 _finish_112
+00:1227 _test_data_113
+00:123d _finish_113
+00:124d _test_data_114
+00:1263 _finish_114
+00:1273 _test_data_115
+00:1289 _finish_115
+00:1299 _test_data_116
+00:12af _finish_116
+00:12bf _test_data_117
+00:12d5 _finish_117
+00:12e5 _test_data_118
+00:12fb _finish_118
+00:130b _test_data_119
+00:1321 _finish_119
+00:1331 _test_data_120
+00:1347 _finish_120
+00:1357 _test_data_121
+00:136d _finish_121
+00:137d _test_data_122
+00:1393 _finish_122
+00:13a3 _test_data_123
+00:13b9 _finish_123
+00:13c9 _test_data_124
+00:13df _finish_124
+00:13ef _test_data_125
+00:1405 _finish_125
+00:1415 _test_data_126
+00:142b _finish_126
+00:143b _test_data_127
+00:1451 _finish_127
+00:1461 _test_data_128
+00:1477 _finish_128
+00:1487 _test_data_129
+00:149d _finish_129
+00:14ad _test_data_130
+00:14c3 _finish_130
+00:14d3 _test_data_131
+00:14e9 _finish_131
+00:14f9 _test_data_132
+00:150f _finish_132
+00:151f _test_data_133
+00:1535 _finish_133
+00:1545 _test_data_134
+00:155b _finish_134
+00:156b _test_data_135
+00:1581 _finish_135
+00:1591 _test_data_136
+00:15a7 _finish_136
+00:15b7 _test_data_137
+00:15cd _finish_137
+00:15dd _test_data_138
+00:15f3 _finish_138
+00:1603 _test_data_139
+00:1619 _finish_139
+00:1629 _test_data_140
+00:163f _finish_140
+00:164f _test_data_141
+00:1665 _finish_141
+00:1675 _test_data_142
+00:168b _finish_142
+00:169b _test_data_143
+00:16b1 _finish_143
+00:16c1 _test_data_144
+00:16d7 _finish_144
+00:16e7 _test_data_145
+00:16fd _finish_145
+00:170d _test_data_146
+00:1723 _finish_146
+00:1733 _test_data_147
+00:1749 _finish_147
+00:1759 _test_data_148
+00:176f _finish_148
+00:177f _test_data_149
+00:1795 _finish_149
+00:17a5 _test_data_150
+00:17bb _finish_150
+00:17cb _test_data_151
+00:17e1 _finish_151
+00:17f1 _test_data_152
+00:1807 _finish_152
+00:1817 _test_data_153
+00:182d _finish_153
+00:1841 _wait_ly_4
+00:1847 _wait_ly_5
+00:185d _print_results_halt_1
+00:1860 _test_ok_cb_0
+00:1868 _print_sl_data55
+00:1870 _print_sl_out55
+00:1873 run_testcase
+00:189e _wait_ly_6
+00:18a4 _wait_ly_7
+00:18ba _print_results_halt_2
+00:18bd test_failure_cb
+00:18c5 _print_sl_data56
+00:18d1 _print_sl_out56
+00:18df _print_sl_data57
+00:18e3 _print_sl_out57
+00:18f1 _print_sl_data58
+00:1901 _print_sl_out58
+00:190f _print_sl_data59
+00:191c _print_sl_out59
+00:192d _print_sl_data60
+00:193a _print_sl_out60
+00:194b _print_sl_data61
+00:1958 _print_sl_out61
+00:195e fetch_test_data
+00:1978 print_got
+00:198a _print_zero
+00:198e _print_one
+00:1990 _print_bit
+00:1999 _skip
+00:199a _next
+00:c000 test_addr
+00:c002 test_got
+00:c003 test_reg
+00:c004 test_mask
+00:c005 test_str_write
+00:c00e test_str_expect
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/manifest.yml
new file mode 100644
index 000000000..1e96f6ccf
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/manifest.yml
@@ -0,0 +1 @@
+config: {gb.model: SGB}
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.gb
new file mode 100644
index 000000000..f046094b9
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.sym
new file mode 100644
index 000000000..0e9f27e5d
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.sym
@@ -0,0 +1,212 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/boot_hwio-S.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_ok_cb_0
+00:020d _print_sl_data55
+00:0215 _print_sl_out55
+00:0218 mismatch
+00:023b _wait_ly_6
+00:0241 _wait_ly_7
+00:0257 _print_results_halt_2
+00:025a mismatch_cb
+00:0262 _print_sl_data56
+00:0270 _print_sl_out56
+00:028a _print_sl_data57
+00:0294 _print_sl_out57
+00:02a5 _print_sl_data58
+00:02af _print_sl_out58
+00:02b8 hwio_data
+00:c014 mismatch_addr
+00:c016 mismatch_data
+00:c017 mismatch_mem
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.gb
new file mode 100644
index 000000000..e9d4b47a7
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.sym
new file mode 100644
index 000000000..f7b5e27b9
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.sym
@@ -0,0 +1,212 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/boot_hwio-dmg0.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_ok_cb_0
+00:020d _print_sl_data55
+00:0215 _print_sl_out55
+00:0218 mismatch
+00:023b _wait_ly_6
+00:0241 _wait_ly_7
+00:0257 _print_results_halt_2
+00:025a mismatch_cb
+00:0262 _print_sl_data56
+00:0270 _print_sl_out56
+00:028a _print_sl_data57
+00:0294 _print_sl_out57
+00:02a5 _print_sl_data58
+00:02af _print_sl_out58
+00:02b8 hwio_data
+00:c014 mismatch_addr
+00:c016 mismatch_data
+00:c017 mismatch_mem
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.gb
new file mode 100644
index 000000000..320b1be89
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.sav b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.sav
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.sym
new file mode 100644
index 000000000..f89b1f3f0
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.sym
@@ -0,0 +1,212 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/boot_hwio-dmgABCXmgb.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_ok_cb_0
+00:020d _print_sl_data55
+00:0215 _print_sl_out55
+00:0218 mismatch
+00:023b _wait_ly_6
+00:0241 _wait_ly_7
+00:0257 _print_results_halt_2
+00:025a mismatch_cb
+00:0262 _print_sl_data56
+00:0270 _print_sl_out56
+00:028a _print_sl_data57
+00:0294 _print_sl_out57
+00:02a5 _print_sl_data58
+00:02af _print_sl_out58
+00:02b8 hwio_data
+00:c014 mismatch_addr
+00:c016 mismatch_data
+00:c017 mismatch_mem
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/baseline_0000.png
new file mode 100644
index 000000000..ca834e18a
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.gb
new file mode 100644
index 000000000..3ed5eb152
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.sym
new file mode 100644
index 000000000..8bb6e4482
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.sym
@@ -0,0 +1,198 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/jeffrey/Scratch/mooneye-gb/tests/build/acceptance/boot_regs-dmg.gb".
+
+[labels]
+0001:4bf2 print_load_font
+0001:4bff print_string
+0001:4c09 print_a
+0001:4c13 print_newline
+0001:4c1e print_digit
+0001:4c2b print_regs
+0001:4c34 _print_sl_data0
+0001:4c3a _print_sl_out0
+0001:4c47 _print_sl_data1
+0001:4c4d _print_sl_out1
+0001:4c5f _print_sl_data2
+0001:4c65 _print_sl_out2
+0001:4c72 _print_sl_data3
+0001:4c78 _print_sl_out3
+0001:4c8a _print_sl_data4
+0001:4c90 _print_sl_out4
+0001:4c9d _print_sl_data5
+0001:4ca3 _print_sl_out5
+0001:4cb5 _print_sl_data6
+0001:4cbb _print_sl_out6
+0001:4cc8 _print_sl_data7
+0001:4cce _print_sl_out7
+0001:4000 font
+0000:c000 regs_save
+0000:c000 regs_save.f
+0000:c001 regs_save.a
+0000:c002 regs_save.c
+0000:c003 regs_save.b
+0000:c004 regs_save.e
+0000:c005 regs_save.d
+0000:c006 regs_save.l
+0000:c007 regs_save.h
+0000:c008 regs_flags
+0000:c009 regs_assert
+0000:c009 regs_assert.f
+0000:c00a regs_assert.a
+0000:c00b regs_assert.c
+0000:c00c regs_assert.b
+0000:c00d regs_assert.e
+0000:c00e regs_assert.d
+0000:c00f regs_assert.l
+0000:c010 regs_assert.h
+0000:c011 memdump_len
+0000:c012 memdump_addr
+0001:47f0 memcpy
+0001:47f9 memset
+0001:4802 clear_vram
+0001:480d reset_screen
+0001:481a process_results
+0001:481f _wait_ly_0
+0001:4825 _wait_ly_1
+0001:4841 _wait_ly_2
+0001:4847 _wait_ly_3
+0001:4860 _process_results_cb
+0001:486b _print_sl_data8
+0001:4875 _print_sl_out8
+0001:488f _print_sl_data9
+0001:489a _print_sl_out9
+0001:48b2 _print_sl_data10
+0001:48be _print_sl_out10
+0001:48bf dump_mem
+0001:48cf _wait_ly_4
+0001:48d5 _wait_ly_5
+0001:48f1 _dump_mem_line
+0001:491b _check_asserts
+0001:4929 _print_sl_data11
+0001:492c _print_sl_out11
+0001:4938 _print_sl_data12
+0001:493a _print_sl_out12
+0001:4942 _print_sl_data13
+0001:4945 _print_sl_out13
+0001:494f __check_assert_fail0
+0001:495a _print_sl_data14
+0001:495d _print_sl_out14
+0001:4960 __check_assert_ok0
+0001:4968 _print_sl_data15
+0001:496d _print_sl_out15
+0001:496f __check_assert_skip0
+0001:4977 _print_sl_data16
+0001:497f _print_sl_out16
+0001:497f __check_assert_out0
+0001:498b _print_sl_data17
+0001:498d _print_sl_out17
+0001:4995 _print_sl_data18
+0001:4998 _print_sl_out18
+0001:49a2 __check_assert_fail1
+0001:49ad _print_sl_data19
+0001:49b0 _print_sl_out19
+0001:49b3 __check_assert_ok1
+0001:49bb _print_sl_data20
+0001:49c0 _print_sl_out20
+0001:49c2 __check_assert_skip1
+0001:49ca _print_sl_data21
+0001:49d2 _print_sl_out21
+0001:49d2 __check_assert_out1
+0001:49dd _print_sl_data22
+0001:49e0 _print_sl_out22
+0001:49ec _print_sl_data23
+0001:49ee _print_sl_out23
+0001:49f6 _print_sl_data24
+0001:49f9 _print_sl_out24
+0001:4a03 __check_assert_fail2
+0001:4a0e _print_sl_data25
+0001:4a11 _print_sl_out25
+0001:4a14 __check_assert_ok2
+0001:4a1c _print_sl_data26
+0001:4a21 _print_sl_out26
+0001:4a23 __check_assert_skip2
+0001:4a2b _print_sl_data27
+0001:4a33 _print_sl_out27
+0001:4a33 __check_assert_out2
+0001:4a3f _print_sl_data28
+0001:4a41 _print_sl_out28
+0001:4a49 _print_sl_data29
+0001:4a4c _print_sl_out29
+0001:4a56 __check_assert_fail3
+0001:4a61 _print_sl_data30
+0001:4a64 _print_sl_out30
+0001:4a67 __check_assert_ok3
+0001:4a6f _print_sl_data31
+0001:4a74 _print_sl_out31
+0001:4a76 __check_assert_skip3
+0001:4a7e _print_sl_data32
+0001:4a86 _print_sl_out32
+0001:4a86 __check_assert_out3
+0001:4a91 _print_sl_data33
+0001:4a94 _print_sl_out33
+0001:4aa0 _print_sl_data34
+0001:4aa2 _print_sl_out34
+0001:4aaa _print_sl_data35
+0001:4aad _print_sl_out35
+0001:4ab7 __check_assert_fail4
+0001:4ac2 _print_sl_data36
+0001:4ac5 _print_sl_out36
+0001:4ac8 __check_assert_ok4
+0001:4ad0 _print_sl_data37
+0001:4ad5 _print_sl_out37
+0001:4ad7 __check_assert_skip4
+0001:4adf _print_sl_data38
+0001:4ae7 _print_sl_out38
+0001:4ae7 __check_assert_out4
+0001:4af3 _print_sl_data39
+0001:4af5 _print_sl_out39
+0001:4afd _print_sl_data40
+0001:4b00 _print_sl_out40
+0001:4b0a __check_assert_fail5
+0001:4b15 _print_sl_data41
+0001:4b18 _print_sl_out41
+0001:4b1b __check_assert_ok5
+0001:4b23 _print_sl_data42
+0001:4b28 _print_sl_out42
+0001:4b2a __check_assert_skip5
+0001:4b32 _print_sl_data43
+0001:4b3a _print_sl_out43
+0001:4b3a __check_assert_out5
+0001:4b45 _print_sl_data44
+0001:4b48 _print_sl_out44
+0001:4b54 _print_sl_data45
+0001:4b56 _print_sl_out45
+0001:4b5e _print_sl_data46
+0001:4b61 _print_sl_out46
+0001:4b6b __check_assert_fail6
+0001:4b76 _print_sl_data47
+0001:4b79 _print_sl_out47
+0001:4b7c __check_assert_ok6
+0001:4b84 _print_sl_data48
+0001:4b89 _print_sl_out48
+0001:4b8b __check_assert_skip6
+0001:4b93 _print_sl_data49
+0001:4b9b _print_sl_out49
+0001:4b9b __check_assert_out6
+0001:4ba7 _print_sl_data50
+0001:4ba9 _print_sl_out50
+0001:4bb1 _print_sl_data51
+0001:4bb4 _print_sl_out51
+0001:4bbe __check_assert_fail7
+0001:4bc9 _print_sl_data52
+0001:4bcc _print_sl_out52
+0001:4bcf __check_assert_ok7
+0001:4bd7 _print_sl_data53
+0001:4bdc _print_sl_out53
+0001:4bde __check_assert_skip7
+0001:4be6 _print_sl_data54
+0001:4bee _print_sl_out54
+0001:4bee __check_assert_out7
+0000:01d2 invalid_sp
+0000:01d7 _wait_ly_6
+0000:01dd _wait_ly_7
+0000:01f9 _wait_ly_8
+0000:01ff _wait_ly_9
+0000:0218 _test_failure_cb_0
+0000:0220 _print_sl_data55
+0000:0231 _print_sl_out55
+0000:c014 sp_save
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/baseline_0000.png
new file mode 100644
index 000000000..2dd6bdb38
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.gb
new file mode 100644
index 000000000..533f13681
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.sym
new file mode 100644
index 000000000..062765d0b
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/boot_regs-dmg0.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01d2 invalid_sp
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_failure_cb_0
+00:020d _print_sl_data55
+00:021e _print_sl_out55
+00:c014 sp_save
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/baseline_0000.png
new file mode 100644
index 000000000..ca834e18a
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.gb
new file mode 100644
index 000000000..f3ca735dc
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.sym
new file mode 100644
index 000000000..c6f3e5ac5
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/boot_regs-dmgABCX.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01d2 invalid_sp
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_failure_cb_0
+00:020d _print_sl_data55
+00:021e _print_sl_out55
+00:c014 sp_save
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/baseline_0000.png
new file mode 100644
index 000000000..6d33be323
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/manifest.yml
new file mode 100644
index 000000000..ac2b1940f
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/manifest.yml
@@ -0,0 +1 @@
+config: {gb.model: MGB}
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.gb
new file mode 100644
index 000000000..749b13ce6
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.sym
new file mode 100644
index 000000000..bc2c5e877
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/boot_regs-mgb.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01d2 invalid_sp
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_failure_cb_0
+00:020d _print_sl_data55
+00:021e _print_sl_out55
+00:c014 sp_save
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/baseline_0000.png
new file mode 100644
index 000000000..b9a0bbda2
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/manifest.yml
new file mode 100644
index 000000000..1e96f6ccf
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/manifest.yml
@@ -0,0 +1 @@
+config: {gb.model: SGB}
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.gb
new file mode 100644
index 000000000..84a9e3110
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.sym
new file mode 100644
index 000000000..2c87dce6d
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/boot_regs-sgb.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01d2 invalid_sp
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_failure_cb_0
+00:020d _print_sl_data55
+00:021e _print_sl_out55
+00:c014 sp_save
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/baseline_0000.png
new file mode 100644
index 000000000..94b57dbcf
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/manifest.yml
new file mode 100644
index 000000000..0a0ffd6cb
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/manifest.yml
@@ -0,0 +1 @@
+config: {gb.model: SGB2}
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.gb
new file mode 100644
index 000000000..f6133cd5b
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.sym
new file mode 100644
index 000000000..44fc2036e
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/boot_regs-sgb2.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01d2 invalid_sp
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_failure_cb_0
+00:020d _print_sl_data55
+00:021e _print_sl_out55
+00:c014 sp_save
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.gb
new file mode 100644
index 000000000..28f580b8a
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.sym
new file mode 100644
index 000000000..d5e92cd8b
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.sym
@@ -0,0 +1,223 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/call_cc_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0184 test_finish
+00:0198 _wait_ly_6
+00:019e _wait_ly_7
+00:01b4 _print_results_halt_1
+00:01b7 _test_ok_cb_0
+00:01bf _print_sl_data55
+00:01c7 _print_sl_out55
+00:01ca wram_test
+00:01cd fail_round1
+00:01e1 _wait_ly_8
+00:01e7 _wait_ly_9
+00:01fd _print_results_halt_2
+00:0200 _test_failure_cb_0
+00:0208 _print_sl_data56
+00:0216 _print_sl_out56
+00:0219 fail_round2
+00:022d _wait_ly_10
+00:0233 _wait_ly_11
+00:0249 _print_results_halt_3
+00:024c _test_failure_cb_1
+00:0254 _print_sl_data57
+00:0262 _print_sl_out57
+00:1f80 hiram_test
+00:1f87 _wait_ly_12
+00:1f8d _wait_ly_13
+00:1fa1 test_round2
+00:1fa8 _wait_ly_14
+00:1fae _wait_ly_15
+00:1fca finish_round1
+00:1ada finish_round2
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/baseline_0000.png
new file mode 100644
index 000000000..6793b1881
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.gb
new file mode 100644
index 000000000..8c71f685e
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.sym
new file mode 100644
index 000000000..bef813fa7
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.sym
@@ -0,0 +1,204 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/call_cc_timing2.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0177 test_finish
+00:01cf hiram_test
+00:01d2 _wait_ly_6
+00:01d8 _wait_ly_7
+00:01ec finish_round1
+00:01ed _wait_ly_8
+00:01f3 _wait_ly_9
+00:0208 finish_round2
+00:0209 _wait_ly_10
+00:020f _wait_ly_11
+00:0225 finish_round3
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing/test.gb
new file mode 100644
index 000000000..da3eec149
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing/test.sym
new file mode 100644
index 000000000..d8d67a7cb
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing/test.sym
@@ -0,0 +1,223 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/call_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0184 test_finish
+00:0198 _wait_ly_6
+00:019e _wait_ly_7
+00:01b4 _print_results_halt_1
+00:01b7 _test_ok_cb_0
+00:01bf _print_sl_data55
+00:01c7 _print_sl_out55
+00:01ca wram_test
+00:01cd fail_round1
+00:01e1 _wait_ly_8
+00:01e7 _wait_ly_9
+00:01fd _print_results_halt_2
+00:0200 _test_failure_cb_0
+00:0208 _print_sl_data56
+00:0216 _print_sl_out56
+00:0219 fail_round2
+00:022d _wait_ly_10
+00:0233 _wait_ly_11
+00:0249 _print_results_halt_3
+00:024c _test_failure_cb_1
+00:0254 _print_sl_data57
+00:0262 _print_sl_out57
+00:1f80 hiram_test
+00:1f87 _wait_ly_12
+00:1f8d _wait_ly_13
+00:1fa1 test_round2
+00:1fa8 _wait_ly_14
+00:1fae _wait_ly_15
+00:1fca finish_round1
+00:1ada finish_round2
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing2/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing2/baseline_0000.png
new file mode 100644
index 000000000..dc8b90726
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing2/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing2/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing2/test.gb
new file mode 100644
index 000000000..d6e5af9e4
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing2/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing2/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing2/test.sym
new file mode 100644
index 000000000..0597fcf6e
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/call_timing2/test.sym
@@ -0,0 +1,204 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/call_timing2.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0177 test_finish
+00:01cf hiram_test
+00:01d2 _wait_ly_6
+00:01d8 _wait_ly_7
+00:01ec finish_round1
+00:01ed _wait_ly_8
+00:01f3 _wait_ly_9
+00:0208 finish_round2
+00:0209 _wait_ly_10
+00:020f _wait_ly_11
+00:0225 finish_round3
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/di_timing-GS/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/di_timing-GS/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/di_timing-GS/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.gb
new file mode 100644
index 000000000..2021714d4
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.sym
new file mode 100644
index 000000000..049dcc7dc
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.sym
@@ -0,0 +1,228 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/di_timing-GS.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0158 _wait_ly_4
+00:015e _wait_ly_5
+00:016d test_round1
+00:0177 _delay_long_time_0
+00:0186 finish_round1
+00:0189 _wait_ly_6
+00:018f _wait_ly_7
+00:019e test_round2
+00:01a8 _delay_long_time_1
+00:01b4 test_finish
+00:01c8 _wait_ly_8
+00:01ce _wait_ly_9
+00:01e4 _print_results_halt_1
+00:01e7 _test_ok_cb_0
+00:01ef _print_sl_data55
+00:01f7 _print_sl_out55
+00:01fa fail_halt
+00:020e _wait_ly_10
+00:0214 _wait_ly_11
+00:022a _print_results_halt_2
+00:022d _test_failure_cb_0
+00:0235 _print_sl_data56
+00:0240 _print_sl_out56
+00:0243 fail_round1
+00:0257 _wait_ly_12
+00:025d _wait_ly_13
+00:0273 _print_results_halt_3
+00:0276 _test_failure_cb_1
+00:027e _print_sl_data57
+00:028c _print_sl_out57
+00:028f fail_round2
+00:02a3 _wait_ly_14
+00:02a9 _wait_ly_15
+00:02bf _print_results_halt_4
+00:02c2 _test_failure_cb_2
+00:02ca _print_sl_data58
+00:02d8 _print_sl_out58
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/div_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/div_timing/baseline_0000.png
new file mode 100644
index 000000000..67f91d461
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/div_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/div_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/div_timing/test.gb
new file mode 100644
index 000000000..76c0f925b
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/div_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/div_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/div_timing/test.sym
new file mode 100644
index 000000000..0be27e009
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/div_timing/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/div_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0232 test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ei_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ei_timing/baseline_0000.png
new file mode 100644
index 000000000..e2bd92765
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ei_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ei_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ei_timing/test.gb
new file mode 100644
index 000000000..c1584a879
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ei_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ei_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ei_timing/test.sym
new file mode 100644
index 000000000..f5d0a7625
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ei_timing/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/ei_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0160 test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.gb
new file mode 100644
index 000000000..b6b9da4de
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.sym
new file mode 100644
index 000000000..ddf7da6b3
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.sym
@@ -0,0 +1,219 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/hblank_ly_scx_timing-GS.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:03a2 _wait_ly_6
+00:03a8 _wait_ly_7
+00:03be _print_results_halt_1
+00:03c1 _test_ok_cb_0
+00:03c9 _print_sl_data55
+00:03d1 _print_sl_out55
+00:03d4 test_fail
+00:0404 _wait_ly_8
+00:040a _wait_ly_9
+00:0420 _print_results_halt_2
+00:0423 _test_failure_dump_cb_0
+00:042e _print_sl_data56
+00:0438 _print_sl_out56
+00:044c _print_sl_data57
+00:0458 _print_sl_out57
+00:045b standard_delay
+00:0473 setup_and_wait
+00:0473 _wait_ly_10
+00:0479 _wait_ly_11
+00:048d fail_halt
+00:04a1 _wait_ly_12
+00:04a7 _wait_ly_13
+00:04bd _print_results_halt_3
+00:04c0 _test_failure_cb_0
+00:04c8 _print_sl_data58
+00:04d3 _print_sl_out58
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/baseline_0000.png
new file mode 100644
index 000000000..3b4cc1095
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.gb
new file mode 100644
index 000000000..ee87fd9e1
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.sym
new file mode 100644
index 000000000..ef6df762b
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.sym
@@ -0,0 +1,203 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/intr_1_2_timing-GS.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:01ab setup_and_wait_mode1
+00:01ab _wait_ly_6
+00:01be setup_and_wait_mode2
+00:01cb fail_halt
+00:01df _wait_ly_7
+00:01e5 _wait_ly_8
+00:01fb _print_results_halt_1
+00:01fe _test_failure_cb_0
+00:0206 _print_sl_data55
+00:0211 _print_sl_out55
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/baseline_0000.png
new file mode 100644
index 000000000..7eb77961d
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.gb
new file mode 100644
index 000000000..aa8bd6e13
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.sym
new file mode 100644
index 000000000..e94a96a1b
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.sym
@@ -0,0 +1,203 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/intr_2_0_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:01a9 setup_and_wait_mode2
+00:01a9 _wait_ly_6
+00:01cc setup_and_wait_mode0
+00:01d9 fail_halt
+00:01ed _wait_ly_7
+00:01f3 _wait_ly_8
+00:0209 _print_results_halt_1
+00:020c _test_failure_cb_0
+00:0214 _print_sl_data55
+00:021f _print_sl_out55
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/baseline_0000.png
new file mode 100644
index 000000000..8bd6ee7d8
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.gb
new file mode 100644
index 000000000..508e64891
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.sym
new file mode 100644
index 000000000..0f55f61b3
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.sym
@@ -0,0 +1,202 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/intr_2_mode0_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0207 setup_and_wait_mode2
+00:0207 _wait_ly_6
+00:022a fail_halt
+00:023e _wait_ly_7
+00:0244 _wait_ly_8
+00:025a _print_results_halt_1
+00:025d _test_failure_cb_0
+00:0265 _print_sl_data55
+00:0270 _print_sl_out55
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/baseline_0000.png
new file mode 100644
index 000000000..0090d69bc
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.gb
new file mode 100644
index 000000000..ee6e82ca9
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.sym
new file mode 100644
index 000000000..b5f7cac3b
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.sym
@@ -0,0 +1,437 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/intr_2_mode0_timing_sprites.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c0c2 regs_save
+00:c0c2 regs_save.f
+00:c0c3 regs_save.a
+00:c0c4 regs_save.c
+00:c0c5 regs_save.b
+00:c0c6 regs_save.e
+00:c0c7 regs_save.d
+00:c0c8 regs_save.l
+00:c0c9 regs_save.h
+00:c0ca regs_flags
+00:c0cb regs_assert
+00:c0cb regs_assert.f
+00:c0cc regs_assert.a
+00:c0cd regs_assert.c
+00:c0ce regs_assert.b
+00:c0cf regs_assert.e
+00:c0d0 regs_assert.d
+00:c0d1 regs_assert.l
+00:c0d2 regs_assert.h
+00:c0d3 memdump_len
+00:c0d4 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0174 _testcase_data_0
+00:0176 _testcase_end_0
+00:0187 _testcase_data_1
+00:018a _testcase_end_1
+00:019b _testcase_data_2
+00:019f _testcase_end_2
+00:01b0 _testcase_data_3
+00:01b5 _testcase_end_3
+00:01c6 _testcase_data_4
+00:01cc _testcase_end_4
+00:01dd _testcase_data_5
+00:01e4 _testcase_end_5
+00:01f5 _testcase_data_6
+00:01fd _testcase_end_6
+00:020e _testcase_data_7
+00:0217 _testcase_end_7
+00:0228 _testcase_data_8
+00:0232 _testcase_end_8
+00:0243 _testcase_data_9
+00:024e _testcase_end_9
+00:025f _testcase_data_10
+00:026a _testcase_end_10
+00:027b _testcase_data_11
+00:0286 _testcase_end_11
+00:0297 _testcase_data_12
+00:02a2 _testcase_end_12
+00:02b3 _testcase_data_13
+00:02be _testcase_end_13
+00:02cf _testcase_data_14
+00:02da _testcase_end_14
+00:02eb _testcase_data_15
+00:02f6 _testcase_end_15
+00:0307 _testcase_data_16
+00:0312 _testcase_end_16
+00:0323 _testcase_data_17
+00:032e _testcase_end_17
+00:033f _testcase_data_18
+00:034a _testcase_end_18
+00:035b _testcase_data_19
+00:0366 _testcase_end_19
+00:0377 _testcase_data_20
+00:0382 _testcase_end_20
+00:0393 _testcase_data_21
+00:039e _testcase_end_21
+00:03af _testcase_data_22
+00:03ba _testcase_end_22
+00:03cb _testcase_data_23
+00:03d6 _testcase_end_23
+00:03e7 _testcase_data_24
+00:03f2 _testcase_end_24
+00:0403 _testcase_data_25
+00:040e _testcase_end_25
+00:041f _testcase_data_26
+00:042a _testcase_end_26
+00:043b _testcase_data_27
+00:0446 _testcase_end_27
+00:0457 _testcase_data_28
+00:0462 _testcase_end_28
+00:0473 _testcase_data_29
+00:047e _testcase_end_29
+00:048f _testcase_data_30
+00:049a _testcase_end_30
+00:04ab _testcase_data_31
+00:04b6 _testcase_end_31
+00:04c7 _testcase_data_32
+00:04d2 _testcase_end_32
+00:04e3 _testcase_data_33
+00:04ee _testcase_end_33
+00:04ff _testcase_data_34
+00:050a _testcase_end_34
+00:051b _testcase_data_35
+00:0526 _testcase_end_35
+00:0537 _testcase_data_36
+00:0542 _testcase_end_36
+00:0553 _testcase_data_37
+00:055e _testcase_end_37
+00:056f _testcase_data_38
+00:057a _testcase_end_38
+00:058b _testcase_data_39
+00:0596 _testcase_end_39
+00:05a7 _testcase_data_40
+00:05b2 _testcase_end_40
+00:05c3 _testcase_data_41
+00:05ce _testcase_end_41
+00:05df _testcase_data_42
+00:05ea _testcase_end_42
+00:05fb _testcase_data_43
+00:0606 _testcase_end_43
+00:0617 _testcase_data_44
+00:0622 _testcase_end_44
+00:0633 _testcase_data_45
+00:063e _testcase_end_45
+00:064f _testcase_data_46
+00:065a _testcase_end_46
+00:066b _testcase_data_47
+00:0676 _testcase_end_47
+00:0687 _testcase_data_48
+00:0692 _testcase_end_48
+00:06a3 _testcase_data_49
+00:06ae _testcase_end_49
+00:06bf _testcase_data_50
+00:06ca _testcase_end_50
+00:06db _testcase_data_51
+00:06e6 _testcase_end_51
+00:06f7 _testcase_data_52
+00:06f9 _testcase_end_52
+00:070a _testcase_data_53
+00:070c _testcase_end_53
+00:071d _testcase_data_54
+00:071f _testcase_end_54
+00:0730 _testcase_data_55
+00:0732 _testcase_end_55
+00:0743 _testcase_data_56
+00:0745 _testcase_end_56
+00:0756 _testcase_data_57
+00:0758 _testcase_end_57
+00:0769 _testcase_data_58
+00:076b _testcase_end_58
+00:077c _testcase_data_59
+00:077e _testcase_end_59
+00:078f _testcase_data_60
+00:0791 _testcase_end_60
+00:07a2 _testcase_data_61
+00:07a4 _testcase_end_61
+00:07b5 _testcase_data_62
+00:07b7 _testcase_end_62
+00:07c8 _testcase_data_63
+00:07ca _testcase_end_63
+00:07db _testcase_data_64
+00:07dd _testcase_end_64
+00:07ee _testcase_data_65
+00:07f0 _testcase_end_65
+00:0801 _testcase_data_66
+00:0803 _testcase_end_66
+00:0814 _testcase_data_67
+00:0816 _testcase_end_67
+00:0827 _testcase_data_68
+00:0829 _testcase_end_68
+00:083a _testcase_data_69
+00:083c _testcase_end_69
+00:084d _testcase_data_70
+00:084f _testcase_end_70
+00:0860 _testcase_data_71
+00:0862 _testcase_end_71
+00:0873 _testcase_data_72
+00:0875 _testcase_end_72
+00:0886 _testcase_data_73
+00:0888 _testcase_end_73
+00:0899 _testcase_data_74
+00:089b _testcase_end_74
+00:08ac _testcase_data_75
+00:08ae _testcase_end_75
+00:08bf _testcase_data_76
+00:08c1 _testcase_end_76
+00:08d2 _testcase_data_77
+00:08d4 _testcase_end_77
+00:08e5 _testcase_data_78
+00:08e8 _testcase_end_78
+00:08f9 _testcase_data_79
+00:08fc _testcase_end_79
+00:090d _testcase_data_80
+00:0910 _testcase_end_80
+00:0921 _testcase_data_81
+00:0924 _testcase_end_81
+00:0935 _testcase_data_82
+00:0938 _testcase_end_82
+00:0949 _testcase_data_83
+00:094c _testcase_end_83
+00:095d _testcase_data_84
+00:0960 _testcase_end_84
+00:0971 _testcase_data_85
+00:0974 _testcase_end_85
+00:0985 _testcase_data_86
+00:0988 _testcase_end_86
+00:0999 _testcase_data_87
+00:099c _testcase_end_87
+00:09ad _testcase_data_88
+00:09b0 _testcase_end_88
+00:09c1 _testcase_data_89
+00:09c4 _testcase_end_89
+00:09d5 _testcase_data_90
+00:09d8 _testcase_end_90
+00:09e9 _testcase_data_91
+00:09ec _testcase_end_91
+00:09fd _testcase_data_92
+00:0a00 _testcase_end_92
+00:0a11 _testcase_data_93
+00:0a14 _testcase_end_93
+00:0a25 _testcase_data_94
+00:0a28 _testcase_end_94
+00:0a39 _testcase_data_95
+00:0a44 _testcase_end_95
+00:0a55 _testcase_data_96
+00:0a60 _testcase_end_96
+00:0a71 _testcase_data_97
+00:0a7c _testcase_end_97
+00:0a8d _testcase_data_98
+00:0a98 _testcase_end_98
+00:0aa9 _testcase_data_99
+00:0ab4 _testcase_end_99
+00:0ac5 _testcase_data_100
+00:0ad0 _testcase_end_100
+00:0ae1 _testcase_data_101
+00:0aec _testcase_end_101
+00:0afd _testcase_data_102
+00:0b08 _testcase_end_102
+00:0b19 _testcase_data_103
+00:0b24 _testcase_end_103
+00:0b35 _testcase_data_104
+00:0b40 _testcase_end_104
+00:0b54 _wait_ly_4
+00:0b5a _wait_ly_5
+00:0b70 _print_results_halt_1
+00:0b73 _test_ok_cb_0
+00:0b7b _print_sl_data55
+00:0b83 _print_sl_out55
+00:0b86 run_testcase
+00:0b88 _wait_ly_6
+00:0b8e _wait_ly_7
+00:0bb9 testcase_round_a
+00:0bc4 testcase_round_a_ret
+00:0bd4 testcase_round_b
+00:0bdf testcase_round_b_ret
+00:0bf0 prepare_sprites
+00:0c06 prepare_nop_area
+00:0c0f setup_and_wait_mode2
+00:0c0f _wait_ly_8
+00:0c32 test_fail
+00:0c46 _wait_ly_9
+00:0c4c _wait_ly_10
+00:0c62 _print_results_halt_2
+00:0c65 _test_fail_cb
+00:0c6d _print_sl_data56
+00:0c74 _print_sl_out56
+00:0c82 _print_sl_data57
+00:0c8a _print_sl_out57
+00:0c8d fail_halt
+00:0ca1 _wait_ly_11
+00:0ca7 _wait_ly_12
+00:0cbd _print_results_halt_3
+00:0cc0 _test_failure_cb_0
+00:0cc8 _print_sl_data58
+00:0cd3 _print_sl_out58
+00:c000 testcase_id
+00:c002 nop_area_a
+00:c062 nop_area_b
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/baseline_0000.png
new file mode 100644
index 000000000..34626054e
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.gb
new file mode 100644
index 000000000..c7b2b1052
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.sym
new file mode 100644
index 000000000..4cc8629e1
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.sym
@@ -0,0 +1,202 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/intr_2_mode3_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:01b5 setup_and_wait_mode2
+00:01b5 _wait_ly_6
+00:01d8 fail_halt
+00:01ec _wait_ly_7
+00:01f2 _wait_ly_8
+00:0208 _print_results_halt_1
+00:020b _test_failure_cb_0
+00:0213 _print_sl_data55
+00:021e _print_sl_out55
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/baseline_0000.png
new file mode 100644
index 000000000..42de5e8c0
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.gb
new file mode 100644
index 000000000..8196451a4
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.sym
new file mode 100644
index 000000000..ded62c5a8
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.sym
@@ -0,0 +1,202 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/intr_2_oam_ok_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:020a setup_and_wait_mode2
+00:020a _wait_ly_6
+00:022d fail_halt
+00:0241 _wait_ly_7
+00:0247 _wait_ly_8
+00:025d _print_results_halt_1
+00:0260 _test_failure_cb_0
+00:0268 _print_sl_data55
+00:0273 _print_sl_out55
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.gb
new file mode 100644
index 000000000..00a9a878e
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.sym
new file mode 100644
index 000000000..8b0bd688d
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.sym
@@ -0,0 +1,236 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/lcdon_timing-dmgABCXmgbS.gb".
+
+[labels]
+01:5087 print_load_font
+01:5094 print_string
+01:509e print_a
+01:50a8 print_newline
+01:50b3 print_digit
+01:50c0 print_regs
+01:50c9 _print_sl_data0
+01:50cf _print_sl_out0
+01:50dc _print_sl_data1
+01:50e2 _print_sl_out1
+01:50f4 _print_sl_data2
+01:50fa _print_sl_out2
+01:5107 _print_sl_data3
+01:510d _print_sl_out3
+01:511f _print_sl_data4
+01:5125 _print_sl_out4
+01:5132 _print_sl_data5
+01:5138 _print_sl_out5
+01:514a _print_sl_data6
+01:5150 _print_sl_out6
+01:515d _print_sl_data7
+01:5163 _print_sl_out7
+01:4000 font
+00:c01d regs_save
+00:c01d regs_save.f
+00:c01e regs_save.a
+00:c01f regs_save.c
+00:c020 regs_save.b
+00:c021 regs_save.e
+00:c022 regs_save.d
+00:c023 regs_save.l
+00:c024 regs_save.h
+00:c025 regs_flags
+00:c026 regs_assert
+00:c026 regs_assert.f
+00:c027 regs_assert.a
+00:c028 regs_assert.c
+00:c029 regs_assert.b
+00:c02a regs_assert.e
+00:c02b regs_assert.d
+00:c02c regs_assert.l
+00:c02d regs_assert.h
+00:c02e memdump_len
+00:c02f memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:015a test_ly
+00:0166 test_stat_lyc0
+00:0175 test_stat_lyc1
+00:0185 test_oam_access
+00:0191 test_vram_access
+00:019d test_finish
+00:01b1 _wait_ly_4
+00:01b7 _wait_ly_5
+00:01cd _print_results_halt_1
+00:01d0 _test_ok_cb_0
+00:01d8 _print_sl_data55
+00:01e0 _print_sl_out55
+01:4ed8 cycle_counts
+01:4ef0 expect_ly
+01:4f0b expect_stat_lyc0
+01:4f2e expect_stat_lyc1
+01:4f51 expect_oam_access
+01:4f74 expect_vram_access
+01:4f98 verify_results
+01:4faf verify_fail
+01:4fdd _wait_ly_6
+01:4fe3 _wait_ly_7
+01:4ff9 _print_results_halt_2
+01:4ffc _verify_fail_cb
+01:5004 _print_sl_data56
+01:5012 _print_sl_out56
+01:502e _print_sl_data57
+01:503a _print_sl_out57
+01:5055 _print_sl_data58
+01:5061 _print_sl_out58
+01:5072 _print_sl_data59
+01:507e _print_sl_out59
+00:c000 v_pass1_results
+00:c008 v_pass2_results
+00:c010 v_pass3_results
+00:c018 v_fail_round
+00:c019 v_fail_expect
+00:c01a v_fail_actual
+00:c01b v_fail_str
+00:c01b v_fail_str_l
+00:c01c v_fail_str_h
+01:4bff test_passes
+01:4bff test_pass1
+01:4cf1 test_pass2
+01:4de4 test_pass3
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.gb
new file mode 100644
index 000000000..414811dbe
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.sym
new file mode 100644
index 000000000..67acc5419
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.sym
@@ -0,0 +1,230 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/lcdon_write_timing-GS.gb".
+
+[labels]
+01:4d3c print_load_font
+01:4d49 print_string
+01:4d53 print_a
+01:4d5d print_newline
+01:4d68 print_digit
+01:4d75 print_regs
+01:4d7e _print_sl_data0
+01:4d84 _print_sl_out0
+01:4d91 _print_sl_data1
+01:4d97 _print_sl_out1
+01:4da9 _print_sl_data2
+01:4daf _print_sl_out2
+01:4dbc _print_sl_data3
+01:4dc2 _print_sl_out3
+01:4dd4 _print_sl_data4
+01:4dda _print_sl_out4
+01:4de7 _print_sl_data5
+01:4ded _print_sl_out5
+01:4dff _print_sl_data6
+01:4e05 _print_sl_out6
+01:4e12 _print_sl_data7
+01:4e18 _print_sl_out7
+01:4000 font
+00:c144 regs_save
+00:c144 regs_save.f
+00:c145 regs_save.a
+00:c146 regs_save.c
+00:c147 regs_save.b
+00:c148 regs_save.e
+00:c149 regs_save.d
+00:c14a regs_save.l
+00:c14b regs_save.h
+00:c14c regs_flags
+00:c14d regs_assert
+00:c14d regs_assert.f
+00:c14e regs_assert.a
+00:c14f regs_assert.c
+00:c150 regs_assert.b
+00:c151 regs_assert.e
+00:c152 regs_assert.d
+00:c153 regs_assert.l
+00:c154 regs_assert.h
+00:c155 memdump_len
+00:c156 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:015a test_oam_access
+00:0166 test_vram_access
+00:0172 test_finish
+00:0186 _wait_ly_4
+00:018c _wait_ly_5
+00:01a2 _print_results_halt_1
+00:01a5 _test_ok_cb_0
+00:01ad _print_sl_data55
+00:01b5 _print_sl_out55
+01:4bff nop_counts
+01:4c12 expect_oam_access
+01:4c2f expect_vram_access
+01:4c4d verify_results
+01:4c64 verify_fail
+01:4c92 _wait_ly_6
+01:4c98 _wait_ly_7
+01:4cae _print_results_halt_2
+01:4cb1 _verify_fail_cb
+01:4cb9 _print_sl_data56
+01:4cc7 _print_sl_out56
+01:4ce3 _print_sl_data57
+01:4cef _print_sl_out57
+01:4d0a _print_sl_data58
+01:4d16 _print_sl_out58
+01:4d27 _print_sl_data59
+01:4d33 _print_sl_out59
+00:c000 v_test_code
+00:c12c v_test_results
+00:c13f v_fail_round
+00:c140 v_fail_expect
+00:c141 v_fail_actual
+00:c142 v_fail_str
+00:c142 v_fail_str_l
+00:c143 v_fail_str_h
+01:4e22 run_tests
+01:4e3b test_case
+01:4e6f test_case_prologue
+01:4e73 test_case_epilogue
+01:4e75 test_case_end
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.gb
new file mode 100644
index 000000000..d91c3e1a5
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.sym
new file mode 100644
index 000000000..96dee6c56
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.sym
@@ -0,0 +1,219 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/stat_irq_blocking.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 test_round1
+00:0156 _wait_ly_4
+00:015c _wait_ly_5
+00:016b fail_round1
+00:0180 _wait_ly_6
+00:0186 _wait_ly_7
+00:019c _print_results_halt_1
+00:019f _test_failure_cb_0
+00:01a7 _print_sl_data55
+00:01b9 _print_sl_out55
+00:01bc test_round2
+00:01c6 ly_iteration
+00:01dc finish_round2
+00:01f1 _wait_ly_8
+00:01f7 _wait_ly_9
+00:020d _print_results_halt_2
+00:0210 _test_ok_cb_0
+00:0218 _print_sl_data56
+00:0220 _print_sl_out56
+00:0223 fail_round2
+00:0250 _wait_ly_10
+00:0256 _wait_ly_11
+00:026c _print_results_halt_3
+00:026f _test_failure_dump_cb_0
+00:027a _print_sl_data57
+00:0284 _print_sl_out57
+00:0298 _print_sl_data58
+00:02a4 _print_sl_out58
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/baseline_0000.png
new file mode 100644
index 000000000..b8320c449
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.gb
new file mode 100644
index 000000000..46066d52a
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.sym
new file mode 100644
index 000000000..3573e7337
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.sym
@@ -0,0 +1,216 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/gpu/vblank_stat_intr-GS.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0169 fail_halt
+00:017d _wait_ly_4
+00:0183 _wait_ly_5
+00:0199 _print_results_halt_1
+00:019c _test_failure_cb_0
+00:01a4 _print_sl_data55
+00:01a9 _print_sl_out55
+00:01ac test_round1
+00:01b8 _wait_ly_6
+00:0203 finish_round1
+00:0221 test_round2
+00:022d _wait_ly_7
+00:0279 finish_round2
+00:029b test_round3
+00:02a7 _wait_ly_8
+00:02f2 finish_round3
+00:0310 test_round4
+00:031c _wait_ly_9
+00:0368 finish_round4
+00:036a test_finish
+00:c014 intr_vec_vblank
+00:c017 intr_vec_stat
+00:c01a round1
+00:c01b round2
+00:c01c round3
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.gb
new file mode 100644
index 000000000..d93cfc812
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.sym
new file mode 100644
index 000000000..dc2e3d007
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.sym
@@ -0,0 +1,206 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/halt_ime0_ei.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0161 result_ime0
+00:0175 _wait_ly_5
+00:017b _wait_ly_6
+00:0191 _print_results_halt_1
+00:0194 _test_failure_cb_0
+00:019c _print_sl_data55
+00:01a2 _print_sl_out55
+00:01a5 result_ime1
+00:01b9 _wait_ly_7
+00:01bf _wait_ly_8
+00:01d5 _print_results_halt_2
+00:01d8 _test_ok_cb_0
+00:01e0 _print_sl_data56
+00:01e8 _print_sl_out56
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/baseline_0000.png
new file mode 100644
index 000000000..de3b4f986
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.gb
new file mode 100644
index 000000000..738e35c10
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.sym
new file mode 100644
index 000000000..dae8dc6a3
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.sym
@@ -0,0 +1,210 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/halt_ime0_nointr_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0167 test_round1
+00:0184 finish_round1
+00:0193 test_round2
+00:01af finish_round2
+00:01e2 fail_halt
+00:01f6 _wait_ly_5
+00:01fc _wait_ly_6
+00:0212 _print_results_halt_1
+00:0215 _test_failure_cb_0
+00:021d _print_sl_data55
+00:0228 _print_sl_out55
+00:022b fail_intr
+00:023f _wait_ly_7
+00:0245 _wait_ly_8
+00:025b _print_results_halt_2
+00:025e _test_failure_cb_1
+00:0266 _print_sl_data56
+00:0276 _print_sl_out56
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/baseline_0000.png
new file mode 100644
index 000000000..330cf4ba5
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.gb
new file mode 100644
index 000000000..cf04278d8
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.sym
new file mode 100644
index 000000000..ae72e40f4
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.sym
@@ -0,0 +1,198 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/halt_ime1_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0175 _wait_ly_4
+00:017b _wait_ly_5
+00:0191 _print_results_halt_1
+00:0194 _test_failure_cb_0
+00:019c _print_sl_data55
+00:01a8 _print_sl_out55
+00:01ab test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/baseline_0000.png
new file mode 100644
index 000000000..ff8a0a684
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.gb
new file mode 100644
index 000000000..9c929a106
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.sym
new file mode 100644
index 000000000..87bc44d5b
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.sym
@@ -0,0 +1,237 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/halt_ime1_timing2-GS.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0167 test_round1
+00:0183 _delay_long_time_0
+00:0193 finish_round1
+00:01a2 test_round2
+00:01bd _delay_long_time_1
+00:01ce finish_round2
+00:01dd test_round3
+00:01f8 finish_round3
+00:0207 test_round4
+00:0221 finish_round4
+00:0268 fail_halt
+00:027c _wait_ly_5
+00:0282 _wait_ly_6
+00:0298 _print_results_halt_1
+00:029b _test_failure_cb_0
+00:02a3 _print_sl_data55
+00:02ae _print_sl_out55
+00:02b1 fail_round1
+00:02c5 _wait_ly_7
+00:02cb _wait_ly_8
+00:02e1 _print_results_halt_2
+00:02e4 _test_failure_cb_1
+00:02ec _print_sl_data56
+00:02fa _print_sl_out56
+00:02fd fail_round2
+00:0311 _wait_ly_9
+00:0317 _wait_ly_10
+00:032d _print_results_halt_3
+00:0330 _test_failure_cb_2
+00:0338 _print_sl_data57
+00:0346 _print_sl_out57
+00:0349 fail_round3
+00:035d _wait_ly_11
+00:0363 _wait_ly_12
+00:0379 _print_results_halt_4
+00:037c _test_failure_cb_3
+00:0384 _print_sl_data58
+00:0392 _print_sl_out58
+00:0395 fail_round4
+00:03a9 _wait_ly_13
+00:03af _wait_ly_14
+00:03c5 _print_results_halt_5
+00:03c8 _test_failure_cb_4
+00:03d0 _print_sl_data59
+00:03de _print_sl_out59
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.gb
new file mode 100644
index 000000000..4c77279b4
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.sym
new file mode 100644
index 000000000..1ff5bc335
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.sym
@@ -0,0 +1,195 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/hdma_lcdc.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0154 test
+00:0161 test_finish
+00:017f _wait_ly_4
+00:0185 _wait_ly_5
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/if_ie_registers/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/if_ie_registers/baseline_0000.png
new file mode 100644
index 000000000..020e83af2
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/if_ie_registers/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.gb
new file mode 100644
index 000000000..f0e497f6f
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.sym
new file mode 100644
index 000000000..114073a61
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/if_ie_registers.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01ef test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.gb
new file mode 100644
index 000000000..404d9b0d6
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.sym
new file mode 100644
index 000000000..84a14d360
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.sym
@@ -0,0 +1,282 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/interrupts/ie_push.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0200 round1
+00:0214 finish_round1
+00:021d round2
+00:0224 round3
+00:0235 target
+00:0238 finish_round3
+00:023f round4
+00:0253 finish_round4
+00:0270 _wait_ly_4
+00:0276 _wait_ly_5
+00:028c _print_results_halt_1
+00:028f _test_ok_cb_0
+00:0297 _print_sl_data55
+00:029f _print_sl_out55
+00:1000 fail_round1_nointr
+00:1017 _wait_ly_6
+00:101d _wait_ly_7
+00:1033 _print_results_halt_2
+00:1036 _test_failure_cb_0
+00:103e _print_sl_data56
+00:104f _print_sl_out56
+00:1052 fail_round1_nocancel
+00:1069 _wait_ly_8
+00:106f _wait_ly_9
+00:1085 _print_results_halt_3
+00:1088 _test_failure_cb_1
+00:1090 _print_sl_data57
+00:10a2 _print_sl_out57
+00:10a5 fail_round1_if
+00:10bc _wait_ly_10
+00:10c2 _wait_ly_11
+00:10d8 _print_results_halt_4
+00:10db _test_failure_cb_2
+00:10e3 _print_sl_data58
+00:10f3 _print_sl_out58
+00:10f6 fail_round2_intr
+00:110d _wait_ly_12
+00:1113 _wait_ly_13
+00:1129 _print_results_halt_5
+00:112c _test_failure_cb_3
+00:1134 _print_sl_data59
+00:1146 _print_sl_out59
+00:1149 fail_round3_nointr
+00:1160 _wait_ly_14
+00:1166 _wait_ly_15
+00:117c _print_results_halt_6
+00:117f _test_failure_cb_4
+00:1187 _print_sl_data60
+00:1198 _print_sl_out60
+00:119b fail_round3_cancel
+00:11b2 _wait_ly_16
+00:11b8 _wait_ly_17
+00:11ce _print_results_halt_7
+00:11d1 _test_failure_cb_5
+00:11d9 _print_sl_data61
+00:11ed _print_sl_out61
+00:11f0 fail_round3_if
+00:1207 _wait_ly_18
+00:120d _wait_ly_19
+00:1223 _print_results_halt_8
+00:1226 _test_failure_cb_6
+00:122e _print_sl_data62
+00:123e _print_sl_out62
+00:1241 fail_round4_nointr
+00:1258 _wait_ly_20
+00:125e _wait_ly_21
+00:1274 _print_results_halt_9
+00:1277 _test_failure_cb_7
+00:127f _print_sl_data63
+00:1290 _print_sl_out63
+00:1293 fail_round4_cancel
+00:12aa _wait_ly_22
+00:12b0 _wait_ly_23
+00:12c6 _print_results_halt_10
+00:12c9 _test_failure_cb_8
+00:12d1 _print_sl_data64
+00:12e5 _print_sl_out64
+00:12e8 fail_round4_if
+00:12ff _wait_ly_24
+00:1305 _wait_ly_25
+00:131b _print_results_halt_11
+00:131e _test_failure_cb_9
+00:1326 _print_sl_data65
+00:1333 _print_sl_out65
+00:1336 fail_round4_vblank
+00:134d _wait_ly_26
+00:1353 _wait_ly_27
+00:1369 _print_results_halt_12
+00:136c _test_failure_cb_10
+00:1374 _print_sl_data66
+00:1383 _print_sl_out66
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/intr_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/intr_timing/baseline_0000.png
new file mode 100644
index 000000000..367742f57
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/intr_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/intr_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/intr_timing/test.gb
new file mode 100644
index 000000000..fc0248ce6
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/intr_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/intr_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/intr_timing/test.sym
new file mode 100644
index 000000000..78f547ba7
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/intr_timing/test.sym
@@ -0,0 +1,208 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/intr_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0157 test_round1
+00:01a7 _wait_ly_4
+00:01ad _wait_ly_5
+00:01c3 _print_results_halt_1
+00:01c6 _test_failure_cb_0
+00:01ce _print_sl_data55
+00:01dc _print_sl_out55
+00:01df finish_round1
+00:01e1 test_round2
+00:0232 _wait_ly_6
+00:0238 _wait_ly_7
+00:024e _print_results_halt_2
+00:0251 _test_failure_cb_1
+00:0259 _print_sl_data56
+00:0267 _print_sl_out56
+00:026a finish_round2
+00:026f test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.gb
new file mode 100644
index 000000000..ccd0466aa
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.sym
new file mode 100644
index 000000000..d91d4810d
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.sym
@@ -0,0 +1,223 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/jp_cc_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0184 test_finish
+00:0198 _wait_ly_6
+00:019e _wait_ly_7
+00:01b4 _print_results_halt_1
+00:01b7 _test_ok_cb_0
+00:01bf _print_sl_data55
+00:01c7 _print_sl_out55
+00:01ca wram_test
+00:01cd fail_round1
+00:01e1 _wait_ly_8
+00:01e7 _wait_ly_9
+00:01fd _print_results_halt_2
+00:0200 _test_failure_cb_0
+00:0208 _print_sl_data56
+00:0216 _print_sl_out56
+00:0219 fail_round2
+00:022d _wait_ly_10
+00:0233 _wait_ly_11
+00:0249 _print_results_halt_3
+00:024c _test_failure_cb_1
+00:0254 _print_sl_data57
+00:0262 _print_sl_out57
+00:1f80 hiram_test
+00:1f87 _wait_ly_12
+00:1f8d _wait_ly_13
+00:1fa1 test_round2
+00:1fa8 _wait_ly_14
+00:1fae _wait_ly_15
+00:1fca finish_round1
+00:1ada finish_round2
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_timing/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_timing/test.gb
new file mode 100644
index 000000000..671a7bbcf
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_timing/test.sym
new file mode 100644
index 000000000..d30786137
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/jp_timing/test.sym
@@ -0,0 +1,223 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/jp_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0184 test_finish
+00:0198 _wait_ly_6
+00:019e _wait_ly_7
+00:01b4 _print_results_halt_1
+00:01b7 _test_ok_cb_0
+00:01bf _print_sl_data55
+00:01c7 _print_sl_out55
+00:01ca wram_test
+00:01cd fail_round1
+00:01e1 _wait_ly_8
+00:01e7 _wait_ly_9
+00:01fd _print_results_halt_2
+00:0200 _test_failure_cb_0
+00:0208 _print_sl_data56
+00:0216 _print_sl_out56
+00:0219 fail_round2
+00:022d _wait_ly_10
+00:0233 _wait_ly_11
+00:0249 _print_results_halt_3
+00:024c _test_failure_cb_1
+00:0254 _print_sl_data57
+00:0262 _print_sl_out57
+00:1f80 hiram_test
+00:1f87 _wait_ly_12
+00:1f8d _wait_ly_13
+00:1fa1 test_round2
+00:1fa8 _wait_ly_14
+00:1fae _wait_ly_15
+00:1fca finish_round1
+00:1ada finish_round2
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/baseline_0000.png
new file mode 100644
index 000000000..be0ce56b7
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.gb
new file mode 100644
index 000000000..4091efade
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.sym
new file mode 100644
index 000000000..a7994dc6d
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.sym
@@ -0,0 +1,202 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/ld_hl_sp_e_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0187 test_finish
+00:01cb wram_test
+00:01d1 hiram_test
+00:01d3 _wait_ly_6
+00:01d9 _wait_ly_7
+00:01ee finish_round1
+00:01f0 _wait_ly_8
+00:01f6 _wait_ly_9
+00:020c finish_round2
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/baseline_0000.png
new file mode 100644
index 000000000..b1b0446c4
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.gb
new file mode 100644
index 000000000..9f3d5fad7
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.sym
new file mode 100644
index 000000000..bb30af546
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/oam_dma_restart.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0171 test_finish
+00:01a1 hiram_test
+00:01a6 _wait_ly_6
+00:01ac _wait_ly_7
+00:01c6 _wait_ly_8
+00:01cc _wait_ly_9
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/baseline_0000.png
new file mode 100644
index 000000000..177f3bdd3
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.gb
new file mode 100644
index 000000000..88687e9c4
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.sym
new file mode 100644
index 000000000..273d38beb
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.sym
@@ -0,0 +1,218 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/oam_dma_start.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:015f test_round1
+00:0186 _wait_ly_4
+00:018c _wait_ly_5
+00:019c fail_round1
+00:01b0 _wait_ly_6
+00:01b6 _wait_ly_7
+00:01cc _print_results_halt_1
+00:01cf _test_failure_cb_0
+00:01d7 _print_sl_data55
+00:01ed _print_sl_out55
+00:01f0 finish_round1
+00:01fd test_round2
+00:022a _wait_ly_8
+00:0230 _wait_ly_9
+00:0240 fail_round2
+00:0254 _wait_ly_10
+00:025a _wait_ly_11
+00:0270 _print_results_halt_2
+00:0273 _test_failure_cb_1
+00:027b _print_sl_data56
+00:0291 _print_sl_out56
+00:0294 finish_round2
+00:0299 test_finish
+00:c014 vector_10
+00:c016 vector_38
+00:c018 round1_oam
+00:c019 round1_b
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/baseline_0000.png
new file mode 100644
index 000000000..b1b0446c4
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.gb
new file mode 100644
index 000000000..af20b3fbf
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.sym
new file mode 100644
index 000000000..bcd8a4683
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/oam_dma_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0171 test_finish
+00:01a1 hiram_test
+00:01a6 _wait_ly_6
+00:01ac _wait_ly_7
+00:01bd _wait_ly_8
+00:01c3 _wait_ly_9
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/pop_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/pop_timing/baseline_0000.png
new file mode 100644
index 000000000..ed9567863
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/pop_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/pop_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/pop_timing/test.gb
new file mode 100644
index 000000000..e58237ca0
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/pop_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/pop_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/pop_timing/test.sym
new file mode 100644
index 000000000..ee3bc1203
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/pop_timing/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/pop_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:02ad test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/baseline_0000.png
new file mode 100644
index 000000000..25b9aab9e
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/test.gb
new file mode 100644
index 000000000..b57ffa261
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/test.sym
new file mode 100644
index 000000000..d259ae971
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/push_timing/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/push_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0177 test_finish
+00:01bb hiram_test
+00:01c2 _wait_ly_6
+00:01c8 _wait_ly_7
+00:01e2 _wait_ly_8
+00:01e8 _wait_ly_9
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/baseline_0000.png
new file mode 100644
index 000000000..724d67aea
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.gb
new file mode 100644
index 000000000..1a034b1ac
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.sym
new file mode 100644
index 000000000..c376b30e3
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/rapid_di_ei.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:018b test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.gb
new file mode 100644
index 000000000..acb9f20cd
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.sym
new file mode 100644
index 000000000..a47bbfc12
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.sym
@@ -0,0 +1,223 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/ret_cc_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:015c test_round1
+00:015c _wait_ly_4
+00:0162 _wait_ly_5
+00:017c _wait_ly_6
+00:0182 _wait_ly_7
+00:0192 finish_round1
+00:01a9 _wait_ly_8
+00:01af _wait_ly_9
+00:01c5 _print_results_halt_1
+00:01c8 _test_failure_cb_0
+00:01d0 _print_sl_data55
+00:01de _print_sl_out55
+00:01e1 test_round2
+00:01e1 _wait_ly_10
+00:01e7 _wait_ly_11
+00:01fb _wait_ly_12
+00:0201 _wait_ly_13
+00:0212 finish_round2
+00:0229 _wait_ly_14
+00:022f _wait_ly_15
+00:0245 _print_results_halt_2
+00:0248 _test_failure_cb_1
+00:0250 _print_sl_data56
+00:025e _print_sl_out56
+00:0261 test_success
+00:0275 _wait_ly_16
+00:027b _wait_ly_17
+00:0291 _print_results_halt_3
+00:0294 _test_ok_cb_0
+00:029c _print_sl_data57
+00:02a4 _print_sl_out57
+00:02a7 hiram_cb
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_timing/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_timing/test.gb
new file mode 100644
index 000000000..c53dc71fd
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_timing/test.sym
new file mode 100644
index 000000000..11f387de4
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/ret_timing/test.sym
@@ -0,0 +1,223 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/ret_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:015c test_round1
+00:015c _wait_ly_4
+00:0162 _wait_ly_5
+00:017c _wait_ly_6
+00:0182 _wait_ly_7
+00:0193 finish_round1
+00:01aa _wait_ly_8
+00:01b0 _wait_ly_9
+00:01c6 _print_results_halt_1
+00:01c9 _test_failure_cb_0
+00:01d1 _print_sl_data55
+00:01df _print_sl_out55
+00:01e2 test_round2
+00:01e2 _wait_ly_10
+00:01e8 _wait_ly_11
+00:01fc _wait_ly_12
+00:0202 _wait_ly_13
+00:0214 finish_round2
+00:022b _wait_ly_14
+00:0231 _wait_ly_15
+00:0247 _print_results_halt_2
+00:024a _test_failure_cb_1
+00:0252 _print_sl_data56
+00:0260 _print_sl_out56
+00:0263 test_success
+00:0277 _wait_ly_16
+00:027d _wait_ly_17
+00:0293 _print_results_halt_3
+00:0296 _test_ok_cb_0
+00:029e _print_sl_data57
+00:02a6 _print_sl_out57
+00:02a9 hiram_cb
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/baseline_0000.png
new file mode 100644
index 000000000..1cadf780c
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.gb
new file mode 100644
index 000000000..e01c0031a
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.sym
new file mode 100644
index 000000000..8e838d547
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/reti_intr_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0160 test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_timing/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_timing/test.gb
new file mode 100644
index 000000000..d90276343
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_timing/test.sym
new file mode 100644
index 000000000..cc3bd7b43
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/reti_timing/test.sym
@@ -0,0 +1,223 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/reti_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:015c test_round1
+00:015c _wait_ly_4
+00:0162 _wait_ly_5
+00:017c _wait_ly_6
+00:0182 _wait_ly_7
+00:0193 finish_round1
+00:01aa _wait_ly_8
+00:01b0 _wait_ly_9
+00:01c6 _print_results_halt_1
+00:01c9 _test_failure_cb_0
+00:01d1 _print_sl_data55
+00:01df _print_sl_out55
+00:01e2 test_round2
+00:01e2 _wait_ly_10
+00:01e8 _wait_ly_11
+00:01fc _wait_ly_12
+00:0202 _wait_ly_13
+00:0214 finish_round2
+00:022b _wait_ly_14
+00:0231 _wait_ly_15
+00:0247 _print_results_halt_2
+00:024a _test_failure_cb_1
+00:0252 _print_sl_data56
+00:0260 _print_sl_out56
+00:0263 test_success
+00:0277 _wait_ly_16
+00:027d _wait_ly_17
+00:0293 _print_results_halt_3
+00:0296 _test_ok_cb_0
+00:029e _print_sl_data57
+00:02a6 _print_sl_out57
+00:02a9 hiram_cb
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rst_timing/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rst_timing/baseline_0000.png
new file mode 100644
index 000000000..92be0be99
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rst_timing/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rst_timing/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rst_timing/test.gb
new file mode 100644
index 000000000..b77fd99f9
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rst_timing/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rst_timing/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rst_timing/test.sym
new file mode 100644
index 000000000..5c3762543
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/rst_timing/test.sym
@@ -0,0 +1,201 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/rst_timing.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0151 _wait_ly_4
+00:0157 _wait_ly_5
+00:0177 test_finish
+00:01bb hiram_test
+00:01be _wait_ly_6
+00:01c4 _wait_ly_7
+00:01d9 finish_round1
+00:01dc _wait_ly_8
+00:01e2 _wait_ly_9
+00:01f8 finish_round2
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.gb
new file mode 100644
index 000000000..4b71b5a29
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.sav b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.sav
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.sym
new file mode 100644
index 000000000..f266d3b95
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.sym
@@ -0,0 +1,198 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/serial/boot_sclk_align-dmgABCXmgb.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:3828 _wait_ly_4
+00:382e _wait_ly_5
+00:3844 _print_results_halt_1
+00:3847 _test_failure_cb_0
+00:384f _print_sl_data55
+00:385e _print_sl_out55
+00:3861 test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/div_write/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/div_write/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/div_write/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.gb
new file mode 100644
index 000000000..60f4ec325
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.sym
new file mode 100644
index 000000000..feb7bf6ff
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.sym
@@ -0,0 +1,205 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/div_write.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
+00:0182 _wait_ly_4
+00:0188 _wait_ly_5
+00:019e _print_results_halt_1
+00:01a1 _test_ok_cb_0
+00:01a9 _print_sl_data55
+00:01b1 _print_sl_out55
+00:01b4 test_failure
+00:01c8 _wait_ly_6
+00:01ce _wait_ly_7
+00:01e4 _print_results_halt_2
+00:01e7 _test_failure_cb_0
+00:01ef _print_sl_data56
+00:01fa _print_sl_out56
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/baseline_0000.png
new file mode 100644
index 000000000..df025f2f2
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.gb
new file mode 100644
index 000000000..95522c15d
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.sym
new file mode 100644
index 000000000..b4a5cd5bc
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/rapid_toggle.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
+00:0186 _wait_ly_4
+00:018c _wait_ly_5
+00:01a2 _print_results_halt_1
+00:01a5 _test_failure_cb_0
+00:01ad _print_sl_data55
+00:01bb _print_sl_out55
+00:01be test_finish
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00/baseline_0000.png
new file mode 100644
index 000000000..477643895
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.gb
new file mode 100644
index 000000000..afb0f6c1e
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.sym
new file mode 100644
index 000000000..27f27b8aa
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tim00.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/baseline_0000.png
new file mode 100644
index 000000000..477643895
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.gb
new file mode 100644
index 000000000..8bc8a83e4
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.sym
new file mode 100644
index 000000000..fa6a0342e
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tim00_div_trigger.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01/baseline_0000.png
new file mode 100644
index 000000000..2edb1ad91
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.gb
new file mode 100644
index 000000000..1e6391811
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.sym
new file mode 100644
index 000000000..f01524dea
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tim01.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/baseline_0000.png
new file mode 100644
index 000000000..dbccb8a19
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.gb
new file mode 100644
index 000000000..c16aa0c8e
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.sym
new file mode 100644
index 000000000..ed41503b5
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tim01_div_trigger.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10/baseline_0000.png
new file mode 100644
index 000000000..477643895
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.gb
new file mode 100644
index 000000000..1848096cf
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.sym
new file mode 100644
index 000000000..bcb8a2318
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tim10.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/baseline_0000.png
new file mode 100644
index 000000000..5452e96cc
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.gb
new file mode 100644
index 000000000..0272d5a44
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.sym
new file mode 100644
index 000000000..a981747b1
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tim10_div_trigger.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11/baseline_0000.png
new file mode 100644
index 000000000..477643895
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.gb
new file mode 100644
index 000000000..cfa08a828
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.sym
new file mode 100644
index 000000000..b9e6628d6
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tim11.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/baseline_0000.png
new file mode 100644
index 000000000..477643895
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.gb
new file mode 100644
index 000000000..9bc1e4e9f
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.sym
new file mode 100644
index 000000000..ac4941fa6
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tim11_div_trigger.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/baseline_0000.png
new file mode 100644
index 000000000..de7890388
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.gb
new file mode 100644
index 000000000..ae58d4ce6
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.sym
new file mode 100644
index 000000000..45c4b2ead
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tima_reload.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/baseline_0000.png
new file mode 100644
index 000000000..f4dff77b8
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.gb
new file mode 100644
index 000000000..c91a23678
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.sym
new file mode 100644
index 000000000..c45291083
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tima_write_reloading.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/baseline_0000.png
new file mode 100644
index 000000000..8cd0a9fde
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.gb
new file mode 100644
index 000000000..56d1303ee
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.sym
new file mode 100644
index 000000000..c34066714
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.sym
@@ -0,0 +1,192 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/timer/tma_write_reloading.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.gb
new file mode 100644
index 000000000..1b1506b07
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.sym
new file mode 100644
index 000000000..6e0cc401c
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.sym
@@ -0,0 +1,226 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/multicart_rom_8Mb.gb".
+
+[labels]
+01:4001 print_load_font
+01:400e print_string
+01:4018 print_a
+01:4022 print_newline
+01:402d print_digit
+01:403a print_regs
+01:4043 _print_sl_data0
+01:4049 _print_sl_out0
+01:4056 _print_sl_data1
+01:405c _print_sl_out1
+01:406e _print_sl_data2
+01:4074 _print_sl_out2
+01:4081 _print_sl_data3
+01:4087 _print_sl_out3
+01:4099 _print_sl_data4
+01:409f _print_sl_out4
+01:40ac _print_sl_data5
+01:40b2 _print_sl_out5
+01:40c4 _print_sl_data6
+01:40ca _print_sl_out6
+01:40d7 _print_sl_data7
+01:40dd _print_sl_out7
+01:4134 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:4924 memcpy
+01:492d memset
+01:4936 memcmp
+01:4944 clear_vram
+01:494e clear_oam
+01:4958 disable_lcd_safe
+01:495e _wait_ly_0
+01:4964 _wait_ly_1
+01:496d reset_screen
+01:4981 process_results
+01:4995 _wait_ly_2
+01:499b _wait_ly_3
+01:49b1 _print_results_halt_0
+01:49b4 _process_results_cb
+01:49bf _print_sl_data8
+01:49c9 _print_sl_out8
+01:49e3 _print_sl_data9
+01:49ee _print_sl_out9
+01:4a06 _print_sl_data10
+01:4a12 _print_sl_out10
+01:4a13 dump_mem
+01:4a32 _dump_mem_line
+01:4a5c _check_asserts
+01:4a6a _print_sl_data11
+01:4a6d _print_sl_out11
+01:4a79 _print_sl_data12
+01:4a7b _print_sl_out12
+01:4a83 _print_sl_data13
+01:4a86 _print_sl_out13
+01:4a90 __check_assert_fail0
+01:4a9b _print_sl_data14
+01:4a9e _print_sl_out14
+01:4aa1 __check_assert_ok0
+01:4aa9 _print_sl_data15
+01:4aae _print_sl_out15
+01:4ab0 __check_assert_skip0
+01:4ab8 _print_sl_data16
+01:4ac0 _print_sl_out16
+01:4ac0 __check_assert_out0
+01:4acc _print_sl_data17
+01:4ace _print_sl_out17
+01:4ad6 _print_sl_data18
+01:4ad9 _print_sl_out18
+01:4ae3 __check_assert_fail1
+01:4aee _print_sl_data19
+01:4af1 _print_sl_out19
+01:4af4 __check_assert_ok1
+01:4afc _print_sl_data20
+01:4b01 _print_sl_out20
+01:4b03 __check_assert_skip1
+01:4b0b _print_sl_data21
+01:4b13 _print_sl_out21
+01:4b13 __check_assert_out1
+01:4b1e _print_sl_data22
+01:4b21 _print_sl_out22
+01:4b2d _print_sl_data23
+01:4b2f _print_sl_out23
+01:4b37 _print_sl_data24
+01:4b3a _print_sl_out24
+01:4b44 __check_assert_fail2
+01:4b4f _print_sl_data25
+01:4b52 _print_sl_out25
+01:4b55 __check_assert_ok2
+01:4b5d _print_sl_data26
+01:4b62 _print_sl_out26
+01:4b64 __check_assert_skip2
+01:4b6c _print_sl_data27
+01:4b74 _print_sl_out27
+01:4b74 __check_assert_out2
+01:4b80 _print_sl_data28
+01:4b82 _print_sl_out28
+01:4b8a _print_sl_data29
+01:4b8d _print_sl_out29
+01:4b97 __check_assert_fail3
+01:4ba2 _print_sl_data30
+01:4ba5 _print_sl_out30
+01:4ba8 __check_assert_ok3
+01:4bb0 _print_sl_data31
+01:4bb5 _print_sl_out31
+01:4bb7 __check_assert_skip3
+01:4bbf _print_sl_data32
+01:4bc7 _print_sl_out32
+01:4bc7 __check_assert_out3
+01:4bd2 _print_sl_data33
+01:4bd5 _print_sl_out33
+01:4be1 _print_sl_data34
+01:4be3 _print_sl_out34
+01:4beb _print_sl_data35
+01:4bee _print_sl_out35
+01:4bf8 __check_assert_fail4
+01:4c03 _print_sl_data36
+01:4c06 _print_sl_out36
+01:4c09 __check_assert_ok4
+01:4c11 _print_sl_data37
+01:4c16 _print_sl_out37
+01:4c18 __check_assert_skip4
+01:4c20 _print_sl_data38
+01:4c28 _print_sl_out38
+01:4c28 __check_assert_out4
+01:4c34 _print_sl_data39
+01:4c36 _print_sl_out39
+01:4c3e _print_sl_data40
+01:4c41 _print_sl_out40
+01:4c4b __check_assert_fail5
+01:4c56 _print_sl_data41
+01:4c59 _print_sl_out41
+01:4c5c __check_assert_ok5
+01:4c64 _print_sl_data42
+01:4c69 _print_sl_out42
+01:4c6b __check_assert_skip5
+01:4c73 _print_sl_data43
+01:4c7b _print_sl_out43
+01:4c7b __check_assert_out5
+01:4c86 _print_sl_data44
+01:4c89 _print_sl_out44
+01:4c95 _print_sl_data45
+01:4c97 _print_sl_out45
+01:4c9f _print_sl_data46
+01:4ca2 _print_sl_out46
+01:4cac __check_assert_fail6
+01:4cb7 _print_sl_data47
+01:4cba _print_sl_out47
+01:4cbd __check_assert_ok6
+01:4cc5 _print_sl_data48
+01:4cca _print_sl_out48
+01:4ccc __check_assert_skip6
+01:4cd4 _print_sl_data49
+01:4cdc _print_sl_out49
+01:4cdc __check_assert_out6
+01:4ce8 _print_sl_data50
+01:4cea _print_sl_out50
+01:4cf2 _print_sl_data51
+01:4cf5 _print_sl_out51
+01:4cff __check_assert_fail7
+01:4d0a _print_sl_data52
+01:4d0d _print_sl_out52
+01:4d10 __check_assert_ok7
+01:4d18 _print_sl_data53
+01:4d1d _print_sl_out53
+01:4d1f __check_assert_skip7
+01:4d27 _print_sl_data54
+01:4d2f _print_sl_out54
+01:4d2f __check_assert_out7
+00:016b fail
+00:017f _wait_ly_4
+00:0185 _wait_ly_5
+00:019b _print_results_halt_1
+00:019e _fail_cb
+00:01a6 _print_sl_data55
+00:01b2 _print_sl_out55
+00:01c2 _print_sl_data56
+00:01ce _print_sl_out56
+00:01d8 _print_sl_data57
+00:01e4 _print_sl_out57
+00:01ef _print_sl_data58
+00:01f5 _print_sl_out58
+00:0208 _print_sl_data59
+00:0215 _print_sl_out59
+00:0225 _print_sl_data60
+00:0232 _print_sl_out60
+00:0242 _print_sl_data61
+00:024f _print_sl_out61
+00:025a c000_functions_start
+00:025a run_test_suite
+00:0284 _wait_ly_6
+00:028a _wait_ly_7
+00:02a0 _print_results_halt_2
+00:02a3 _test_ok_cb_0
+00:02ab _print_sl_data62
+00:02b3 _print_sl_out62
+00:02b6 run_tests
+00:02c4 run_test_cases
+00:02d2 test_case
+00:02ef restore_mbc1
+00:02f8 switch_bank
+00:0309 fetch_expected_value
+00:0328 c000_functions_end
+00:0328 expected_banks
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.gb
new file mode 100644
index 000000000..e00f3dfc2
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.sym
new file mode 100644
index 000000000..c24fc1363
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.sym
@@ -0,0 +1,252 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/ram_256Kb.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test_round1
+00:016e test_round2
+00:01d2 test_round3
+00:0232 test_round4
+00:02a0 test_round5
+00:02fc test_round6
+00:0330 test_finish
+00:0347 _wait_ly_4
+00:034d _wait_ly_5
+00:0363 _print_results_halt_1
+00:0366 _test_ok_cb_0
+00:036e _print_sl_data55
+00:0376 _print_sl_out55
+00:0379 copy_bank_data
+00:0398 check_bank_data
+00:03b8 all_ff
+00:03c8 all_00
+00:1000 bank_data
+00:1040 clear_ram
+00:1062 fail_round1
+00:1079 _wait_ly_6
+00:107f _wait_ly_7
+00:1095 _print_results_halt_2
+00:1098 _test_failure_cb_0
+00:10a0 _print_sl_data56
+00:10ae _print_sl_out56
+00:10b1 fail_round2
+00:10c8 _wait_ly_8
+00:10ce _wait_ly_9
+00:10e4 _print_results_halt_3
+00:10e7 _test_failure_cb_1
+00:10ef _print_sl_data57
+00:10fd _print_sl_out57
+00:1100 fail_round3
+00:1117 _wait_ly_10
+00:111d _wait_ly_11
+00:1133 _print_results_halt_4
+00:1136 _test_failure_cb_2
+00:113e _print_sl_data58
+00:114c _print_sl_out58
+00:114f fail_round4
+00:1166 _wait_ly_12
+00:116c _wait_ly_13
+00:1182 _print_results_halt_5
+00:1185 _test_failure_cb_3
+00:118d _print_sl_data59
+00:119b _print_sl_out59
+00:119e fail_round5
+00:11b5 _wait_ly_14
+00:11bb _wait_ly_15
+00:11d1 _print_results_halt_6
+00:11d4 _test_failure_cb_4
+00:11dc _print_sl_data60
+00:11ea _print_sl_out60
+00:11ed fail_round6
+00:1204 _wait_ly_16
+00:120a _wait_ly_17
+00:1220 _print_results_halt_7
+00:1223 _test_failure_cb_5
+00:122b _print_sl_data61
+00:1239 _print_sl_out61
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.gb
new file mode 100644
index 000000000..c15f9eb89
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.sym
new file mode 100644
index 000000000..8f184d5a5
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.sym
@@ -0,0 +1,244 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/ram_64Kb.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0150 test_round1
+00:016e test_round2
+00:01c2 test_round3
+00:01cb test_round4
+00:01fb test_round5
+00:022c test_finish
+00:0243 _wait_ly_4
+00:0249 _wait_ly_5
+00:025f _print_results_halt_1
+00:0262 _test_ok_cb_0
+00:026a _print_sl_data55
+00:0272 _print_sl_out55
+00:0275 copy_bank_data
+00:028d check_bank_data
+00:02a6 all_ff
+00:02b6 all_00
+00:1000 bank_data
+00:1010 clear_ram
+00:1032 fail_round1
+00:1049 _wait_ly_6
+00:104f _wait_ly_7
+00:1065 _print_results_halt_2
+00:1068 _test_failure_cb_0
+00:1070 _print_sl_data56
+00:107e _print_sl_out56
+00:1081 fail_round2
+00:1098 _wait_ly_8
+00:109e _wait_ly_9
+00:10b4 _print_results_halt_3
+00:10b7 _test_failure_cb_1
+00:10bf _print_sl_data57
+00:10cd _print_sl_out57
+00:10d0 fail_round3
+00:10e7 _wait_ly_10
+00:10ed _wait_ly_11
+00:1103 _print_results_halt_4
+00:1106 _test_failure_cb_2
+00:110e _print_sl_data58
+00:111c _print_sl_out58
+00:111f fail_round4
+00:1136 _wait_ly_12
+00:113c _wait_ly_13
+00:1152 _print_results_halt_5
+00:1155 _test_failure_cb_3
+00:115d _print_sl_data59
+00:116b _print_sl_out59
+00:116e fail_round5
+00:1185 _wait_ly_14
+00:118b _wait_ly_15
+00:11a1 _print_results_halt_6
+00:11a4 _test_failure_cb_4
+00:11ac _print_sl_data60
+00:11ba _print_sl_out60
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.gb
new file mode 100644
index 000000000..37d016acb
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.sym
new file mode 100644
index 000000000..47e9eed71
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.sym
@@ -0,0 +1,226 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/rom_16Mb.gb".
+
+[labels]
+01:4c00 print_load_font
+01:4c0d print_string
+01:4c17 print_a
+01:4c21 print_newline
+01:4c2c print_digit
+01:4c39 print_regs
+01:4c42 _print_sl_data0
+01:4c48 _print_sl_out0
+01:4c55 _print_sl_data1
+01:4c5b _print_sl_out1
+01:4c6d _print_sl_data2
+01:4c73 _print_sl_out2
+01:4c80 _print_sl_data3
+01:4c86 _print_sl_out3
+01:4c98 _print_sl_data4
+01:4c9e _print_sl_out4
+01:4cab _print_sl_data5
+01:4cb1 _print_sl_out5
+01:4cc3 _print_sl_data6
+01:4cc9 _print_sl_out6
+01:4cd6 _print_sl_data7
+01:4cdc _print_sl_out7
+01:4001 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f1 memcpy
+01:47fa memset
+01:4803 memcmp
+01:4811 clear_vram
+01:481b clear_oam
+01:4825 disable_lcd_safe
+01:482b _wait_ly_0
+01:4831 _wait_ly_1
+01:483a reset_screen
+01:484e process_results
+01:4862 _wait_ly_2
+01:4868 _wait_ly_3
+01:487e _print_results_halt_0
+01:4881 _process_results_cb
+01:488c _print_sl_data8
+01:4896 _print_sl_out8
+01:48b0 _print_sl_data9
+01:48bb _print_sl_out9
+01:48d3 _print_sl_data10
+01:48df _print_sl_out10
+01:48e0 dump_mem
+01:48ff _dump_mem_line
+01:4929 _check_asserts
+01:4937 _print_sl_data11
+01:493a _print_sl_out11
+01:4946 _print_sl_data12
+01:4948 _print_sl_out12
+01:4950 _print_sl_data13
+01:4953 _print_sl_out13
+01:495d __check_assert_fail0
+01:4968 _print_sl_data14
+01:496b _print_sl_out14
+01:496e __check_assert_ok0
+01:4976 _print_sl_data15
+01:497b _print_sl_out15
+01:497d __check_assert_skip0
+01:4985 _print_sl_data16
+01:498d _print_sl_out16
+01:498d __check_assert_out0
+01:4999 _print_sl_data17
+01:499b _print_sl_out17
+01:49a3 _print_sl_data18
+01:49a6 _print_sl_out18
+01:49b0 __check_assert_fail1
+01:49bb _print_sl_data19
+01:49be _print_sl_out19
+01:49c1 __check_assert_ok1
+01:49c9 _print_sl_data20
+01:49ce _print_sl_out20
+01:49d0 __check_assert_skip1
+01:49d8 _print_sl_data21
+01:49e0 _print_sl_out21
+01:49e0 __check_assert_out1
+01:49eb _print_sl_data22
+01:49ee _print_sl_out22
+01:49fa _print_sl_data23
+01:49fc _print_sl_out23
+01:4a04 _print_sl_data24
+01:4a07 _print_sl_out24
+01:4a11 __check_assert_fail2
+01:4a1c _print_sl_data25
+01:4a1f _print_sl_out25
+01:4a22 __check_assert_ok2
+01:4a2a _print_sl_data26
+01:4a2f _print_sl_out26
+01:4a31 __check_assert_skip2
+01:4a39 _print_sl_data27
+01:4a41 _print_sl_out27
+01:4a41 __check_assert_out2
+01:4a4d _print_sl_data28
+01:4a4f _print_sl_out28
+01:4a57 _print_sl_data29
+01:4a5a _print_sl_out29
+01:4a64 __check_assert_fail3
+01:4a6f _print_sl_data30
+01:4a72 _print_sl_out30
+01:4a75 __check_assert_ok3
+01:4a7d _print_sl_data31
+01:4a82 _print_sl_out31
+01:4a84 __check_assert_skip3
+01:4a8c _print_sl_data32
+01:4a94 _print_sl_out32
+01:4a94 __check_assert_out3
+01:4a9f _print_sl_data33
+01:4aa2 _print_sl_out33
+01:4aae _print_sl_data34
+01:4ab0 _print_sl_out34
+01:4ab8 _print_sl_data35
+01:4abb _print_sl_out35
+01:4ac5 __check_assert_fail4
+01:4ad0 _print_sl_data36
+01:4ad3 _print_sl_out36
+01:4ad6 __check_assert_ok4
+01:4ade _print_sl_data37
+01:4ae3 _print_sl_out37
+01:4ae5 __check_assert_skip4
+01:4aed _print_sl_data38
+01:4af5 _print_sl_out38
+01:4af5 __check_assert_out4
+01:4b01 _print_sl_data39
+01:4b03 _print_sl_out39
+01:4b0b _print_sl_data40
+01:4b0e _print_sl_out40
+01:4b18 __check_assert_fail5
+01:4b23 _print_sl_data41
+01:4b26 _print_sl_out41
+01:4b29 __check_assert_ok5
+01:4b31 _print_sl_data42
+01:4b36 _print_sl_out42
+01:4b38 __check_assert_skip5
+01:4b40 _print_sl_data43
+01:4b48 _print_sl_out43
+01:4b48 __check_assert_out5
+01:4b53 _print_sl_data44
+01:4b56 _print_sl_out44
+01:4b62 _print_sl_data45
+01:4b64 _print_sl_out45
+01:4b6c _print_sl_data46
+01:4b6f _print_sl_out46
+01:4b79 __check_assert_fail6
+01:4b84 _print_sl_data47
+01:4b87 _print_sl_out47
+01:4b8a __check_assert_ok6
+01:4b92 _print_sl_data48
+01:4b97 _print_sl_out48
+01:4b99 __check_assert_skip6
+01:4ba1 _print_sl_data49
+01:4ba9 _print_sl_out49
+01:4ba9 __check_assert_out6
+01:4bb5 _print_sl_data50
+01:4bb7 _print_sl_out50
+01:4bbf _print_sl_data51
+01:4bc2 _print_sl_out51
+01:4bcc __check_assert_fail7
+01:4bd7 _print_sl_data52
+01:4bda _print_sl_out52
+01:4bdd __check_assert_ok7
+01:4be5 _print_sl_data53
+01:4bea _print_sl_out53
+01:4bec __check_assert_skip7
+01:4bf4 _print_sl_data54
+01:4bfc _print_sl_out54
+01:4bfc __check_assert_out7
+00:016b fail
+00:017f _wait_ly_4
+00:0185 _wait_ly_5
+00:019b _print_results_halt_1
+00:019e _fail_cb
+00:01a6 _print_sl_data55
+00:01b2 _print_sl_out55
+00:01c2 _print_sl_data56
+00:01ce _print_sl_out56
+00:01d8 _print_sl_data57
+00:01e4 _print_sl_out57
+00:01ef _print_sl_data58
+00:01f5 _print_sl_out58
+00:0208 _print_sl_data59
+00:0215 _print_sl_out59
+00:0225 _print_sl_data60
+00:0232 _print_sl_out60
+00:0242 _print_sl_data61
+00:024f _print_sl_out61
+00:025a c000_functions_start
+00:025a run_test_suite
+00:0284 _wait_ly_6
+00:028a _wait_ly_7
+00:02a0 _print_results_halt_2
+00:02a3 _test_ok_cb_0
+00:02ab _print_sl_data62
+00:02b3 _print_sl_out62
+00:02b6 run_tests
+00:02c4 run_test_cases
+00:02d2 test_case
+00:02ef restore_mbc1
+00:02f8 switch_bank
+00:0309 fetch_expected_value
+00:0328 c000_functions_end
+00:0328 expected_banks
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.gb
new file mode 100644
index 000000000..9b638d498
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.sym
new file mode 100644
index 000000000..bfe04a18b
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.sym
@@ -0,0 +1,226 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/rom_1Mb.gb".
+
+[labels]
+01:4c00 print_load_font
+01:4c0d print_string
+01:4c17 print_a
+01:4c21 print_newline
+01:4c2c print_digit
+01:4c39 print_regs
+01:4c42 _print_sl_data0
+01:4c48 _print_sl_out0
+01:4c55 _print_sl_data1
+01:4c5b _print_sl_out1
+01:4c6d _print_sl_data2
+01:4c73 _print_sl_out2
+01:4c80 _print_sl_data3
+01:4c86 _print_sl_out3
+01:4c98 _print_sl_data4
+01:4c9e _print_sl_out4
+01:4cab _print_sl_data5
+01:4cb1 _print_sl_out5
+01:4cc3 _print_sl_data6
+01:4cc9 _print_sl_out6
+01:4cd6 _print_sl_data7
+01:4cdc _print_sl_out7
+01:4001 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f1 memcpy
+01:47fa memset
+01:4803 memcmp
+01:4811 clear_vram
+01:481b clear_oam
+01:4825 disable_lcd_safe
+01:482b _wait_ly_0
+01:4831 _wait_ly_1
+01:483a reset_screen
+01:484e process_results
+01:4862 _wait_ly_2
+01:4868 _wait_ly_3
+01:487e _print_results_halt_0
+01:4881 _process_results_cb
+01:488c _print_sl_data8
+01:4896 _print_sl_out8
+01:48b0 _print_sl_data9
+01:48bb _print_sl_out9
+01:48d3 _print_sl_data10
+01:48df _print_sl_out10
+01:48e0 dump_mem
+01:48ff _dump_mem_line
+01:4929 _check_asserts
+01:4937 _print_sl_data11
+01:493a _print_sl_out11
+01:4946 _print_sl_data12
+01:4948 _print_sl_out12
+01:4950 _print_sl_data13
+01:4953 _print_sl_out13
+01:495d __check_assert_fail0
+01:4968 _print_sl_data14
+01:496b _print_sl_out14
+01:496e __check_assert_ok0
+01:4976 _print_sl_data15
+01:497b _print_sl_out15
+01:497d __check_assert_skip0
+01:4985 _print_sl_data16
+01:498d _print_sl_out16
+01:498d __check_assert_out0
+01:4999 _print_sl_data17
+01:499b _print_sl_out17
+01:49a3 _print_sl_data18
+01:49a6 _print_sl_out18
+01:49b0 __check_assert_fail1
+01:49bb _print_sl_data19
+01:49be _print_sl_out19
+01:49c1 __check_assert_ok1
+01:49c9 _print_sl_data20
+01:49ce _print_sl_out20
+01:49d0 __check_assert_skip1
+01:49d8 _print_sl_data21
+01:49e0 _print_sl_out21
+01:49e0 __check_assert_out1
+01:49eb _print_sl_data22
+01:49ee _print_sl_out22
+01:49fa _print_sl_data23
+01:49fc _print_sl_out23
+01:4a04 _print_sl_data24
+01:4a07 _print_sl_out24
+01:4a11 __check_assert_fail2
+01:4a1c _print_sl_data25
+01:4a1f _print_sl_out25
+01:4a22 __check_assert_ok2
+01:4a2a _print_sl_data26
+01:4a2f _print_sl_out26
+01:4a31 __check_assert_skip2
+01:4a39 _print_sl_data27
+01:4a41 _print_sl_out27
+01:4a41 __check_assert_out2
+01:4a4d _print_sl_data28
+01:4a4f _print_sl_out28
+01:4a57 _print_sl_data29
+01:4a5a _print_sl_out29
+01:4a64 __check_assert_fail3
+01:4a6f _print_sl_data30
+01:4a72 _print_sl_out30
+01:4a75 __check_assert_ok3
+01:4a7d _print_sl_data31
+01:4a82 _print_sl_out31
+01:4a84 __check_assert_skip3
+01:4a8c _print_sl_data32
+01:4a94 _print_sl_out32
+01:4a94 __check_assert_out3
+01:4a9f _print_sl_data33
+01:4aa2 _print_sl_out33
+01:4aae _print_sl_data34
+01:4ab0 _print_sl_out34
+01:4ab8 _print_sl_data35
+01:4abb _print_sl_out35
+01:4ac5 __check_assert_fail4
+01:4ad0 _print_sl_data36
+01:4ad3 _print_sl_out36
+01:4ad6 __check_assert_ok4
+01:4ade _print_sl_data37
+01:4ae3 _print_sl_out37
+01:4ae5 __check_assert_skip4
+01:4aed _print_sl_data38
+01:4af5 _print_sl_out38
+01:4af5 __check_assert_out4
+01:4b01 _print_sl_data39
+01:4b03 _print_sl_out39
+01:4b0b _print_sl_data40
+01:4b0e _print_sl_out40
+01:4b18 __check_assert_fail5
+01:4b23 _print_sl_data41
+01:4b26 _print_sl_out41
+01:4b29 __check_assert_ok5
+01:4b31 _print_sl_data42
+01:4b36 _print_sl_out42
+01:4b38 __check_assert_skip5
+01:4b40 _print_sl_data43
+01:4b48 _print_sl_out43
+01:4b48 __check_assert_out5
+01:4b53 _print_sl_data44
+01:4b56 _print_sl_out44
+01:4b62 _print_sl_data45
+01:4b64 _print_sl_out45
+01:4b6c _print_sl_data46
+01:4b6f _print_sl_out46
+01:4b79 __check_assert_fail6
+01:4b84 _print_sl_data47
+01:4b87 _print_sl_out47
+01:4b8a __check_assert_ok6
+01:4b92 _print_sl_data48
+01:4b97 _print_sl_out48
+01:4b99 __check_assert_skip6
+01:4ba1 _print_sl_data49
+01:4ba9 _print_sl_out49
+01:4ba9 __check_assert_out6
+01:4bb5 _print_sl_data50
+01:4bb7 _print_sl_out50
+01:4bbf _print_sl_data51
+01:4bc2 _print_sl_out51
+01:4bcc __check_assert_fail7
+01:4bd7 _print_sl_data52
+01:4bda _print_sl_out52
+01:4bdd __check_assert_ok7
+01:4be5 _print_sl_data53
+01:4bea _print_sl_out53
+01:4bec __check_assert_skip7
+01:4bf4 _print_sl_data54
+01:4bfc _print_sl_out54
+01:4bfc __check_assert_out7
+00:016b fail
+00:017f _wait_ly_4
+00:0185 _wait_ly_5
+00:019b _print_results_halt_1
+00:019e _fail_cb
+00:01a6 _print_sl_data55
+00:01b2 _print_sl_out55
+00:01c2 _print_sl_data56
+00:01ce _print_sl_out56
+00:01d8 _print_sl_data57
+00:01e4 _print_sl_out57
+00:01ef _print_sl_data58
+00:01f5 _print_sl_out58
+00:0208 _print_sl_data59
+00:0215 _print_sl_out59
+00:0225 _print_sl_data60
+00:0232 _print_sl_out60
+00:0242 _print_sl_data61
+00:024f _print_sl_out61
+00:025a c000_functions_start
+00:025a run_test_suite
+00:0284 _wait_ly_6
+00:028a _wait_ly_7
+00:02a0 _print_results_halt_2
+00:02a3 _test_ok_cb_0
+00:02ab _print_sl_data62
+00:02b3 _print_sl_out62
+00:02b6 run_tests
+00:02c4 run_test_cases
+00:02d2 test_case
+00:02ef restore_mbc1
+00:02f8 switch_bank
+00:0309 fetch_expected_value
+00:0328 c000_functions_end
+00:0328 expected_banks
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.gb
new file mode 100644
index 000000000..8a9ce00e7
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.sym
new file mode 100644
index 000000000..e96b0029f
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.sym
@@ -0,0 +1,226 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/rom_2Mb.gb".
+
+[labels]
+01:4c00 print_load_font
+01:4c0d print_string
+01:4c17 print_a
+01:4c21 print_newline
+01:4c2c print_digit
+01:4c39 print_regs
+01:4c42 _print_sl_data0
+01:4c48 _print_sl_out0
+01:4c55 _print_sl_data1
+01:4c5b _print_sl_out1
+01:4c6d _print_sl_data2
+01:4c73 _print_sl_out2
+01:4c80 _print_sl_data3
+01:4c86 _print_sl_out3
+01:4c98 _print_sl_data4
+01:4c9e _print_sl_out4
+01:4cab _print_sl_data5
+01:4cb1 _print_sl_out5
+01:4cc3 _print_sl_data6
+01:4cc9 _print_sl_out6
+01:4cd6 _print_sl_data7
+01:4cdc _print_sl_out7
+01:4001 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f1 memcpy
+01:47fa memset
+01:4803 memcmp
+01:4811 clear_vram
+01:481b clear_oam
+01:4825 disable_lcd_safe
+01:482b _wait_ly_0
+01:4831 _wait_ly_1
+01:483a reset_screen
+01:484e process_results
+01:4862 _wait_ly_2
+01:4868 _wait_ly_3
+01:487e _print_results_halt_0
+01:4881 _process_results_cb
+01:488c _print_sl_data8
+01:4896 _print_sl_out8
+01:48b0 _print_sl_data9
+01:48bb _print_sl_out9
+01:48d3 _print_sl_data10
+01:48df _print_sl_out10
+01:48e0 dump_mem
+01:48ff _dump_mem_line
+01:4929 _check_asserts
+01:4937 _print_sl_data11
+01:493a _print_sl_out11
+01:4946 _print_sl_data12
+01:4948 _print_sl_out12
+01:4950 _print_sl_data13
+01:4953 _print_sl_out13
+01:495d __check_assert_fail0
+01:4968 _print_sl_data14
+01:496b _print_sl_out14
+01:496e __check_assert_ok0
+01:4976 _print_sl_data15
+01:497b _print_sl_out15
+01:497d __check_assert_skip0
+01:4985 _print_sl_data16
+01:498d _print_sl_out16
+01:498d __check_assert_out0
+01:4999 _print_sl_data17
+01:499b _print_sl_out17
+01:49a3 _print_sl_data18
+01:49a6 _print_sl_out18
+01:49b0 __check_assert_fail1
+01:49bb _print_sl_data19
+01:49be _print_sl_out19
+01:49c1 __check_assert_ok1
+01:49c9 _print_sl_data20
+01:49ce _print_sl_out20
+01:49d0 __check_assert_skip1
+01:49d8 _print_sl_data21
+01:49e0 _print_sl_out21
+01:49e0 __check_assert_out1
+01:49eb _print_sl_data22
+01:49ee _print_sl_out22
+01:49fa _print_sl_data23
+01:49fc _print_sl_out23
+01:4a04 _print_sl_data24
+01:4a07 _print_sl_out24
+01:4a11 __check_assert_fail2
+01:4a1c _print_sl_data25
+01:4a1f _print_sl_out25
+01:4a22 __check_assert_ok2
+01:4a2a _print_sl_data26
+01:4a2f _print_sl_out26
+01:4a31 __check_assert_skip2
+01:4a39 _print_sl_data27
+01:4a41 _print_sl_out27
+01:4a41 __check_assert_out2
+01:4a4d _print_sl_data28
+01:4a4f _print_sl_out28
+01:4a57 _print_sl_data29
+01:4a5a _print_sl_out29
+01:4a64 __check_assert_fail3
+01:4a6f _print_sl_data30
+01:4a72 _print_sl_out30
+01:4a75 __check_assert_ok3
+01:4a7d _print_sl_data31
+01:4a82 _print_sl_out31
+01:4a84 __check_assert_skip3
+01:4a8c _print_sl_data32
+01:4a94 _print_sl_out32
+01:4a94 __check_assert_out3
+01:4a9f _print_sl_data33
+01:4aa2 _print_sl_out33
+01:4aae _print_sl_data34
+01:4ab0 _print_sl_out34
+01:4ab8 _print_sl_data35
+01:4abb _print_sl_out35
+01:4ac5 __check_assert_fail4
+01:4ad0 _print_sl_data36
+01:4ad3 _print_sl_out36
+01:4ad6 __check_assert_ok4
+01:4ade _print_sl_data37
+01:4ae3 _print_sl_out37
+01:4ae5 __check_assert_skip4
+01:4aed _print_sl_data38
+01:4af5 _print_sl_out38
+01:4af5 __check_assert_out4
+01:4b01 _print_sl_data39
+01:4b03 _print_sl_out39
+01:4b0b _print_sl_data40
+01:4b0e _print_sl_out40
+01:4b18 __check_assert_fail5
+01:4b23 _print_sl_data41
+01:4b26 _print_sl_out41
+01:4b29 __check_assert_ok5
+01:4b31 _print_sl_data42
+01:4b36 _print_sl_out42
+01:4b38 __check_assert_skip5
+01:4b40 _print_sl_data43
+01:4b48 _print_sl_out43
+01:4b48 __check_assert_out5
+01:4b53 _print_sl_data44
+01:4b56 _print_sl_out44
+01:4b62 _print_sl_data45
+01:4b64 _print_sl_out45
+01:4b6c _print_sl_data46
+01:4b6f _print_sl_out46
+01:4b79 __check_assert_fail6
+01:4b84 _print_sl_data47
+01:4b87 _print_sl_out47
+01:4b8a __check_assert_ok6
+01:4b92 _print_sl_data48
+01:4b97 _print_sl_out48
+01:4b99 __check_assert_skip6
+01:4ba1 _print_sl_data49
+01:4ba9 _print_sl_out49
+01:4ba9 __check_assert_out6
+01:4bb5 _print_sl_data50
+01:4bb7 _print_sl_out50
+01:4bbf _print_sl_data51
+01:4bc2 _print_sl_out51
+01:4bcc __check_assert_fail7
+01:4bd7 _print_sl_data52
+01:4bda _print_sl_out52
+01:4bdd __check_assert_ok7
+01:4be5 _print_sl_data53
+01:4bea _print_sl_out53
+01:4bec __check_assert_skip7
+01:4bf4 _print_sl_data54
+01:4bfc _print_sl_out54
+01:4bfc __check_assert_out7
+00:016b fail
+00:017f _wait_ly_4
+00:0185 _wait_ly_5
+00:019b _print_results_halt_1
+00:019e _fail_cb
+00:01a6 _print_sl_data55
+00:01b2 _print_sl_out55
+00:01c2 _print_sl_data56
+00:01ce _print_sl_out56
+00:01d8 _print_sl_data57
+00:01e4 _print_sl_out57
+00:01ef _print_sl_data58
+00:01f5 _print_sl_out58
+00:0208 _print_sl_data59
+00:0215 _print_sl_out59
+00:0225 _print_sl_data60
+00:0232 _print_sl_out60
+00:0242 _print_sl_data61
+00:024f _print_sl_out61
+00:025a c000_functions_start
+00:025a run_test_suite
+00:0284 _wait_ly_6
+00:028a _wait_ly_7
+00:02a0 _print_results_halt_2
+00:02a3 _test_ok_cb_0
+00:02ab _print_sl_data62
+00:02b3 _print_sl_out62
+00:02b6 run_tests
+00:02c4 run_test_cases
+00:02d2 test_case
+00:02ef restore_mbc1
+00:02f8 switch_bank
+00:0309 fetch_expected_value
+00:0328 c000_functions_end
+00:0328 expected_banks
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.gb
new file mode 100644
index 000000000..f51f7dbb0
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.sym
new file mode 100644
index 000000000..b55df8f0e
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.sym
@@ -0,0 +1,226 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/rom_4Mb.gb".
+
+[labels]
+01:4c00 print_load_font
+01:4c0d print_string
+01:4c17 print_a
+01:4c21 print_newline
+01:4c2c print_digit
+01:4c39 print_regs
+01:4c42 _print_sl_data0
+01:4c48 _print_sl_out0
+01:4c55 _print_sl_data1
+01:4c5b _print_sl_out1
+01:4c6d _print_sl_data2
+01:4c73 _print_sl_out2
+01:4c80 _print_sl_data3
+01:4c86 _print_sl_out3
+01:4c98 _print_sl_data4
+01:4c9e _print_sl_out4
+01:4cab _print_sl_data5
+01:4cb1 _print_sl_out5
+01:4cc3 _print_sl_data6
+01:4cc9 _print_sl_out6
+01:4cd6 _print_sl_data7
+01:4cdc _print_sl_out7
+01:4001 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f1 memcpy
+01:47fa memset
+01:4803 memcmp
+01:4811 clear_vram
+01:481b clear_oam
+01:4825 disable_lcd_safe
+01:482b _wait_ly_0
+01:4831 _wait_ly_1
+01:483a reset_screen
+01:484e process_results
+01:4862 _wait_ly_2
+01:4868 _wait_ly_3
+01:487e _print_results_halt_0
+01:4881 _process_results_cb
+01:488c _print_sl_data8
+01:4896 _print_sl_out8
+01:48b0 _print_sl_data9
+01:48bb _print_sl_out9
+01:48d3 _print_sl_data10
+01:48df _print_sl_out10
+01:48e0 dump_mem
+01:48ff _dump_mem_line
+01:4929 _check_asserts
+01:4937 _print_sl_data11
+01:493a _print_sl_out11
+01:4946 _print_sl_data12
+01:4948 _print_sl_out12
+01:4950 _print_sl_data13
+01:4953 _print_sl_out13
+01:495d __check_assert_fail0
+01:4968 _print_sl_data14
+01:496b _print_sl_out14
+01:496e __check_assert_ok0
+01:4976 _print_sl_data15
+01:497b _print_sl_out15
+01:497d __check_assert_skip0
+01:4985 _print_sl_data16
+01:498d _print_sl_out16
+01:498d __check_assert_out0
+01:4999 _print_sl_data17
+01:499b _print_sl_out17
+01:49a3 _print_sl_data18
+01:49a6 _print_sl_out18
+01:49b0 __check_assert_fail1
+01:49bb _print_sl_data19
+01:49be _print_sl_out19
+01:49c1 __check_assert_ok1
+01:49c9 _print_sl_data20
+01:49ce _print_sl_out20
+01:49d0 __check_assert_skip1
+01:49d8 _print_sl_data21
+01:49e0 _print_sl_out21
+01:49e0 __check_assert_out1
+01:49eb _print_sl_data22
+01:49ee _print_sl_out22
+01:49fa _print_sl_data23
+01:49fc _print_sl_out23
+01:4a04 _print_sl_data24
+01:4a07 _print_sl_out24
+01:4a11 __check_assert_fail2
+01:4a1c _print_sl_data25
+01:4a1f _print_sl_out25
+01:4a22 __check_assert_ok2
+01:4a2a _print_sl_data26
+01:4a2f _print_sl_out26
+01:4a31 __check_assert_skip2
+01:4a39 _print_sl_data27
+01:4a41 _print_sl_out27
+01:4a41 __check_assert_out2
+01:4a4d _print_sl_data28
+01:4a4f _print_sl_out28
+01:4a57 _print_sl_data29
+01:4a5a _print_sl_out29
+01:4a64 __check_assert_fail3
+01:4a6f _print_sl_data30
+01:4a72 _print_sl_out30
+01:4a75 __check_assert_ok3
+01:4a7d _print_sl_data31
+01:4a82 _print_sl_out31
+01:4a84 __check_assert_skip3
+01:4a8c _print_sl_data32
+01:4a94 _print_sl_out32
+01:4a94 __check_assert_out3
+01:4a9f _print_sl_data33
+01:4aa2 _print_sl_out33
+01:4aae _print_sl_data34
+01:4ab0 _print_sl_out34
+01:4ab8 _print_sl_data35
+01:4abb _print_sl_out35
+01:4ac5 __check_assert_fail4
+01:4ad0 _print_sl_data36
+01:4ad3 _print_sl_out36
+01:4ad6 __check_assert_ok4
+01:4ade _print_sl_data37
+01:4ae3 _print_sl_out37
+01:4ae5 __check_assert_skip4
+01:4aed _print_sl_data38
+01:4af5 _print_sl_out38
+01:4af5 __check_assert_out4
+01:4b01 _print_sl_data39
+01:4b03 _print_sl_out39
+01:4b0b _print_sl_data40
+01:4b0e _print_sl_out40
+01:4b18 __check_assert_fail5
+01:4b23 _print_sl_data41
+01:4b26 _print_sl_out41
+01:4b29 __check_assert_ok5
+01:4b31 _print_sl_data42
+01:4b36 _print_sl_out42
+01:4b38 __check_assert_skip5
+01:4b40 _print_sl_data43
+01:4b48 _print_sl_out43
+01:4b48 __check_assert_out5
+01:4b53 _print_sl_data44
+01:4b56 _print_sl_out44
+01:4b62 _print_sl_data45
+01:4b64 _print_sl_out45
+01:4b6c _print_sl_data46
+01:4b6f _print_sl_out46
+01:4b79 __check_assert_fail6
+01:4b84 _print_sl_data47
+01:4b87 _print_sl_out47
+01:4b8a __check_assert_ok6
+01:4b92 _print_sl_data48
+01:4b97 _print_sl_out48
+01:4b99 __check_assert_skip6
+01:4ba1 _print_sl_data49
+01:4ba9 _print_sl_out49
+01:4ba9 __check_assert_out6
+01:4bb5 _print_sl_data50
+01:4bb7 _print_sl_out50
+01:4bbf _print_sl_data51
+01:4bc2 _print_sl_out51
+01:4bcc __check_assert_fail7
+01:4bd7 _print_sl_data52
+01:4bda _print_sl_out52
+01:4bdd __check_assert_ok7
+01:4be5 _print_sl_data53
+01:4bea _print_sl_out53
+01:4bec __check_assert_skip7
+01:4bf4 _print_sl_data54
+01:4bfc _print_sl_out54
+01:4bfc __check_assert_out7
+00:016b fail
+00:017f _wait_ly_4
+00:0185 _wait_ly_5
+00:019b _print_results_halt_1
+00:019e _fail_cb
+00:01a6 _print_sl_data55
+00:01b2 _print_sl_out55
+00:01c2 _print_sl_data56
+00:01ce _print_sl_out56
+00:01d8 _print_sl_data57
+00:01e4 _print_sl_out57
+00:01ef _print_sl_data58
+00:01f5 _print_sl_out58
+00:0208 _print_sl_data59
+00:0215 _print_sl_out59
+00:0225 _print_sl_data60
+00:0232 _print_sl_out60
+00:0242 _print_sl_data61
+00:024f _print_sl_out61
+00:025a c000_functions_start
+00:025a run_test_suite
+00:0284 _wait_ly_6
+00:028a _wait_ly_7
+00:02a0 _print_results_halt_2
+00:02a3 _test_ok_cb_0
+00:02ab _print_sl_data62
+00:02b3 _print_sl_out62
+00:02b6 run_tests
+00:02c4 run_test_cases
+00:02d2 test_case
+00:02ef restore_mbc1
+00:02f8 switch_bank
+00:0309 fetch_expected_value
+00:0328 c000_functions_end
+00:0328 expected_banks
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/baseline_0000.png
new file mode 100644
index 000000000..282b639d3
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.gb
new file mode 100644
index 000000000..6ad98dafc
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.sym
new file mode 100644
index 000000000..113503729
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.sym
@@ -0,0 +1,226 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/rom_512Kb.gb".
+
+[labels]
+01:4c00 print_load_font
+01:4c0d print_string
+01:4c17 print_a
+01:4c21 print_newline
+01:4c2c print_digit
+01:4c39 print_regs
+01:4c42 _print_sl_data0
+01:4c48 _print_sl_out0
+01:4c55 _print_sl_data1
+01:4c5b _print_sl_out1
+01:4c6d _print_sl_data2
+01:4c73 _print_sl_out2
+01:4c80 _print_sl_data3
+01:4c86 _print_sl_out3
+01:4c98 _print_sl_data4
+01:4c9e _print_sl_out4
+01:4cab _print_sl_data5
+01:4cb1 _print_sl_out5
+01:4cc3 _print_sl_data6
+01:4cc9 _print_sl_out6
+01:4cd6 _print_sl_data7
+01:4cdc _print_sl_out7
+01:4001 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f1 memcpy
+01:47fa memset
+01:4803 memcmp
+01:4811 clear_vram
+01:481b clear_oam
+01:4825 disable_lcd_safe
+01:482b _wait_ly_0
+01:4831 _wait_ly_1
+01:483a reset_screen
+01:484e process_results
+01:4862 _wait_ly_2
+01:4868 _wait_ly_3
+01:487e _print_results_halt_0
+01:4881 _process_results_cb
+01:488c _print_sl_data8
+01:4896 _print_sl_out8
+01:48b0 _print_sl_data9
+01:48bb _print_sl_out9
+01:48d3 _print_sl_data10
+01:48df _print_sl_out10
+01:48e0 dump_mem
+01:48ff _dump_mem_line
+01:4929 _check_asserts
+01:4937 _print_sl_data11
+01:493a _print_sl_out11
+01:4946 _print_sl_data12
+01:4948 _print_sl_out12
+01:4950 _print_sl_data13
+01:4953 _print_sl_out13
+01:495d __check_assert_fail0
+01:4968 _print_sl_data14
+01:496b _print_sl_out14
+01:496e __check_assert_ok0
+01:4976 _print_sl_data15
+01:497b _print_sl_out15
+01:497d __check_assert_skip0
+01:4985 _print_sl_data16
+01:498d _print_sl_out16
+01:498d __check_assert_out0
+01:4999 _print_sl_data17
+01:499b _print_sl_out17
+01:49a3 _print_sl_data18
+01:49a6 _print_sl_out18
+01:49b0 __check_assert_fail1
+01:49bb _print_sl_data19
+01:49be _print_sl_out19
+01:49c1 __check_assert_ok1
+01:49c9 _print_sl_data20
+01:49ce _print_sl_out20
+01:49d0 __check_assert_skip1
+01:49d8 _print_sl_data21
+01:49e0 _print_sl_out21
+01:49e0 __check_assert_out1
+01:49eb _print_sl_data22
+01:49ee _print_sl_out22
+01:49fa _print_sl_data23
+01:49fc _print_sl_out23
+01:4a04 _print_sl_data24
+01:4a07 _print_sl_out24
+01:4a11 __check_assert_fail2
+01:4a1c _print_sl_data25
+01:4a1f _print_sl_out25
+01:4a22 __check_assert_ok2
+01:4a2a _print_sl_data26
+01:4a2f _print_sl_out26
+01:4a31 __check_assert_skip2
+01:4a39 _print_sl_data27
+01:4a41 _print_sl_out27
+01:4a41 __check_assert_out2
+01:4a4d _print_sl_data28
+01:4a4f _print_sl_out28
+01:4a57 _print_sl_data29
+01:4a5a _print_sl_out29
+01:4a64 __check_assert_fail3
+01:4a6f _print_sl_data30
+01:4a72 _print_sl_out30
+01:4a75 __check_assert_ok3
+01:4a7d _print_sl_data31
+01:4a82 _print_sl_out31
+01:4a84 __check_assert_skip3
+01:4a8c _print_sl_data32
+01:4a94 _print_sl_out32
+01:4a94 __check_assert_out3
+01:4a9f _print_sl_data33
+01:4aa2 _print_sl_out33
+01:4aae _print_sl_data34
+01:4ab0 _print_sl_out34
+01:4ab8 _print_sl_data35
+01:4abb _print_sl_out35
+01:4ac5 __check_assert_fail4
+01:4ad0 _print_sl_data36
+01:4ad3 _print_sl_out36
+01:4ad6 __check_assert_ok4
+01:4ade _print_sl_data37
+01:4ae3 _print_sl_out37
+01:4ae5 __check_assert_skip4
+01:4aed _print_sl_data38
+01:4af5 _print_sl_out38
+01:4af5 __check_assert_out4
+01:4b01 _print_sl_data39
+01:4b03 _print_sl_out39
+01:4b0b _print_sl_data40
+01:4b0e _print_sl_out40
+01:4b18 __check_assert_fail5
+01:4b23 _print_sl_data41
+01:4b26 _print_sl_out41
+01:4b29 __check_assert_ok5
+01:4b31 _print_sl_data42
+01:4b36 _print_sl_out42
+01:4b38 __check_assert_skip5
+01:4b40 _print_sl_data43
+01:4b48 _print_sl_out43
+01:4b48 __check_assert_out5
+01:4b53 _print_sl_data44
+01:4b56 _print_sl_out44
+01:4b62 _print_sl_data45
+01:4b64 _print_sl_out45
+01:4b6c _print_sl_data46
+01:4b6f _print_sl_out46
+01:4b79 __check_assert_fail6
+01:4b84 _print_sl_data47
+01:4b87 _print_sl_out47
+01:4b8a __check_assert_ok6
+01:4b92 _print_sl_data48
+01:4b97 _print_sl_out48
+01:4b99 __check_assert_skip6
+01:4ba1 _print_sl_data49
+01:4ba9 _print_sl_out49
+01:4ba9 __check_assert_out6
+01:4bb5 _print_sl_data50
+01:4bb7 _print_sl_out50
+01:4bbf _print_sl_data51
+01:4bc2 _print_sl_out51
+01:4bcc __check_assert_fail7
+01:4bd7 _print_sl_data52
+01:4bda _print_sl_out52
+01:4bdd __check_assert_ok7
+01:4be5 _print_sl_data53
+01:4bea _print_sl_out53
+01:4bec __check_assert_skip7
+01:4bf4 _print_sl_data54
+01:4bfc _print_sl_out54
+01:4bfc __check_assert_out7
+00:016b fail
+00:017f _wait_ly_4
+00:0185 _wait_ly_5
+00:019b _print_results_halt_1
+00:019e _fail_cb
+00:01a6 _print_sl_data55
+00:01b2 _print_sl_out55
+00:01c2 _print_sl_data56
+00:01ce _print_sl_out56
+00:01d8 _print_sl_data57
+00:01e4 _print_sl_out57
+00:01ef _print_sl_data58
+00:01f5 _print_sl_out58
+00:0208 _print_sl_data59
+00:0215 _print_sl_out59
+00:0225 _print_sl_data60
+00:0232 _print_sl_out60
+00:0242 _print_sl_data61
+00:024f _print_sl_out61
+00:025a c000_functions_start
+00:025a run_test_suite
+00:0284 _wait_ly_6
+00:028a _wait_ly_7
+00:02a0 _print_results_halt_2
+00:02a3 _test_ok_cb_0
+00:02ab _print_sl_data62
+00:02b3 _print_sl_out62
+00:02b6 run_tests
+00:02c4 run_test_cases
+00:02d2 test_case
+00:02ef restore_mbc1
+00:02f8 switch_bank
+00:0309 fetch_expected_value
+00:0328 c000_functions_end
+00:0328 expected_banks
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.gb
new file mode 100644
index 000000000..a7a41958e
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.sym
new file mode 100644
index 000000000..9217d7990
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.sym
@@ -0,0 +1,226 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/rom_8Mb.gb".
+
+[labels]
+01:4c00 print_load_font
+01:4c0d print_string
+01:4c17 print_a
+01:4c21 print_newline
+01:4c2c print_digit
+01:4c39 print_regs
+01:4c42 _print_sl_data0
+01:4c48 _print_sl_out0
+01:4c55 _print_sl_data1
+01:4c5b _print_sl_out1
+01:4c6d _print_sl_data2
+01:4c73 _print_sl_out2
+01:4c80 _print_sl_data3
+01:4c86 _print_sl_out3
+01:4c98 _print_sl_data4
+01:4c9e _print_sl_out4
+01:4cab _print_sl_data5
+01:4cb1 _print_sl_out5
+01:4cc3 _print_sl_data6
+01:4cc9 _print_sl_out6
+01:4cd6 _print_sl_data7
+01:4cdc _print_sl_out7
+01:4001 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f1 memcpy
+01:47fa memset
+01:4803 memcmp
+01:4811 clear_vram
+01:481b clear_oam
+01:4825 disable_lcd_safe
+01:482b _wait_ly_0
+01:4831 _wait_ly_1
+01:483a reset_screen
+01:484e process_results
+01:4862 _wait_ly_2
+01:4868 _wait_ly_3
+01:487e _print_results_halt_0
+01:4881 _process_results_cb
+01:488c _print_sl_data8
+01:4896 _print_sl_out8
+01:48b0 _print_sl_data9
+01:48bb _print_sl_out9
+01:48d3 _print_sl_data10
+01:48df _print_sl_out10
+01:48e0 dump_mem
+01:48ff _dump_mem_line
+01:4929 _check_asserts
+01:4937 _print_sl_data11
+01:493a _print_sl_out11
+01:4946 _print_sl_data12
+01:4948 _print_sl_out12
+01:4950 _print_sl_data13
+01:4953 _print_sl_out13
+01:495d __check_assert_fail0
+01:4968 _print_sl_data14
+01:496b _print_sl_out14
+01:496e __check_assert_ok0
+01:4976 _print_sl_data15
+01:497b _print_sl_out15
+01:497d __check_assert_skip0
+01:4985 _print_sl_data16
+01:498d _print_sl_out16
+01:498d __check_assert_out0
+01:4999 _print_sl_data17
+01:499b _print_sl_out17
+01:49a3 _print_sl_data18
+01:49a6 _print_sl_out18
+01:49b0 __check_assert_fail1
+01:49bb _print_sl_data19
+01:49be _print_sl_out19
+01:49c1 __check_assert_ok1
+01:49c9 _print_sl_data20
+01:49ce _print_sl_out20
+01:49d0 __check_assert_skip1
+01:49d8 _print_sl_data21
+01:49e0 _print_sl_out21
+01:49e0 __check_assert_out1
+01:49eb _print_sl_data22
+01:49ee _print_sl_out22
+01:49fa _print_sl_data23
+01:49fc _print_sl_out23
+01:4a04 _print_sl_data24
+01:4a07 _print_sl_out24
+01:4a11 __check_assert_fail2
+01:4a1c _print_sl_data25
+01:4a1f _print_sl_out25
+01:4a22 __check_assert_ok2
+01:4a2a _print_sl_data26
+01:4a2f _print_sl_out26
+01:4a31 __check_assert_skip2
+01:4a39 _print_sl_data27
+01:4a41 _print_sl_out27
+01:4a41 __check_assert_out2
+01:4a4d _print_sl_data28
+01:4a4f _print_sl_out28
+01:4a57 _print_sl_data29
+01:4a5a _print_sl_out29
+01:4a64 __check_assert_fail3
+01:4a6f _print_sl_data30
+01:4a72 _print_sl_out30
+01:4a75 __check_assert_ok3
+01:4a7d _print_sl_data31
+01:4a82 _print_sl_out31
+01:4a84 __check_assert_skip3
+01:4a8c _print_sl_data32
+01:4a94 _print_sl_out32
+01:4a94 __check_assert_out3
+01:4a9f _print_sl_data33
+01:4aa2 _print_sl_out33
+01:4aae _print_sl_data34
+01:4ab0 _print_sl_out34
+01:4ab8 _print_sl_data35
+01:4abb _print_sl_out35
+01:4ac5 __check_assert_fail4
+01:4ad0 _print_sl_data36
+01:4ad3 _print_sl_out36
+01:4ad6 __check_assert_ok4
+01:4ade _print_sl_data37
+01:4ae3 _print_sl_out37
+01:4ae5 __check_assert_skip4
+01:4aed _print_sl_data38
+01:4af5 _print_sl_out38
+01:4af5 __check_assert_out4
+01:4b01 _print_sl_data39
+01:4b03 _print_sl_out39
+01:4b0b _print_sl_data40
+01:4b0e _print_sl_out40
+01:4b18 __check_assert_fail5
+01:4b23 _print_sl_data41
+01:4b26 _print_sl_out41
+01:4b29 __check_assert_ok5
+01:4b31 _print_sl_data42
+01:4b36 _print_sl_out42
+01:4b38 __check_assert_skip5
+01:4b40 _print_sl_data43
+01:4b48 _print_sl_out43
+01:4b48 __check_assert_out5
+01:4b53 _print_sl_data44
+01:4b56 _print_sl_out44
+01:4b62 _print_sl_data45
+01:4b64 _print_sl_out45
+01:4b6c _print_sl_data46
+01:4b6f _print_sl_out46
+01:4b79 __check_assert_fail6
+01:4b84 _print_sl_data47
+01:4b87 _print_sl_out47
+01:4b8a __check_assert_ok6
+01:4b92 _print_sl_data48
+01:4b97 _print_sl_out48
+01:4b99 __check_assert_skip6
+01:4ba1 _print_sl_data49
+01:4ba9 _print_sl_out49
+01:4ba9 __check_assert_out6
+01:4bb5 _print_sl_data50
+01:4bb7 _print_sl_out50
+01:4bbf _print_sl_data51
+01:4bc2 _print_sl_out51
+01:4bcc __check_assert_fail7
+01:4bd7 _print_sl_data52
+01:4bda _print_sl_out52
+01:4bdd __check_assert_ok7
+01:4be5 _print_sl_data53
+01:4bea _print_sl_out53
+01:4bec __check_assert_skip7
+01:4bf4 _print_sl_data54
+01:4bfc _print_sl_out54
+01:4bfc __check_assert_out7
+00:016b fail
+00:017f _wait_ly_4
+00:0185 _wait_ly_5
+00:019b _print_results_halt_1
+00:019e _fail_cb
+00:01a6 _print_sl_data55
+00:01b2 _print_sl_out55
+00:01c2 _print_sl_data56
+00:01ce _print_sl_out56
+00:01d8 _print_sl_data57
+00:01e4 _print_sl_out57
+00:01ef _print_sl_data58
+00:01f5 _print_sl_out58
+00:0208 _print_sl_data59
+00:0215 _print_sl_out59
+00:0225 _print_sl_data60
+00:0232 _print_sl_out60
+00:0242 _print_sl_data61
+00:024f _print_sl_out61
+00:025a c000_functions_start
+00:025a run_test_suite
+00:0284 _wait_ly_6
+00:028a _wait_ly_7
+00:02a0 _print_results_halt_2
+00:02a3 _test_ok_cb_0
+00:02ab _print_sl_data62
+00:02b3 _print_sl_out62
+00:02b6 run_tests
+00:02c4 run_test_cases
+00:02d2 test_case
+00:02ef restore_mbc1
+00:02f8 switch_bank
+00:0309 fetch_expected_value
+00:0328 c000_functions_end
+00:0328 expected_banks
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.gb
new file mode 100644
index 000000000..0ae17db54
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.sym
new file mode 100644
index 000000000..95fa3e20a
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.sym
@@ -0,0 +1,205 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/jeffrey/Scratch/mooneye-gb/tests/build/emulator-only/mbc1_rom_4banks.gb".
+
+[labels]
+0001:4bf3 print_load_font
+0001:4c00 print_string
+0001:4c0a print_a
+0001:4c14 print_newline
+0001:4c1f print_digit
+0001:4c2c print_regs
+0001:4c35 _print_sl_data0
+0001:4c3b _print_sl_out0
+0001:4c48 _print_sl_data1
+0001:4c4e _print_sl_out1
+0001:4c60 _print_sl_data2
+0001:4c66 _print_sl_out2
+0001:4c73 _print_sl_data3
+0001:4c79 _print_sl_out3
+0001:4c8b _print_sl_data4
+0001:4c91 _print_sl_out4
+0001:4c9e _print_sl_data5
+0001:4ca4 _print_sl_out5
+0001:4cb6 _print_sl_data6
+0001:4cbc _print_sl_out6
+0001:4cc9 _print_sl_data7
+0001:4ccf _print_sl_out7
+0001:4001 font
+0000:c000 regs_save
+0000:c000 regs_save.f
+0000:c001 regs_save.a
+0000:c002 regs_save.c
+0000:c003 regs_save.b
+0000:c004 regs_save.e
+0000:c005 regs_save.d
+0000:c006 regs_save.l
+0000:c007 regs_save.h
+0000:c008 regs_flags
+0000:c009 regs_assert
+0000:c009 regs_assert.f
+0000:c00a regs_assert.a
+0000:c00b regs_assert.c
+0000:c00c regs_assert.b
+0000:c00d regs_assert.e
+0000:c00e regs_assert.d
+0000:c00f regs_assert.l
+0000:c010 regs_assert.h
+0000:c011 memdump_len
+0000:c012 memdump_addr
+0001:47f1 memcpy
+0001:47fa memset
+0001:4803 clear_vram
+0001:480e reset_screen
+0001:481b process_results
+0001:4820 _wait_ly_0
+0001:4826 _wait_ly_1
+0001:4842 _wait_ly_2
+0001:4848 _wait_ly_3
+0001:4861 _process_results_cb
+0001:486c _print_sl_data8
+0001:4876 _print_sl_out8
+0001:4890 _print_sl_data9
+0001:489b _print_sl_out9
+0001:48b3 _print_sl_data10
+0001:48bf _print_sl_out10
+0001:48c0 dump_mem
+0001:48d0 _wait_ly_4
+0001:48d6 _wait_ly_5
+0001:48f2 _dump_mem_line
+0001:491c _check_asserts
+0001:492a _print_sl_data11
+0001:492d _print_sl_out11
+0001:4939 _print_sl_data12
+0001:493b _print_sl_out12
+0001:4943 _print_sl_data13
+0001:4946 _print_sl_out13
+0001:4950 __check_assert_fail0
+0001:495b _print_sl_data14
+0001:495e _print_sl_out14
+0001:4961 __check_assert_ok0
+0001:4969 _print_sl_data15
+0001:496e _print_sl_out15
+0001:4970 __check_assert_skip0
+0001:4978 _print_sl_data16
+0001:4980 _print_sl_out16
+0001:4980 __check_assert_out0
+0001:498c _print_sl_data17
+0001:498e _print_sl_out17
+0001:4996 _print_sl_data18
+0001:4999 _print_sl_out18
+0001:49a3 __check_assert_fail1
+0001:49ae _print_sl_data19
+0001:49b1 _print_sl_out19
+0001:49b4 __check_assert_ok1
+0001:49bc _print_sl_data20
+0001:49c1 _print_sl_out20
+0001:49c3 __check_assert_skip1
+0001:49cb _print_sl_data21
+0001:49d3 _print_sl_out21
+0001:49d3 __check_assert_out1
+0001:49de _print_sl_data22
+0001:49e1 _print_sl_out22
+0001:49ed _print_sl_data23
+0001:49ef _print_sl_out23
+0001:49f7 _print_sl_data24
+0001:49fa _print_sl_out24
+0001:4a04 __check_assert_fail2
+0001:4a0f _print_sl_data25
+0001:4a12 _print_sl_out25
+0001:4a15 __check_assert_ok2
+0001:4a1d _print_sl_data26
+0001:4a22 _print_sl_out26
+0001:4a24 __check_assert_skip2
+0001:4a2c _print_sl_data27
+0001:4a34 _print_sl_out27
+0001:4a34 __check_assert_out2
+0001:4a40 _print_sl_data28
+0001:4a42 _print_sl_out28
+0001:4a4a _print_sl_data29
+0001:4a4d _print_sl_out29
+0001:4a57 __check_assert_fail3
+0001:4a62 _print_sl_data30
+0001:4a65 _print_sl_out30
+0001:4a68 __check_assert_ok3
+0001:4a70 _print_sl_data31
+0001:4a75 _print_sl_out31
+0001:4a77 __check_assert_skip3
+0001:4a7f _print_sl_data32
+0001:4a87 _print_sl_out32
+0001:4a87 __check_assert_out3
+0001:4a92 _print_sl_data33
+0001:4a95 _print_sl_out33
+0001:4aa1 _print_sl_data34
+0001:4aa3 _print_sl_out34
+0001:4aab _print_sl_data35
+0001:4aae _print_sl_out35
+0001:4ab8 __check_assert_fail4
+0001:4ac3 _print_sl_data36
+0001:4ac6 _print_sl_out36
+0001:4ac9 __check_assert_ok4
+0001:4ad1 _print_sl_data37
+0001:4ad6 _print_sl_out37
+0001:4ad8 __check_assert_skip4
+0001:4ae0 _print_sl_data38
+0001:4ae8 _print_sl_out38
+0001:4ae8 __check_assert_out4
+0001:4af4 _print_sl_data39
+0001:4af6 _print_sl_out39
+0001:4afe _print_sl_data40
+0001:4b01 _print_sl_out40
+0001:4b0b __check_assert_fail5
+0001:4b16 _print_sl_data41
+0001:4b19 _print_sl_out41
+0001:4b1c __check_assert_ok5
+0001:4b24 _print_sl_data42
+0001:4b29 _print_sl_out42
+0001:4b2b __check_assert_skip5
+0001:4b33 _print_sl_data43
+0001:4b3b _print_sl_out43
+0001:4b3b __check_assert_out5
+0001:4b46 _print_sl_data44
+0001:4b49 _print_sl_out44
+0001:4b55 _print_sl_data45
+0001:4b57 _print_sl_out45
+0001:4b5f _print_sl_data46
+0001:4b62 _print_sl_out46
+0001:4b6c __check_assert_fail6
+0001:4b77 _print_sl_data47
+0001:4b7a _print_sl_out47
+0001:4b7d __check_assert_ok6
+0001:4b85 _print_sl_data48
+0001:4b8a _print_sl_out48
+0001:4b8c __check_assert_skip6
+0001:4b94 _print_sl_data49
+0001:4b9c _print_sl_out49
+0001:4b9c __check_assert_out6
+0001:4ba8 _print_sl_data50
+0001:4baa _print_sl_out50
+0001:4bb2 _print_sl_data51
+0001:4bb5 _print_sl_out51
+0001:4bbf __check_assert_fail7
+0001:4bca _print_sl_data52
+0001:4bcd _print_sl_out52
+0001:4bd0 __check_assert_ok7
+0001:4bd8 _print_sl_data53
+0001:4bdd _print_sl_out53
+0001:4bdf __check_assert_skip7
+0001:4be7 _print_sl_data54
+0001:4bef _print_sl_out54
+0001:4bef __check_assert_out7
+0000:01c8 _wait_ly_6
+0000:01ce _wait_ly_7
+0000:01ea _wait_ly_8
+0000:01f0 _wait_ly_9
+0000:0209 _test_ok_cb_0
+0000:0211 _print_sl_data55
+0000:0219 _print_sl_out55
+0000:021c switch_bank
+0000:0225 test_mbc
+0000:0236 _wait_ly_10
+0000:023c _wait_ly_11
+0000:0258 _wait_ly_12
+0000:025e _wait_ly_13
+0000:0277 _test_failure_cb_0
+0000:027f _print_sl_data56
+0000:028b _print_sl_out56
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/baseline_0000.png
new file mode 100644
index 000000000..78773f1a8
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.gb
new file mode 100644
index 000000000..05b502f26
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.sym
new file mode 100644
index 000000000..cfaa2ab88
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.sym
@@ -0,0 +1,200 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/madness/mgb_oam_dma_halt_sprites.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0199 _wait_ly_4
+00:019f _wait_ly_5
+00:01b4 hiram_test
+00:01b9 _wait_ly_6
+00:01bf _wait_ly_7
+00:01cc vram_checkerboard
+00:05cc vram_checkerboard_end
+00:05cc initial_data
+00:05d4 initial_data_end
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/manifest.yml
new file mode 100644
index 000000000..bbd7d13ba
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/manifest.yml
@@ -0,0 +1,4 @@
+skip: 60
+frames: 1
+config:
+ sgb.borders: false
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/baseline_0000.png
new file mode 100644
index 000000000..e35683164
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.gb
new file mode 100644
index 000000000..9df4d749d
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.sym
new file mode 100644
index 000000000..bb4fc461f
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.sym
@@ -0,0 +1,193 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/manual-only/sprite_priority.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0180 data
+00:0214 data_end
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/manifest.yml
new file mode 100755
index 000000000..c9aa5eb1d
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/manifest.yml
@@ -0,0 +1,3 @@
+config:
+ gb.model: CGB
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.gb
new file mode 100644
index 000000000..d2d4e08ae
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.sym
new file mode 100644
index 000000000..fdf31f0d3
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.sym
@@ -0,0 +1,535 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/misc/bits/unused_hwio-C.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c017 regs_save
+00:c017 regs_save.f
+00:c018 regs_save.a
+00:c019 regs_save.c
+00:c01a regs_save.b
+00:c01b regs_save.e
+00:c01c regs_save.d
+00:c01d regs_save.l
+00:c01e regs_save.h
+00:c01f regs_flags
+00:c020 regs_assert
+00:c020 regs_assert.f
+00:c021 regs_assert.a
+00:c022 regs_assert.c
+00:c023 regs_assert.b
+00:c024 regs_assert.e
+00:c025 regs_assert.d
+00:c026 regs_assert.l
+00:c027 regs_assert.h
+00:c028 memdump_len
+00:c029 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0161 _test_data_0
+00:0177 _finish_0
+00:0187 _test_data_1
+00:019d _finish_1
+00:01ad _test_data_2
+00:01c3 _finish_2
+00:01d3 _test_data_3
+00:01e9 _finish_3
+00:01f9 _test_data_4
+00:020f _finish_4
+00:021f _test_data_5
+00:0235 _finish_5
+00:0245 _test_data_6
+00:025b _finish_6
+00:026b _test_data_7
+00:0281 _finish_7
+00:0291 _test_data_8
+00:02a7 _finish_8
+00:02b7 _test_data_9
+00:02cd _finish_9
+00:02dd _test_data_10
+00:02f3 _finish_10
+00:0303 _test_data_11
+00:0319 _finish_11
+00:0329 _test_data_12
+00:033f _finish_12
+00:034f _test_data_13
+00:0365 _finish_13
+00:0375 _test_data_14
+00:038b _finish_14
+00:039b _test_data_15
+00:03b1 _finish_15
+00:03c1 _test_data_16
+00:03d7 _finish_16
+00:03e7 _test_data_17
+00:03fd _finish_17
+00:040d _test_data_18
+00:0423 _finish_18
+00:0433 _test_data_19
+00:0449 _finish_19
+00:0459 _test_data_20
+00:046f _finish_20
+00:047f _test_data_21
+00:0495 _finish_21
+00:04a5 _test_data_22
+00:04bb _finish_22
+00:04cb _test_data_23
+00:04e1 _finish_23
+00:04f1 _test_data_24
+00:0507 _finish_24
+00:0517 _test_data_25
+00:052d _finish_25
+00:053d _test_data_26
+00:0553 _finish_26
+00:0563 _test_data_27
+00:0579 _finish_27
+00:0589 _test_data_28
+00:059f _finish_28
+00:05af _test_data_29
+00:05c5 _finish_29
+00:05d5 _test_data_30
+00:05eb _finish_30
+00:05fb _test_data_31
+00:0611 _finish_31
+00:0621 _test_data_32
+00:0637 _finish_32
+00:0647 _test_data_33
+00:065d _finish_33
+00:066d _test_data_34
+00:0683 _finish_34
+00:0693 _test_data_35
+00:06a9 _finish_35
+00:06b9 _test_data_36
+00:06cf _finish_36
+00:06df _test_data_37
+00:06f5 _finish_37
+00:0705 _test_data_38
+00:071b _finish_38
+00:072b _test_data_39
+00:0741 _finish_39
+00:0751 _test_data_40
+00:0767 _finish_40
+00:0777 _test_data_41
+00:078d _finish_41
+00:079d _test_data_42
+00:07b3 _finish_42
+00:07c3 _test_data_43
+00:07d9 _finish_43
+00:07e9 _test_data_44
+00:07ff _finish_44
+00:080f _test_data_45
+00:0825 _finish_45
+00:0835 _test_data_46
+00:084b _finish_46
+00:085b _test_data_47
+00:0871 _finish_47
+00:0881 _test_data_48
+00:0897 _finish_48
+00:08a7 _test_data_49
+00:08bd _finish_49
+00:08cd _test_data_50
+00:08e3 _finish_50
+00:08f3 _test_data_51
+00:0909 _finish_51
+00:0919 _test_data_52
+00:092f _finish_52
+00:093f _test_data_53
+00:0955 _finish_53
+00:0965 _test_data_54
+00:097b _finish_54
+00:098b _test_data_55
+00:09a1 _finish_55
+00:09b1 _test_data_56
+00:09c7 _finish_56
+00:09d7 _test_data_57
+00:09ed _finish_57
+00:09fd _test_data_58
+00:0a13 _finish_58
+00:0a23 _test_data_59
+00:0a39 _finish_59
+00:0a49 _test_data_60
+00:0a5f _finish_60
+00:0a6f _test_data_61
+00:0a85 _finish_61
+00:0a95 _test_data_62
+00:0aab _finish_62
+00:0abb _test_data_63
+00:0ad1 _finish_63
+00:0ae1 _test_data_64
+00:0af7 _finish_64
+00:0b07 _test_data_65
+00:0b1d _finish_65
+00:0b2d _test_data_66
+00:0b43 _finish_66
+00:0b53 _test_data_67
+00:0b69 _finish_67
+00:0b79 _test_data_68
+00:0b8f _finish_68
+00:0b9f _test_data_69
+00:0bb5 _finish_69
+00:0bc5 _test_data_70
+00:0bdb _finish_70
+00:0beb _test_data_71
+00:0c01 _finish_71
+00:0c11 _test_data_72
+00:0c27 _finish_72
+00:0c37 _test_data_73
+00:0c4d _finish_73
+00:0c5d _test_data_74
+00:0c73 _finish_74
+00:0c83 _test_data_75
+00:0c99 _finish_75
+00:0ca9 _test_data_76
+00:0cbf _finish_76
+00:0ccf _test_data_77
+00:0ce5 _finish_77
+00:0cf5 _test_data_78
+00:0d0b _finish_78
+00:0d1b _test_data_79
+00:0d31 _finish_79
+00:0d41 _test_data_80
+00:0d57 _finish_80
+00:0d67 _test_data_81
+00:0d7d _finish_81
+00:0d8d _test_data_82
+00:0da3 _finish_82
+00:0db3 _test_data_83
+00:0dc9 _finish_83
+00:0dd9 _test_data_84
+00:0def _finish_84
+00:0dff _test_data_85
+00:0e15 _finish_85
+00:0e25 _test_data_86
+00:0e3b _finish_86
+00:0e4b _test_data_87
+00:0e61 _finish_87
+00:0e71 _test_data_88
+00:0e87 _finish_88
+00:0e97 _test_data_89
+00:0ead _finish_89
+00:0ebd _test_data_90
+00:0ed3 _finish_90
+00:0ee3 _test_data_91
+00:0ef9 _finish_91
+00:0f09 _test_data_92
+00:0f1f _finish_92
+00:0f2f _test_data_93
+00:0f45 _finish_93
+00:0f55 _test_data_94
+00:0f6b _finish_94
+00:0f7b _test_data_95
+00:0f91 _finish_95
+00:0fa1 _test_data_96
+00:0fb7 _finish_96
+00:0fc7 _test_data_97
+00:0fdd _finish_97
+00:0fed _test_data_98
+00:1003 _finish_98
+00:1013 _test_data_99
+00:1029 _finish_99
+00:1039 _test_data_100
+00:104f _finish_100
+00:105f _test_data_101
+00:1075 _finish_101
+00:1085 _test_data_102
+00:109b _finish_102
+00:10ab _test_data_103
+00:10c1 _finish_103
+00:10d1 _test_data_104
+00:10e7 _finish_104
+00:10f7 _test_data_105
+00:110d _finish_105
+00:111d _test_data_106
+00:1133 _finish_106
+00:1143 _test_data_107
+00:1159 _finish_107
+00:1169 _test_data_108
+00:117f _finish_108
+00:118f _test_data_109
+00:11a5 _finish_109
+00:11b5 _test_data_110
+00:11cb _finish_110
+00:11db _test_data_111
+00:11f1 _finish_111
+00:1201 _test_data_112
+00:1217 _finish_112
+00:1227 _test_data_113
+00:123d _finish_113
+00:124d _test_data_114
+00:1263 _finish_114
+00:1273 _test_data_115
+00:1289 _finish_115
+00:1299 _test_data_116
+00:12af _finish_116
+00:12bf _test_data_117
+00:12d5 _finish_117
+00:12e5 _test_data_118
+00:12fb _finish_118
+00:130b _test_data_119
+00:1321 _finish_119
+00:1331 _test_data_120
+00:1347 _finish_120
+00:1357 _test_data_121
+00:136d _finish_121
+00:137d _test_data_122
+00:1393 _finish_122
+00:13a3 _test_data_123
+00:13b9 _finish_123
+00:13c9 _test_data_124
+00:13df _finish_124
+00:13ef _test_data_125
+00:1405 _finish_125
+00:1415 _test_data_126
+00:142b _finish_126
+00:143b _test_data_127
+00:1451 _finish_127
+00:1461 _test_data_128
+00:1477 _finish_128
+00:1487 _test_data_129
+00:149d _finish_129
+00:14ad _test_data_130
+00:14c3 _finish_130
+00:14d3 _test_data_131
+00:14e9 _finish_131
+00:14f9 _test_data_132
+00:150f _finish_132
+00:151f _test_data_133
+00:1535 _finish_133
+00:1545 _test_data_134
+00:155b _finish_134
+00:156b _test_data_135
+00:1581 _finish_135
+00:1591 _test_data_136
+00:15a7 _finish_136
+00:15b7 _test_data_137
+00:15cd _finish_137
+00:15dd _test_data_138
+00:15f3 _finish_138
+00:1603 _test_data_139
+00:1619 _finish_139
+00:1629 _test_data_140
+00:163f _finish_140
+00:164f _test_data_141
+00:1665 _finish_141
+00:1675 _test_data_142
+00:168b _finish_142
+00:169b _test_data_143
+00:16b1 _finish_143
+00:16c1 _test_data_144
+00:16d7 _finish_144
+00:16e7 _test_data_145
+00:16fd _finish_145
+00:170d _test_data_146
+00:1723 _finish_146
+00:1733 _test_data_147
+00:1749 _finish_147
+00:1759 _test_data_148
+00:176f _finish_148
+00:177f _test_data_149
+00:1795 _finish_149
+00:17a5 _test_data_150
+00:17bb _finish_150
+00:17cb _test_data_151
+00:17e1 _finish_151
+00:17f1 _test_data_152
+00:1807 _finish_152
+00:1817 _test_data_153
+00:182d _finish_153
+00:1841 _wait_ly_4
+00:1847 _wait_ly_5
+00:185d _print_results_halt_1
+00:1860 _test_ok_cb_0
+00:1868 _print_sl_data55
+00:1870 _print_sl_out55
+00:1873 run_testcase
+00:189e _wait_ly_6
+00:18a4 _wait_ly_7
+00:18ba _print_results_halt_2
+00:18bd test_failure_cb
+00:18c5 _print_sl_data56
+00:18d1 _print_sl_out56
+00:18df _print_sl_data57
+00:18e3 _print_sl_out57
+00:18f1 _print_sl_data58
+00:1901 _print_sl_out58
+00:190f _print_sl_data59
+00:191c _print_sl_out59
+00:192d _print_sl_data60
+00:193a _print_sl_out60
+00:194b _print_sl_data61
+00:1958 _print_sl_out61
+00:195e fetch_test_data
+00:1978 print_got
+00:198a _print_zero
+00:198e _print_one
+00:1990 _print_bit
+00:1999 _skip
+00:199a _next
+00:c000 test_addr
+00:c002 test_got
+00:c003 test_reg
+00:c004 test_mask
+00:c005 test_str_write
+00:c00e test_str_expect
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/baseline_0000.png
new file mode 100644
index 000000000..30590ffab
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/manifest.yml
new file mode 100755
index 000000000..c9aa5eb1d
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/manifest.yml
@@ -0,0 +1,3 @@
+config:
+ gb.model: CGB
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.gb
new file mode 100644
index 000000000..214a87ab7
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.sav b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.sav
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.sym
new file mode 100644
index 000000000..a0639ed09
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.sym
@@ -0,0 +1,212 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/misc/boot_hwio-C.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01db _wait_ly_4
+00:01e1 _wait_ly_5
+00:01f7 _print_results_halt_1
+00:01fa _test_ok_cb_0
+00:0202 _print_sl_data55
+00:020a _print_sl_out55
+00:020d mismatch
+00:0230 _wait_ly_6
+00:0236 _wait_ly_7
+00:024c _print_results_halt_2
+00:024f mismatch_cb
+00:0257 _print_sl_data56
+00:0265 _print_sl_out56
+00:027f _print_sl_data57
+00:0289 _print_sl_out57
+00:029a _print_sl_data58
+00:02a4 _print_sl_out58
+00:02ad hwio_data
+00:c014 mismatch_addr
+00:c016 mismatch_data
+00:c017 mismatch_mem
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/baseline_0000.png
new file mode 100644
index 000000000..e29254b10
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/manifest.yml
new file mode 100755
index 000000000..ddd792e5b
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/manifest.yml
@@ -0,0 +1 @@
+config: {gb.model: AGB}
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/test.gb
new file mode 100644
index 000000000..80d5e9b9a
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/test.sym
new file mode 100644
index 000000000..0e44909cc
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-A/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/misc/boot_regs-A.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01d2 invalid_sp
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_failure_cb_0
+00:020d _print_sl_data55
+00:021e _print_sl_out55
+00:c014 sp_save
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/baseline_0000.png
new file mode 100644
index 000000000..2bb2235a5
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/manifest.yml
new file mode 100755
index 000000000..970c243ab
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/manifest.yml
@@ -0,0 +1 @@
+config: {gb.model: CGB}
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.gb
new file mode 100644
index 000000000..76995e885
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.sym
new file mode 100644
index 000000000..9421cd102
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.sym
@@ -0,0 +1,199 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/misc/boot_regs-cgb.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:01d2 invalid_sp
+00:01e6 _wait_ly_4
+00:01ec _wait_ly_5
+00:0202 _print_results_halt_1
+00:0205 _test_failure_cb_0
+00:020d _print_sl_data55
+00:021e _print_sl_out55
+00:c014 sp_save
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/baseline_0000.png b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/baseline_0000.png
new file mode 100644
index 000000000..a129e5e88
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/manifest.yml b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/manifest.yml
new file mode 100755
index 000000000..970c243ab
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/manifest.yml
@@ -0,0 +1 @@
+config: {gb.model: CGB}
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.gb b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.gb
new file mode 100644
index 000000000..e7b06ccdc
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.gb differ
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.sym b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.sym
new file mode 100644
index 000000000..7ebdacba7
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.sym
@@ -0,0 +1,216 @@
+; this file was created with wlalink by ville helin .
+; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/misc/gpu/vblank_stat_intr-C.gb".
+
+[labels]
+01:4bff print_load_font
+01:4c0c print_string
+01:4c16 print_a
+01:4c20 print_newline
+01:4c2b print_digit
+01:4c38 print_regs
+01:4c41 _print_sl_data0
+01:4c47 _print_sl_out0
+01:4c54 _print_sl_data1
+01:4c5a _print_sl_out1
+01:4c6c _print_sl_data2
+01:4c72 _print_sl_out2
+01:4c7f _print_sl_data3
+01:4c85 _print_sl_out3
+01:4c97 _print_sl_data4
+01:4c9d _print_sl_out4
+01:4caa _print_sl_data5
+01:4cb0 _print_sl_out5
+01:4cc2 _print_sl_data6
+01:4cc8 _print_sl_out6
+01:4cd5 _print_sl_data7
+01:4cdb _print_sl_out7
+01:4000 font
+00:c000 regs_save
+00:c000 regs_save.f
+00:c001 regs_save.a
+00:c002 regs_save.c
+00:c003 regs_save.b
+00:c004 regs_save.e
+00:c005 regs_save.d
+00:c006 regs_save.l
+00:c007 regs_save.h
+00:c008 regs_flags
+00:c009 regs_assert
+00:c009 regs_assert.f
+00:c00a regs_assert.a
+00:c00b regs_assert.c
+00:c00c regs_assert.b
+00:c00d regs_assert.e
+00:c00e regs_assert.d
+00:c00f regs_assert.l
+00:c010 regs_assert.h
+00:c011 memdump_len
+00:c012 memdump_addr
+01:47f0 memcpy
+01:47f9 memset
+01:4802 memcmp
+01:4810 clear_vram
+01:481a clear_oam
+01:4824 disable_lcd_safe
+01:482a _wait_ly_0
+01:4830 _wait_ly_1
+01:4839 reset_screen
+01:484d process_results
+01:4861 _wait_ly_2
+01:4867 _wait_ly_3
+01:487d _print_results_halt_0
+01:4880 _process_results_cb
+01:488b _print_sl_data8
+01:4895 _print_sl_out8
+01:48af _print_sl_data9
+01:48ba _print_sl_out9
+01:48d2 _print_sl_data10
+01:48de _print_sl_out10
+01:48df dump_mem
+01:48fe _dump_mem_line
+01:4928 _check_asserts
+01:4936 _print_sl_data11
+01:4939 _print_sl_out11
+01:4945 _print_sl_data12
+01:4947 _print_sl_out12
+01:494f _print_sl_data13
+01:4952 _print_sl_out13
+01:495c __check_assert_fail0
+01:4967 _print_sl_data14
+01:496a _print_sl_out14
+01:496d __check_assert_ok0
+01:4975 _print_sl_data15
+01:497a _print_sl_out15
+01:497c __check_assert_skip0
+01:4984 _print_sl_data16
+01:498c _print_sl_out16
+01:498c __check_assert_out0
+01:4998 _print_sl_data17
+01:499a _print_sl_out17
+01:49a2 _print_sl_data18
+01:49a5 _print_sl_out18
+01:49af __check_assert_fail1
+01:49ba _print_sl_data19
+01:49bd _print_sl_out19
+01:49c0 __check_assert_ok1
+01:49c8 _print_sl_data20
+01:49cd _print_sl_out20
+01:49cf __check_assert_skip1
+01:49d7 _print_sl_data21
+01:49df _print_sl_out21
+01:49df __check_assert_out1
+01:49ea _print_sl_data22
+01:49ed _print_sl_out22
+01:49f9 _print_sl_data23
+01:49fb _print_sl_out23
+01:4a03 _print_sl_data24
+01:4a06 _print_sl_out24
+01:4a10 __check_assert_fail2
+01:4a1b _print_sl_data25
+01:4a1e _print_sl_out25
+01:4a21 __check_assert_ok2
+01:4a29 _print_sl_data26
+01:4a2e _print_sl_out26
+01:4a30 __check_assert_skip2
+01:4a38 _print_sl_data27
+01:4a40 _print_sl_out27
+01:4a40 __check_assert_out2
+01:4a4c _print_sl_data28
+01:4a4e _print_sl_out28
+01:4a56 _print_sl_data29
+01:4a59 _print_sl_out29
+01:4a63 __check_assert_fail3
+01:4a6e _print_sl_data30
+01:4a71 _print_sl_out30
+01:4a74 __check_assert_ok3
+01:4a7c _print_sl_data31
+01:4a81 _print_sl_out31
+01:4a83 __check_assert_skip3
+01:4a8b _print_sl_data32
+01:4a93 _print_sl_out32
+01:4a93 __check_assert_out3
+01:4a9e _print_sl_data33
+01:4aa1 _print_sl_out33
+01:4aad _print_sl_data34
+01:4aaf _print_sl_out34
+01:4ab7 _print_sl_data35
+01:4aba _print_sl_out35
+01:4ac4 __check_assert_fail4
+01:4acf _print_sl_data36
+01:4ad2 _print_sl_out36
+01:4ad5 __check_assert_ok4
+01:4add _print_sl_data37
+01:4ae2 _print_sl_out37
+01:4ae4 __check_assert_skip4
+01:4aec _print_sl_data38
+01:4af4 _print_sl_out38
+01:4af4 __check_assert_out4
+01:4b00 _print_sl_data39
+01:4b02 _print_sl_out39
+01:4b0a _print_sl_data40
+01:4b0d _print_sl_out40
+01:4b17 __check_assert_fail5
+01:4b22 _print_sl_data41
+01:4b25 _print_sl_out41
+01:4b28 __check_assert_ok5
+01:4b30 _print_sl_data42
+01:4b35 _print_sl_out42
+01:4b37 __check_assert_skip5
+01:4b3f _print_sl_data43
+01:4b47 _print_sl_out43
+01:4b47 __check_assert_out5
+01:4b52 _print_sl_data44
+01:4b55 _print_sl_out44
+01:4b61 _print_sl_data45
+01:4b63 _print_sl_out45
+01:4b6b _print_sl_data46
+01:4b6e _print_sl_out46
+01:4b78 __check_assert_fail6
+01:4b83 _print_sl_data47
+01:4b86 _print_sl_out47
+01:4b89 __check_assert_ok6
+01:4b91 _print_sl_data48
+01:4b96 _print_sl_out48
+01:4b98 __check_assert_skip6
+01:4ba0 _print_sl_data49
+01:4ba8 _print_sl_out49
+01:4ba8 __check_assert_out6
+01:4bb4 _print_sl_data50
+01:4bb6 _print_sl_out50
+01:4bbe _print_sl_data51
+01:4bc1 _print_sl_out51
+01:4bcb __check_assert_fail7
+01:4bd6 _print_sl_data52
+01:4bd9 _print_sl_out52
+01:4bdc __check_assert_ok7
+01:4be4 _print_sl_data53
+01:4be9 _print_sl_out53
+01:4beb __check_assert_skip7
+01:4bf3 _print_sl_data54
+01:4bfb _print_sl_out54
+01:4bfb __check_assert_out7
+00:0169 fail_halt
+00:017d _wait_ly_4
+00:0183 _wait_ly_5
+00:0199 _print_results_halt_1
+00:019c _test_failure_cb_0
+00:01a4 _print_sl_data55
+00:01a9 _print_sl_out55
+00:01ac test_round1
+00:01b8 _wait_ly_6
+00:0203 finish_round1
+00:0221 test_round2
+00:022d _wait_ly_7
+00:0279 finish_round2
+00:029b test_round3
+00:02a7 _wait_ly_8
+00:02f1 finish_round3
+00:030f test_round4
+00:031b _wait_ly_9
+00:0366 finish_round4
+00:0368 test_finish
+00:c014 intr_vec_vblank
+00:c017 intr_vec_stat
+00:c01a round1
+00:c01b round2
+00:c01c round3
diff --git a/src/platform/python/tests/cinema/gb/mooneye-gb/update.py b/src/platform/python/tests/cinema/gb/mooneye-gb/update.py
new file mode 100644
index 000000000..6f126b349
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/mooneye-gb/update.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+import os
+import os.path
+import shutil
+import yaml
+from cinema.util import dictMerge
+
+suffixes = {
+ 'C': 'CGB',
+ 'S': 'SGB',
+ 'A': 'AGB',
+ 'mgb': 'MGB',
+ 'sgb': 'SGB',
+ 'sgb2': 'SGB2',
+ 'cgb': 'CGB',
+ 'agb': 'AGB',
+ 'ags': 'AGB',
+}
+
+def ingestDirectory(path, dest):
+ for root, _, files in os.walk(path, topdown=False):
+ root = root[len(os.path.commonprefix([root, path])):]
+ if root.startswith('utils'):
+ continue
+ for file in files:
+ fname, ext = os.path.splitext(file)
+ if ext not in ('.gb', '.sym'):
+ continue
+
+ try:
+ os.makedirs(os.path.join(dest, root, fname))
+ except OSError:
+ pass
+
+ if ext in ('.gb', '.sym'):
+ shutil.copy(os.path.join(path, root, file), os.path.join(dest, root, fname, 'test' + ext))
+
+ for suffix, model in suffixes.items():
+ if fname.endswith('-' + suffix):
+ manifest = {}
+ try:
+ with open(os.path.join(dest, root, fname, 'manifest.yml'), 'r') as f:
+ manifest = yaml.safe_load(f) or {}
+ except IOError:
+ pass
+ dictMerge(manifest, {
+ 'config': {
+ 'gb.model': model
+ }
+ })
+ with open(os.path.join(dest, root, fname, 'manifest.yml'), 'w') as f:
+ yaml.dump(manifest, f)
+
+if __name__ == '__main__':
+ import argparse
+ parser = argparse.ArgumentParser(description='Update mooneye-gb test suite')
+ parser.add_argument('source', type=str, help='directory containing built tests')
+ parser.add_argument('dest', type=str, nargs='?', default=os.path.dirname(__file__), help='directory to contain ingested tests')
+ args = parser.parse_args()
+
+ ingestDirectory(args.source, args.dest)
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0000.png b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0000.png
new file mode 100644
index 000000000..9c91f7846
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0001.png b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0001.png
new file mode 100644
index 000000000..9c91f7846
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0002.png b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0002.png
new file mode 100644
index 000000000..aa201764a
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0003.png b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0003.png
new file mode 100644
index 000000000..3421f7465
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0004.png b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0004.png
new file mode 100644
index 000000000..3421f7465
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0004.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0005.png b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0005.png
new file mode 100644
index 000000000..3421f7465
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0005.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0006.png b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0006.png
new file mode 100644
index 000000000..adfd0a701
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0006.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0007.png b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0007.png
new file mode 100644
index 000000000..b654f7bf7
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0007.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0008.png b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0008.png
new file mode 100644
index 000000000..b654f7bf7
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/baseline_0008.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/test.mvl b/src/platform/python/tests/cinema/gb/window/dk94-split/test.mvl
new file mode 100644
index 000000000..fc900d59c
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/dk94-split/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gb/window/dk94-split/test.sav b/src/platform/python/tests/cinema/gb/window/dk94-split/test.sav
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0000.png b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0000.png
new file mode 100644
index 000000000..44380a405
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0001.png b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0001.png
new file mode 100644
index 000000000..13171fec7
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0002.png b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0002.png
new file mode 100644
index 000000000..cce64a953
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0003.png b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0003.png
new file mode 100644
index 000000000..cce64a953
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0004.png b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0004.png
new file mode 100644
index 000000000..cce64a953
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/gsc-battle/baseline_0004.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/gsc-battle/manifest.yml b/src/platform/python/tests/cinema/gb/window/gsc-battle/manifest.yml
new file mode 100644
index 000000000..a697ada66
--- /dev/null
+++ b/src/platform/python/tests/cinema/gb/window/gsc-battle/manifest.yml
@@ -0,0 +1 @@
+fail: true
diff --git a/src/platform/python/tests/cinema/gb/window/gsc-battle/test.mvl b/src/platform/python/tests/cinema/gb/window/gsc-battle/test.mvl
new file mode 100644
index 000000000..ca2a2efde
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/gsc-battle/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gb/window/gsc-battle/test.sav b/src/platform/python/tests/cinema/gb/window/gsc-battle/test.sav
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0000.png b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0000.png
new file mode 100644
index 000000000..fcc5ca11f
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0001.png b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0001.png
new file mode 100644
index 000000000..fcc5ca11f
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0002.png b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0002.png
new file mode 100644
index 000000000..fcc5ca11f
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0003.png b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0003.png
new file mode 100644
index 000000000..41dbf8912
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0004.png b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0004.png
new file mode 100644
index 000000000..41dbf8912
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0004.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0005.png b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0005.png
new file mode 100644
index 000000000..41dbf8912
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0005.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0006.png b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0006.png
new file mode 100644
index 000000000..41dbf8912
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/zoos-intro/baseline_0006.png differ
diff --git a/src/platform/python/tests/cinema/gb/window/zoos-intro/test.mvl b/src/platform/python/tests/cinema/gb/window/zoos-intro/test.mvl
new file mode 100644
index 000000000..a9fd102ea
Binary files /dev/null and b/src/platform/python/tests/cinema/gb/window/zoos-intro/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gb/window/zoos-intro/test.sav b/src/platform/python/tests/cinema/gb/window/zoos-intro/test.sav
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0000.png b/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0000.png
new file mode 100644
index 000000000..53ffb604e
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0001.png b/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0001.png
new file mode 100644
index 000000000..f7cc51299
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0002.png b/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0002.png
new file mode 100644
index 000000000..df4d6402a
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0003.png b/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0003.png
new file mode 100644
index 000000000..9bd30f5fd
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/bg/lady-sia/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gba/bg/lady-sia/test.mvl b/src/platform/python/tests/cinema/gba/bg/lady-sia/test.mvl
new file mode 100644
index 000000000..214133dd2
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/bg/lady-sia/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0000.png b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0000.png
new file mode 100644
index 000000000..aea1b7608
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0001.png b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0001.png
new file mode 100644
index 000000000..b26facdff
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0002.png b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0002.png
new file mode 100644
index 000000000..1cd68a9b9
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0003.png b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0003.png
new file mode 100644
index 000000000..7571a66a3
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0004.png b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0004.png
new file mode 100644
index 000000000..0f05e6295
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0004.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0005.png b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0005.png
new file mode 100644
index 000000000..3007a98c9
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/baseline_0005.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/test.mvl b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/test.mvl
new file mode 100644
index 000000000..a36112b6d
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/gs-obj-modes/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0000.png b/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0000.png
new file mode 100644
index 000000000..f42797b63
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0001.png b/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0001.png
new file mode 100644
index 000000000..911eaf973
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0002.png b/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0002.png
new file mode 100644
index 000000000..429d6a22e
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0003.png b/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0003.png
new file mode 100644
index 000000000..1d7b8c310
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/kam-knockout/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/kam-knockout/test.mvl b/src/platform/python/tests/cinema/gba/blend/kam-knockout/test.mvl
new file mode 100644
index 000000000..828cc4c3d
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/kam-knockout/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0000.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0000.png
new file mode 100644
index 000000000..7e7d73b3f
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0001.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0001.png
new file mode 100644
index 000000000..e081ca1b9
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0002.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0002.png
new file mode 100644
index 000000000..eae1286ae
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0003.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0003.png
new file mode 100644
index 000000000..4b7c369a7
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0004.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0004.png
new file mode 100644
index 000000000..a9a061914
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0004.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0005.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0005.png
new file mode 100644
index 000000000..511643590
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0005.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0006.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0006.png
new file mode 100644
index 000000000..b93c95d6f
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0006.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0007.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0007.png
new file mode 100644
index 000000000..cc586feb6
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0007.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0008.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0008.png
new file mode 100644
index 000000000..403730bb6
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0008.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0009.png b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0009.png
new file mode 100644
index 000000000..183413016
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/baseline_0009.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/test.mvl b/src/platform/python/tests/cinema/gba/blend/mzm-layering/test.mvl
new file mode 100644
index 000000000..e34208c44
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/mzm-layering/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gba/blend/mzm-layering/test.sav b/src/platform/python/tests/cinema/gba/blend/mzm-layering/test.sav
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/platform/python/tests/cinema/gba/blend/sma-knockout/baseline_0000.png b/src/platform/python/tests/cinema/gba/blend/sma-knockout/baseline_0000.png
new file mode 100644
index 000000000..4cabeb0cb
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/sma-knockout/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/sma-knockout/baseline_0001.png b/src/platform/python/tests/cinema/gba/blend/sma-knockout/baseline_0001.png
new file mode 100644
index 000000000..4b5a7fa1f
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/sma-knockout/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/sma-knockout/baseline_0002.png b/src/platform/python/tests/cinema/gba/blend/sma-knockout/baseline_0002.png
new file mode 100644
index 000000000..52f941083
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/sma-knockout/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gba/blend/sma-knockout/test.mvl b/src/platform/python/tests/cinema/gba/blend/sma-knockout/test.mvl
new file mode 100644
index 000000000..6186b2761
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/blend/sma-knockout/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0000.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0000.png
new file mode 100644
index 000000000..732404859
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0001.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0001.png
new file mode 100644
index 000000000..80da05aed
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0002.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0002.png
new file mode 100644
index 000000000..ce543d086
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0003.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0003.png
new file mode 100644
index 000000000..09b675662
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0004.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0004.png
new file mode 100644
index 000000000..2ae596fa2
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0004.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0005.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0005.png
new file mode 100644
index 000000000..48ebe894c
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0005.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0006.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0006.png
new file mode 100644
index 000000000..5d72e0a24
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0006.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0007.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0007.png
new file mode 100644
index 000000000..5c567dd8e
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0007.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0008.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0008.png
new file mode 100644
index 000000000..19e181403
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0008.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0009.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0009.png
new file mode 100644
index 000000000..a984a6e56
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0009.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0010.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0010.png
new file mode 100644
index 000000000..51fed1cc5
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0010.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0011.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0011.png
new file mode 100644
index 000000000..482a468de
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0011.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0012.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0012.png
new file mode 100644
index 000000000..1c1ac3d1c
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0012.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0013.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0013.png
new file mode 100644
index 000000000..311173c90
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0013.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0014.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0014.png
new file mode 100644
index 000000000..af9d6978c
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0014.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0015.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0015.png
new file mode 100644
index 000000000..567d5aa0d
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0015.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0016.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0016.png
new file mode 100644
index 000000000..323eda541
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0016.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0017.png b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0017.png
new file mode 100644
index 000000000..a075efd16
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/baseline_0017.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/test.mvl b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/test.mvl
new file mode 100644
index 000000000..6e42cf4f8
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/gs-clock-wipe/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0000.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0000.png
new file mode 100644
index 000000000..dc47c0ca9
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0001.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0001.png
new file mode 100644
index 000000000..d8c9f020e
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0002.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0002.png
new file mode 100644
index 000000000..d8c9f020e
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0003.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0003.png
new file mode 100644
index 000000000..cd448127a
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0004.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0004.png
new file mode 100644
index 000000000..cd448127a
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0004.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0005.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0005.png
new file mode 100644
index 000000000..e3b44f977
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0005.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0006.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0006.png
new file mode 100644
index 000000000..e3b44f977
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0006.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0007.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0007.png
new file mode 100644
index 000000000..ed9be82eb
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0007.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0008.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0008.png
new file mode 100644
index 000000000..ed9be82eb
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0008.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0009.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0009.png
new file mode 100644
index 000000000..675eb6ebc
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0009.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0010.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0010.png
new file mode 100644
index 000000000..675eb6ebc
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0010.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0011.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0011.png
new file mode 100644
index 000000000..7b550cd1e
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0011.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0012.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0012.png
new file mode 100644
index 000000000..7b550cd1e
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0012.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0013.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0013.png
new file mode 100644
index 000000000..cad8b9bce
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0013.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0014.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0014.png
new file mode 100644
index 000000000..cad8b9bce
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0014.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0015.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0015.png
new file mode 100644
index 000000000..47d18f16b
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0015.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0016.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0016.png
new file mode 100644
index 000000000..47d18f16b
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0016.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0017.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0017.png
new file mode 100644
index 000000000..99bf210ac
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0017.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0018.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0018.png
new file mode 100644
index 000000000..99bf210ac
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0018.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0019.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0019.png
new file mode 100644
index 000000000..f57bbfc95
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0019.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0020.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0020.png
new file mode 100644
index 000000000..f57bbfc95
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0020.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0021.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0021.png
new file mode 100644
index 000000000..4f7aae974
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0021.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0022.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0022.png
new file mode 100644
index 000000000..4f7aae974
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0022.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0023.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0023.png
new file mode 100644
index 000000000..fcb4e868d
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0023.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0024.png b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0024.png
new file mode 100644
index 000000000..fcb4e868d
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/baseline_0024.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/test.mvl b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/test.mvl
new file mode 100644
index 000000000..77dcfacaf
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/tgr-objwin-order/test.mvl differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0000.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0000.png
new file mode 100644
index 000000000..cd1b2c32f
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0000.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0001.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0001.png
new file mode 100644
index 000000000..53aee91ec
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0001.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0002.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0002.png
new file mode 100644
index 000000000..237eab692
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0002.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0003.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0003.png
new file mode 100644
index 000000000..05f308fa4
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0003.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0004.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0004.png
new file mode 100644
index 000000000..6c8b94d45
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0004.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0005.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0005.png
new file mode 100644
index 000000000..044cf6ebe
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0005.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0006.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0006.png
new file mode 100644
index 000000000..13ebb47bc
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0006.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0007.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0007.png
new file mode 100644
index 000000000..b3835e1d1
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0007.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0008.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0008.png
new file mode 100644
index 000000000..ef7b0b212
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0008.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0009.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0009.png
new file mode 100644
index 000000000..35d54bf96
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0009.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0010.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0010.png
new file mode 100644
index 000000000..8b555e49e
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0010.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0011.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0011.png
new file mode 100644
index 000000000..cecd0ff34
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0011.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0012.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0012.png
new file mode 100644
index 000000000..4e4165d5e
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0012.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0013.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0013.png
new file mode 100644
index 000000000..3f8d3a57a
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0013.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0014.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0014.png
new file mode 100644
index 000000000..eb1e1c9fe
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0014.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0015.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0015.png
new file mode 100644
index 000000000..3edbaea2b
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0015.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0016.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0016.png
new file mode 100644
index 000000000..d3636525a
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0016.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0017.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0017.png
new file mode 100644
index 000000000..2d6086460
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0017.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0018.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0018.png
new file mode 100644
index 000000000..c8cd44f8c
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0018.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0019.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0019.png
new file mode 100644
index 000000000..2d9b989e9
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0019.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0020.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0020.png
new file mode 100644
index 000000000..706120316
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0020.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0021.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0021.png
new file mode 100644
index 000000000..792199be6
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0021.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0022.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0022.png
new file mode 100644
index 000000000..08a6d3dba
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0022.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0023.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0023.png
new file mode 100644
index 000000000..57d99fa3c
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0023.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0024.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0024.png
new file mode 100644
index 000000000..a49291156
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0024.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0025.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0025.png
new file mode 100644
index 000000000..1dfa40cbe
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0025.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0026.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0026.png
new file mode 100644
index 000000000..ce427ed73
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0026.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0027.png b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0027.png
new file mode 100644
index 000000000..b9f6dc6f2
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/baseline_0027.png differ
diff --git a/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/test.mvl b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/test.mvl
new file mode 100644
index 000000000..cd3574304
Binary files /dev/null and b/src/platform/python/tests/cinema/gba/window/zmc-window-mosaic/test.mvl differ
diff --git a/src/platform/python/tests/mgba/__init__.py b/src/platform/python/tests/mgba/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/platform/python/tests/mgba/test_core.py b/src/platform/python/tests/mgba/test_core.py
new file mode 100644
index 000000000..03cb72667
--- /dev/null
+++ b/src/platform/python/tests/mgba/test_core.py
@@ -0,0 +1,7 @@
+import pytest
+
+def test_core_import():
+ try:
+ import mgba.core
+ except:
+ raise AssertionError
diff --git a/src/platform/python/tests/mgba/test_vfs.py b/src/platform/python/tests/mgba/test_vfs.py
new file mode 100644
index 000000000..2315e2a32
--- /dev/null
+++ b/src/platform/python/tests/mgba/test_vfs.py
@@ -0,0 +1,57 @@
+import pytest
+import os
+
+import mgba.vfs as vfs
+from mgba._pylib import ffi
+
+def test_vfs_open():
+ with open(__file__) as f:
+ vf = vfs.open(f)
+ assert vf
+ assert vf.close()
+
+def test_vfs_openPath():
+ vf = vfs.openPath(__file__)
+ assert vf
+ assert vf.close()
+
+def test_vfs_read():
+ vf = vfs.openPath(__file__)
+ buffer = ffi.new('char[13]')
+ assert vf.read(buffer, 13) == 13
+ assert ffi.string(buffer) == 'import pytest'
+ vf.close()
+
+def test_vfs_readline():
+ vf = vfs.openPath(__file__)
+ buffer = ffi.new('char[16]')
+ linelen = vf.readline(buffer, 16)
+ assert linelen in (14, 15)
+ if linelen == 14:
+ assert ffi.string(buffer) == 'import pytest\n'
+ elif linelen == 15:
+ assert ffi.string(buffer) == 'import pytest\r\n'
+ vf.close()
+
+def test_vfs_readAllSize():
+ vf = vfs.openPath(__file__)
+ buffer = vf.readAll()
+ assert buffer
+ assert len(buffer)
+ assert len(buffer) == vf.size()
+ vf.close()
+
+def test_vfs_seek():
+ vf = vfs.openPath(__file__)
+ assert vf.seek(0, os.SEEK_SET) == 0
+ assert vf.seek(1, os.SEEK_SET) == 1
+ assert vf.seek(1, os.SEEK_CUR) == 2
+ assert vf.seek(-1, os.SEEK_CUR) == 1
+ assert vf.seek(0, os.SEEK_CUR) == 1
+ assert vf.seek(0, os.SEEK_END) == vf.size()
+ assert vf.seek(-1, os.SEEK_END) == vf.size() -1
+ vf.close()
+
+def test_vfs_openPath_invalid():
+ vf = vfs.openPath('.invalid')
+ assert not vf
diff --git a/src/platform/qt/AboutScreen.h b/src/platform/qt/AboutScreen.h
index aebf1bdc1..ddced8f40 100644
--- a/src/platform/qt/AboutScreen.h
+++ b/src/platform/qt/AboutScreen.h
@@ -3,8 +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/. */
-#ifndef QGBA_ABOUT_SCREEN
-#define QGBA_ABOUT_SCREEN
+#pragma once
#include
@@ -23,5 +22,3 @@ private:
};
}
-
-#endif
diff --git a/src/platform/qt/ArchiveInspector.h b/src/platform/qt/ArchiveInspector.h
index c7b471335..8caaa283d 100644
--- a/src/platform/qt/ArchiveInspector.h
+++ b/src/platform/qt/ArchiveInspector.h
@@ -3,8 +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/. */
-#ifndef QGBA_ARCHIVE_INSPECTOR
-#define QGBA_ARCHIVE_INSPECTOR
+#pragma once
#include "ui_ArchiveInspector.h"
@@ -26,5 +25,3 @@ private:
};
}
-
-#endif
diff --git a/src/platform/qt/AssetTile.cpp b/src/platform/qt/AssetTile.cpp
index c82ffe424..9bdb57150 100644
--- a/src/platform/qt/AssetTile.cpp
+++ b/src/platform/qt/AssetTile.cpp
@@ -9,6 +9,7 @@
#include "GBAApp.h"
#include
+#include
#include
#ifdef M_CORE_GBA
@@ -34,14 +35,27 @@ AssetTile::AssetTile(QWidget* parent)
const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
m_ui.tileId->setFont(font);
+ m_ui.paletteId->setFont(font);
m_ui.address->setFont(font);
m_ui.r->setFont(font);
m_ui.g->setFont(font);
m_ui.b->setFont(font);
}
+void AssetTile::addCustomProperty(const QString& id, const QString& visibleName) {
+ QHBoxLayout* newLayout = new QHBoxLayout;
+ newLayout->addWidget(new QLabel(visibleName));
+ QLabel* value = new QLabel;
+ value->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
+ value->setAlignment(Qt::AlignRight);
+ newLayout->addWidget(value);
+ m_customProperties[id] = value;
+ int index = layout()->indexOf(m_ui.line);
+ static_cast(layout())->insertLayout(index, newLayout);
+}
+
void AssetTile::setController(std::shared_ptr controller) {
- m_tileCache = controller->tileCache();
+ m_cacheSet = controller->graphicCaches();
switch (controller->platform()) {
#ifdef M_CORE_GBA
case PLATFORM_GBA:
@@ -70,68 +84,76 @@ void AssetTile::setPalette(int palette) {
selectIndex(m_index);
}
-void AssetTile::setPaletteSet(int palette, int boundary, int max) {
- m_index = m_index * (1 + m_paletteSet) / (1 + palette);
- if (m_index >= max) {
- m_index = max - 1;
- }
+void AssetTile::setBoundary(int boundary, int set0, int set1) {
m_boundary = boundary;
- m_paletteSet = palette;
- selectIndex(m_index);
+ m_tileCaches[0] = mTileCacheSetGetPointer(&m_cacheSet->tiles, set0);
+ m_tileCaches[1] = mTileCacheSetGetPointer(&m_cacheSet->tiles, set1);
}
void AssetTile::selectIndex(int index) {
m_index = index;
- const uint16_t* data;
+ const color_t* data;
+ mTileCache* tileCache = m_tileCaches[index >= m_boundary];
- mTileCacheSetPalette(m_tileCache, m_paletteSet);
- unsigned bpp = 8 << m_tileCache->bpp;
- int dispIndex = index;
+ unsigned bpp = 8 << tileCache->bpp;
int paletteId = m_paletteId;
int base = m_addressBase;
if (index >= m_boundary) {
base = m_boundaryBase;
- // XXX: Do this better
-#ifdef M_CORE_GBA
- if (m_boundaryBase == (BASE_VRAM | 0x10000)) {
- paletteId += m_tileCache->count / 2;
- }
-#endif
- dispIndex -= m_boundary;
+ index -= m_boundary;
}
- data = mTileCacheGetTile(m_tileCache, index, paletteId);
- m_ui.tileId->setText(QString::number(dispIndex * (1 + m_paletteSet)));
+ int dispIndex = index;
+ if (m_addressWidth == 4 && index >= m_boundary / 2) {
+ dispIndex -= m_boundary / 2;
+ }
+ data = mTileCacheGetTile(tileCache, index, paletteId);
+ m_ui.tileId->setText(QString::number(dispIndex));
+ m_ui.paletteId->setText(QString::number(paletteId));
m_ui.address->setText(tr("%0%1%2")
- .arg(m_addressWidth == 4 ? index >= m_boundary : 0)
+ .arg(m_addressWidth == 4 ? index >= m_boundary / 2 : 0)
.arg(m_addressWidth == 4 ? ":" : "x")
.arg(dispIndex * bpp | base, m_addressWidth, 16, QChar('0')));
+ int flip = 0;
+ if (m_flipH) {
+ flip |= 007;
+ }
+ if (m_flipV) {
+ flip |= 070;
+ }
for (int i = 0; i < 64; ++i) {
- m_ui.preview->setColor(i, data[i]);
+ m_ui.preview->setColor(i ^ flip, data[i]);
}
m_ui.preview->update();
}
+void AssetTile::setFlip(bool h, bool v) {
+ m_flipH = h;
+ m_flipV = v;
+ selectIndex(m_index);
+}
+
void AssetTile::selectColor(int index) {
- const uint16_t* data;
- mTileCacheSetPalette(m_tileCache, m_paletteSet);
- unsigned bpp = 8 << m_tileCache->bpp;
+ const color_t* data;
+ mTileCache* tileCache = m_tileCaches[m_index >= m_boundary];
+ unsigned bpp = 8 << tileCache->bpp;
int paletteId = m_paletteId;
- // XXX: Do this better
-#ifdef M_CORE_GBA
- if (m_index >= m_boundary && m_boundaryBase == (BASE_VRAM | 0x10000)) {
- paletteId += m_tileCache->count / 2;
- }
-#endif
- data = mTileCacheGetTile(m_tileCache, m_index, m_paletteId);
- uint16_t color = data[index];
+ data = mTileCacheGetTile(tileCache, m_index, m_paletteId);
+ color_t color = data[index];
m_ui.color->setColor(0, color);
m_ui.color->update();
- uint32_t r = M_R5(color);
- uint32_t g = M_G5(color);
- uint32_t b = M_B5(color);
+ uint32_t r = color & 0xF8;
+ uint32_t g = (color >> 8) & 0xF8;
+ uint32_t b = (color >> 16) & 0xF8;
m_ui.r->setText(tr("0x%0 (%1)").arg(r, 2, 16, QChar('0')).arg(r, 2, 10, QChar('0')));
m_ui.g->setText(tr("0x%0 (%1)").arg(g, 2, 16, QChar('0')).arg(g, 2, 10, QChar('0')));
m_ui.b->setText(tr("0x%0 (%1)").arg(b, 2, 16, QChar('0')).arg(b, 2, 10, QChar('0')));
}
+void AssetTile::setCustomProperty(const QString& id, const QVariant& value) {
+ QLabel* label = m_customProperties[id];
+ if (!label) {
+ return;
+ }
+ label->setText(value.toString());
+}
diff --git a/src/platform/qt/AssetTile.h b/src/platform/qt/AssetTile.h
index 7d5f77be6..35dd14e5b 100644
--- a/src/platform/qt/AssetTile.h
+++ b/src/platform/qt/AssetTile.h
@@ -3,14 +3,13 @@
* 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 QGBA_ASSET_TILE
-#define QGBA_ASSET_TILE
+#pragma once
#include "ui_AssetTile.h"
#include
-#include
+#include
namespace QGBA {
@@ -22,27 +21,32 @@ Q_OBJECT
public:
AssetTile(QWidget* parent = nullptr);
void setController(std::shared_ptr);
+ void addCustomProperty(const QString& id, const QString& visibleName);
public slots:
void setPalette(int);
- void setPaletteSet(int, int boundary, int max);
+ void setBoundary(int boundary, int set0, int set1);
void selectIndex(int);
+ void setFlip(bool h, bool v);
void selectColor(int);
+ void setCustomProperty(const QString& id, const QVariant& value);
private:
Ui::AssetTile m_ui;
- mTileCache* m_tileCache;
+ mCacheSet* m_cacheSet;
+ mTileCache* m_tileCaches[2];
int m_paletteId = 0;
- int m_paletteSet = 0;
int m_index = 0;
int m_addressWidth;
int m_addressBase;
int m_boundary;
int m_boundaryBase;
+ bool m_flipH = false;
+ bool m_flipV = false;
+
+ QMap m_customProperties;
};
}
-
-#endif
diff --git a/src/platform/qt/AssetTile.ui b/src/platform/qt/AssetTile.ui
index b9075f24f..92a8623e1 100644
--- a/src/platform/qt/AssetTile.ui
+++ b/src/platform/qt/AssetTile.ui
@@ -2,6 +2,14 @@