diff -Nru mgba-0.6.3+dfsg1/CHANGES mgba-0.7.0/CHANGES --- mgba-0.6.3+dfsg1/CHANGES 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/CHANGES 2019-01-27 00:06:06.000000000 +0000 @@ -1,10 +1,171 @@ -0.6.3: (2017-04-14) +0.7.0: (2019-01-26) +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 + - Automatic cheat loading and saving + - GameShark and Action Replay button support + - AGBPrint support + - Debugger: Conditional breakpoints and watchpoints + - Ability to select GB/GBC/SGB BIOS on console ports + - Optional automatic state saving/loading + - Access to ur0 and uma0 partitions on the Vita + - Partial support for MBC6, MMM01, TAMA and HuC-1 GB mappers + - GBA: ARMIPS/A22i-style and ELF symbol table support + - Initial Switch port +Bugfixes: + - ARM: Fix MSR when T bit is set + - Core: Fix audio sync breaking when interrupted + - Core: Fix ordering events when scheduling during events + - FFmpeg: Fix encoding audio/video queue issues + - GB: Revamp IRQ handling based on new information + - GB: Fix IRQ disabling on the same T-cycle as an assert + - GB Audio: Make audio unsigned with bias (fixes mgba.io/i/749) + - GB Audio: Clock frame events on DIV + - GB Audio: Fix channel 3 reset value + - GB Audio: Fix channel 4 initial LFSR + - GB Audio: Fix channel 1, 2 and 4 reset timing + - GB I/O: DMA register is R/W + - GB MBC: Improve multicart detection heuristic (fixes mgba.io/i/1177) + - GB, GBA Savedata: Fix savestate loading overwriting saves on reset + - GB, GBA Savedata: Fix unmasking savedata crash + - GB Serialize: Fix audio state loading + - GB Serialize: Fix game title check + - GB Serialize: Fix IRQ pending/EI pending confusion + - GB Timer: Minor accuracy improvements + - GB Video: Fix dot clock timing being slightly wrong + - GB Video: Fix loading states while in mode 3 + - GB Video: Fix enabling window when LY > WY (fixes mgba.io/i/409) + - GB Video: Fix SCX timing + - GB, GBA Video: Don't call finishFrame twice in thread proxy + - GBA: Reset WAITCNT properly + - GBA BIOS: Fix BitUnPack final byte + - GBA BIOS: Fix BitUnPack narrowing + - GBA DMA: Fix invalid DMA reads (fixes mgba.io/i/142) + - GBA DMA: Fix temporal sorting of DMAs of different priorities + - GBA Hardware: Fix RTC overriding light sensor (fixes mgba.io/i/1069) + - GBA Hardware: Fix RTC handshake transition (fixes mgba.io/i/1134) + - GBA Memory: Fix Vast Fame support (taizou) (fixes mgba.io/i/1170) + - GBA Savedata: Fix savedata modified time updating when read-only + - GBA Serialize: Fix loading channel 3 volume (fixes mgba.io/i/1107) + - GBA Serialize: Fix loading states in Hblank + - GBA SIO: Fix unconnected SIOCNT for multi mode (fixes mgba.io/i/1105) + - GBA Timer: Fix timers sometimes being late (fixes mgba.io/i/1012) + - GBA Video: Don't mask out high bits of BLDY (fixes mgba.io/i/899) + - GBA Video: Add delay when enabling BGs (fixes mgba.io/i/744, mgba.io/i/752) + - GBA Video: Start timing mid-scanline when skipping BIOS + - GBA Video: Improve sprite cycle counting (fixes mgba.io/i/1126) + - GBA Video: Make layer disabling work consistently + - PSP2: Fix more issues causing poor audio + - Qt: Fix GL display when loading a game from CLI (fixes mgba.io/i/843) + - Qt: Improve FPS timer stability + - Util: Fix wrapping edge cases in RingFIFO +Misc: + - 3DS: Remove deprecated CSND interface + - All: Make FIXED_ROM_BUFFER an option instead of 3DS-only + - Core: Remove broken option for whether rewinding restores save games + - Feature: Added loading savestates from command line + - FFmpeg: Support libswresample (fixes mgba.io/i/1120, mgba.io/b/123) + - FFmpeg: Support lossless h.264 encoding + - FFmpeg: Support lossless VP9 encoding + - GBA Cheats: Allow multiple ROM patches in the same slot + - GB: Skip BIOS option now works + - GB: Fix VRAM/palette locking (fixes mgba.io/i/1109) + - GB Audio: Improved audio quality + - GB, GBA Audio: Increase max audio volume + - GB MBC: Remove erroneous bank 0 wrapping + - GB Video: Darken colors in GBA mode + - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) + - GBA: Implement display start DMAs + - GBA: Improve multiboot image detection + - GBA Memory: 64 MiB GBA Video cartridge support + - GBA Savedata: Remove ability to disable realistic timing + - GBA Timer: Use global cycles for timers + - Libretro: Add frameskip option + - mGUI: Add fast forward toggle + - PSP2: Use system enter key by default + - Python: Integrate tests from cinema test suite + - Qt: Redo GameController into multiple classes + - Qt: Prevent window from being created off-screen + - Qt: Add option to disable FPS display + - Qt: Options to mess around with layer placement + - Qt: Add load alternate save option + - Qt: Allow pausing game at load (fixes mgba.io/i/1129) + - Qt: Clean up FPS target UI (fixes mgba.io/i/436) + - Test: Restructure test suite into multiple executables + - Util: Don't build crc32 if the function already exists + - Wii: Move audio handling to callbacks (fixes mgba.io/i/803) +Changes from beta 1: +Features: + - Libretro: Add Game Boy cheat support + - Qt: Separate fast forward volume control (fixes mgba.io/i/846, mgba.io/i/1143) + - Switch: Rumble support + - Switch: Rotation support + - Switch: Screen stretching options + - Qt: State file load/save menu options + - Windows installer + - Tile viewer now has adjustable width + - Python: Experimental audio API +Bugfixes: + - 3DS: Fix unused screens not clearing (fixes mgba.io/i/1184) + - Core: Remember to deinit proxy ring FIFO + - Core: Reroot timing list when (de)scheduling + - GB, GBA: Fix broken opposing button filter (fixes mgba.io/i/1191) + - GB MBC: Fix MBC30 SRAM + - GB, GBA Savedata: Fix leaks when loading masked save (fixes mgba.io/i/1197) + - GB Video: Fix SGB border hole size + - GB Video: Changing LYC while LCDC off doesn't affect STAT (fixes mgba.io/i/1224) + - GBA: Fix GB Player features + - GBA I/O: SOUNDCNT_HI is readable when sound is off + - GBA Savedata: Fix EEPROM writing codepath when savetype is not EEPROM + - GBA Video: Fix caching with background toggling (fixes mgba.io/i/1118) + - Libretro: Fix adding codes with hooks + - PSP2: Fix audio crackling after fast forward + - PSP2: Fix audio crackling when buffer is full + - Qt: Fix jumbled background when paused + - Qt: Fix FPS counter on Windows + - Qt: Fix focus issues with load/save state overlay + - Switch: Fix incorrect mapping for fast forward cap + - Wii: Fix drawing caching regression (fixes mgba.io/i/1185) + - PSP2: Fix tearing issues (fixes mgba.io/i/1211) + - Qt: Fix mapping analog triggers (fixes mgba.io/i/495) + - Qt: Grab focus when game starts (fixes mgba.io/i/804) + - Qt: Ensure FATAL logs reach log view + - SDL: Fix handling of invalid gamepads (fixes mgba.io/i/1239) +Misc: + - CMake: Fix libswresample version dependencies (fixes mgba.io/i/1229) + - Debugger: Minor text fixes + - Debugger: Readability improvements (fixes mgba.io/i/1238) + - GB: Improved SGB2 support + - GB Audio: Skip frame if enabled when clock is high + - Libretro: Reduce rumble callbacks + - mGUI: Add SGB border configuration option + - mGUI: Add support for different settings types + - Python: Minor API improvements + - Qt: Ensure camera image is valid + - Qt: Debugger console history + - Qt: Detect presence of GL_ARB_framebuffer_object + - Qt: Minor memory view tweaks + - Res: Improve modeling of AGB/AGS screen in shaders + - Wii: Define _GNU_SOURCE (fixes mgba.io/i/1106) + - Wii: Expose stretch configuration in settings + - Wii: Stretch now sets pixel-accurate mode size cap + +0.7 beta 1: (2018-09-24) +- Initial beta for 0.7 + +0.6.3: (2018-04-14) Bugfixes: - GB Audio: Revert unsigned audio changes - GB Video: Fix bad merge (fixes mgba.io/i/1040) - GBA Video: Fix OBJ blending regression (fixes mgba.io/i/1037) -0.6.2: (2017-04-03) +0.6.2: (2018-04-03) Bugfixes: - Core: Fix ROM patches not being unloaded when disabled (fixes mgba.io/i/962) - 3DS: Fix opening files in directory names with trailing slashes @@ -72,7 +233,6 @@ - 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) - - GB Audio: Make audio unsigned with bias (fixes mgba.io/i/749) Misc: - CMake: Fix CPack dependencies for libpng 1.6 - GBA: Detect hardware for Pokémon FireRed ROM hacks @@ -108,7 +268,6 @@ - Video log recording for testing and bug reporting - Debugger: Segment/bank support - Debugger: Execution tracing - - Partial Python scripting support - Qt: German translation (by Lothar Serra Mari) - Qt: Spanish translation (by Kevin López) - Qt: Italian translation (by theheroGAC) @@ -144,6 +303,8 @@ - LR35902: Fix decoding LD r, $imm and 0-valued immediates (fixes mgba.io/i/735) - OpenGL: Fix some shaders causing offset graphics - GB Timer: Fix sub-M-cycle DIV reset timing and edge triggering + - Qt: Fix window icon being stretched + - Qt: Fix data directory path - Qt: Fix timing issues on high refresh rate monitors - Qt: Fix linking after some windows have been closed - Qt: Fix crash when changing audio settings after a game is closed @@ -239,7 +400,6 @@ - Qt: Italian translation (by theheroGAC) - Qt: Updated German translation Bugfixes: - - Core: Fix rewinding getting out of sync (fixes mgba.io/i/791) - GB Audio: Fix incorrect channel 4 iteration - GB Audio: Fix zombie mode bit masking - GB Serialize: Fix timer serialization @@ -255,6 +415,7 @@ - Qt: Fix translation initialization (fixes mgba.io/i/776) - Qt: Fix patch loading while a game is running - Qt: Fix shader selector on Ubuntu (fixes mgba.io/i/767) + - Core: Fix rewinding getting out of sync (fixes mgba.io/i/791) - Qt: Fix GL-less build - Qt: Fix Software renderer not handling alpha bits properly - Qt: Fix screen background improperly stretching @@ -265,7 +426,7 @@ - GBA Timer: Improve accuracy of timers - PSP2: Update toolchain to use vita.cmake - Qt: Add language selector - - Qt: Minor text fixes + - Qt: Minor test fixes - Qt: Move shader settings into main settings window - Qt: Dismiss game crashing/failing dialogs when a new game loads - Qt: Properly ship Qt translations Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/add_sp_e_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/mem_oam/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/reg_f/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/reg_f/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/reg_f/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/bits/unused_hwio-GS/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmg0/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-dmgABCXmgb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +config: {gb.model: SGB} Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_hwio-S/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmg0/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-dmgABCX/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +config: {gb.model: MGB} Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-mgb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +config: {gb.model: SGB} Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +config: {gb.model: SGB2} Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/boot_regs-sgb2/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_cc_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_cc_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_cc_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_cc_timing2/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_timing2/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_timing2/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_timing2/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_timing2/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_timing2/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_timing2/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/call_timing2/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/call_timing2/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/di_timing-GS/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/di_timing-GS/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/di_timing-GS/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/div_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/div_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/div_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/div_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/div_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/div_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/div_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/div_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ei_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ei_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ei_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ei_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ei_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ei_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ei_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ei_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/hblank_ly_scx_timing-GS/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_1_2_timing-GS/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_0_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode0_timing_sprites/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_mode3_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/intr_2_oam_ok_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_timing-dmgABCXmgbS/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/lcdon_write_timing-GS/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/stat_irq_blocking/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/gpu/vblank_stat_intr-GS/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime0_ei/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime0_nointr_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/halt_ime1_timing2-GS/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,2 @@ +config: + gb.model: CGB Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/hdma_lcdc/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/if_ie_registers/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/if_ie_registers/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/if_ie_registers/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/interrupts/ie_push/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/intr_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/intr_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/intr_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/intr_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/intr_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/intr_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/intr_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/intr_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/jp_cc_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/jp_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/jp_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/jp_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/jp_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/jp_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/jp_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/jp_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/jp_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ld_hl_sp_e_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_restart/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_start/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_start/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_start/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_start/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_start/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_start/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_start/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/oam_dma_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/pop_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/pop_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/pop_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/pop_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/pop_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/pop_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/pop_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/pop_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/push_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/push_timing/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/push_timing/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/push_timing/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/push_timing/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/push_timing/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/push_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/push_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/push_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/push_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/push_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/push_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/rapid_di_ei/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ret_cc_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/reti_intr_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/reti_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/reti_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/reti_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/reti_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/reti_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/reti_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/reti_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/reti_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ret_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ret_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ret_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ret_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ret_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ret_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/ret_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/ret_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/rst_timing/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/rst_timing/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/rst_timing/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/rst_timing/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/rst_timing/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/rst_timing/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/rst_timing/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/rst_timing/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/serial/boot_sclk_align-dmgABCXmgb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/div_write/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/div_write/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/div_write/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/rapid_toggle/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim00/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim00/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim00/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim00_div_trigger/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim01/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim01/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim01/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim01_div_trigger/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim10/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim10/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim10/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim10_div_trigger/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim11/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim11/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim11/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tim11_div_trigger/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tima_reload/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tima_write_reloading/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/acceptance/timer/tma_write_reloading/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/multicart_rom_8Mb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_256Kb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/ram_64Kb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_16Mb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_1Mb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_2Mb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_4Mb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_512Kb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1/rom_8Mb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/emulator-only/mbc1_rom_4banks/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/LICENSE mgba-0.7.0/cinema/gb/mooneye-gb/LICENSE --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/LICENSE 2019-01-27 00:06:06.000000000 +0000 @@ -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. Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/madness/mgb_oam_dma_halt_sprites/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,4 @@ +skip: 60 +frames: 1 +config: + sgb.borders: false Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/manual-only/sprite_priority/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/manual-only/sprite_priority/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/manual-only/sprite_priority/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/manual-only/sprite_priority/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/manual-only/sprite_priority/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/manual-only/sprite_priority/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/manual-only/sprite_priority/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,3 @@ +config: + gb.model: CGB +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/bits/unused_hwio-C/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_hwio-C/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_hwio-C/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_hwio-C/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_hwio-C/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_hwio-C/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_hwio-C/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,3 @@ +config: + gb.model: CGB +fail: true Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_hwio-C/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-A/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-A/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-A/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-A/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-A/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-A/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +config: {gb.model: AGB} Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-A/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-A/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-A/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-A/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-A/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-A/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-cgb/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-cgb/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-cgb/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-cgb/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-cgb/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-cgb/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +config: {gb.model: CGB} Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/boot_regs-cgb/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/baseline_0000.png differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/manifest.yml mgba-0.7.0/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/manifest.yml --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/manifest.yml 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/manifest.yml 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +config: {gb.model: CGB} Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.gb and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.gb differ diff -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.sym mgba-0.7.0/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.sym --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.sym 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/misc/gpu/vblank_stat_intr-C/test.sym 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/update.py mgba-0.7.0/cinema/gb/mooneye-gb/update.py --- mgba-0.6.3+dfsg1/cinema/gb/mooneye-gb/update.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/gb/mooneye-gb/update.py 2019-01-27 00:06:06.000000000 +0000 @@ -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) Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/baseline_0005.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/baseline_0005.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/baseline_0006.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/baseline_0006.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/baseline_0007.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/baseline_0007.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/baseline_0008.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/baseline_0008.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/dk94-split/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/dk94-split/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/gsc-battle/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/gsc-battle/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/gsc-battle/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/gsc-battle/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/gsc-battle/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/gsc-battle/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/gsc-battle/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/gsc-battle/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/gsc-battle/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/gsc-battle/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/gsc-battle/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/gsc-battle/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/wmm-hud/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/wmm-hud/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/wmm-hud/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/wmm-hud/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/wmm-hud/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/wmm-hud/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/wmm-hud/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/wmm-hud/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/wmm-hud/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/wmm-hud/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/wmm-hud/baseline_0005.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/wmm-hud/baseline_0005.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/wmm-hud/baseline_0006.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/wmm-hud/baseline_0006.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/wmm-hud/baseline_0007.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/wmm-hud/baseline_0007.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/wmm-hud/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/wmm-hud/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/zoos-intro/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/zoos-intro/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/zoos-intro/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/zoos-intro/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/zoos-intro/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/zoos-intro/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/zoos-intro/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/zoos-intro/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/zoos-intro/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/zoos-intro/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/zoos-intro/baseline_0005.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/zoos-intro/baseline_0005.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/zoos-intro/baseline_0006.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/zoos-intro/baseline_0006.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gb/window/zoos-intro/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gb/window/zoos-intro/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/bg/lady-sia/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/bg/lady-sia/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/bg/lady-sia/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/bg/lady-sia/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/bg/lady-sia/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/bg/lady-sia/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/bg/lady-sia/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/bg/lady-sia/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/bg/lady-sia/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/bg/lady-sia/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/gs-obj-modes/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/gs-obj-modes/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/gs-obj-modes/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/gs-obj-modes/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/gs-obj-modes/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/gs-obj-modes/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/gs-obj-modes/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/gs-obj-modes/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/gs-obj-modes/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/gs-obj-modes/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/gs-obj-modes/baseline_0005.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/gs-obj-modes/baseline_0005.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/gs-obj-modes/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/gs-obj-modes/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/kam-knockout/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/kam-knockout/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/kam-knockout/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/kam-knockout/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/kam-knockout/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/kam-knockout/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/kam-knockout/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/kam-knockout/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/kam-knockout/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/kam-knockout/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0005.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0005.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0006.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0006.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0007.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0007.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0008.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0008.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/baseline_0009.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/baseline_0009.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/mzm-layering/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/mzm-layering/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/sma-knockout/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/sma-knockout/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/sma-knockout/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/sma-knockout/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/sma-knockout/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/sma-knockout/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/blend/sma-knockout/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/blend/sma-knockout/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256-linear/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256-linear/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256-linear/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256-linear/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256-linear/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256-linear/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256-linear/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256-linear/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256-linear/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256-linear/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256-linear/baseline_0005.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256-linear/baseline_0005.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/obj/unaligned-256-linear/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/obj/unaligned-256-linear/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0005.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0005.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0006.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0006.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0007.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0007.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0008.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0008.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0009.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0009.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0010.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0010.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0011.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0011.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0012.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0012.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0013.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0013.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0014.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0014.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0015.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0015.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0016.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0016.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/baseline_0017.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/baseline_0017.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/gs-clock-wipe/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/gs-clock-wipe/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/sthg-objwin-blend/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/sthg-objwin-blend/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/sthg-objwin-blend/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/sthg-objwin-blend/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/sthg-objwin-blend/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/sthg-objwin-blend/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/sthg-objwin-blend/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/sthg-objwin-blend/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/sthg-objwin-blend/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/sthg-objwin-blend/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0005.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0005.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0006.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0006.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0007.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0007.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0008.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0008.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0009.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0009.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0010.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0010.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0011.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0011.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0012.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0012.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0013.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0013.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0014.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0014.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0015.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0015.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0016.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0016.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0017.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0017.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0018.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0018.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0019.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0019.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0020.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0020.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0021.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0021.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0022.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0022.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0023.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0023.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/baseline_0024.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/baseline_0024.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/tgr-objwin-order/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/tgr-objwin-order/test.mvl differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0000.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0000.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0001.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0001.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0002.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0002.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0003.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0003.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0004.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0004.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0005.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0005.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0006.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0006.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0007.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0007.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0008.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0008.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0009.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0009.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0010.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0010.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0011.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0011.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0012.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0012.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0013.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0013.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0014.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0014.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0015.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0015.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0016.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0016.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0017.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0017.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0018.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0018.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0019.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0019.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0020.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0020.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0021.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0021.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0022.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0022.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0023.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0023.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0024.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0024.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0025.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0025.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0026.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0026.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/baseline_0027.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/baseline_0027.png differ Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/cinema/gba/window/zmc-window-mosaic/test.mvl and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/cinema/gba/window/zmc-window-mosaic/test.mvl differ diff -Nru mgba-0.6.3+dfsg1/cinema/.gitignore mgba-0.7.0/cinema/.gitignore --- mgba-0.6.3+dfsg1/cinema/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/cinema/.gitignore 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1 @@ +*.sav diff -Nru mgba-0.6.3+dfsg1/CMakeLists.txt mgba-0.7.0/CMakeLists.txt --- mgba-0.6.3+dfsg1/CMakeLists.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/CMakeLists.txt 2019-01-27 00:06:06.000000000 +0000 @@ -1,12 +1,17 @@ -cmake_minimum_required(VERSION 2.8.11) +cmake_minimum_required(VERSION 3.1) if(POLICY CMP0025) cmake_policy(SET CMP0025 NEW) endif() +if(POLICY CMP0072) + cmake_policy(SET CMP0072 NEW) +endif() project(mGBA) set(BINARY_NAME mgba CACHE INTERNAL "Name of output binaries") if(NOT MSVC) set(GCC_STD "c99") - if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_COMPILER_VERSION VERSION_LESS "4.3") + if(SWITCH) + set(GCC_STD "gnu11") + elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_COMPILER_VERSION VERSION_LESS "4.3") set(GCC_STD "gnu99") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-missing-field-initializers -std=${GCC_STD}") @@ -25,9 +30,11 @@ set(USE_LIBZIP ON CACHE BOOL "Whether or not to enable LIBZIP support") set(USE_MAGICK ON CACHE BOOL "Whether or not to enable ImageMagick support") set(USE_SQLITE3 ON CACHE BOOL "Whether or not to enable SQLite3 support") +set(USE_ELF ON CACHE BOOL "Whether or not to enable ELF support") set(M_CORE_GBA ON CACHE BOOL "Build Game Boy Advance core") set(M_CORE_GB ON CACHE BOOL "Build Game Boy core") set(USE_LZMA ON CACHE BOOL "Whether or not to enable 7-Zip support") +set(ENABLE_SCRIPTING ON CACHE BOOL "Whether or not to enable scripting support") set(BUILD_QT ON CACHE BOOL "Build Qt frontend") set(BUILD_SDL ON CACHE BOOL "Build SDL frontend") set(BUILD_LIBRETRO OFF CACHE BOOL "Build libretro core") @@ -42,10 +49,12 @@ set(BUILD_STATIC OFF CACHE BOOL "Build a static library") set(BUILD_SHARED ON CACHE BOOL "Build a shared library") set(SKIP_LIBRARY OFF CACHE BOOL "Skip building the library (useful for only building libretro or OpenEmu cores)") -set(BUILD_GL ON CACHE STRING "Build with OpenGL") -set(BUILD_GLES2 OFF CACHE STRING "Build with OpenGL|ES 2") +set(BUILD_GL ON CACHE BOOL "Build with OpenGL") +set(BUILD_GLES2 OFF CACHE BOOL "Build with OpenGL|ES 2") +set(BUILD_GLES3 OFF CACHE BOOL "Build with OpenGL|ES 3") set(USE_EPOXY ON CACHE STRING "Build with libepoxy") set(DISABLE_DEPS OFF CACHE BOOL "Build without dependencies") +set(DISTBUILD OFF CACHE BOOL "Build distribution packages") if(WIN32) set(WIN32_UNIX_PATHS OFF CACHE BOOL "Use Unix-like paths") mark_as_advanced(WIN32_UNIX_PATHS) @@ -62,13 +71,13 @@ file(GLOB GBA_RR_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/rr/*.c) file(GLOB CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/core/*.c) file(GLOB CORE_TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/core/test/*.c) -file(GLOB UTIL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/*.[cSs]) +file(GLOB UTIL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/*.c) file(GLOB UTIL_TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/test/*.c) file(GLOB GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/gui/*.c ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/gui/*.c) 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_SIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/sio/*.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 THIRD_PARTY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/third-party/inih/*.c) @@ -84,10 +93,10 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src) if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type (e.g. Release or Debug)" FORCE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type (e.g. Release, RelWithDebInfo, or Debug)" FORCE) endif() -if(NOT WIN32 OR WIN32_UNIX_PATHS) +if(UNIX OR WIN32_UNIX_PATHS) include(GNUInstallDirs) else() set(CMAKE_INSTALL_LIBDIR ".") @@ -110,8 +119,13 @@ mark_as_advanced(OE_LIBDIR) endif() +if (DISTBUILD) + set(EXTRA_LICENSES "" CACHE FILEPATH "Extra licenses to include in distribution packaages") + mark_as_advanced(EXTRA_LICENSES) +endif() +mark_as_advanced(DISTBUILD) -set(CMAKE_INSTALL_RPATH "${LIBDIR}") +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIBDIR}") if (NOT DEFINED MANDIR) set(MANDIR ${CMAKE_INSTALL_MANDIR}) @@ -182,7 +196,7 @@ source_group("Generated sources" FILES ${CMAKE_CURRENT_BINARY_DIR}/version.c) # Advanced settings -if(NOT DEFINED 3DS) +if(NOT DEFINED 3DS AND NOT (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_COMPILER_VERSION VERSION_LESS "4.5")) # LTO appears to make 3DS binary slower set(DEFAULT_LTO ON) else() @@ -253,6 +267,14 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto") endif() +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") + find_program(OBJCOPY ${cross_prefix}objcopy) + find_program(STRIP ${cross_prefix}strip) + + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE} -gdwarf") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf") +endif() + if(BUILD_BBB OR BUILD_RASPI OR BUILD_PANDORA) if(NOT BUILD_EGL) add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5) @@ -275,11 +297,20 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format") endif() -if(DEFINED 3DS OR DEFINED PSP2 OR DEFINED WII) +if(DEFINED 3DS OR DEFINED PSP2 OR DEFINED WII OR DEFINED SWITCH) + set(IS_EMBEDDED ON) set(USE_DEBUGGERS OFF) set(USE_SQLITE3 OFF) endif() +if(DEFINED 3DS) + add_definitions(-DFIXED_ROM_BUFFER) +endif() + +if(DEFINED SWITCH) + set(BUILD_GLES3 ON CACHE BOOL "Build with OpenGL|ES 3" FORCE) +endif() + if(NOT M_CORE_GBA) set(USE_GDB_STUB OFF) endif() @@ -293,16 +324,18 @@ add_definitions(-U__STRICT_ANSI__) endif() -if(DEFINED 3DS) +if(3DS OR WII) add_definitions(-D_GNU_SOURCE) endif() include(CheckFunctionExists) +include(CheckIncludeFiles) check_function_exists(strdup HAVE_STRDUP) check_function_exists(strndup HAVE_STRNDUP) if(NOT DEFINED PSP2) check_function_exists(localtime_r HAVE_LOCALTIME_R) endif() +check_include_files("xlocale.h" HAVE_XLOCALE) if(NOT CMAKE_SYSTEM_NAME STREQUAL "Generic") check_function_exists(snprintf_l HAVE_SNPRINTF_L) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") @@ -316,7 +349,7 @@ check_function_exists(uselocale HAVE_USELOCALE) check_function_exists(setlocale HAVE_SETLOCALE) else() - if(DEFINED 3DS OR DEFINED WII) + if(DEFINED 3DS OR DEFINED WII OR DEFINED SWITCH) set(CMAKE_REQUIRED_FLAGS -Wl,--require-defined,snprintf_l) check_function_exists(snprintf_l HAVE_SNPRINTF_L) set(CMAKE_REQUIRED_FLAGS -Wl,--require-defined,strtof_l) @@ -331,9 +364,11 @@ check_function_exists(setlocale HAVE_SETLOCALE) unset(CMAKE_REQUIRED_FLAGS) endif() - if(NOT DEFINED 3DS AND NOT DEFINED PSP2 AND NOT DEFINED WII) + if(NOT IS_EMBEDDED) set(DISABLE_DEPS ON CACHE BOOL "This platform cannot build with dependencies" FORCE) endif() + set(BUILD_STATIC ON CACHE BOOL "" FORCE) + set(BUILD_SHARED OFF CACHE BOOL "" FORCE) set(DISABLE_FRONTENDS ON) set(MINIMAL_CORE ON) set(ENABLE_EXTRA ON) @@ -358,9 +393,6 @@ if(HAVE_NEWLOCALE AND HAVE_FREELOCALE AND HAVE_USELOCALE OR APPLE) list(APPEND FUNCTION_DEFINES HAVE_LOCALE) - if (HAVE_STRTOF_L) - list(APPEND FUNCTION_DEFINES HAVE_STRTOF_L) - endif() if (HAVE_SNPRINTF_L) list(APPEND FUNCTION_DEFINES HAVE_SNPRINTF_L) endif() @@ -370,6 +402,14 @@ list(APPEND FUNCTION_DEFINES HAVE_SETLOCALE) endif() +if (HAVE_STRTOF_L) + list(APPEND FUNCTION_DEFINES HAVE_STRTOF_L) +endif() + +if(HAVE_XLOCALE) + list(APPEND FUNCTION_DEFINES HAVE_XLOCALE) +endif() + if(HAVE_CHMOD) list(APPEND FUNCTION_DEFINES HAVE_CHMOD) endif() @@ -382,6 +422,7 @@ set(FEATURE_DEFINES) set(FEATURE_FLAGS) set(FEATURES) +set(ENABLES) if(CMAKE_SYSTEM_NAME MATCHES .*BSD) set(LIBEDIT_LIBRARIES -ledit) if (CMAKE_SYSTEM_NAME STREQUAL OpenBSD) @@ -409,13 +450,20 @@ if(NOT BUILD_GLES2) set(OPENGLES2_LIBRARY "" CACHE PATH "" FORCE) endif() +if(BUILD_GLES3) + find_path(OPENGLES3_INCLUDE_DIR NAMES GLES3/gl3.h) + find_library(OPENGLES3_LIBRARY NAMES GLESv3 GLESv2) + if(NOT OPENGLES3_INCLUDE_DIR OR NOT OPENGLES3_LIBRARY) + set(BUILD_GLES3 OFF CACHE BOOL "OpenGL|ES 3 not found" FORCE) + endif() +endif() set(WANT_ZLIB ${USE_ZLIB}) set(WANT_PNG ${USE_PNG}) set(WANT_LIBZIP ${USE_LIBZIP}) set(WANT_SQLITE3 ${USE_SQLITE3}) set(USE_CMOCKA ${BUILD_SUITE}) -find_feature(USE_FFMPEG "libavcodec;libavformat;libavresample;libavutil;libswscale") +find_feature(USE_FFMPEG "libavcodec;libavformat;libavutil;libswscale") find_feature(USE_ZLIB "ZLIB") find_feature(USE_MINIZIP "minizip") find_feature(USE_PNG "PNG") @@ -424,6 +472,15 @@ find_feature(USE_EPOXY "epoxy") find_feature(USE_CMOCKA "cmocka") find_feature(USE_SQLITE3 "sqlite3") +find_feature(USE_ELF "libelf") +find_feature(ENABLE_PYTHON "PythonLibs") + +if(USE_FFMPEG) + set(USE_LIBAVRESAMPLE ON) + set(USE_LIBSWRESAMPLE ON) + find_feature(USE_LIBAVRESAMPLE "libavresample") + find_feature(USE_LIBSWRESAMPLE "libswresample") +endif() # Features set(DEBUGGER_SRC @@ -432,6 +489,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/symbols.c ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/cli-debugger.c) +file(GLOB DEBUGGER_TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/test/*.c) + set(FEATURE_SRC) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6") @@ -458,22 +517,29 @@ if(USE_FFMPEG) list(APPEND FEATURES FFMPEG) - pkg_search_module(LIBSWRESAMPLE QUIET libswresample) - if(NOT LIBSWRESAMPLE_FOUND) + if(USE_LIBSWRESAMPLE) + list(APPEND FEATURES LIBSWRESAMPLE) + else() + list(APPEND FEATURES LIBAVRESAMPLE) list(APPEND FEATURES LIBAV) endif() - include_directories(AFTER ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS}) - link_directories(${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS}) + include_directories(AFTER ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWRESAMPLE_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS}) + link_directories(${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWRESAMPLE_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS}) list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-encoder.c") string(REGEX MATCH "^[0-9]+" LIBAVCODEC_VERSION_MAJOR ${libavcodec_VERSION}) string(REGEX MATCH "^[0-9]+" LIBAVFORMAT_VERSION_MAJOR ${libavformat_VERSION}) - string(REGEX MATCH "^[0-9]+" LIBAVRESAMPLE_VERSION_MAJOR ${libavresample_VERSION}) string(REGEX MATCH "^[0-9]+" LIBAVUTIL_VERSION_MAJOR ${libavutil_VERSION}) string(REGEX MATCH "^[0-9]+" LIBSWSCALE_VERSION_MAJOR ${libswscale_VERSION}) - list(APPEND DEPENDENCY_LIB ${LIBAVCODEC_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES}) + list(APPEND DEPENDENCY_LIB ${LIBAVCODEC_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES} ${LIBSWRESAMPLE_LIBRARIES}) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavcodec${LIBAVCODEC_VERSION_MAJOR}|libavcodec-extra-${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}") set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavformat${LIBAVFORMAT_VERSION_MAJOR}|libavformat-ffmpeg${LIBAVFORMAT_VERSION_MAJOR}") - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavresample${LIBAVRESAMPLE_VERSION_MAJOR}|libavresample-ffmpeg${LIBAVRESAMPLE_VERSION_MAJOR}") + if(USE_LIBSWRESAMPLE) + string(REGEX MATCH "^[0-9]+" LIBSWRESAMPLE_VERSION_MAJOR ${libswresample_VERSION}) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswresample${LIBSWRESAMPLE_VERSION_MAJOR}|libswresample-ffmpeg${LIBSWRESAMPLE_VERSION_MAJOR}") + else() + string(REGEX MATCH "^[0-9]+" LIBAVRESAMPLE_VERSION_MAJOR ${libavresample_VERSION}) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavresample${LIBAVRESAMPLE_VERSION_MAJOR}|libavresample-ffmpeg${LIBAVRESAMPLE_VERSION_MAJOR}") + endif() set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavutil${LIBAVUTIL_VERSION_MAJOR}|libavutil-ffmpeg${LIBAVUTIL_VERSION_MAJOR}") set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswscale${LIBSWSCALE_VERSION_MAJOR}|libswscale-ffmpeg${LIBSWSCALE_VERSION_MAJOR}") set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libavcodec-extra|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}") @@ -495,6 +561,8 @@ string(REGEX MATCH "^[0-9]+" MAGICKWAND_VERSION_MAJOR ${MagickWand_VERSION}) if(${MAGICKWAND_VERSION_PARTIAL} EQUAL "6.7") set(MAGICKWAND_DEB_VERSION "5") + elseif(${MagickWand_VERSION} EQUAL "6.9.10") + set(MAGICKWAND_DEB_VERSION "-6.q16-6") elseif(${MagickWand_VERSION} EQUAL "6.9.7") set(MAGICKWAND_DEB_VERSION "-6.q16-3") else() @@ -525,6 +593,15 @@ 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) + list(APPEND OS_LIB ${ZLIB_LIBRARIES}) +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) @@ -532,10 +609,13 @@ set(PNG_SHARED OFF CACHE BOOL "" FORCE) set(PNG_TESTS OFF CACHE BOOL "" FORCE) set(SKIP_INSTALL_ALL ON) + if (SWITCH) + set(PNG_ARM_NEON "off" CACHE STRING "" FORCE) + endif() add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/third-party/libpng libpng) - set_property(TARGET png16_static PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}/libpng;${CMAKE_CURRENT_SOURCE_DIR}/src/third-party/libpng;${ZLIB_INCLUDE_DIRS}) + set_property(TARGET png_static PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}/libpng;${CMAKE_CURRENT_SOURCE_DIR}/src/third-party/libpng;${ZLIB_INCLUDE_DIRS}) set(PNG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/third-party/libpng ${CMAKE_CURRENT_BINARY_DIR}/libpng) - list(APPEND DEPENDENCY_LIB png16_static) + list(APPEND DEPENDENCY_LIB png_static) set(USE_PNG ON) endif() @@ -637,6 +717,24 @@ list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/sqlite3/no-intro.c") endif() +if(USE_ELF) + list(APPEND FEATURES ELF) + include_directories(AFTER ${LIBELF_INCLUDE_DIRS}) + list(APPEND DEPENDENCY_LIB ${LIBELF_LIBRARIES}) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libelf1") +endif() + +if(ENABLE_SCRIPTING) + list(APPEND ENABLES SCRIPTING) + + if(BUILD_PYTHON) + find_package(PythonLibs ${USE_PYTHON_VERSION}) + list(APPEND DEPENDENCY_LIB ${PYTHON_LIBRARIES}) + include_directories(AFTER ${PYTHON_INCLUDE_DIRS}) + list(APPEND ENABLES PYTHON) + endif() +endif() + set(TEST_SRC ${CORE_TEST_SRC}) if(M_CORE_GB) add_definitions(-DM_CORE_GB) @@ -677,6 +775,7 @@ if(USE_DEBUGGERS) list(APPEND FEATURE_SRC ${DEBUGGER_SRC}) + list(APPEND TEST_SRC ${DEBUGGER_TEST_SRC}) list(APPEND FEATURES DEBUGGERS) endif() @@ -684,6 +783,10 @@ list(APPEND FEATURE_DEFINES "USE_${FEATURE}") endforeach() +foreach(ENABLE IN LISTS ENABLES) + list(APPEND FEATURE_DEFINES "ENABLE_${ENABLE}") +endforeach() + source_group("Virtual files" FILES ${CORE_VFS_SRC} ${VFS_SRC}) source_group("Extra features" FILES ${FEATURE_SRC}) source_group("Third-party code" FILES ${THIRD_PARTY_SRC}) @@ -701,6 +804,10 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/psp2 ${CMAKE_CURRENT_BINARY_DIR}/psp2) endif() +if(DEFINED SWITCH) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/switch ${CMAKE_CURRENT_BINARY_DIR}/switch) +endif() + # Binaries list(APPEND CORE_SRC ${UTIL_SRC} @@ -761,15 +868,15 @@ target_link_libraries(${BINARY_NAME} ${DEBUGGER_LIB} ${DEPENDENCY_LIB} ${OS_LIB}) install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME} NAMELINK_SKIP ARCHIVE DESTINATION ${LIBDIR} RUNTIME DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME}) if(UNIX AND NOT APPLE AND NOT HAIKU) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-16.png DESTINATION share/icons/hicolor/16x16/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-24.png DESTINATION share/icons/hicolor/24x24/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-32.png DESTINATION share/icons/hicolor/32x32/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-48.png DESTINATION share/icons/hicolor/48x48/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-64.png DESTINATION share/icons/hicolor/64x64/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-96.png DESTINATION share/icons/hicolor/96x96/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-128.png DESTINATION share/icons/hicolor/128x128/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-256.png DESTINATION share/icons/hicolor/256x256/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-512.png DESTINATION share/icons/hicolor/512x512/apps RENAME mgba.png COMPONENT lib${BINARY_NAME}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-16.png DESTINATION share/icons/hicolor/16x16/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-24.png DESTINATION share/icons/hicolor/24x24/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-32.png DESTINATION share/icons/hicolor/32x32/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-48.png DESTINATION share/icons/hicolor/48x48/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-64.png DESTINATION share/icons/hicolor/64x64/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-96.png DESTINATION share/icons/hicolor/96x96/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-128.png DESTINATION share/icons/hicolor/128x128/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-256.png DESTINATION share/icons/hicolor/256x256/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-512.png DESTINATION share/icons/hicolor/512x512/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) endif() else() set(BUILD_SHARED OFF) @@ -791,24 +898,37 @@ add_definitions(-DBUILD_GLES2) endif() +if(BUILD_GLES3) + add_definitions(-DBUILD_GLES3) +endif() + if(DISABLE_FRONTENDS) set(BUILD_SDL OFF) set(BUILD_QT OFF) endif() +if(BUILD_PYTHON) + enable_testing() + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/python ${CMAKE_CURRENT_BINARY_DIR}/python) +endif() + if(BUILD_LIBRETRO) file(GLOB RETRO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/libretro/*.c) add_library(${BINARY_NAME}_libretro SHARED ${CORE_SRC} ${RETRO_SRC}) set_target_properties(${BINARY_NAME}_libretro PROPERTIES PREFIX "" COMPILE_DEFINITIONS "COLOR_16_BIT;COLOR_5_6_5;DISABLE_THREADING;${OS_DEFINES};${FUNCTION_DEFINES};MINIMAL_CORE=2") target_link_libraries(${BINARY_NAME}_libretro ${OS_LIB}) - install(TARGETS ${BINARY_NAME}_libretro LIBRARY DESTINATION ${LIBRETRO_LIBDIR} COMPONENT ${BINARY_NAME}_libretro NAMELINK_SKIP) + if(MSVC) + install(TARGETS ${BINARY_NAME}_libretro RUNTIME DESTINATION ${LIBRETRO_LIBDIR} COMPONENT ${BINARY_NAME}_libretro) + else() + install(TARGETS ${BINARY_NAME}_libretro LIBRARY DESTINATION ${LIBRETRO_LIBDIR} COMPONENT ${BINARY_NAME}_libretro NAMELINK_SKIP) + endif() endif() if(BUILD_OPENEMU) find_library(FOUNDATION Foundation) find_library(OPENEMUBASE OpenEmuBase) file(GLOB OE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/openemu/*.m) - add_library(${BINARY_NAME}-openemu MODULE ${CORE_SRC} ${OE_SRC}) + add_library(${BINARY_NAME}-openemu MODULE ${CORE_SRC} ${OS_SRC}) set_target_properties(${BINARY_NAME}-openemu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/openemu/Info.plist.in BUNDLE TRUE @@ -821,10 +941,6 @@ if(BUILD_SDL) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/sdl ${CMAKE_CURRENT_BINARY_DIR}/sdl) - # The SDL platform CMakeLists could decide to disable SDL, so check again before adding the define. - if(BUILD_SDL) - add_definitions(-DBUILD_SDL) - endif() endif() if(BUILD_QT) @@ -840,8 +956,8 @@ add_executable(${BINARY_NAME}-perf ${PERF_SRC}) target_link_libraries(${BINARY_NAME}-perf ${BINARY_NAME} ${PERF_LIB} ${OS_LIB}) set_target_properties(${BINARY_NAME}-perf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") - install(TARGETS ${BINARY_NAME}-perf DESTINATION bin COMPONENT ${BINARY_NAME}-perf) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tools/perf.py DESTINATION "${CMAKE_INSTALL_LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf) + install(TARGETS ${BINARY_NAME}-perf DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-perf) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tools/perf.py DESTINATION "${LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf) endif() if(BUILD_TEST) @@ -851,7 +967,7 @@ add_executable(tbl-fuzz ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/test/tbl-fuzz-main.c) target_link_libraries(tbl-fuzz ${BINARY_NAME}) set_target_properties(tbl-fuzz PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") - install(TARGETS ${BINARY_NAME}-fuzz tbl-fuzz DESTINATION bin COMPONENT ${BINARY_NAME}-test) + install(TARGETS ${BINARY_NAME}-fuzz tbl-fuzz DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-test) endif() if(NOT USE_CMOCKA) @@ -862,15 +978,16 @@ 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) -endif() - -if(BUILD_PYTHON) - enable_testing() - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/python ${CMAKE_CURRENT_BINARY_DIR}/python) + 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) @@ -878,7 +995,7 @@ target_link_libraries(${BINARY_NAME}-example-server ${BINARY_NAME}) set_target_properties(${BINARY_NAME}-example-server PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") - if(BUILD_SDL) + if(SDL_FOUND) add_executable(${BINARY_NAME}-example-client ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/example/client-server/client.c) target_link_libraries(${BINARY_NAME}-example-client ${BINARY_NAME} ${SDL_LIBRARY} ${SDLMAIN_LIBRARY} ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) set_target_properties(${BINARY_NAME}-example-client PROPERTIES @@ -890,7 +1007,84 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/core/flags.h.in ${CMAKE_CURRENT_BINARY_DIR}/flags.h) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/flags.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mgba COMPONENT lib${BINARY_NAME}) +if(WIN32) + set(BIN_DIR ".\\") + string(REGEX REPLACE "[^-A-Za-z0-9_.]" "-" CLEAN_VERSION_STRING "${VERSION_STRING}") + file(RELATIVE_PATH SETUP_DIR_SLASH "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/setup") + file(RELATIVE_PATH RES_DIR_SLASH "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/res") + string(REPLACE "/" "\\" SETUP_DIR "${SETUP_DIR_SLASH}") + string(REPLACE "/" "\\" RES_DIR "${RES_DIR_SLASH}") + if(CMAKE_SYSTEM_PROCESSOR MATCHES ".*64$") + set(WIN_BITS 64) + else() + set(WIN_BITS 32) + endif() + if(GIT_TAG) + set(IS_RELEASE 1) + else() + set(IS_RELEASE 0) + endif() + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/setup/setup.iss.in" ${CMAKE_CURRENT_BINARY_DIR}/setup.iss) +endif() + # Packaging +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/res/licenses DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) +if(EXTRA_LICENSES) + install(FILES ${EXTRA_LICENSES} DESTINATION ${CMAKE_INSTALL_DOCDIR}/licenses COMPONENT ${BINARY_NAME}) +endif() + +file(GLOB READMES ${CMAKE_CURRENT_SOURCE_DIR}/README*.md) + +find_program(UNIX2DOS NAMES unix2dos) +find_program(MARKDOWN NAMES markdown kramdown pandoc) + +if(UNIX OR NOT UNIX2DOS) + if(UNIX OR NOT MARKDOWN) + install(FILES ${READMES} DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) + endif() + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES" "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) +else() + add_custom_command(OUTPUT CHANGES.txt COMMAND ${UNIX2DOS} -n "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES" "${CMAKE_CURRENT_BINARY_DIR}/CHANGES.txt" MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES") + add_custom_command(OUTPUT LICENSE.txt COMMAND ${UNIX2DOS} -n "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt" MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") + add_custom_target(CHANGES ALL DEPENDS CHANGES.txt) + add_custom_target(LICENSE ALL DEPENDS LICENSE.txt) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CHANGES.txt ${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) + if(DISTBUILD AND WIN32) + if(INSTALLER_NAME) + set(INSTALLER_TARGET "${INSTALLER_NAME}.exe") + set(ISCC_FLAGS "/F${INSTALLER_NAME}") + else() + set(INSTALLER_TARGET "${PROJECT_NAME}-setup-${CLEAN_VERSION_STRING}-win${WIN_BITS}.exe") + endif() + if(CMAKE_CROSSCOMPILING) + find_program(WINE NAMES wine wine-stable wine-development) + find_file(ISCC ISCC.exe HINTS "$ENV{HOME}/.wine/drive_c/Program Files/" PATH_SUFFIXES "Inno Setup 5") + message(STATUS "${WINE}" "${ISCC}" setup.iss /Q ${ISCC_FLAGS}) + add_custom_command(OUTPUT ${INSTALLER_TARGET} + COMMAND "${WINE}" "${ISCC}" setup.iss /Q ${ISCC_FLAGS} + DEPENDS ${BINARY_NAME}-qt ${BINARY_NAME}-sdl CHANGES LICENSE) + else() + find_program(ISCC NAMES ISCC ISCC.exe PATH_SUFFIXES "Inno Setup 5") + add_custom_command(OUTPUT ${INSTALLER_TARGET} + COMMAND "${ISCC}" setup.iss /Q ${ISCC_FLAGS} + DEPENDS ${BINARY_NAME}-qt ${BINARY_NAME}-sdl CHANGES LICENSE) + endif() + if(ISCC) + add_custom_target(installer ALL DEPENDS ${INSTALLER_TARGET}) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${INSTALLER_TARGET}" DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT installer) + endif() + endif() +endif() + +if(MARKDOWN) + foreach(README ${READMES}) + get_filename_component(README_BASE "${README}" NAME_WE) + add_custom_command(OUTPUT ${README_BASE}.html COMMAND ${MARKDOWN} "${README}" > ${README_BASE}.html MAIN_DEPENDENCY "${README}") + add_custom_target(${README_BASE} ALL DEPENDS ${README_BASE}.html) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${README_BASE}.html DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) + endforeach() +endif() + set(CPACK_PACKAGE_VERSION ${VERSION_STRING}) set(CPACK_PACKAGE_VERSION_MAJOR ${LIB_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${LIB_VERSION_MINOR}) @@ -904,14 +1098,96 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") set(CPACK_DEBIAN_PACKAGE_SECTION "games") -SET(CPACK_DEB_COMPONENT_INSTALL ON) +set(CPACK_DEB_COMPONENT_INSTALL ON) -set(CPACK_STRIP_FILES ${BINARY_NAME}) +if(CMAKE_BUILD_TYPE STREQUAL "Release") + set(CPACK_STRIP_FILES ON) +endif() -install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/README.md ${CMAKE_CURRENT_SOURCE_DIR}/CHANGES DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib${BINARY_NAME}) +if(DISTBUILD) + set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) + if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" AND BUILD_SHARED) + if(NOT APPLE) + add_custom_command(TARGET ${BINARY_NAME} POST_BUILD COMMAND "${OBJCOPY}" --only-keep-debug "$" "$.dSYM") + add_custom_command(TARGET ${BINARY_NAME} POST_BUILD COMMAND "${STRIP}" -S "$") + install(FILES "$.dSYM" DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME}-dbg) + endif() + endif() + if(APPLE) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-qt ${BINARY_NAME}-sdl ${BINARY_NAME}-qt-dbg ${BINARY_NAME}-sdl-dbg ${BINARY_NAME}-perf) + set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) + elseif(WIN32) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-qt ${BINARY_NAME}-sdl ${BINARY_NAME}-qt-dbg ${BINARY_NAME}-sdl-dbg ${BINARY_NAME}-perf installer) + elseif(3DS) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-dbg ${BINARY_NAME}-3ds ${BINARY_NAME}-perf) + elseif(WII) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-dbg ${BINARY_NAME}-wii) + elseif(PSP2) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-dbg ${BINARY_NAME}-psp2) + elseif(SWITCH) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-dbg ${BINARY_NAME}-switch) + endif() +endif() include(CPack) +cpack_add_component_group(base) +cpack_add_component(${BINARY_NAME} GROUP base) + +cpack_add_component_group(dev PARENT_GROUP base) +if(BUILD_SHARED) + cpack_add_component(lib${BINARY_NAME} GROUP base) + if(BUILD_STATIC) + cpack_add_component(lib${BINARY_NAME}-static GROUP dev) + endif() +elseif(BUILD_STATIC) + cpack_add_component(lib${BINARY_NAME} GROUP dev) +endif() + +if(3DS) + cpack_add_component(${BINARY_NAME}-3ds GROUP base) +elseif(PSP2) + cpack_add_component(${BINARY_NAME}-psp2 GROUP base) +elseif(WII) + cpack_add_component(${BINARY_NAME}-wii GROUP base) +elseif(SWITCH) + cpack_add_component(${BINARY_NAME}-switch GROUP base) +endif() + +if(BUILD_QT) + cpack_add_component_group(qt PARENT_GROUP base) + cpack_add_component(${BINARY_NAME}-qt GROUP qt) +endif() + +if(SDL_FOUND) + cpack_add_component_group(sdl PARENT_GROUP base) + cpack_add_component(${BINARY_NAME}-sdl GROUP sdl) +endif() + +if(DISTBUILD) + cpack_add_component_group(debug PARENT_GROUP dev) + if(BUILD_SHARED AND NOT IS_EMBEDDED) + cpack_add_component(lib${BINARY_NAME}-dbg GROUP debug) + endif() + if(IS_EMBEDDED) + cpack_add_component(${BINARY_NAME}-dbg GROUP debug) + endif() + if(BUILD_QT) + cpack_add_component(${BINARY_NAME}-qt-dbg GROUP debug) + endif() + if(SDL_FOUND) + cpack_add_component(${BINARY_NAME}-sdl-dbg GROUP debug) + endif() + if(WIN32) + cpack_add_component_group(installer PARENT_GROUP base) + endif() +endif() + +cpack_add_component_group(test PARENT_GROUP dev) +cpack_add_component(${BINARY_NAME}-perf GROUP test) +cpack_add_component(${BINARY_NAME}-fuzz GROUP test) +cpack_add_component(tbl-fuzz GROUP test) + # Summaries set(SUMMARY_GL_LIST) if(USE_EPOXY) @@ -923,6 +1199,9 @@ if(BUILD_GLES2) list(APPEND SUMMARY_GL_LIST "OpenGL|ES 2") endif() + if(BUILD_GLES3) + list(APPEND SUMMARY_GL_LIST "OpenGL|ES 3") + endif() endif() if(NOT SUMMARY_GL_LIST) set(SUMMARY_GL OFF) @@ -956,6 +1235,7 @@ message(STATUS " ZIP support: ${SUMMARY_ZIP}") message(STATUS " 7-Zip support: ${USE_LZMA}") message(STATUS " SQLite3 game database: ${USE_SQLITE3}") + message(STATUS " ELF loading support: ${USE_ELF}") message(STATUS " OpenGL support: ${SUMMARY_GL}") message(STATUS "Frontends:") message(STATUS " Qt: ${BUILD_QT}") diff -Nru mgba-0.6.3+dfsg1/debian/changelog mgba-0.7.0/debian/changelog --- mgba-0.6.3+dfsg1/debian/changelog 2019-01-19 01:23:46.000000000 +0000 +++ mgba-0.7.0/debian/changelog 2019-02-03 22:53:12.000000000 +0000 @@ -1,20 +1,24 @@ -mgba (0.6.3+dfsg1-2ubuntu1) disco; urgency=medium +mgba (0.7.0-1) unstable; urgency=medium - * Add .libretro file for integration with GNOME Games + * Team upload. - -- Jeremy Bicha Fri, 18 Jan 2019 20:23:46 -0500 + [ Jeremy Bicha ] + * Import packaging to https://salsa.debian.org/ (Closes: #872484) + * Add .libretro file for integration with GNOME Games. (Closes: #911327) + * Add minimal debian/gbp.conf. + * Use dh-exec instead of manual .sh script for install file. + + [ Reiner Herrmann ] + * New upstream release. + * Drop patch applied upstream and refresh other one. + * Update Standards-Version to 4.3.0. + - Declare that debian/rules does not require root. + * Depend on debhelper-compat and bump compat level to 12. + * Add upstream metadata. + * Add libelf-dev as new build dependency. + * Update debian/copyright. -mgba (0.6.3+dfsg1-2build2) disco; urgency=high - - * No change rebuild to recover from imagemagick ABI breakage - - -- Balint Reczey Tue, 08 Jan 2019 20:55:52 +0700 - -mgba (0.6.3+dfsg1-2build1) disco; urgency=medium - - * No-change rebuild against latest libzip - - -- Jeremy Bicha Mon, 26 Nov 2018 08:07:10 -0500 + -- Reiner Herrmann Sun, 03 Feb 2019 23:53:12 +0100 mgba (0.6.3+dfsg1-2) unstable; urgency=medium diff -Nru mgba-0.6.3+dfsg1/debian/compat mgba-0.7.0/debian/compat --- mgba-0.6.3+dfsg1/debian/compat 2019-01-19 01:23:46.000000000 +0000 +++ mgba-0.7.0/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -10 diff -Nru mgba-0.6.3+dfsg1/debian/control mgba-0.7.0/debian/control --- mgba-0.6.3+dfsg1/debian/control 2019-01-19 01:23:46.000000000 +0000 +++ mgba-0.7.0/debian/control 2019-02-03 22:53:12.000000000 +0000 @@ -1,17 +1,18 @@ Source: mgba Section: games Priority: optional -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Debian Games Team +Maintainer: Debian Games Team Uploaders: Sérgio Benjamim Build-Depends: cmake (>= 2.8.11), - debhelper (>= 10), + debhelper-compat (= 12), + dh-exec, desktop-file-utils, libavcodec-dev, libavformat-dev, libavresample-dev, libavutil-dev, libedit-dev, + libelf-dev, libepoxy-dev [armel armhf], libmagickwand-dev, libpng-dev, @@ -25,8 +26,11 @@ qtmultimedia5-dev, qttools5-dev-tools, zlib1g-dev -Standards-Version: 4.1.4 +Standards-Version: 4.3.0 Homepage: https://mgba.io/ +Rules-Requires-Root: no +Vcs-Git: https://salsa.debian.org/games-team/mgba.git +Vcs-Browser: https://salsa.debian.org/games-team/mgba Package: libmgba Architecture: any diff -Nru mgba-0.6.3+dfsg1/debian/copyright mgba-0.7.0/debian/copyright --- mgba-0.6.3+dfsg1/debian/copyright 2019-01-19 01:23:46.000000000 +0000 +++ mgba-0.7.0/debian/copyright 2019-02-03 22:53:12.000000000 +0000 @@ -9,9 +9,13 @@ Files: * -Copyright: 2013-2018 Jeffrey Pfau +Copyright: 2013-2019 Jeffrey Pfau License: MPL-2.0 +Files: cinema/gb/mooneye-gb/* +Copyright: 2014-2017 Joonas Javanainen +License: Expat + Files: doc/mgba.6 doc/mgba-qt.6 diff -Nru mgba-0.6.3+dfsg1/debian/gbp.conf mgba-0.7.0/debian/gbp.conf --- mgba-0.6.3+dfsg1/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/debian/gbp.conf 2019-02-03 22:53:12.000000000 +0000 @@ -0,0 +1,5 @@ +[DEFAULT] +pristine-tar = True + +[pq] +patch-numbers = False diff -Nru mgba-0.6.3+dfsg1/debian/libretro-mgba.install mgba-0.7.0/debian/libretro-mgba.install --- mgba-0.6.3+dfsg1/debian/libretro-mgba.install 2019-01-19 01:23:46.000000000 +0000 +++ mgba-0.7.0/debian/libretro-mgba.install 2019-02-03 22:53:12.000000000 +0000 @@ -1,4 +1,4 @@ -#!/bin/sh -echo "obj-*/mgba_libretro.so usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/libretro" -echo "debian/mgba.libretro usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/libretro" -echo "debian/libretro-mgba.metainfo.xml usr/share/metainfo" +#!/usr/bin/dh-exec +obj-*/mgba_libretro.so usr/lib/${DEB_HOST_MULTIARCH}/libretro +debian/libretro-mgba.metainfo.xml usr/share/metainfo +debian/mgba.libretro usr/lib/${DEB_HOST_MULTIARCH}/libretro diff -Nru mgba-0.6.3+dfsg1/debian/patches/01_fix-about-strings.patch mgba-0.7.0/debian/patches/01_fix-about-strings.patch --- mgba-0.6.3+dfsg1/debian/patches/01_fix-about-strings.patch 2019-01-19 01:23:46.000000000 +0000 +++ mgba-0.7.0/debian/patches/01_fix-about-strings.patch 2019-02-03 22:53:12.000000000 +0000 @@ -1,31 +1,20 @@ Description: fix Branch and Revision strings in the about window -Index: mgba-0.6.3/version.cmake -=================================================================== ---- mgba-0.6.3.orig/version.cmake -+++ mgba-0.6.3/version.cmake -@@ -3,7 +3,7 @@ if(NOT PROJECT_NAME) - endif() - set(LIB_VERSION_MAJOR 0) - set(LIB_VERSION_MINOR 6) --set(LIB_VERSION_PATCH 1) -+set(LIB_VERSION_PATCH 3) - set(LIB_VERSION_ABI 0.6) - set(LIB_VERSION_STRING ${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${LIB_VERSION_PATCH}) - set(SUMMARY "${PROJECT_NAME} Game Boy Advance Emulator") -@@ -37,13 +37,13 @@ else() +--- a/version.cmake ++++ b/version.cmake +@@ -37,13 +37,13 @@ endif() if(NOT GIT_COMMIT) - set(GIT_COMMIT "(unknown)") -+ set(GIT_COMMIT "5fad3d1") ++ set(GIT_COMMIT "0ddade3") endif() if(NOT GIT_COMMIT_SHORT) - set(GIT_COMMIT_SHORT "(unknown)") -+ set(GIT_COMMIT_SHORT "5fad3d1") ++ set(GIT_COMMIT_SHORT "0ddade3") endif() if(NOT GIT_BRANCH) - set(GIT_BRANCH "(unknown)") -+ set(GIT_BRANCH "0.6") ++ set(GIT_BRANCH "0.7") endif() if(DEFINED PRINT_STRING) diff -Nru mgba-0.6.3+dfsg1/debian/patches/7f41dd354176b720c8e3310553c6b772278b9dca.patch mgba-0.7.0/debian/patches/7f41dd354176b720c8e3310553c6b772278b9dca.patch --- mgba-0.6.3+dfsg1/debian/patches/7f41dd354176b720c8e3310553c6b772278b9dca.patch 2019-01-19 01:23:46.000000000 +0000 +++ mgba-0.7.0/debian/patches/7f41dd354176b720c8e3310553c6b772278b9dca.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -## Description: add some description -## Origin/Author: add some origin or author -## Bug: bug URL -From 7f41dd354176b720c8e3310553c6b772278b9dca Mon Sep 17 00:00:00 2001 -From: Vicki Pfau -Date: Fri, 25 May 2018 18:04:16 -0700 -Subject: [PATCH] Qt: Fix build with Qt 5.11 - ---- - src/platform/qt/LoadSaveState.cpp | 1 + - src/platform/qt/Window.h | 1 + - 2 files changed, 2 insertions(+) - -Index: mgba-0.6.3+dfsg1/src/platform/qt/LoadSaveState.cpp -=================================================================== ---- mgba-0.6.3+dfsg1.orig/src/platform/qt/LoadSaveState.cpp -+++ mgba-0.6.3+dfsg1/src/platform/qt/LoadSaveState.cpp -@@ -10,6 +10,7 @@ - #include "GamepadButtonEvent.h" - #include "VFileDevice.h" - -+#include - #include - #include - #include -Index: mgba-0.6.3+dfsg1/src/platform/qt/Window.h -=================================================================== ---- mgba-0.6.3+dfsg1.orig/src/platform/qt/Window.h -+++ mgba-0.6.3+dfsg1/src/platform/qt/Window.h -@@ -6,6 +6,7 @@ - #ifndef QGBA_WINDOW - #define QGBA_WINDOW - -+#include - #include - #include - #include diff -Nru mgba-0.6.3+dfsg1/debian/patches/series mgba-0.7.0/debian/patches/series --- mgba-0.6.3+dfsg1/debian/patches/series 2019-01-19 01:23:46.000000000 +0000 +++ mgba-0.7.0/debian/patches/series 2019-02-03 22:53:12.000000000 +0000 @@ -1,2 +1 @@ 01_fix-about-strings.patch -7f41dd354176b720c8e3310553c6b772278b9dca.patch diff -Nru mgba-0.6.3+dfsg1/debian/upstream/metadata mgba-0.7.0/debian/upstream/metadata --- mgba-0.6.3+dfsg1/debian/upstream/metadata 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/debian/upstream/metadata 2019-02-03 22:53:12.000000000 +0000 @@ -0,0 +1,8 @@ +Name: mGBA +Bug-Database: https://github.com/mgba-emu/mgba/issues +Bug-Submit: https://github.com/mgba-emu/mgba/issues +Contact: https://forums.mgba.io/ +Donation: https://mgba.io/donate.html +FAQ: https://mgba.io/faq.html +Repository: https://github.com/mgba-emu/mgba.git +Repository-Browse: https://github.com/mgba-emu/mgba diff -Nru mgba-0.6.3+dfsg1/doc/mgba.6 mgba-0.7.0/doc/mgba.6 --- mgba-0.6.3+dfsg1/doc/mgba.6 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/doc/mgba.6 2019-01-27 00:06:06.000000000 +0000 @@ -13,11 +13,12 @@ .Nm mgba .Op Fl 123456dfg .Op Fl b Ar biosfile +.Op Fl C Ar option Ns = Ns Ar value .Op Fl c Ar cheatfile .Op Fl l Ar loglevel .Op Fl p Ar patchfile .Op Fl s Ar n -.Op Fl v Ar moviefile +.Op Fl t Ar statefile .Ar file .Sh DESCRIPTION .Nm @@ -42,6 +43,11 @@ .Nm will use the BIOS specified in the configuration file, or a high\(hylevel emulated BIOS if none is specified. +.It Fl C Ar option Ns = Ns Ar value , Fl -config Ar option Ns = Ns Ar value +Override the given config +.Ar option +with +.Ar value . .It Fl c Ar cheatfile , Fl -cheats Ar cheatfile Apply cheat codes from .Ar cheatfile . @@ -73,13 +79,7 @@ .It 32 \(en stub messages for unimplemented features .It -256 \(en in\(hygame errors -.It -512 \(en software interrupts -.It -1024 \(en emulator status messages -.It -2048 \(en serial I/O messages +64 \(en in\(hygame errors .El The default is to log warnings, errors, fatal errors, and status messages. .It Fl p Ar patchfile , Fl -patch Ar patchfile @@ -88,9 +88,9 @@ Skip every .Ar n frames. -.It Fl v Ar moviefile , Fl -movie Ar moviefile -Play back a movie of recording input from -.Ar moviefile . +.It Fl t Ar statefile , Fl -savestate Ar statefile +Load initial game state from +.Ar statefile . .El .Sh CONTROLS The default controls are as follows: @@ -244,7 +244,7 @@ .Bl -tag -width Ds -compact .It Pa $XDG_CONFIG_HOME/mgba/config.ini Default -.Xr mgba 6 +.Nm mgba configuration file. .It Pa portable.ini If this file exists in the current directory, diff -Nru mgba-0.6.3+dfsg1/doc/mgba-qt.6 mgba-0.7.0/doc/mgba-qt.6 --- mgba-0.6.3+dfsg1/doc/mgba-qt.6 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/doc/mgba-qt.6 2019-01-27 00:06:06.000000000 +0000 @@ -13,9 +13,11 @@ .Nm mgba-qt .Op Fl 123456fg .Op Fl b Ar biosfile +.Op Fl C Ar option Ns = Ns Ar value .Op Fl l Ar loglevel .Op Fl p Ar patchfile .Op Fl s Ar n +.Op Fl t Ar statefile .Ar file .Sh DESCRIPTION .Nm @@ -40,6 +42,11 @@ .Nm will use the BIOS specified in the configuration file, or a high\(hylevel emulated BIOS if none is specified. +.It Fl C Ar option Ns = Ns Ar value , Fl -config Ar option Ns = Ns Ar value +Override the given config +.Ar option +with +.Ar value . .It Fl f Start the emulator full\(hyscreen. .It Fl g @@ -65,13 +72,7 @@ .It 32 \(en stub messages for unimplemented features .It -256 \(en in\(hygame errors -.It -512 \(en software interrupts -.It -1024 \(en emulator status messages -.It -2048 \(en serial I/O messages +64 \(en in\(hygame errors .El The default is to log warnings, errors, fatal errors, and status messages. .It Fl p Ar patchfile , Fl -patch Ar patchfile @@ -80,6 +81,9 @@ Skip every .Ar n frames. +.It Fl t Ar statefile , Fl -savestate Ar statefile +Load initial game state from +.Ar statefile . .El .Sh CONTROLS The default controls are as follows: diff -Nru mgba-0.6.3+dfsg1/.gitignore mgba-0.7.0/.gitignore --- mgba-0.6.3+dfsg1/.gitignore 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/.gitignore 2019-01-27 00:06:06.000000000 +0000 @@ -1,5 +1,17 @@ -/build *.user* *~ *.swp *.pyc + +/build +/build-* + +*.a +*.dylib +*.dll +*.exe +*.o +*.so +CMakeCache.txt +CMakeFiles +version.c diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/cache-set.h mgba-0.7.0/include/mgba/core/cache-set.h --- mgba-0.6.3+dfsg1/include/mgba/core/cache-set.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/cache-set.h 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/include/mgba/core/cheats.h mgba-0.7.0/include/mgba/core/cheats.h --- mgba-0.6.3+dfsg1/include/mgba/core/cheats.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/cheats.h 2019-01-27 00:06:06.000000000 +0000 @@ -14,8 +14,6 @@ #include #include -#define MAX_ROM_PATCHES 4 - enum mCheatType { CHEAT_ASSIGN, CHEAT_ASSIGN_INDIRECT, @@ -30,7 +28,8 @@ CHEAT_IF_UGT, CHEAT_IF_AND, CHEAT_IF_LAND, - CHEAT_IF_NAND + CHEAT_IF_NAND, + CHEAT_IF_BUTTON, }; struct mCheat { @@ -79,6 +78,8 @@ struct mCheatSet* (*createSet)(struct mCheatDevice*, const char* name); struct mCheatSets cheats; + bool autosave; + bool buttonDown; }; struct VFile; @@ -99,7 +100,12 @@ bool mCheatParseFile(struct mCheatDevice*, struct VFile*); bool mCheatSaveFile(struct mCheatDevice*, struct VFile*); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +void mCheatAutosave(struct mCheatDevice*); +#endif + void mCheatRefresh(struct mCheatDevice*, struct mCheatSet*); +void mCheatPressButton(struct mCheatDevice*, bool down); CXX_GUARD_END diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/config.h mgba-0.7.0/include/mgba/core/config.h --- mgba-0.6.3+dfsg1/include/mgba/core/config.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/config.h 2019-01-27 00:06:06.000000000 +0000 @@ -33,7 +33,6 @@ int frameskip; bool rewindEnable; int rewindBufferCapacity; - bool rewindSave; float fpsTarget; size_t audioBuffers; unsigned sampleRate; @@ -51,6 +50,7 @@ char* savestatePath; char* screenshotPath; char* patchPath; + char* cheatsPath; int volume; bool mute; diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/core.h mgba-0.7.0/include/mgba/core/core.h --- mgba-0.6.3+dfsg1/include/mgba/core/core.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/core.h 2019-01-27 00:06:06.000000000 +0000 @@ -141,6 +141,7 @@ void (*detachDebugger)(struct mCore*); void (*loadSymbols)(struct mCore*, struct VFile*); + bool (*lookupIdentifier)(struct mCore*, const char* name, int32_t* value, int* segment); #endif struct mCheatDevice* (*cheatDevice)(struct mCore*); @@ -152,6 +153,7 @@ size_t (*listAudioChannels)(const struct mCore*, const struct mCoreChannelInfo**); void (*enableVideoLayer)(struct mCore*, size_t id, bool enable); void (*enableAudioChannel)(struct mCore*, size_t id, bool enable); + void (*adjustVideoLayer)(struct mCore*, size_t id, int32_t x, int32_t y); #ifndef MINIMAL_CORE void (*startVideoLog)(struct mCore*, struct mVideoLogContext*); @@ -168,6 +170,7 @@ bool mCoreAutoloadSave(struct mCore* core); bool mCoreAutoloadPatch(struct mCore* core); +bool mCoreAutoloadCheats(struct mCore* core); bool mCoreSaveState(struct mCore* core, int slot, int flags); bool mCoreLoadState(struct mCore* core, int slot, int flags); @@ -189,6 +192,16 @@ void mCoreSetRTC(struct mCore* core, struct mRTCSource* rtc); +void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size); + +#ifdef USE_ELF +struct ELF; +bool mCoreLoadELF(struct mCore* core, struct ELF* elf); +#ifdef USE_DEBUGGERS +void mCoreLoadELFSymbols(struct mDebuggerSymbols* symbols, struct ELF*); +#endif +#endif + CXX_GUARD_END #endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/directories.h mgba-0.7.0/include/mgba/core/directories.h --- mgba-0.6.3+dfsg1/include/mgba/core/directories.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/directories.h 2019-01-27 00:06:06.000000000 +0000 @@ -21,6 +21,7 @@ struct VDir* patch; struct VDir* state; struct VDir* screenshot; + struct VDir* cheats; }; void mDirectorySetInit(struct mDirectorySet* dirs); diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/interface.h mgba-0.7.0/include/mgba/core/interface.h --- mgba-0.6.3+dfsg1/include/mgba/core/interface.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/interface.h 2019-01-27 00:06:06.000000000 +0000 @@ -35,8 +35,50 @@ #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); @@ -61,6 +103,7 @@ enum mPeripheral { mPERIPH_ROTATION = 1, mPERIPH_RUMBLE, + mPERIPH_IMAGE_SOURCE, mPERIPH_CUSTOM = 0x1000 }; @@ -82,6 +125,12 @@ 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 -Nru mgba-0.6.3+dfsg1/include/mgba/core/map-cache.h mgba-0.7.0/include/mgba/core/map-cache.h --- mgba-0.6.3+dfsg1/include/mgba/core/map-cache.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/map-cache.h 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/include/mgba/core/mem-search.h mgba-0.7.0/include/mgba/core/mem-search.h --- mgba-0.6.3+dfsg1/include/mgba/core/mem-search.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/mem-search.h 2019-01-27 00:06:06.000000000 +0000 @@ -13,29 +13,38 @@ #include enum mCoreMemorySearchType { - mCORE_MEMORY_SEARCH_32, - mCORE_MEMORY_SEARCH_16, - mCORE_MEMORY_SEARCH_8, + mCORE_MEMORY_SEARCH_INT, mCORE_MEMORY_SEARCH_STRING, mCORE_MEMORY_SEARCH_GUESS, }; +enum mCoreMemorySearchOp { + mCORE_MEMORY_SEARCH_EQUAL, + mCORE_MEMORY_SEARCH_GREATER, + mCORE_MEMORY_SEARCH_LESS, + mCORE_MEMORY_SEARCH_DELTA, +}; + struct mCoreMemorySearchParams { int memoryFlags; enum mCoreMemorySearchType type; + enum mCoreMemorySearchOp op; + int align; + int width; union { const char* valueStr; - uint32_t value32; - uint32_t value16; - uint32_t value8; + int32_t valueInt; }; }; struct mCoreMemorySearchResult { uint32_t address; int segment; - uint64_t guessDivisor; + uint32_t guessDivisor; + uint32_t guessMultiplier; enum mCoreMemorySearchType type; + int width; + int32_t oldValue; }; DECLARE_VECTOR(mCoreMemorySearchResults, struct mCoreMemorySearchResult); diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/rewind.h mgba-0.7.0/include/mgba/core/rewind.h --- mgba-0.6.3+dfsg1/include/mgba/core/rewind.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/rewind.h 2019-01-27 00:06:06.000000000 +0000 @@ -22,7 +22,6 @@ struct mCoreRewindPatches patchMemory; size_t current; size_t size; - int stateFlags; struct VFile* previousState; struct VFile* currentState; diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/scripting.h mgba-0.7.0/include/mgba/core/scripting.h --- mgba-0.6.3+dfsg1/include/mgba/core/scripting.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/scripting.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,52 @@ +/* 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_SCRIPTING_H +#define M_SCRIPTING_H + +#include + +CXX_GUARD_START + +#ifdef USE_DEBUGGERS +#include +#endif + +struct mScriptBridge; +struct VFile; +struct mScriptEngine { + const char* (*name)(struct mScriptEngine*); + + bool (*init)(struct mScriptEngine*, struct mScriptBridge*); + void (*deinit)(struct mScriptEngine*); + bool (*isScript)(struct mScriptEngine*, const char* name, struct VFile* vf); + bool (*loadScript)(struct mScriptEngine*, const char* name, struct VFile* vf); + void (*run)(struct mScriptEngine*); + bool (*lookupSymbol)(struct mScriptEngine*, const char* name, int32_t* out); + +#ifdef USE_DEBUGGERS + void (*debuggerEntered)(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); +#endif +}; + +struct mScriptBridge* mScriptBridgeCreate(void); +void mScriptBridgeDestroy(struct mScriptBridge*); + +void mScriptBridgeInstallEngine(struct mScriptBridge*, struct mScriptEngine*); + +#ifdef USE_DEBUGGERS +void mScriptBridgeSetDebugger(struct mScriptBridge*, struct mDebugger*); +struct mDebugger* mScriptBridgeGetDebugger(struct mScriptBridge*); +void mScriptBridgeDebuggerEntered(struct mScriptBridge*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); +#endif + +void mScriptBridgeRun(struct mScriptBridge*); +bool mScriptBridgeLoadScript(struct mScriptBridge*, const char* name); + +bool mScriptBridgeLookupSymbol(struct mScriptBridge*, const char* name, int32_t* out); + +CXX_GUARD_END + +#endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/sync.h mgba-0.7.0/include/mgba/core/sync.h --- mgba-0.6.3+dfsg1/include/mgba/core/sync.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/sync.h 2019-01-27 00:06:06.000000000 +0000 @@ -33,7 +33,8 @@ void mCoreSyncWaitFrameEnd(struct mCoreSync* sync); void mCoreSyncSetVideoSync(struct mCoreSync* sync, bool wait); -void mCoreSyncProduceAudio(struct mCoreSync* sync, bool wait); +struct blip_t; +bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t*, size_t samples); void mCoreSyncLockAudio(struct mCoreSync* sync); void mCoreSyncUnlockAudio(struct mCoreSync* sync); void mCoreSyncConsumeAudio(struct mCoreSync* sync); diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/thread.h mgba-0.7.0/include/mgba/core/thread.h --- mgba-0.6.3+dfsg1/include/mgba/core/thread.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/thread.h 2019-01-27 00:06:06.000000000 +0000 @@ -11,43 +11,66 @@ CXX_GUARD_START #include -#include -#include -#include struct mCoreThread; struct mCore; typedef void (*ThreadCallback)(struct mCoreThread* threadContext); +struct mCoreThread; +struct mThreadLogger { + struct mLogger d; + struct mCoreThread* p; +}; + +struct mCoreThreadInternal; +struct mCoreThread { + // Input + struct mCore* core; + + struct mThreadLogger logger; + ThreadCallback startCallback; + ThreadCallback resetCallback; + ThreadCallback cleanCallback; + ThreadCallback frameCallback; + ThreadCallback sleepCallback; + ThreadCallback pauseCallback; + ThreadCallback unpauseCallback; + void* userData; + void (*run)(struct mCoreThread*); + + struct mCoreThreadInternal* impl; +}; + +#ifndef OPAQUE_THREADING +#include +#include +#include + enum mCoreThreadState { THREAD_INITIALIZED = -1, 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 }; -struct mCoreThread; -struct mThreadLogger { - struct mLogger d; - struct mCoreThread* p; -}; - -struct mCoreThread { - // Input - struct mCore* core; - - // Threading state +struct mCoreThreadInternal { Thread thread; enum mCoreThreadState state; @@ -57,19 +80,12 @@ int interruptDepth; bool frameWasOn; - struct mThreadLogger logger; - ThreadCallback startCallback; - ThreadCallback resetCallback; - ThreadCallback cleanCallback; - ThreadCallback frameCallback; - ThreadCallback sleepCallback; - void* userData; - void (*run)(struct mCoreThread*); - struct mCoreSync sync; struct mCoreRewindContext rewind; }; +#endif + bool mCoreThreadStart(struct mCoreThread* threadContext); bool mCoreThreadHasStarted(struct mCoreThread* threadContext); bool mCoreThreadHasExited(struct mCoreThread* threadContext); @@ -95,6 +111,7 @@ void mCoreThreadStopWaiting(struct mCoreThread* threadContext); void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool); +void mCoreThreadRewindParamsChanged(struct mCoreThread* threadContext); struct mCoreThread* mCoreThreadGet(void); struct mLogger* mCoreThreadLogger(void); diff -Nru mgba-0.6.3+dfsg1/include/mgba/core/tile-cache.h mgba-0.7.0/include/mgba/core/tile-cache.h --- mgba-0.6.3+dfsg1/include/mgba/core/tile-cache.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/tile-cache.h 2019-01-27 00:06:06.000000000 +0000 @@ -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 @@ 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 @@ 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 -Nru mgba-0.6.3+dfsg1/include/mgba/core/timing.h mgba-0.7.0/include/mgba/core/timing.h --- mgba-0.6.3+dfsg1/include/mgba/core/timing.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/core/timing.h 2019-01-27 00:06:06.000000000 +0000 @@ -23,6 +23,7 @@ struct mTiming { struct mTimingEvent* root; + struct mTimingEvent* reroot; uint32_t masterCycles; int32_t* relativeCycles; diff -Nru mgba-0.6.3+dfsg1/include/mgba/debugger/debugger.h mgba-0.7.0/include/mgba/debugger/debugger.h --- mgba-0.6.3+dfsg1/include/mgba/debugger/debugger.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/debugger/debugger.h 2019-01-27 00:06:06.000000000 +0000 @@ -70,6 +70,7 @@ }; struct mDebugger; +struct ParseTree; struct mDebuggerPlatform { struct mDebugger* p; @@ -79,19 +80,26 @@ bool (*hasBreakpoints)(struct mDebuggerPlatform*); void (*setBreakpoint)(struct mDebuggerPlatform*, uint32_t address, int segment); + void (*setConditionalBreakpoint)(struct mDebuggerPlatform*, uint32_t address, int segment, struct ParseTree* condition); void (*clearBreakpoint)(struct mDebuggerPlatform*, uint32_t address, int segment); void (*setWatchpoint)(struct mDebuggerPlatform*, uint32_t address, int segment, enum mWatchpointType type); + void (*setConditionalWatchpoint)(struct mDebuggerPlatform*, uint32_t address, int segment, enum mWatchpointType type, struct ParseTree* condition); void (*clearWatchpoint)(struct mDebuggerPlatform*, uint32_t address, int segment); void (*checkBreakpoints)(struct mDebuggerPlatform*); void (*trace)(struct mDebuggerPlatform*, char* out, size_t* length); + + bool (*getRegister)(struct mDebuggerPlatform*, const char* name, int32_t* value); + bool (*setRegister)(struct mDebuggerPlatform*, const char* name, int32_t value); + bool (*lookupIdentifier)(struct mDebuggerPlatform*, const char* name, int32_t* value, int* segment); }; -struct mDebuggerSymbols; struct mDebugger { struct mCPUComponent d; struct mDebuggerPlatform* platform; enum mDebuggerState state; + enum mDebuggerType type; struct mCore* core; + struct mScriptBridge* bridge; void (*init)(struct mDebugger*); void (*deinit)(struct mDebugger*); @@ -107,6 +115,8 @@ void mDebuggerRunFrame(struct mDebugger*); void mDebuggerEnter(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); +bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int32_t* value, int* segment); + CXX_GUARD_END #endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/feature/commandline.h mgba-0.7.0/include/mgba/feature/commandline.h --- mgba-0.6.3+dfsg1/include/mgba/feature/commandline.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/feature/commandline.h 2019-01-27 00:06:06.000000000 +0000 @@ -18,7 +18,7 @@ char* fname; char* patch; char* cheatsFile; - char* movie; + char* savestate; char* bios; int logLevel; int frameskip; diff -Nru mgba-0.6.3+dfsg1/include/mgba/gb/interface.h mgba-0.7.0/include/mgba/gb/interface.h --- mgba-0.6.3+dfsg1/include/mgba/gb/interface.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/gb/interface.h 2019-01-27 00:06:06.000000000 +0000 @@ -12,10 +12,12 @@ 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 @@ GB_HuC1 = 0x11, GB_HuC3 = 0x12, GB_POCKETCAM = 0x13, + GB_TAMA5 = 0x14, GB_MBC3_RTC = 0x103, GB_MBC5_RUMBLE = 0x105 }; @@ -44,6 +47,9 @@ uint8_t (*writeSC)(struct GBSIODriver* driver, uint8_t value); }; +enum GBModel GBNameToModel(const char*); +const char* GBModelToName(enum GBModel); + CXX_GUARD_END #endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/gba/interface.h mgba-0.7.0/include/mgba/gba/interface.h --- mgba-0.6.3+dfsg1/include/mgba/gba/interface.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/gba/interface.h 2019-01-27 00:06:06.000000000 +0000 @@ -21,6 +21,13 @@ SIO_JOYBUS = 12 }; +enum GBASIOJOYCommand { + JOY_RESET = 0xFF, + JOY_POLL = 0x00, + JOY_TRANS = 0x14, + JOY_RECV = 0x15 +}; + struct GBA; struct GBAAudio; struct GBASIO; @@ -48,6 +55,10 @@ uint16_t (*writeRegister)(struct GBASIODriver* driver, uint32_t address, uint16_t value); }; +void GBASIOJOYCreate(struct GBASIODriver* sio); +int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data); + + CXX_GUARD_END #endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/arm/debugger/debugger.h mgba-0.7.0/include/mgba/internal/arm/debugger/debugger.h --- mgba-0.6.3+dfsg1/include/mgba/internal/arm/debugger/debugger.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/arm/debugger/debugger.h 2019-01-27 00:06:06.000000000 +0000 @@ -15,8 +15,10 @@ #include #include +struct ParseTree; struct ARMDebugBreakpoint { uint32_t address; + struct ParseTree* condition; bool isSw; struct { uint32_t opcode; @@ -27,6 +29,7 @@ struct ARMDebugWatchpoint { uint32_t address; enum mWatchpointType type; + struct ParseTree* condition; }; DECLARE_VECTOR(ARMDebugBreakpointList, struct ARMDebugBreakpoint); diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/debugger/cli-debugger.h mgba-0.7.0/include/mgba/internal/debugger/cli-debugger.h --- mgba-0.6.3+dfsg1/include/mgba/internal/debugger/cli-debugger.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/debugger/cli-debugger.h 2019-01-27 00:06:06.000000000 +0000 @@ -14,6 +14,7 @@ extern const char* ERROR_MISSING_ARGS; extern const char* ERROR_OVERFLOW; +extern const char* ERROR_INVALID_ARGS; struct CLIDebugger; @@ -30,12 +31,11 @@ }; typedef void (*CLIDebuggerCommand)(struct CLIDebugger*, struct CLIDebugVector*); -typedef struct CLIDebugVector* (*CLIDVParser)(struct CLIDebugger* debugger, const char* string, size_t length); struct CLIDebuggerCommandSummary { const char* name; CLIDebuggerCommand command; - CLIDVParser parser; + const char* format; const char* summary; }; @@ -47,8 +47,6 @@ bool (*custom)(struct CLIDebuggerSystem*); void (*disassemble)(struct CLIDebuggerSystem*, struct CLIDebugVector* dv); - uint32_t (*lookupIdentifier)(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); - uint32_t (*lookupPlatformIdentifier)(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); void (*printStatus)(struct CLIDebuggerSystem*); struct CLIDebuggerCommandSummary* commands; @@ -78,9 +76,6 @@ struct CLIDebuggerBackend* backend; }; -struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length); -struct CLIDebugVector* CLIDVStringParse(struct CLIDebugger* debugger, const char* string, size_t length); - void CLIDebuggerCreate(struct CLIDebugger*); void CLIDebuggerAttachSystem(struct CLIDebugger*, struct CLIDebuggerSystem*); void CLIDebuggerAttachBackend(struct CLIDebugger*, struct CLIDebuggerBackend*); diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/debugger/parser.h mgba-0.7.0/include/mgba/internal/debugger/parser.h --- mgba-0.6.3+dfsg1/include/mgba/internal/debugger/parser.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/debugger/parser.h 2019-01-27 00:06:06.000000000 +0000 @@ -8,27 +8,36 @@ #include -CXX_GUARD_START +#include -#include +CXX_GUARD_START -enum LexState { - LEX_ERROR = -1, - LEX_ROOT = 0, - LEX_EXPECT_IDENTIFIER, - LEX_EXPECT_BINARY, - LEX_EXPECT_DECIMAL, - LEX_EXPECT_HEX, - LEX_EXPECT_PREFIX, - LEX_EXPECT_OPERATOR -}; +struct Token; +DECLARE_VECTOR(LexVector, struct Token); enum Operation { OP_ASSIGN, OP_ADD, OP_SUBTRACT, OP_MULTIPLY, - OP_DIVIDE + OP_DIVIDE, + OP_MODULO, + OP_AND, + OP_OR, + OP_XOR, + OP_LESS, + OP_GREATER, + OP_EQUAL, + OP_NOT_EQUAL, + OP_LOGICAL_AND, + OP_LOGICAL_OR, + OP_LE, + OP_GE, + OP_NEGATE, + OP_FLIP, + OP_NOT, + OP_SHIFT_L, + OP_SHIFT_R, }; struct Token { @@ -48,23 +57,21 @@ }; }; -struct LexVector { - struct LexVector* next; - struct Token token; -}; - struct ParseTree { struct Token token; struct ParseTree* lhs; struct ParseTree* rhs; }; -size_t lexExpression(struct LexVector* lv, const char* string, size_t length); +size_t lexExpression(struct LexVector* lv, const char* string, size_t length, const char* eol); void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv); void lexFree(struct LexVector* lv); void parseFree(struct ParseTree* tree); +struct mDebugger; +bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, int32_t* value, int* segment); + CXX_GUARD_END #endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/debugger/symbols.h mgba-0.7.0/include/mgba/internal/debugger/symbols.h --- mgba-0.6.3+dfsg1/include/mgba/internal/debugger/symbols.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/debugger/symbols.h 2019-01-27 00:06:06.000000000 +0000 @@ -20,6 +20,9 @@ void mDebuggerSymbolAdd(struct mDebuggerSymbols*, const char* name, int32_t value, int segment); void mDebuggerSymbolRemove(struct mDebuggerSymbols*, const char* name); +struct VFile; +void mDebuggerLoadARMIPSSymbols(struct mDebuggerSymbols*, struct VFile* vf); + CXX_GUARD_END #endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/audio.h mgba-0.7.0/include/mgba/internal/gb/audio.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/audio.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/audio.h 2019-01-27 00:06:06.000000000 +0000 @@ -137,11 +137,15 @@ int length; uint32_t lfsr; + int nSamples; + int samples; + int8_t sample; }; 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 @@ -160,6 +164,8 @@ struct blip_t* right; int16_t lastLeft; int16_t lastRight; + int32_t capLeft; + int32_t capRight; int clock; int32_t clockRate; @@ -181,6 +187,7 @@ uint8_t* nr52; int frame; + bool skipFrame; int32_t sampleInterval; enum GBAudioStyle style; @@ -231,6 +238,8 @@ void GBAudioWriteNR51(struct GBAudio* audio, uint8_t); void GBAudioWriteNR52(struct GBAudio* audio, uint8_t); +void GBAudioUpdateFrame(struct GBAudio* audio, struct mTiming* timing); + void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right); struct GBSerializedPSGState; diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/gb.h mgba-0.7.0/include/mgba/internal/gb/gb.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/gb.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/gb.h 2019-01-27 00:06:06.000000000 +0000 @@ -44,6 +44,34 @@ 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_REQ, + 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,12 @@ int32_t sramDirtAge; bool sramMaskWriteback; + int sgbBit; + int currentSgbBits; + uint8_t sgbPacket[16]; + uint8_t sgbControllers; + uint8_t sgbCurrentController; + struct mCoreCallbacksList coreCallbacks; struct mAVStream* stream; @@ -83,6 +117,8 @@ bool earlyExit; struct mTimingEvent eiPending; unsigned doubleSpeed; + + bool allowOpposingDirections; }; struct GBCartridge { @@ -113,6 +149,8 @@ void GBDestroy(struct GB* gb); void GBReset(struct LR35902Core* cpu); +void GBSkipBIOS(struct GB* gb); +void GBUnmapBIOS(struct GB* gb); void GBDetectModel(struct GB* gb); void GBUpdateIRQs(struct GB* gb); @@ -141,6 +179,7 @@ void GBTestKeypadIRQ(struct GB* gb); +void GBFrameStarted(struct GB* gb); void GBFrameEnded(struct GB* gb); CXX_GUARD_END diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/io.h mgba-0.7.0/include/mgba/internal/gb/io.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/io.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/io.h 2019-01-27 00:06:06.000000000 +0000 @@ -84,6 +84,7 @@ REG_WX = 0x4B, // CGB + REG_UNK4C = 0x4C, REG_KEY1 = 0x4D, REG_VBK = 0x4F, REG_HDMA1 = 0x51, @@ -102,8 +103,8 @@ REG_UNK73 = 0x73, REG_UNK74 = 0x74, REG_UNK75 = 0x75, - REG_UNK76 = 0x76, - REG_UNK77 = 0x77, + REG_PCM12 = 0x76, + REG_PCM34 = 0x77, REG_MAX = 0x100 }; diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/mbc.h mgba-0.7.0/include/mgba/internal/gb/mbc.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/mbc.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/mbc.h 2019-01-27 00:06:06.000000000 +0000 @@ -19,7 +19,14 @@ 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); +void GBMBCSwitchSramHalfBank(struct GB* gb, int half, int bank); + +enum GBCam { + GBCAM_WIDTH = 128, + GBCAM_HEIGHT = 112 +}; struct GBMBCRTCSaveBuffer { uint32_t sec; @@ -37,8 +44,6 @@ 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 -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/memory.h mgba-0.7.0/include/mgba/internal/gb/memory.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/memory.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/memory.h 2019-01-27 00:06:06.000000000 +0000 @@ -22,8 +22,12 @@ 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_EXTERNAL_RAM_HALFBANK0 = 0xA000, + GB_BASE_EXTERNAL_RAM_HALFBANK1 = 0xB000, GB_BASE_WORKING_RAM_BANK0 = 0xC000, GB_BASE_WORKING_RAM_BANK1 = 0xD000, GB_BASE_OAM = 0xFE00, @@ -46,10 +50,12 @@ 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, GB_SIZE_EXTERNAL_RAM = 0x2000, + GB_SIZE_EXTERNAL_RAM_HALFBANK = 0x1000, GB_SIZE_WORKING_RAM = 0x8000, GB_SIZE_WORKING_RAM_BANK0 = 0x1000, GB_SIZE_OAM = 0xA0, @@ -86,11 +92,32 @@ 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; + bool sramAccess; + int currentSramBank1; + uint8_t* sramBank1; +}; + struct GBMBC7State { enum GBMBC7MachineState state; uint16_t sr; @@ -102,14 +129,28 @@ GBMBC7Field eeprom; }; +struct GBMMM01State { + bool locked; + int currentBank0; +}; + 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 GBMMM01State mmm01; struct GBPocketCamState pocketCam; + struct GBTAMA5State tama5; }; struct mRotationSource; @@ -160,6 +201,7 @@ struct mRTCSource* rtc; struct mRotationSource* rotation; struct mRumble* rumble; + struct mImageSource* cam; }; struct LR35902Core; diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/overrides.h mgba-0.7.0/include/mgba/internal/gb/overrides.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/overrides.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/overrides.h 2019-01-27 00:06:06.000000000 +0000 @@ -17,7 +17,7 @@ enum GBModel model; enum GBMemoryBankControllerType mbc; - uint32_t gbColors[4]; + uint32_t gbColors[12]; }; struct Configuration; diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/renderers/cache-set.h mgba-0.7.0/include/mgba/internal/gb/renderers/cache-set.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/renderers/cache-set.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/renderers/cache-set.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,23 @@ +/* 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 GB_TILE_CACHE_H +#define GB_TILE_CACHE_H + +#include + +CXX_GUARD_START + +struct GBVideo; +struct mCacheSet; + +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 + +#endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/renderers/software.h mgba-0.7.0/include/mgba/internal/gb/renderers/software.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/renderers/software.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/renderers/software.h 2019-01-27 00:06:06.000000000 +0000 @@ -23,6 +23,7 @@ uint8_t row[GB_VIDEO_HORIZONTAL_PIXELS + 8]; color_t palette[128]; + uint8_t lookup[64]; uint32_t* temporaryBuffer; @@ -36,6 +37,18 @@ GBRegisterLCDC lcdc; enum GBModel model; + + int16_t objOffsetX; + int16_t objOffsetY; + int16_t offsetScx; + int16_t offsetScy; + int16_t offsetWx; + int16_t offsetWy; + + int sgbTransfer; + uint8_t sgbPacket[128]; + uint8_t sgbCommandHeader; + bool sgbBorders; }; void GBVideoSoftwareRendererCreate(struct GBVideoSoftwareRenderer*); diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/renderers/tile-cache.h mgba-0.7.0/include/mgba/internal/gb/renderers/tile-cache.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/renderers/tile-cache.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/renderers/tile-cache.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +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 GB_TILE_CACHE_H -#define GB_TILE_CACHE_H - -#include - -CXX_GUARD_START - -struct GBVideo; -struct mTileCache; - -void GBVideoTileCacheInit(struct mTileCache* cache); -void GBVideoTileCacheAssociate(struct mTileCache* cache, struct GBVideo* video); - -CXX_GUARD_END - -#endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/serialize.h mgba-0.7.0/include/mgba/internal/gb/serialize.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/serialize.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/serialize.h 2019-01-27 00:06:06.000000000 +0000 @@ -19,7 +19,7 @@ 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,12 +42,12 @@ * | 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 * | bit 0: Is condition met? - * | bit 1: Is condition IRQ pending? + * | bit 1: Is IRQ pending? * | bit 2: Double speed * | bit 3: Is EI pending? * | bits 4 - 31: Reserved @@ -103,7 +103,8 @@ * | bit 5: Has channel 1 sweep occurred? * | bit 6: Is channel 3's memory readable? * | bit 7: Reserved - * | 0x000A8 - 0x000AF: Rserved + * | 0x000A8 - 0x000AB: Left capacitor charge + * | 0x000AC - 0x000AF: Right capacitor charge * | 0x000B0 - 0x000B3: Next sample * 0x000B4 - 0x000153: Video state * | 0x000B4 - 0x000B5: Current x @@ -161,7 +162,24 @@ * 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 + * | bit 4: Is a mode event not scheduled? + * | bit 5: Is a frame event not scheduled? + * | bits 6 - 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); @@ -177,6 +195,7 @@ DECL_BIT(GBSerializedAudioFlags, Ch1SweepEnabled, 25); DECL_BIT(GBSerializedAudioFlags, Ch1SweepOccurred, 26); DECL_BIT(GBSerializedAudioFlags, Ch3Readable, 27); +DECL_BIT(GBSerializedAudioFlags, SkipFrame, 28); DECL_BITFIELD(GBSerializedAudioEnvelope, uint32_t); DECL_BITS(GBSerializedAudioEnvelope, Length, 0, 7); @@ -214,7 +233,7 @@ DECL_BIT(GBSerializedCpuFlags, Condition, 0); DECL_BIT(GBSerializedCpuFlags, IrqPending, 1); DECL_BIT(GBSerializedCpuFlags, DoubleSpeed, 2); -DECL_BIT(GBSerializedCpuFlags, EiPending, 1); +DECL_BIT(GBSerializedCpuFlags, EiPending, 3); DECL_BITFIELD(GBSerializedTimerFlags, uint8_t); DECL_BIT(GBSerializedTimerFlags, IrqPending, 0); @@ -238,6 +257,13 @@ 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); +DECL_BITS(GBSerializedSGBFlags, BufferIndex, 4, 3); +DECL_BITS(GBSerializedSGBFlags, CurrentController, 7, 2); +DECL_BITS(GBSerializedSGBFlags, ReqControllers, 9, 2); + #pragma pack(push, 1) struct GBSerializedState { uint32_t versionMagic; @@ -268,7 +294,7 @@ uint8_t bus; uint8_t executionState; - uint16_t irqVector; + uint16_t reserved; uint32_t eiPending; int32_t reservedDiPending; @@ -278,7 +304,8 @@ struct { struct GBSerializedPSGState psg; GBSerializedAudioFlags flags; - int32_t reserved[2]; + int32_t capLeft; + int32_t capRight; uint32_t nextSample; } audio; @@ -348,6 +375,10 @@ uint32_t writable; } mbc7; struct { + uint8_t locked; + uint8_t bank0; + } mmm01; + struct { uint8_t reserved[16]; } padding; }; @@ -366,6 +397,21 @@ uint8_t vram[GB_SIZE_VRAM]; uint8_t wram[GB_SIZE_WORKING_RAM]; + + uint32_t reserved2[0xC4]; + + struct { + uint8_t attributes[90]; + uint8_t command; + uint8_t bits; + GBSerializedSGBFlags flags; + uint8_t inProgressPacket[16]; + uint8_t packet[128]; + 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 -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/sio/printer.h mgba-0.7.0/include/mgba/internal/gb/sio/printer.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/sio/printer.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/sio/printer.h 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gb/video.h mgba-0.7.0/include/mgba/internal/gb/video.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gb/video.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gb/video.h 2019-01-27 00:06:06.000000000 +0000 @@ -29,7 +29,12 @@ 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); @@ -40,6 +45,13 @@ 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; @@ -52,25 +64,34 @@ 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); void (*drawRange)(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* objOnLine, size_t nObj); void (*finishScanline)(struct GBVideoRenderer* renderer, int y); void (*finishFrame)(struct GBVideoRenderer* renderer); + void (*enableSGBBorder)(struct GBVideoRenderer* renderer, bool enable); void (*getPixels)(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels); void (*putPixels)(struct GBVideoRenderer* renderer, size_t stride, const void* pixels); 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; @@ -108,7 +129,7 @@ struct mTimingEvent modeEvent; struct mTimingEvent frameEvent; - uint32_t dotClock; + int32_t dotClock; uint8_t* vram; uint8_t* vramBank; @@ -122,10 +143,15 @@ bool bcpIncrement; int ocpIndex; bool ocpIncrement; + uint8_t sgbCommandHeader; + int sgbBufferIndex; + uint8_t sgbPacketBuffer[128]; - uint16_t dmgPalette[4]; + uint16_t dmgPalette[12]; uint16_t palette[64]; + bool sgbBorders; + int32_t frameCounter; int frameskip; int frameskipCounter; @@ -135,7 +161,7 @@ void GBVideoReset(struct GBVideo* video); void GBVideoDeinit(struct GBVideo* video); void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer); -void GBVideoProcessDots(struct GBVideo* video); +void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate); void GBVideoWriteLCDC(struct GBVideo* video, GBRegisterLCDC value); void GBVideoWriteSTAT(struct GBVideo* video, GBRegisterSTAT value); @@ -143,8 +169,11 @@ 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 -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/cheats.h mgba-0.7.0/include/mgba/internal/gba/cheats.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/cheats.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/cheats.h 2019-01-27 00:06:06.000000000 +0000 @@ -13,7 +13,7 @@ #include #include -#define MAX_ROM_PATCHES 4 +#define MAX_ROM_PATCHES 10 #define COMPLETE ((size_t) -1) enum GBACheatType { diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/dma.h mgba-0.7.0/include/mgba/internal/gba/dma.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/dma.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/dma.h 2019-01-27 00:06:06.000000000 +0000 @@ -10,6 +10,42 @@ CXX_GUARD_START +enum GBADMAControl { + GBA_DMA_INCREMENT = 0, + GBA_DMA_DECREMENT = 1, + GBA_DMA_FIXED = 2, + GBA_DMA_INCREMENT_RELOAD = 3 +}; + +enum GBADMATiming { + GBA_DMA_TIMING_NOW = 0, + GBA_DMA_TIMING_VBLANK = 1, + GBA_DMA_TIMING_HBLANK = 2, + GBA_DMA_TIMING_CUSTOM = 3 +}; + +DECL_BITFIELD(GBADMARegister, uint16_t); +DECL_BITS(GBADMARegister, DestControl, 5, 2); +DECL_BITS(GBADMARegister, SrcControl, 7, 2); +DECL_BIT(GBADMARegister, Repeat, 9); +DECL_BIT(GBADMARegister, Width, 10); +DECL_BIT(GBADMARegister, DRQ, 11); +DECL_BITS(GBADMARegister, Timing, 12, 2); +DECL_BIT(GBADMARegister, DoIRQ, 14); +DECL_BIT(GBADMARegister, Enable, 15); + +struct GBADMA { + GBADMARegister reg; + + uint32_t source; + uint32_t dest; + int32_t count; + uint32_t nextSource; + uint32_t nextDest; + int32_t nextCount; + uint32_t when; +}; + struct GBA; void GBADMAInit(struct GBA* gba); void GBADMAReset(struct GBA* gba); @@ -23,6 +59,7 @@ void GBADMASchedule(struct GBA* gba, int number, struct GBADMA* info); void GBADMARunHblank(struct GBA* gba, int32_t cycles); void GBADMARunVblank(struct GBA* gba, int32_t cycles); +void GBADMARunDisplayStart(struct GBA* gba, int32_t cycles); void GBADMAUpdate(struct GBA* gba); CXX_GUARD_END diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/gba.h mgba-0.7.0/include/mgba/internal/gba/gba.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/gba.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/gba.h 2019-01-27 00:06:06.000000000 +0000 @@ -112,7 +112,6 @@ int32_t cachedRegisters[16]; bool taintedRegisters[16]; - bool realisticTiming; bool hardCrash; bool allowOpposingDirections; @@ -168,6 +167,7 @@ void GBAApplyPatch(struct GBA* gba, struct Patch* patch); bool GBALoadMB(struct GBA* gba, struct VFile* vf); +bool GBALoadNull(struct GBA* gba); bool GBAIsROM(struct VFile* vf); bool GBAIsMB(struct VFile* vf); diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/matrix.h mgba-0.7.0/include/mgba/internal/gba/matrix.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/matrix.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/matrix.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,28 @@ +/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GBA_MATRIX_H +#define GBA_MATRIX_H + +#include + +CXX_GUARD_START + +struct GBAMatrix { + uint32_t cmd; + uint32_t paddr; + uint32_t vaddr; + uint32_t size; +}; + +struct GBA; +struct GBAMemory; +void GBAMatrixReset(struct GBA*); +void GBAMatrixWrite(struct GBA*, uint32_t address, uint32_t value); +void GBAMatrixWrite16(struct GBA*, uint32_t address, uint16_t value); + +CXX_GUARD_END + +#endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/memory.h mgba-0.7.0/include/mgba/internal/gba/memory.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/memory.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/memory.h 2019-01-27 00:06:06.000000000 +0000 @@ -13,9 +13,11 @@ #include #include +#include #include #include #include +#include enum GBAMemoryRegion { REGION_BIOS = 0x0, @@ -68,7 +70,9 @@ SIZE_CART_FLASH512 = 0x00010000, SIZE_CART_FLASH1M = 0x00020000, SIZE_CART_EEPROM = 0x00002000, - SIZE_CART_EEPROM512 = 0x00000200 + SIZE_CART_EEPROM512 = 0x00000200, + + SIZE_AGB_PRINT = 0x10000 }; enum { @@ -76,42 +80,21 @@ BASE_OFFSET = 24 }; -enum DMAControl { - DMA_INCREMENT = 0, - DMA_DECREMENT = 1, - DMA_FIXED = 2, - DMA_INCREMENT_RELOAD = 3 -}; - -enum DMATiming { - DMA_TIMING_NOW = 0, - DMA_TIMING_VBLANK = 1, - DMA_TIMING_HBLANK = 2, - DMA_TIMING_CUSTOM = 3 +enum { + AGB_PRINT_BASE = 0x00FD0000, + AGB_PRINT_TOP = 0x00FE0000, + AGB_PRINT_PROTECT = 0x00FE2FFE, + AGB_PRINT_STRUCT = 0x01FE20F8, + AGB_PRINT_FLUSH_ADDR = 0x01FE209C, }; mLOG_DECLARE_CATEGORY(GBA_MEM); -DECL_BITFIELD(GBADMARegister, uint16_t); -DECL_BITS(GBADMARegister, DestControl, 5, 2); -DECL_BITS(GBADMARegister, SrcControl, 7, 2); -DECL_BIT(GBADMARegister, Repeat, 9); -DECL_BIT(GBADMARegister, Width, 10); -DECL_BIT(GBADMARegister, DRQ, 11); -DECL_BITS(GBADMARegister, Timing, 12, 2); -DECL_BIT(GBADMARegister, DoIRQ, 14); -DECL_BIT(GBADMARegister, Enable, 15); - -struct GBADMA { - GBADMARegister reg; - - uint32_t source; - uint32_t dest; - int32_t count; - uint32_t nextSource; - uint32_t nextDest; - int32_t nextCount; - uint32_t when; +struct GBAPrintContext { + uint16_t request; + uint16_t bank; + uint16_t get; + uint16_t put; }; struct GBAMemory { @@ -124,6 +107,7 @@ struct GBACartridgeHardware hw; struct GBASavedata savedata; struct GBAVFameCart vfame; + struct GBAMatrix matrix; size_t romSize; uint32_t romMask; uint16_t romID; @@ -141,6 +125,11 @@ struct GBADMA dma[4]; struct mTimingEvent dmaEvent; int activeDMA; + uint32_t dmaTransferRegister; + + uint16_t agbPrint; + struct GBAPrintContext agbPrintCtx; + uint16_t* agbPrintBuffer; bool mirroring; }; @@ -180,6 +169,8 @@ void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state); void GBAMemoryDeserialize(struct GBAMemory* memory, const struct GBASerializedState* state); +void GBAPrintFlush(struct GBA* gba); + CXX_GUARD_END #endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/overrides.h mgba-0.7.0/include/mgba/internal/gba/overrides.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/overrides.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/overrides.h 2019-01-27 00:06:06.000000000 +0000 @@ -28,7 +28,7 @@ struct GBA; void GBAOverrideApply(struct GBA*, const struct GBACartridgeOverride*); -void GBAOverrideApplyDefaults(struct GBA*); +void GBAOverrideApplyDefaults(struct GBA*, const struct Configuration*); CXX_GUARD_END diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/renderers/cache-set.h mgba-0.7.0/include/mgba/internal/gba/renderers/cache-set.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/renderers/cache-set.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/renderers/cache-set.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,22 @@ +/* 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 GBA_CACHE_SET_H +#define GBA_CACHE_SET_H + +#include + +CXX_GUARD_START + +struct GBAVideo; +struct mCacheSet; + +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 + +#endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/renderers/tile-cache.h mgba-0.7.0/include/mgba/internal/gba/renderers/tile-cache.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/renderers/tile-cache.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/renderers/tile-cache.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +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 GBA_TILE_CACHE_H -#define GBA_TILE_CACHE_H - -#include - -CXX_GUARD_START - -struct GBAVideo; -struct mTileCache; - -void GBAVideoTileCacheInit(struct mTileCache* cache); -void GBAVideoTileCacheAssociate(struct mTileCache* cache, struct GBAVideo* video); - -CXX_GUARD_END - -#endif diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/renderers/video-software.h mgba-0.7.0/include/mgba/internal/gba/renderers/video-software.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/renderers/video-software.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/renderers/video-software.h 2019-01-27 00:06:06.000000000 +0000 @@ -11,6 +11,7 @@ CXX_GUARD_START #include +#include #include struct GBAVideoSoftwareSprite { @@ -41,6 +42,10 @@ int16_t dmy; int32_t sx; int32_t sy; + int yCache; + uint16_t mapCache[64]; + int32_t offsetX; + int32_t offsetY; }; enum BlendEffect { @@ -156,6 +161,16 @@ int oamDirty; int oamMax; struct GBAVideoSoftwareSprite sprites[128]; + int16_t objOffsetX; + int16_t objOffsetY; + + 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; diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/savedata.h mgba-0.7.0/include/mgba/internal/gba/savedata.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/savedata.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/savedata.h 2019-01-27 00:06:06.000000000 +0000 @@ -87,7 +87,6 @@ uint8_t* currentBank; struct mTiming* timing; - bool realisticTiming; unsigned settling; struct mTimingEvent dust; @@ -102,13 +101,13 @@ void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback); void GBASavedataUnmask(struct GBASavedata* savedata); -size_t GBASavedataSize(struct GBASavedata* savedata); +size_t GBASavedataSize(const struct GBASavedata* savedata); bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out); bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in); -void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming); +void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type); -void GBASavedataInitFlash(struct GBASavedata* savedata, bool realisticTiming); -void GBASavedataInitEEPROM(struct GBASavedata* savedata, bool realisticTiming); +void GBASavedataInitFlash(struct GBASavedata* savedata); +void GBASavedataInitEEPROM(struct GBASavedata* savedata); void GBASavedataInitSRAM(struct GBASavedata* savedata); uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address); diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/serialize.h mgba-0.7.0/include/mgba/internal/gba/serialize.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/serialize.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/serialize.h 2019-01-27 00:06:06.000000000 +0000 @@ -98,28 +98,28 @@ * | 0x00202 - 0x00203: Old reload value * | 0x00204 - 0x00207: Last event * | 0x00208 - 0x0020B: Next event - * | 0x0020C - 0x0020F: Overflow interval + * | 0x0020C - 0x0020F: Next IRQ * | 0x00210 - 0x00213: Miscellaneous flags * 0x00214 - 0x00227: Timer 1 * | 0x00214 - 0x00215: Reload value * | 0x00216 - 0x00217: Old reload value * | 0x00218 - 0x0021B: Last event * | 0x0021C - 0x0021F: Next event - * | 0x00220 - 0x00223: Overflow interval + * | 0x00220 - 0x00223: Next IRQ * | 0x00224 - 0x00227: Miscellaneous flags * 0x00228 - 0x0023B: Timer 2 * | 0x00228 - 0x00229: Reload value * | 0x0022A - 0x0022B: Old reload value * | 0x0022C - 0x0022F: Last event * | 0x00230 - 0x00233: Next event - * | 0x00234 - 0x00237: Overflow interval + * | 0x00234 - 0x00237: Next IRQ * | 0x00238 - 0x0023B: Miscellaneous flags * 0x0023C - 0x00250: Timer 3 * | 0x0023C - 0x0023D: Reload value * | 0x0023E - 0x0023F: Old reload value * | 0x00240 - 0x00243: Last event * | 0x00244 - 0x00247: Next event - * | 0x00248 - 0x0024B: Overflow interval + * | 0x00248 - 0x0024B: Next IRQ * | 0x0024C - 0x0024F: Miscellaneous flags * 0x00250 - 0x0025F: DMA 0 * | 0x00250 - 0x00253: DMA next source @@ -169,7 +169,8 @@ * | bits 4 - 8: GB Player transmit position * | bits 9 - 23: Reserved * 0x002C4 - 0x002C7: Game Boy Player next event - * 0x002C8 - 0x002DF: Reserved (leave zero) + * 0x002C8 - 0x002CB: Current DMA transfer word + * 0x002CC - 0x002DF: Reserved (leave zero) * 0x002E0 - 0x002EF: Savedata state * | 0x002E0 - 0x002E0: Savedata type * | 0x002E1 - 0x002E1: Savedata command (see savedata.h) @@ -194,6 +195,7 @@ * 0x00318 - 0x0031B: Last prefetched program counter * 0x0031C - 0x0031F: Miscellaneous flags * | bit 0: Is CPU halted? + * | bit 1: POSTFLG * 0x00320 - 0x003FF: Reserved (leave zero) * 0x00400 - 0x007FF: I/O memory * 0x00800 - 0x00BFF: Palette @@ -224,6 +226,7 @@ DECL_BITFIELD(GBASerializedMiscFlags, uint32_t); DECL_BIT(GBASerializedMiscFlags, Halted, 0); +DECL_BIT(GBASerializedMiscFlags, POSTFLG, 1); struct GBASerializedState { uint32_t versionMagic; @@ -264,10 +267,10 @@ struct { uint16_t reload; - uint16_t oldReload; + uint16_t reserved; uint32_t lastEvent; uint32_t nextEvent; - int32_t overflowInterval; + uint32_t nextIrq; GBATimerFlags flags; } timers[4]; @@ -293,7 +296,9 @@ uint32_t gbpNextEvent; } hw; - uint32_t reservedHardware[6]; + uint32_t dmaTransferRegister; + + uint32_t reservedHardware[5]; struct { uint8_t type; diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/timer.h mgba-0.7.0/include/mgba/internal/gba/timer.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/timer.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/timer.h 2019-01-27 00:06:06.000000000 +0000 @@ -17,19 +17,19 @@ DECL_BIT(GBATimerFlags, CountUp, 4); DECL_BIT(GBATimerFlags, DoIrq, 5); DECL_BIT(GBATimerFlags, Enable, 6); +DECL_BIT(GBATimerFlags, IrqPending, 7); struct GBA; struct GBATimer { uint16_t reload; - uint16_t oldReload; - uint32_t lastEvent; + int32_t lastEvent; struct mTimingEvent event; - int32_t overflowInterval; + struct mTimingEvent irq; GBATimerFlags flags; }; void GBATimerInit(struct GBA* gba); -void GBATimerUpdateRegister(struct GBA* gba, int timer); +void GBATimerUpdateRegister(struct GBA* gba, int timer, int32_t cyclesLate); void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t value); void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t value); diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/gba/video.h mgba-0.7.0/include/mgba/internal/gba/video.h --- mgba-0.6.3+dfsg1/include/mgba/internal/gba/video.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/gba/video.h 2019-01-27 00:06:06.000000000 +0000 @@ -164,7 +164,7 @@ uint16_t* palette; uint16_t* vram; union GBAOAM* oam; - struct mTileCache* cache; + struct mCacheSet* cache; bool disableBG[4]; bool disableOBJ; diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/lr35902/debugger/debugger.h mgba-0.7.0/include/mgba/internal/lr35902/debugger/debugger.h --- mgba-0.6.3+dfsg1/include/mgba/internal/lr35902/debugger/debugger.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/lr35902/debugger/debugger.h 2019-01-27 00:06:06.000000000 +0000 @@ -15,16 +15,18 @@ #include #include - +struct ParseTree; struct LR35902DebugBreakpoint { uint16_t address; int segment; + struct ParseTree* condition; }; struct LR35902DebugWatchpoint { uint16_t address; int segment; enum mWatchpointType type; + struct ParseTree* condition; }; struct LR35902Segment { diff -Nru mgba-0.6.3+dfsg1/include/mgba/internal/lr35902/lr35902.h mgba-0.7.0/include/mgba/internal/lr35902/lr35902.h --- mgba-0.6.3+dfsg1/include/mgba/internal/lr35902/lr35902.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba/internal/lr35902/lr35902.h 2019-01-27 00:06:06.000000000 +0000 @@ -66,6 +66,7 @@ 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 @@ LR35902Instruction instruction; bool irqPending; - uint16_t irqVector; struct LR35902Memory memory; struct LR35902InterruptHandler irqh; @@ -136,7 +136,7 @@ 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 -Nru mgba-0.6.3+dfsg1/include/mgba-util/arm-algo.h mgba-0.7.0/include/mgba-util/arm-algo.h --- mgba-0.6.3+dfsg1/include/mgba-util/arm-algo.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/arm-algo.h 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/include/mgba-util/common.h mgba-0.7.0/include/mgba-util/common.h --- mgba-0.6.3+dfsg1/include/mgba-util/common.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/common.h 2019-01-27 00:06:06.000000000 +0000 @@ -119,13 +119,13 @@ #define STORE_32LE(SRC, ADDR, ARR) { \ uint32_t _addr = (ADDR); \ void* _ptr = (ARR); \ - __asm__("stwbrx %0, %1, %2" : : "r"(SRC), "b"(_ptr), "r"(_addr)); \ + __asm__("stwbrx %0, %1, %2" : : "r"(SRC), "b"(_ptr), "r"(_addr) : "memory"); \ } #define STORE_16LE(SRC, ADDR, ARR) { \ uint32_t _addr = (ADDR); \ void* _ptr = (ARR); \ - __asm__("sthbrx %0, %1, %2" : : "r"(SRC), "b"(_ptr), "r"(_addr)); \ + __asm__("sthbrx %0, %1, %2" : : "r"(SRC), "b"(_ptr), "r"(_addr) : "memory"); \ } #define LOAD_64LE(DEST, ADDR, ARR) { \ @@ -136,12 +136,13 @@ uint32_t lo; \ }; \ uint64_t b64; \ - } *bswap = (void*) &DEST; \ + } bswap; \ const void* _ptr = (ARR); \ __asm__( \ "lwbrx %0, %2, %3 \n" \ "lwbrx %1, %2, %4 \n" \ - : "=r"(bswap->lo), "=r"(bswap->hi) : "b"(_ptr), "r"(_addr), "r"(_addr + 4)); \ + : "=&r"(bswap.lo), "=&r"(bswap.hi) : "b"(_ptr), "r"(_addr), "r"(_addr + 4)) ; \ + DEST = bswap.b64; \ } #define STORE_64LE(SRC, ADDR, ARR) { \ @@ -152,12 +153,12 @@ uint32_t lo; \ }; \ uint64_t b64; \ - } *bswap = (void*) &SRC; \ + } bswap = { .b64 = SRC }; \ const void* _ptr = (ARR); \ __asm__( \ "stwbrx %0, %2, %3 \n" \ "stwbrx %1, %2, %4 \n" \ - : : "r"(bswap->hi), "r"(bswap->lo), "b"(_ptr), "r"(_addr), "r"(_addr + 4)); \ + : : "r"(bswap.hi), "r"(bswap.lo), "b"(_ptr), "r"(_addr), "r"(_addr + 4) : "memory"); \ } #elif defined(__llvm__) || (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) @@ -177,8 +178,12 @@ #define STORE_64LE(SRC, ADDR, ARR) *(uint64_t*) ((uintptr_t) (ARR) + (size_t) (ADDR)) = SRC #define STORE_32LE(SRC, ADDR, ARR) *(uint32_t*) ((uintptr_t) (ARR) + (size_t) (ADDR)) = SRC #define STORE_16LE(SRC, ADDR, ARR) *(uint16_t*) ((uintptr_t) (ARR) + (size_t) (ADDR)) = SRC +#ifdef _MSC_VER +#define LOAD_32BE(DEST, ADDR, ARR) DEST = _byteswap_ulong(((uint32_t*) ARR)[(ADDR) >> 2]) +#else #define LOAD_32BE(DEST, ADDR, ARR) DEST = __builtin_bswap32(((uint32_t*) ARR)[(ADDR) >> 2]) #endif +#endif #define MAKE_MASK(START, END) (((1 << ((END) - (START))) - 1) << (START)) #define CHECK_BITS(SRC, START, END) ((SRC) & MAKE_MASK(START, END)) @@ -191,9 +196,11 @@ #ifdef _MSC_VER #define ATTRIBUTE_UNUSED #define ATTRIBUTE_FORMAT(X, Y, Z) +#define ATTRIBUTE_NOINLINE #else #define ATTRIBUTE_UNUSED __attribute__((unused)) #define ATTRIBUTE_FORMAT(X, Y, Z) __attribute__((format(X, Y, Z))) +#define ATTRIBUTE_NOINLINE __attribute__((noinline)) #endif #define DECL_BITFIELD(NAME, TYPE) typedef TYPE NAME diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/crc32.h mgba-0.7.0/include/mgba-util/crc32.h --- mgba-0.6.3+dfsg1/include/mgba-util/crc32.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/crc32.h 2019-01-27 00:06:06.000000000 +0000 @@ -12,8 +12,13 @@ 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 -Nru mgba-0.6.3+dfsg1/include/mgba-util/elf-read.h mgba-0.7.0/include/mgba-util/elf-read.h --- mgba-0.6.3+dfsg1/include/mgba-util/elf-read.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/elf-read.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,45 @@ +/* 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 ELF_READ_H +#define ELF_READ_H + +#include + +CXX_GUARD_START + +#ifdef USE_ELF + +#include + +#include + +struct ELF; +struct VFile; + +DECLARE_VECTOR(ELFProgramHeaders, Elf32_Phdr); +DECLARE_VECTOR(ELFSectionHeaders, Elf32_Shdr); + +struct ELF* ELFOpen(struct VFile*); +void ELFClose(struct ELF*); + +void* ELFBytes(struct ELF*, size_t* size); + +uint16_t ELFMachine(struct ELF*); +uint32_t ELFEntry(struct ELF*); + +void ELFGetProgramHeaders(struct ELF*, struct ELFProgramHeaders*); + +size_t ELFFindSection(struct ELF*, const char* name); +void ELFGetSectionHeaders(struct ELF*, struct ELFSectionHeaders*); +Elf32_Shdr* ELFGetSectionHeader(struct ELF*, size_t index); + +const char* ELFGetString(struct ELF*, size_t section, size_t string); + +#endif + +CXX_GUARD_END + +#endif diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/formatting.h mgba-0.7.0/include/mgba-util/formatting.h --- mgba-0.6.3+dfsg1/include/mgba-util/formatting.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/formatting.h 2019-01-27 00:06:06.000000000 +0000 @@ -12,8 +12,8 @@ #include "locale.h" -#if defined(__APPLE__) || defined(__FreeBSD__) -#include "xlocale.h" +#ifdef HAVE_XLOCALE +#include #elif !defined(HAVE_LOCALE) typedef const char* locale_t; #endif diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/gui/file-select.h mgba-0.7.0/include/mgba-util/gui/file-select.h --- mgba-0.6.3+dfsg1/include/mgba-util/gui/file-select.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/gui/file-select.h 2019-01-27 00:06:06.000000000 +0000 @@ -14,7 +14,7 @@ struct VFile; -bool GUISelectFile(struct GUIParams*, char* outPath, size_t outLen, bool (*filter)(struct VFile*)); +bool GUISelectFile(struct GUIParams*, char* outPath, size_t outLen, bool (*filterName)(const char* name), bool (*filterContents)(struct VFile*)); CXX_GUARD_END diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/gui/menu.h mgba-0.7.0/include/mgba-util/gui/menu.h --- mgba-0.6.3+dfsg1/include/mgba-util/gui/menu.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/gui/menu.h 2019-01-27 00:06:06.000000000 +0000 @@ -12,12 +12,37 @@ #include +#define GUI_V_V (struct GUIVariant) { .type = GUI_VARIANT_VOID } +#define GUI_V_U(U) (struct GUIVariant) { .type = GUI_VARIANT_UNSIGNED, .v.u = (U) } +#define GUI_V_I(I) (struct GUIVariant) { .type = GUI_VARIANT_INT, .v.i = (I) } +#define GUI_V_F(F) (struct GUIVariant) { .type = GUI_VARIANT_FLOAT, .v.f = (F) } +#define GUI_V_S(S) (struct GUIVariant) { .type = GUI_VARIANT_STRING, .v.s = (S) } + +enum GUIVariantType { + GUI_VARIANT_VOID = 0, + GUI_VARIANT_UNSIGNED, + GUI_VARIANT_INT, + GUI_VARIANT_FLOAT, + GUI_VARIANT_STRING +}; + +struct GUIVariant { + enum GUIVariantType type; + union { + unsigned u; + int i; + float f; + const char* s; + } v; +}; + struct GUIMenu; struct GUIMenuItem { const char* title; void* data; unsigned state; const char* const* validStates; + const struct GUIVariant* stateMappings; unsigned nStates; struct GUIMenu* submenu; }; diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/gui.h mgba-0.7.0/include/mgba-util/gui.h --- mgba-0.6.3+dfsg1/include/mgba-util/gui.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/gui.h 2019-01-27 00:06:06.000000000 +0000 @@ -47,7 +47,8 @@ BATTERY_HIGH = 3, BATTERY_FULL = 4, - BATTERY_CHARGING = 8 + BATTERY_CHARGING = 8, + BATTERY_NOT_PRESENT = 16 }; struct GUIBackground { diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/platform/3ds/threading.h mgba-0.7.0/include/mgba-util/platform/3ds/threading.h --- mgba-0.6.3+dfsg1/include/mgba-util/platform/3ds/threading.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/platform/3ds/threading.h 2019-01-27 00:06:06.000000000 +0000 @@ -11,18 +11,9 @@ #include <3ds.h> #include -#ifdef _3DS -// ctrulib already has a type called Thread -#define Thread CustomThread -#endif - #define THREAD_ENTRY void typedef ThreadFunc ThreadEntry; -typedef struct { - Handle handle; - u8* stack; -} Thread; typedef LightLock Mutex; typedef struct { Mutex mutex; @@ -103,22 +94,12 @@ if (!entry || !thread) { return 1; } - thread->stack = memalign(8, 0x8000); - if (!thread->stack) { - return 1; - } - bool isNew3DS; - APT_CheckNew3DS(&isNew3DS); - if (isNew3DS && svcCreateThread(&thread->handle, entry, (u32) context, (u32*) &thread->stack[0x8000], 0x18, 2) == 0) { - return 0; - } - return svcCreateThread(&thread->handle, entry, (u32) context, (u32*) &thread->stack[0x8000], 0x18, -1); + *thread = threadCreate(entry, context, 0x8000, 0x18, 2, true); + return !*thread; } static inline int ThreadJoin(Thread thread) { - svcWaitSynchronization(thread.handle, U64_MAX); - free(thread.stack); - return 0; + return threadJoin(thread, U64_MAX); } static inline void ThreadSetName(const char* name) { diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/platform/switch/threading.h mgba-0.7.0/include/mgba-util/platform/switch/threading.h --- mgba-0.6.3+dfsg1/include/mgba-util/platform/switch/threading.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/platform/switch/threading.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,87 @@ +/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef SWITCH_THREADING_H +#define SWITCH_THREADING_H + +#include + +#include + +#define THREAD_ENTRY void +typedef ThreadFunc ThreadEntry; +typedef CondVar Condition; + +static inline int MutexInit(Mutex* mutex) { + mutexInit(mutex); + return 0; +} + +static inline int MutexDeinit(Mutex* mutex) { + UNUSED(mutex); + return 0; +} + +static inline int MutexLock(Mutex* mutex) { + mutexLock(mutex); + return 0; +} + +static inline int MutexTryLock(Mutex* mutex) { + return mutexTryLock(mutex); +} + +static inline int MutexUnlock(Mutex* mutex) { + mutexUnlock(mutex); + return 0; +} + +static inline int ConditionInit(Condition* cond) { + condvarInit(cond); + return 0; +} + +static inline int ConditionDeinit(Condition* cond) { + UNUSED(cond); + return 0; +} + +static inline int ConditionWait(Condition* cond, Mutex* mutex) { + return condvarWait(cond, mutex); +} + +static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) { + return condvarWaitTimeout(cond, mutex, timeoutMs * 1000000LL); +} + +static inline int ConditionWake(Condition* cond) { + return condvarWakeOne(cond); +} + +static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) { + if (!entry || !thread) { + return 1; + } + int res = threadCreate(thread, entry, context, 0x8000, 0x3B, 1); + if(R_FAILED(res)) { + return res; + } + return threadStart(thread); +} + +static inline int ThreadJoin(Thread thread) { + int res = threadWaitForExit(&thread); + if(R_FAILED(res)) { + return res; + } + return threadClose(&thread); +} + +static inline void ThreadSetName(const char* name) { + UNUSED(name); + // Unimplemented +} + +#endif diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/png-io.h mgba-0.7.0/include/mgba-util/png-io.h --- mgba-0.6.3+dfsg1/include/mgba-util/png-io.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/png-io.h 2019-01-27 00:06:06.000000000 +0000 @@ -26,9 +26,11 @@ 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); @@ -40,6 +42,8 @@ bool PNGInstallChunkHandler(png_structp png, void* context, ChunkHandler handler, const char* chunkName); bool PNGReadHeader(png_structp png, png_infop info); bool PNGReadPixels(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride); +bool PNGReadPixelsA(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride); +bool PNGReadPixels8(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride); bool PNGIgnorePixels(png_structp png, png_infop info); bool PNGReadFooter(png_structp png, png_infop end); void PNGReadClose(png_structp png, png_infop info, png_infop end); diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/ring-fifo.h mgba-0.7.0/include/mgba-util/ring-fifo.h --- mgba-0.6.3+dfsg1/include/mgba-util/ring-fifo.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/ring-fifo.h 2019-01-27 00:06:06.000000000 +0000 @@ -20,6 +20,7 @@ void RingFIFOInit(struct RingFIFO* buffer, size_t capacity); void RingFIFODeinit(struct RingFIFO* buffer); size_t RingFIFOCapacity(const struct RingFIFO* buffer); +size_t RingFIFOSize(const struct RingFIFO* buffer); void RingFIFOClear(struct RingFIFO* buffer); size_t RingFIFOWrite(struct RingFIFO* buffer, const void* value, size_t length); size_t RingFIFORead(struct RingFIFO* buffer, void* output, size_t length); diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/socket.h mgba-0.7.0/include/mgba-util/socket.h --- mgba-0.6.3+dfsg1/include/mgba-util/socket.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/socket.h 2019-01-27 00:06:06.000000000 +0000 @@ -55,6 +55,9 @@ extern u32* SOCUBuffer; #endif +#ifdef __SWITCH__ +#include +#endif static inline void SocketSubsystemInit() { #ifdef _WIN32 @@ -65,6 +68,8 @@ SOCUBuffer = memalign(SOCU_ALIGN, SOCU_BUFFERSIZE); socInit(SOCUBuffer, SOCU_BUFFERSIZE); } +#elif defined(__SWITCH__) + socketInitializeDefault(); #endif } @@ -75,6 +80,8 @@ socExit(); free(SOCUBuffer); SOCUBuffer = NULL; +#elif defined(__SWITCH__) + socketExit(); #endif } @@ -103,7 +110,7 @@ } static inline ssize_t SocketRecv(Socket socket, void* buffer, size_t size) { -#ifdef _WIN32 +#if defined(_WIN32) || defined(__SWITCH__) return recv(socket, (char*) buffer, size, 0); #else return read(socket, buffer, size); diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/threading.h mgba-0.7.0/include/mgba-util/threading.h --- mgba-0.6.3+dfsg1/include/mgba-util/threading.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/threading.h 2019-01-27 00:06:06.000000000 +0000 @@ -13,12 +13,14 @@ #ifndef DISABLE_THREADING #ifdef USE_PTHREADS #include -#elif _WIN32 +#elif defined(_WIN32) #include -#elif PSP2 +#elif defined(PSP2) #include -#elif _3DS +#elif defined(_3DS) #include +#elif defined(__SWITCH__) +#include #else #define DISABLE_THREADING #endif diff -Nru mgba-0.6.3+dfsg1/include/mgba-util/vfs.h mgba-0.7.0/include/mgba-util/vfs.h --- mgba-0.6.3+dfsg1/include/mgba-util/vfs.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/include/mgba-util/vfs.h 2019-01-27 00:06:06.000000000 +0000 @@ -87,7 +87,7 @@ struct VDir* VDirOpen7z(const char* path, int flags); #endif -#if defined(__wii__) || defined(_3DS) +#if defined(__wii__) || defined(_3DS) || defined(PSP2) struct VDir* VDeviceList(void); #endif diff -Nru mgba-0.6.3+dfsg1/opt/libgba/mgba.c mgba-0.7.0/opt/libgba/mgba.c --- mgba-0.6.3+dfsg1/opt/libgba/mgba.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/opt/libgba/mgba.c 2019-01-27 00:06:06.000000000 +0000 @@ -32,7 +32,7 @@ #define REG_DEBUG_FLAGS (vu16*) 0x4FFF700 #define REG_DEBUG_STRING (char*) 0x4FFF600 -ssize_t mgba_stdout_write(struct _reent* r __attribute__((unused)), int fd __attribute__((unused)), const char* ptr, size_t len) { +ssize_t mgba_stdout_write(struct _reent* r __attribute__((unused)), void* fd __attribute__((unused)), const char* ptr, size_t len) { if (len > 0x100) { len = 0x100; } @@ -41,7 +41,7 @@ return len; } -ssize_t mgba_stderr_write(struct _reent* r __attribute__((unused)), int fd __attribute__((unused)), const char* ptr, size_t len) { +ssize_t mgba_stderr_write(struct _reent* r __attribute__((unused)), void* fd __attribute__((unused)), const char* ptr, size_t len) { if (len > 0x100) { len = 0x100; } diff -Nru mgba-0.6.3+dfsg1/README_DE.md mgba-0.7.0/README_DE.md --- mgba-0.6.3+dfsg1/README_DE.md 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/README_DE.md 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,241 @@ +mGBA +==== + +mGBA ist ein Emulator für Game Boy Advance-Spiele. Das Ziel von mGBA ist, schneller und genauer als viele existierende Game Boy Advance-Emulatoren zu sein. Außerdem verfügt mGBA über Funktionen, die anderen Emulatoren fehlen. Zusätzlich werden auch Game Boy- und Game Boy Color-Spiele unterstützt. + +Aktuelle Neuigkeiten und Downloads findest Du auf [mgba.io](https://mgba.io). + +[![Build-Status](https://travis-ci.org/mgba-emu/mgba.svg?branch=master)](https://travis-ci.org/mgba-emu/mgba) + +Features +-------- + +- Sehr genaue Unterstützung der Game Boy Advance-Hardware[[1]](#missing). +- Unterstützung der Game Boy-/Game Boy Color-Hardware. +- Schnelle Emulation. mGBA ist dafür bekannt, auch auf schwacher Hardware wie Netbooks mit voller Geschwindigkeit zu laufen. +- Qt- und SDL-Portierungen für eine vollwertige und eine "leichtgewichtige" Benutzeroberfläche. +- Lokale (gleicher Computer) Unterstützung für Link-Kabel. +- Erkennung des Speichertypes, einschließlich der Größe des Flash-Speichers[[2]](#flashdetect). +- Unterstützung für Spielmodule mit Bewegungssensoren und Rüttel-Effekten (nur verwendbar mit Spiele-Controllern). +- Unterstützung für Echtzeituhren, selbst ohne Konfiguration. +- Unterstützung für den Lichtsensor in Boktai-Spielen +- Unterstützung für Game Boy Printer und Game Boy Camera. +- Eingebaute BIOS-Implementierung mit der Möglichkeit, externe BIOS-Dateien zu laden. +- Turbo/Vorlauf-Unterstützung durch drücken der Tab-Taste. +- Rücklauf-Unterstützung durch drücken der Akzent-Taste. +- Frameskip von bis zu 10 Bildern. +- Unterstützung für Screenshots. +- Unterstützung für Cheat-Codes. +- 9 Speicherstände für Savestates/Spielzustände. Savestates können auch als Screenshots dargestellt werden. +- Video- und GIF-Aufzeichnung. +- Frei wählbare Tastenbelegungen für Tastaturen und Controller. +- Unterstützung für ZIP- und 7z-Archive. +- Unterstützung für Patches im IPS-, UPS- und BPS-Format. +- Spiele-Debugging über ein Kommandozeilen-Interface und IDA Pro-kompatible GDB-Unterstützung. +- Einstellbare Rücklauf-Funktion. +- Unterstützung für das Laden und Exportieren von GameShark- und Action Replay-Abbildern. +- Verfügbare Cores für RetroArch/Libretro und OpenEmu. +- Viele, viele kleinere Dinge. + +### Game Boy-Mapper + +Die folgenden Mapper werden vollständig unterstützt: + +- MBC1 +- MBC1M +- MBC2 +- MBC3 +- MBC3+RTC (MBC3+Echtzeituhr) +- MBC5 +- MBC5+Rumble (MBC5+Rüttel-Modul) +- MBC7 + +Die folgenden Mapper werden teilweise unterstützt: + +- MBC6 +- MMM01 +- Pocket Cam +- TAMA5 +- HuC-1 +- HuC-3 + +### Geplante Features + +- Unterstützung für Link-Kabel-Multiplayer über ein Netzwerk. +- Unterstützung für Link-Kabel über Dolphin/JOY-Bus. +- M4A-Audio-Abmischung für höhere Audio-Qualität als echte Hardware. +- Unterstützung für Tool-Assisted Speedruns. +- Lua-Unterstützung für Scripting. +- Eine umfangreiche Debugging-Suite. +- e-Reader-Unterstützung. +- Unterstützung für Drahtlosadapter. + +Unterstützte Plattformen +------------------------ + +- Windows Vista oder neuer +- OS X 10.7 (Lion)[[3]](#osxver) oder neuer +- Linux +- FreeBSD +- Nintendo 3DS +- Wii +- PlayStation Vita + +Andere Unix-ähnliche Plattformen wie OpenBSD sind ebenfalls dafür bekannt, mit mGBA kompatibel zu sein. Sie sind jedoch nicht getestet und werden nicht voll unterstützt. + +### Systemvoraussetzungen + +Die Systemvoraussetzungen sind minimal. Jeder Computer, der mit Windows Vista oder neuer läuft, sollte in der Lage sein, die Emulation zu bewältigen. Unterstützung für OpenGL 1.1 oder neuer ist ebenfalls voraussgesetzt. + +Downloads +--------- + +Download-Links befinden sich in der [Downloads][downloads]-Sektion auf der offiziellen Website. Der Quellcode befindet sich auf [GitHub][source]. + +Steuerung +--------- + +Die Steuerung kann im Einstellungs-Menü konfiguriert werden. Viele Spiele-Controller werden automatisch erkannt und entsprechend belegt. Für Tastaturen wird standardmäßig folgende Belegung verwendet: + +- **A**: X +- **B**: Z +- **L**: A +- **R**: S +- **Start**: Enter +- **Select**: Rücktaste + +Kompilieren +----------- + +Um mGBA kompilieren zu können, wird CMake 3.1 oder neuer benötigt. GCC und Clang sind beide dafür bekannt, mGBA kompilieren zu können. Visual Studio 2013 und älter funktionieren nicht. Unterstützung für Visual Studio 2015 und neuer wird bald hinzugefügt. + +#### Kompilieren mit Docker + +Der empfohlene Weg, um mGBA für die meisten Plattformen zu kompilieren, ist Docker. Mehrere Docker-Images sind verfügbar, welche die benötigte Compiler-Umgebung und alle benötigten Abhängigkeiten beinhaltet, um mGBA für verschiedene Plattformen zu bauen. + +Um ein Docker-Image zum Bau von mGBA zu verwenden, führe einfach folgenden Befehl in dem Verzeichnis aus, in welches Du den mGBA-Quellcode ausgecheckt hast: + + docker run --rm -t -v $PWD:/home/mgba/src mgba/windows:w32 + +Dieser Befehl erzeugt ein Verzeichnis `build-win32` mit den erzeugten Programmdateien. Ersetze `mgba/windows:32` durch ein Docker-Image für eine andere Plattform, wodurch dann das entsprechende Verzeichnis erzeugt wird. Die folgenden Docker-Images sind im Docker Hub verfügbar: + +- mgba/3ds +- mgba/switch +- mgba/ubuntu:xenial +- mgba/ubuntu:bionic +- mgba/ubuntu:cosmic +- mgba/vita +- mgba/wii +- mgba/windows:w32 +- mgba/windows:w64 + +#### Unter *nix kompilieren + +Verwende folgende Befehle, um mGBA mithilfe von CMake auf einem Unix-basierten System zu bauen: + + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .. + make + sudo make install + +Damit wird mGBA gebaut und in `/usr/bin` und `/usr/lib` installiert. Installierte Abhängigkeiten werden automatisch erkannt. Features, die aufgrund fehlender Abhängigkeiten deaktiviert wurden, werden nach dem `cmake`-Kommando angezeigt. + +Wenn Du macOS verwendest, sind die einzelnen Schritte etwas anders. Angenommen, dass Du den Homebrew-Paketmanager verwendest, werden folgende Schritte zum installieren der Abhängigkeiten und anschließenden bauen von mGBA empfohlen: + + brew install cmake ffmpeg imagemagick libzip qt5 sdl2 libedit pkg-config + mkdir build + cd build + cmake -DCMAKE_PREFIX_PATH='brew --prefix qt5' .. + make + +Bitte beachte, dass Du unter macOS nicht 'make install' verwenden solltest, da dies nicht korrekt funktionieren wird. + +### Für Entwickler: Kompilieren unter Windows + +Um mGBA auf Windows zu kompilieren, wird MSYS2 empfohlen. Befolge die Installationsschritte auf der [MSYS2-Website](https://msys2.github.io). Stelle sicher, dass Du die 32-Bit-Version ("MSYS2 MinGW 32-bit") (oder die 64-Bit-Version "MSYS2 MinGW 64-bit", wenn Du mGBA für x86_64 kompilieren willst) verwendest und führe folgendes Kommando (einschließlich der Klammern) aus, um alle benötigten Abhängigkeiten zu installieren. Bitte beachte, dass dafür über 1100MiB an Paketen heruntergeladen werden, was eine Weile dauern kann: + +Für x86 (32 Bit): + + pacman -Sy --needed base-devel git mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} + +Für x86_64 (64 Bit): + + pacman -Sy --needed base-devel git mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} + +Lade den aktuellen mGBA-Quellcode mithilfe des folgenden Kommandos herunter: + + git clone https://github.com/mgba-emu/mgba.git + +Abschließend wird mGBA über folgende Kommandos kompiliert: + + cd mgba + mkdir build + cd build + cmake .. -G "MSYS Makefiles" + make + +Bitte beachte, dass mGBA für Windows aufgrund der Vielzahl an benötigten DLLs nicht für die weitere Verteilung geeignet ist, wenn es auf diese Weise gebaut wurde. Es ist jedoch perfekt für Entwickler geeignet. Soll mGBA dennoch weiter verteilt werden (beispielsweise zu Testzwecken auf Systemen, auf denen keine MSYS2-Umgebung installiert ist), kann mithilfe des Befehls `cpack -G ZIP` ein ZIP-Archiv mit allen benötigten DLLs erstellt werden. + +#### Kompilieren mithilfe einer Toolchain + +Wenn Du devkitARM (für 3DS), devkitPPC (für Wii), devkitA64 (für Switch) oder vitasdk (für PS Vita) installiert hast, kannst Du die folgenden Befehle zum Kompilieren verwenden: + + mkdir build + cd build + cmake -DCMAKE_TOOLCHAIN_FILE=../src/platform/3ds/CMakeToolchain.txt .. + make + +Ersetze den Parameter `-DCMAKE_TOOLCHAIN_FILE` dabei folgendermaßen: + +- 3DS: `../src/platform/3ds/CMakeToolchain.txt` +- Switch: `../src/platform/switch/CMakeToolchain.txt` +- Vita: `../src/platform/psp2/CMakeToolchain.vitasdk` +- Wii: `../src/platform/wii/CMakeToolchain.txt` + +### Abhängigkeiten + +mGBA hat keine "harten" Abhängigkeiten. Dennoch werden die folgenden optionalen Abhängigkeiten für einige Features benötigt. Diese Features werden automatisch deaktiviert, wenn die benötigten Abhängigkeiten nicht gefunden werden. + +- Qt 5: Für die Benutzeroberfläche. Qt Multimedia oder SDL werden für Audio-Ausgabe benötigt. +- SDL: Für eine einfachere Benutzeroberfläche und Spiele-Controller-Unterstützung in der Qt-Oberfläche. SDL 2 ist empfohlen, SDL 1.2 wird jedoch auch unterstützt. +- zlib und libpng: Für die Unterstützung von Bildschirmfotos und Savestates-in-PNG-Unterstützung. +- libedit: Für die Unterstützung des Kommandozeilen-Debuggers. +- ffmpeg oder libav: Für Videoaufzeichnungen. +- libzip oder zlib: Um ROMs aus ZIP-Dateien zu laden. +- ImageMagick: Für GIF-Aufzeichnungen. +- SQLite3: Für Spiele-Datenbanken. +- libelf: Für das Laden von ELF-Dateien. + +SQLite3, libpng und zlib werden mit dem Emulator mitgeliefert, sodass sie nicht zuerst kompiliert werden müssen. + +Fußnoten +-------- + +[1] Zurzeit fehlende Features sind + +- OBJ-Fenster für die Modi 3, 4 und 5 ([Bug #5](http://mgba.io/b/5)) +- Mosaik-Effekt für umgewandelte OBJs ([Bug #9](http://mgba.io/b/9)) + +[2] In manchen Fällen ist es nicht möglich, die Größe des Flash-Speichers automatisch zu ermitteln. Diese kann dann zur Laufzeit konfiguriert werden, es wird jedoch empfohlen, den Fehler zu melden. + +[3] 10.7 wird nur für die Qt-Portierung benötigt. Die SDL-Portierung ist dafür bekannt, mit 10.5 und möglicherweise auf älteren Versionen zu funktionieren. + +[downloads]: http://mgba.io/downloads.html +[source]: https://github.com/mgba-emu/mgba/ + +Copyright +--------- + +Copyright für mGBA © 2013 – 2019 Jeffrey Pfau. mGBA wird unter der [Mozilla Public License version 2.0](https://www.mozilla.org/MPL/2.0/) veröffentlicht. Eine Kopie der Lizenz ist in der mitgelieferten Datei LICENSE verfügbar. + +mGBA beinhaltet die folgenden Bibliotheken von Drittanbietern: + +- [inih](https://github.com/benhoyt/inih), Copyright © 2009 Ben Hoyt, verwendet unter einer BSD 3-clause-Lizenz. +- [blip-buf](https://code.google.com/archive/b/blip-buf), Copyright © 2003 - 2009 Shay Green, verwendet unter einer Lesser GNU Public License. +- [LZMA SDK](http://www.7-zip.org/sdk.html), Public Domain. +- [MurmurHash3](https://github.com/aappleby/smhasher), Implementierung von Austin Appleby, Public Domain. +- [getopt fot MSVC](https://github.com/skandhurkat/Getopt-for-Visual-Studio/), Public Domain. +- [SQLite3](https://www.sqlite.org), Public Domain. + +Wenn Du ein Spiele-Publisher bist und mGBA für kommerzielle Verwendung lizenzieren möchtest, schreibe bitte eine e-Mail an [licensing@mgba.io](mailto:licensing@mgba.io) für weitere Informationen. diff -Nru mgba-0.6.3+dfsg1/README.md mgba-0.7.0/README.md --- mgba-0.6.3+dfsg1/README.md 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/README.md 2019-01-27 00:06:06.000000000 +0000 @@ -10,7 +10,7 @@ Features -------- -- Near full Game Boy Advance hardware support[[1]](#missing). +- Highly accurate Game Boy Advance hardware support[[1]](#missing). - Game Boy/Game Boy Color hardware support. - Fast emulation. Known to run at full speed even on low end hardware, such as netbooks. - Qt and SDL ports for a heavy-weight and a light-weight frontend. @@ -18,6 +18,8 @@ - Save type detection, even for flash memory size[[2]](#flashdetect). - Support for cartridges with motion sensors and rumble (only usable with game controllers). - Real-time clock support, even without configuration. +- Solar sensor support for Boktai games. +- Game Boy Camera and Game Boy Printer support. - A built-in BIOS implementation, and ability to load external BIOS files. - Turbo/fast-forward support by holding Tab. - Rewind by holding Backquote. @@ -35,6 +37,28 @@ - Cores available for RetroArch/Libretro and OpenEmu. - Many, many smaller things. +#### Game Boy mappers + +The following mappers are fully supported: + +- MBC1 +- MBC1M +- MBC2 +- MBC3 +- MBC3+RTC +- MBC5 +- MBC5+Rumble +- MBC7 + +The following mappers are partially supported: + +- MBC6 +- MMM01 +- Pocket Cam +- TAMA5 +- HuC-1 +- HuC-3 + ### Planned features - Networked multiplayer link cable support. @@ -45,7 +69,6 @@ - A comprehensive debug suite. - e-Reader support. - Wireless adapter support. -- Game Boy Printer support. Supported Platforms ------------------- @@ -84,7 +107,31 @@ Compiling --------- -Compiling requires using CMake 2.8.11 or newer. GCC and Clang are both known to work to compile mGBA, but Visual Studio 2013 and older are known not to work. Support for Visual Studio 2015 and newer is coming soon. To use CMake to build on a Unix-based system, the recommended commands are as follows: +Compiling requires using CMake 3.1 or newer. GCC and Clang are both known to work to compile mGBA, but Visual Studio 2013 and older are known not to work. Support for Visual Studio 2015 and newer is coming soon. + +#### Docker building + +The recommended way to build for most platforms is to use Docker. Several Docker images are provided that contain the requisite toolchain and dependencies for building mGBA across several platforms. + +To use a Docker image to build mGBA, simply run the following command while in the root of an mGBA checkout: + + docker run --rm -t -v $PWD:/home/mgba/src mgba/windows:w32 + +This will produce a `build-win32` directory with the build products. Replace `mgba/windows:w32` with another Docker image for other platforms, which will produce a corresponding other directory. The following Docker images available on Docker Hub: + +- mgba/3ds +- mgba/switch +- mgba/ubuntu:xenial +- mgba/ubuntu:bionic +- mgba/ubuntu:cosmic +- mgba/vita +- mgba/wii +- mgba/windows:w32 +- mgba/windows:w64 + +#### *nix building + +To use CMake to build on a Unix-based system, the recommended commands are as follows: mkdir build cd build @@ -96,7 +143,7 @@ If you are on macOS, the steps are a little different. Assuming you are using the homebrew package manager, the recommended commands to obtain the dependencies and build are: - brew install cmake ffmpeg imagemagick libzip qt5 sdl2 libedit + brew install cmake ffmpeg imagemagick libzip qt5 sdl2 libedit pkg-config mkdir build cd build cmake -DCMAKE_PREFIX_PATH=`brew --prefix qt5` .. @@ -110,11 +157,11 @@ For x86 (32 bit) builds: - pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy --needed base-devel git mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} For x86_64 (64 bit) builds: - pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy --needed base-devel git mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} Check out the source code by running this command: @@ -130,6 +177,22 @@ Please note that this build of mGBA for Windows is not suitable for distribution, due to the scattering of DLLs it needs to run, but is perfect for development. However, if distributing such a build is desired (e.g. for testing on machines that don't have the MSYS2 environment installed), running `cpack -G ZIP` will prepare a zip file with all of the necessary DLLs. +#### Toolchain building + +If you have devkitARM (for 3DS), devkitPPC (for Wii), devkitA64 (for Switch), or vitasdk (for PS Vita), you can use the following commands for building: + + mkdir build + cd build + cmake -DCMAKE_TOOLCHAIN_FILE=../src/platform/3ds/CMakeToolchain.txt .. + make + +Replace the `-DCMAKE_TOOLCHAIN_FILE` parameter for the following platforms: + +- 3DS: `../src/platform/3ds/CMakeToolchain.txt` +- Switch: `../src/platform/switch/CMakeToolchain.txt` +- Vita: `../src/platform/psp2/CMakeToolchain.vitasdk` +- Wii: `../src/platform/wii/CMakeToolchain.txt` + ### Dependencies mGBA has no hard dependencies, however, the following optional dependencies are required for specific features. The features will be disabled if the dependencies can't be found. @@ -142,6 +205,7 @@ - libzip or zlib: for loading ROMs stored in zip files. - ImageMagick: for GIF recording. - SQLite3: for game databases. +- libelf: for ELF loading. SQLite3, libpng, and zlib are included with the emulator, so they do not need to be externally compiled first. @@ -163,7 +227,7 @@ Copyright --------- -mGBA is Copyright © 2013 – 2018 Jeffrey Pfau. It is distributed under the [Mozilla Public License version 2.0](https://www.mozilla.org/MPL/2.0/). A copy of the license is available in the distributed LICENSE file. +mGBA is Copyright © 2013 – 2019 Jeffrey Pfau. It is distributed under the [Mozilla Public License version 2.0](https://www.mozilla.org/MPL/2.0/). A copy of the license is available in the distributed LICENSE file. mGBA contains the following third-party libraries: Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/res/font-new.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/res/font-new.png differ diff -Nru mgba-0.6.3+dfsg1/res/licenses/blip_buf.txt mgba-0.7.0/res/licenses/blip_buf.txt --- mgba-0.6.3+dfsg1/res/licenses/blip_buf.txt 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/res/licenses/blip_buf.txt 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff -Nru mgba-0.6.3+dfsg1/res/licenses/inih.txt mgba-0.7.0/res/licenses/inih.txt --- mgba-0.6.3+dfsg1/res/licenses/inih.txt 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/res/licenses/inih.txt 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,27 @@ + +The "inih" library is distributed under the New BSD license: + +Copyright (c) 2009, Ben Hoyt +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Ben Hoyt nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY BEN HOYT ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BEN HOYT BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/res/no-cam.png and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/res/no-cam.png differ diff -Nru mgba-0.6.3+dfsg1/res/patrons.txt mgba-0.7.0/res/patrons.txt --- mgba-0.6.3+dfsg1/res/patrons.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/res/patrons.txt 2019-01-27 00:06:06.000000000 +0000 @@ -1,7 +1,8 @@ +Elijah Chondropoulos Jaime J. Denizard Fog Philip Horton +Oskenso Kashi Rohit Nirmal Rhys Powell -rootfather Yuri Kunde Schlesner diff -Nru mgba-0.6.3+dfsg1/res/shaders/agb001.shader/agb001.fs mgba-0.7.0/res/shaders/agb001.shader/agb001.fs --- mgba-0.6.3+dfsg1/res/shaders/agb001.shader/agb001.fs 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/res/shaders/agb001.shader/agb001.fs 2019-01-27 00:06:06.000000000 +0000 @@ -4,18 +4,17 @@ void main() { vec4 color = texture2D(tex, texCoord); - vec3 arrayX[4]; - arrayX[0] = vec3(1.0, 0.2, 0.2); + vec3 arrayX[3]; + arrayX[0] = vec3(0.2, 0.2, 1.0); arrayX[1] = vec3(0.2, 1.0, 0.2); - arrayX[2] = vec3(0.2, 0.2, 1.0); - arrayX[3] = vec3(0.4, 0.4, 0.4); + arrayX[2] = vec3(1.0, 0.2, 0.2); vec3 arrayY[4]; arrayY[0] = vec3(1.0, 1.0, 1.0); arrayY[1] = vec3(1.0, 1.0, 1.0); arrayY[2] = vec3(1.0, 1.0, 1.0); arrayY[3] = vec3(0.8, 0.8, 0.8); color.rgb = pow(color.rgb * vec3(0.8, 0.8, 0.8), vec3(1.8, 1.8, 1.8)) + vec3(0.16, 0.16, 0.16); - color.rgb *= arrayX[int(mod(texCoord.s * texSize.x * 4.0, 4.0))]; + color.rgb *= arrayX[int(mod(texCoord.s * texSize.x * 3.0, 3.0))]; color.rgb *= arrayY[int(mod(texCoord.t * texSize.y * 4.0, 4.0))]; color.a = 0.5; gl_FragColor = color; diff -Nru mgba-0.6.3+dfsg1/res/shaders/agb001.shader/manifest.ini mgba-0.7.0/res/shaders/agb001.shader/manifest.ini --- mgba-0.6.3+dfsg1/res/shaders/agb001.shader/manifest.ini 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/res/shaders/agb001.shader/manifest.ini 2019-01-27 00:06:06.000000000 +0000 @@ -7,5 +7,5 @@ [pass.0] fragmentShader=agb001.fs blend=1 -width=-4 +width=-3 height=-4 diff -Nru mgba-0.6.3+dfsg1/res/shaders/ags001.shader/ags001.fs mgba-0.7.0/res/shaders/ags001.shader/ags001.fs --- mgba-0.6.3+dfsg1/res/shaders/ags001.shader/ags001.fs 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/res/shaders/ags001.shader/ags001.fs 2019-01-27 00:06:06.000000000 +0000 @@ -4,18 +4,17 @@ void main() { vec4 color = texture2D(tex, texCoord); - vec3 arrayX[4]; - arrayX[0] = vec3(1.0, 0.2, 0.2); + vec3 arrayX[3]; + arrayX[0] = vec3(0.2, 0.2, 1.0); arrayX[1] = vec3(0.2, 1.0, 0.2); - arrayX[2] = vec3(0.2, 0.2, 1.0); - arrayX[3] = vec3(0.4, 0.4, 0.4); + arrayX[2] = vec3(1.0, 0.2, 0.2); vec3 arrayY[4]; arrayY[0] = vec3(1.0, 1.0, 1.0); arrayY[1] = vec3(1.0, 1.0, 1.0); arrayY[2] = vec3(1.0, 1.0, 1.0); arrayY[3] = vec3(0.9, 0.9, 0.9); color.rgb = pow(color.rgb, vec3(1.6, 1.6, 1.6)); - color.rgb *= arrayX[int(mod(texCoord.s * texSize.x * 4.0, 4.0))]; + color.rgb *= arrayX[int(mod(texCoord.s * texSize.x * 3.0, 3.0))]; color.rgb *= arrayY[int(mod(texCoord.t * texSize.y * 4.0, 4.0))]; color.a = 0.8; gl_FragColor = color; diff -Nru mgba-0.6.3+dfsg1/res/shaders/ags001.shader/manifest.ini mgba-0.7.0/res/shaders/ags001.shader/manifest.ini --- mgba-0.6.3+dfsg1/res/shaders/ags001.shader/manifest.ini 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/res/shaders/ags001.shader/manifest.ini 2019-01-27 00:06:06.000000000 +0000 @@ -7,12 +7,12 @@ [pass.0] fragmentShader=ags001.fs blend=1 -width=-4 +width=-3 height=-4 [pass.1] fragmentShader=ags001-light.fs -width=-4 +width=-3 height=-4 [pass.1.uniform.lightBrightness] diff -Nru mgba-0.6.3+dfsg1/src/arm/debugger/cli-debugger.c mgba-0.7.0/src/arm/debugger/cli-debugger.c --- mgba-0.6.3+dfsg1/src/arm/debugger/cli-debugger.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/arm/debugger/cli-debugger.c 2019-01-27 00:06:06.000000000 +0000 @@ -17,23 +17,21 @@ static void _disassembleThumb(struct CLIDebugger*, struct CLIDebugVector*); static void _setBreakpointARM(struct CLIDebugger*, struct CLIDebugVector*); static void _setBreakpointThumb(struct CLIDebugger*, struct CLIDebugVector*); -static void _writeRegister(struct CLIDebugger*, struct CLIDebugVector*); static void _disassembleMode(struct CLIDebugger*, struct CLIDebugVector*, enum ExecutionMode mode); static uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode); static struct CLIDebuggerCommandSummary _armCommands[] = { - { "b/a", _setBreakpointARM, CLIDVParse, "Set a software breakpoint as ARM" }, - { "b/t", _setBreakpointThumb, CLIDVParse, "Set a software breakpoint as Thumb" }, - { "break/a", _setBreakpointARM, CLIDVParse, "Set a software breakpoint as ARM" }, - { "break/t", _setBreakpointThumb, CLIDVParse, "Set a software breakpoint as Thumb" }, - { "dis/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" }, - { "dis/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" }, - { "disasm/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" }, - { "disasm/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" }, - { "disassemble/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" }, - { "disassemble/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" }, - { "w/r", _writeRegister, CLIDVParse, "Write a register" }, + { "b/a", _setBreakpointARM, "I", "Set a software breakpoint as ARM" }, + { "b/t", _setBreakpointThumb, "I", "Set a software breakpoint as Thumb" }, + { "break/a", _setBreakpointARM, "I", "Set a software breakpoint as ARM" }, + { "break/t", _setBreakpointThumb, "I", "Set a software breakpoint as Thumb" }, + { "dis/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" }, + { "dis/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" }, + { "disasm/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" }, + { "disasm/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" }, + { "disassemble/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" }, + { "disassemble/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" }, { 0, 0, 0, 0 } }; @@ -95,7 +93,7 @@ static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) { struct CLIDebuggerBackend* be = debugger->backend; - char disassembly[48]; + char disassembly[64]; struct ARMInstructionInfo info; be->printf(be, "%08X: ", address); if (mode == MODE_ARM) { @@ -127,13 +125,14 @@ struct CLIDebuggerBackend* be = debugger->p->backend; struct ARMCore* cpu = debugger->p->d.core->cpu; int r; - for (r = 0; r < 4; ++r) { - be->printf(be, "%08X %08X %08X %08X\n", - cpu->gprs[r << 2], - cpu->gprs[(r << 2) + 1], - cpu->gprs[(r << 2) + 2], - cpu->gprs[(r << 2) + 3]); + for (r = 0; r < 16; r += 4) { + be->printf(be, "%sr%i: %08X %sr%i: %08X %sr%i: %08X %sr%i: %08X\n", + r < 10 ? " " : "", r, cpu->gprs[r], + r < 9 ? " " : "", r + 1, cpu->gprs[r + 1], + r < 8 ? " " : "", r + 2, cpu->gprs[r + 2], + r < 7 ? " " : "", r + 3, cpu->gprs[r + 3]); } + be->printf(be, "cpsr: "); _printPSR(be, cpu->cpsr); int instructionLength; enum ExecutionMode mode = cpu->cpsr.t; @@ -145,25 +144,6 @@ _printLine(debugger->p, cpu->gprs[ARM_PC] - instructionLength, mode); } -static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - struct CLIDebuggerBackend* be = debugger->backend; - struct ARMCore* cpu = debugger->d.core->cpu; - if (!dv || dv->type != CLIDV_INT_TYPE) { - be->printf(be, "%s\n", ERROR_MISSING_ARGS); - return; - } - if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - be->printf(be, "%s\n", ERROR_MISSING_ARGS); - return; - } - uint32_t regid = dv->intValue; - uint32_t value = dv->next->intValue; - if (regid >= ARM_PC) { - return; - } - cpu->gprs[regid] = value; -} - static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) { @@ -184,38 +164,9 @@ ARMDebuggerSetSoftwareBreakpoint(debugger->d.platform, address, MODE_THUMB); } -static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) { - struct ARMCore* cpu = debugger->p->d.core->cpu; - if (strcmp(name, "sp") == 0) { - return cpu->gprs[ARM_SP]; - } - if (strcmp(name, "lr") == 0) { - return cpu->gprs[ARM_LR]; - } - if (strcmp(name, "pc") == 0) { - return cpu->gprs[ARM_PC]; - } - if (strcmp(name, "cpsr") == 0) { - return cpu->cpsr.packed; - } - // TODO: test if mode has SPSR - if (strcmp(name, "spsr") == 0) { - return cpu->spsr.packed; - } - if (name[0] == 'r' && name[1] >= '0' && name[1] <= '9') { - int reg = atoi(&name[1]); - if (reg < 16) { - return cpu->gprs[reg]; - } - } - dv->type = CLIDV_ERROR_TYPE; - return 0; -} - void ARMCLIDebuggerCreate(struct CLIDebuggerSystem* debugger) { debugger->printStatus = _printStatus; debugger->disassemble = _disassemble; - debugger->lookupPlatformIdentifier = _lookupPlatformIdentifier; debugger->platformName = "ARM"; debugger->platformCommands = _armCommands; } diff -Nru mgba-0.6.3+dfsg1/src/arm/debugger/debugger.c mgba-0.7.0/src/arm/debugger/debugger.c --- mgba-0.6.3+dfsg1/src/arm/debugger/debugger.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/arm/debugger/debugger.c 2019-01-27 00:06:06.000000000 +0000 @@ -10,6 +10,7 @@ #include #include #include +#include DEFINE_VECTOR(ARMDebugBreakpointList, struct ARMDebugBreakpoint); DEFINE_VECTOR(ARMDebugWatchpointList, struct ARMDebugWatchpoint); @@ -24,6 +25,20 @@ return 0; } +static void _destroyBreakpoint(struct ARMDebugBreakpoint* breakpoint) { + if (breakpoint->condition) { + parseFree(breakpoint->condition); + free(breakpoint->condition); + } +} + +static void _destroyWatchpoint(struct ARMDebugWatchpoint* watchpoint) { + if (watchpoint->condition) { + parseFree(watchpoint->condition); + free(watchpoint->condition); + } +} + static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform* d) { struct ARMDebugger* debugger = (struct ARMDebugger*) d; int instructionLength; @@ -37,6 +52,13 @@ if (!breakpoint) { return; } + if (breakpoint->condition) { + int32_t value; + int segment; + if (!mDebuggerEvaluateParseTree(d->p, breakpoint->condition, &value, &segment) || !(value || segment >= 0)) { + return; + } + } struct mDebuggerEntryInfo info = { .address = breakpoint->address, .type.bp.breakType = BREAKPOINT_HARDWARE @@ -50,12 +72,16 @@ static void ARMDebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info); static void ARMDebuggerSetBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment); +static void ARMDebuggerSetConditionalBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment, struct ParseTree* condition); static void ARMDebuggerClearBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment); static void ARMDebuggerSetWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment, enum mWatchpointType type); +static void ARMDebuggerSetConditionalWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment, enum mWatchpointType type, struct ParseTree* condition); static void ARMDebuggerClearWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment); static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform*); static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform*); static void ARMDebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length); +static bool ARMDebuggerGetRegister(struct mDebuggerPlatform*, const char* name, int32_t* value); +static bool ARMDebuggerSetRegister(struct mDebuggerPlatform*, const char* name, int32_t value); struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) { struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct ARMDebugger)); @@ -63,12 +89,16 @@ platform->init = ARMDebuggerInit; platform->deinit = ARMDebuggerDeinit; platform->setBreakpoint = ARMDebuggerSetBreakpoint; + platform->setConditionalBreakpoint = ARMDebuggerSetConditionalBreakpoint; platform->clearBreakpoint = ARMDebuggerClearBreakpoint; platform->setWatchpoint = ARMDebuggerSetWatchpoint; + platform->setConditionalWatchpoint = ARMDebuggerSetConditionalWatchpoint; platform->clearWatchpoint = ARMDebuggerClearWatchpoint; platform->checkBreakpoints = ARMDebuggerCheckBreakpoints; platform->hasBreakpoints = ARMDebuggerHasBreakpoints; platform->trace = ARMDebuggerTrace; + platform->getRegister = ARMDebuggerGetRegister; + platform->setRegister = ARMDebuggerSetRegister; return platform; } @@ -93,7 +123,15 @@ } ARMDebuggerRemoveMemoryShim(debugger); + size_t i; + for (i = 0; i < ARMDebugBreakpointListSize(&debugger->breakpoints); ++i) { + _destroyBreakpoint(ARMDebugBreakpointListGetPointer(&debugger->breakpoints, i)); + } ARMDebugBreakpointListDeinit(&debugger->breakpoints); + + for (i = 0; i < ARMDebugWatchpointListSize(&debugger->watchpoints); ++i) { + _destroyWatchpoint(ARMDebugWatchpointListGetPointer(&debugger->watchpoints, i)); + } ARMDebugBreakpointListDeinit(&debugger->swBreakpoints); ARMDebugWatchpointListDeinit(&debugger->watchpoints); } @@ -161,9 +199,14 @@ } static void ARMDebuggerSetBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) { + ARMDebuggerSetConditionalBreakpoint(d, address, segment, NULL); +} + +static void ARMDebuggerSetConditionalBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment, struct ParseTree* condition) { UNUSED(segment); struct ARMDebugger* debugger = (struct ARMDebugger*) d; struct ARMDebugBreakpoint* breakpoint = ARMDebugBreakpointListAppend(&debugger->breakpoints); + breakpoint->condition = condition; breakpoint->address = address; breakpoint->isSw = false; } @@ -175,6 +218,7 @@ size_t i; for (i = 0; i < ARMDebugBreakpointListSize(breakpoints); ++i) { if (ARMDebugBreakpointListGetPointer(breakpoints, i)->address == address) { + _destroyBreakpoint(ARMDebugBreakpointListGetPointer(breakpoints, i)); ARMDebugBreakpointListShift(breakpoints, i, 1); } } @@ -186,6 +230,10 @@ } static void ARMDebuggerSetWatchpoint(struct mDebuggerPlatform* d, uint32_t address, int segment, enum mWatchpointType type) { + ARMDebuggerSetConditionalWatchpoint(d, address, segment, type, NULL); +} + +static void ARMDebuggerSetConditionalWatchpoint(struct mDebuggerPlatform* d, uint32_t address, int segment, enum mWatchpointType type, struct ParseTree* condition) { UNUSED(segment); struct ARMDebugger* debugger = (struct ARMDebugger*) d; if (!ARMDebugWatchpointListSize(&debugger->watchpoints)) { @@ -194,6 +242,7 @@ struct ARMDebugWatchpoint* watchpoint = ARMDebugWatchpointListAppend(&debugger->watchpoints); watchpoint->address = address; watchpoint->type = type; + watchpoint->condition = condition; } static void ARMDebuggerClearWatchpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) { @@ -203,6 +252,7 @@ size_t i; for (i = 0; i < ARMDebugWatchpointListSize(watchpoints); ++i) { if (ARMDebugWatchpointListGetPointer(watchpoints, i)->address == address) { + _destroyWatchpoint(ARMDebugWatchpointListGetPointer(watchpoints, i)); ARMDebugWatchpointListShift(watchpoints, i, 1); } } @@ -246,3 +296,81 @@ cpu->gprs[12], cpu->gprs[13], cpu->gprs[14], cpu->gprs[15], cpu->cpsr.packed, disassembly); } + +bool ARMDebuggerGetRegister(struct mDebuggerPlatform* d, const char* name, int32_t* value) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + struct ARMCore* cpu = debugger->cpu; + + if (strcmp(name, "sp") == 0) { + *value = cpu->gprs[ARM_SP]; + return true; + } + if (strcmp(name, "lr") == 0) { + *value = cpu->gprs[ARM_LR]; + return true; + } + if (strcmp(name, "pc") == 0) { + *value = cpu->gprs[ARM_PC]; + return true; + } + if (strcmp(name, "cpsr") == 0) { + *value = cpu->cpsr.packed; + return true; + } + // TODO: test if mode has SPSR + if (strcmp(name, "spsr") == 0) { + *value = cpu->spsr.packed; + return true; + } + if (name[0] == 'r') { + char* end; + uint32_t reg = strtoul(&name[1], &end, 10); + if (reg <= ARM_PC) { + *value = cpu->gprs[reg]; + return true; + } + } + return false; +} + +bool ARMDebuggerSetRegister(struct mDebuggerPlatform* d, const char* name, int32_t value) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + struct ARMCore* cpu = debugger->cpu; + + if (strcmp(name, "sp") == 0) { + cpu->gprs[ARM_SP] = value; + return true; + } + if (strcmp(name, "lr") == 0) { + cpu->gprs[ARM_LR] = value; + return true; + } + if (strcmp(name, "pc") == 0) { + cpu->gprs[ARM_PC] = value; + int32_t currentCycles = 0; + if (cpu->executionMode == MODE_ARM) { + ARM_WRITE_PC; + } else { + THUMB_WRITE_PC; + } + return true; + } + if (name[0] == 'r') { + char* end; + uint32_t reg = strtoul(&name[1], &end, 10); + if (reg > ARM_PC) { + return false; + } + cpu->gprs[reg] = value; + if (reg == ARM_PC) { + int32_t currentCycles = 0; + if (cpu->executionMode == MODE_ARM) { + ARM_WRITE_PC; + } else { + THUMB_WRITE_PC; + } + } + return true; + } + return false; +} diff -Nru mgba-0.6.3+dfsg1/src/arm/debugger/memory-debugger.c mgba-0.7.0/src/arm/debugger/memory-debugger.c --- mgba-0.6.3+dfsg1/src/arm/debugger/memory-debugger.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/arm/debugger/memory-debugger.c 2019-01-27 00:06:06.000000000 +0000 @@ -6,6 +6,7 @@ #include #include +#include #include @@ -97,6 +98,14 @@ for (i = 0; i < ARMDebugWatchpointListSize(&debugger->watchpoints); ++i) { watchpoint = ARMDebugWatchpointListGetPointer(&debugger->watchpoints, i); if (!((watchpoint->address ^ address) & ~width) && watchpoint->type & type) { + if (watchpoint->condition) { + int32_t value; + int segment; + if (!mDebuggerEvaluateParseTree(debugger->d.p, watchpoint->condition, &value, &segment) || !(value || segment >= 0)) { + return false; + } + } + switch (width + 1) { case 1: info->type.wp.oldValue = debugger->originalMemory.load8(debugger->cpu, address, 0); diff -Nru mgba-0.6.3+dfsg1/src/arm/decoder.c mgba-0.7.0/src/arm/decoder.c --- mgba-0.6.3+dfsg1/src/arm/decoder.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/arm/decoder.c 2019-01-27 00:06:06.000000000 +0000 @@ -8,7 +8,7 @@ #include #define ADVANCE(AMOUNT) \ - if (AMOUNT > blen) { \ + if (AMOUNT >= blen) { \ buffer[blen - 1] = '\0'; \ return total; \ } \ diff -Nru mgba-0.6.3+dfsg1/src/arm/isa-arm.c mgba-0.7.0/src/arm/isa-arm.c --- mgba-0.6.3+dfsg1/src/arm/isa-arm.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/arm/isa-arm.c 2019-01-27 00:06:06.000000000 +0000 @@ -184,15 +184,32 @@ // Instruction definitions // Beware pre-processor antics +ATTRIBUTE_NOINLINE static void _additionS(struct ARMCore* cpu, int32_t m, int32_t n, int32_t d) { + cpu->cpsr.n = ARM_SIGN(d); + cpu->cpsr.z = !d; + cpu->cpsr.c = ARM_CARRY_FROM(m, n, d); + cpu->cpsr.v = ARM_V_ADDITION(m, n, d); +} + +ATTRIBUTE_NOINLINE static void _subtractionS(struct ARMCore* cpu, int32_t m, int32_t n, int32_t d) { + cpu->cpsr.n = ARM_SIGN(d); + cpu->cpsr.z = !d; + cpu->cpsr.c = ARM_BORROW_FROM(m, n, d); + cpu->cpsr.v = ARM_V_SUBTRACTION(m, n, d); +} + +ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) { + cpu->cpsr.n = ARM_SIGN(d); + cpu->cpsr.z = !d; \ + cpu->cpsr.c = cpu->shifterCarryOut; \ +} + #define ARM_ADDITION_S(M, N, D) \ if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ cpu->cpsr = cpu->spsr; \ _ARMReadCPSR(cpu); \ } else { \ - cpu->cpsr.n = ARM_SIGN(D); \ - cpu->cpsr.z = !(D); \ - cpu->cpsr.c = ARM_CARRY_FROM(M, N, D); \ - cpu->cpsr.v = ARM_V_ADDITION(M, N, D); \ + _additionS(cpu, M, N, D); \ } #define ARM_SUBTRACTION_S(M, N, D) \ @@ -200,10 +217,7 @@ cpu->cpsr = cpu->spsr; \ _ARMReadCPSR(cpu); \ } else { \ - cpu->cpsr.n = ARM_SIGN(D); \ - cpu->cpsr.z = !(D); \ - cpu->cpsr.c = ARM_BORROW_FROM(M, N, D); \ - cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); \ + _subtractionS(cpu, M, N, D); \ } #define ARM_SUBTRACTION_CARRY_S(M, N, D, C) \ @@ -222,9 +236,7 @@ cpu->cpsr = cpu->spsr; \ _ARMReadCPSR(cpu); \ } else { \ - cpu->cpsr.n = ARM_SIGN(D); \ - cpu->cpsr.z = !(D); \ - cpu->cpsr.c = cpu->shifterCarryOut; \ + _neutralS(cpu, D); \ } #define ARM_NEUTRAL_HI_S(DLO, DHI) \ @@ -663,8 +675,9 @@ } _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); @@ -704,8 +717,9 @@ } _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 -Nru mgba-0.6.3+dfsg1/src/core/cache-set.c mgba-0.7.0/src/core/cache-set.c --- mgba-0.6.3+dfsg1/src/core/cache-set.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/core/cache-set.c 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/src/core/cheats.c mgba-0.7.0/src/core/cheats.c --- mgba-0.6.3+dfsg1/src/core/cheats.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/cheats.c 2019-01-27 00:06:06.000000000 +0000 @@ -51,6 +51,8 @@ device->d.id = M_CHEAT_DEVICE_ID; device->d.init = mCheatDeviceInit; device->d.deinit = mCheatDeviceDeinit; + device->autosave = false; + device->buttonDown = false; mCheatSetsInit(&device->cheats, 4); } @@ -252,6 +254,20 @@ return true; } +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +void mCheatAutosave(struct mCheatDevice* device) { + if (!device->autosave) { + return; + } + struct VFile* vf = mDirectorySetOpenSuffix(&device->p->dirs, device->p->dirs.cheats, ".cheats", O_WRONLY | O_CREAT | O_TRUNC); + if (!vf) { + return; + } + mCheatSaveFile(device, vf); + vf->close(vf); +} +#endif + void mCheatRefresh(struct mCheatDevice* device, struct mCheatSet* cheats) { cheats->refresh(cheats, device); if (!cheats->enabled) { @@ -350,6 +366,12 @@ negativeConditionRemaining = cheat->negativeRepeat; operationsRemaining = 1; break; + case CHEAT_IF_BUTTON: + condition = device->buttonDown; + conditionRemaining = cheat->repeat; + negativeConditionRemaining = cheat->negativeRepeat; + operationsRemaining = 1; + break; } if (performAssignment) { @@ -374,6 +396,10 @@ } } +void mCheatPressButton(struct mCheatDevice* device, bool down) { + device->buttonDown = down; +} + void mCheatDeviceInit(void* cpu, struct mCPUComponent* component) { UNUSED(cpu); struct mCheatDevice* device = (struct mCheatDevice*) component; diff -Nru mgba-0.6.3+dfsg1/src/core/config.c mgba-0.7.0/src/core/config.c --- mgba-0.6.3+dfsg1/src/core/config.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/config.c 2019-01-27 00:06:06.000000000 +0000 @@ -179,7 +179,7 @@ WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, MAX_PATH, 0, 0); StringCchCatA(out, MAX_PATH, "\\portable.ini"); portable = VFileOpen(out, O_WRONLY | O_CREAT); -#elif defined(PSP2) || defined(_3DS) || defined(GEKKO) +#elif defined(PSP2) || defined(_3DS) || defined(__SWITCH__) || defined(GEKKO) // Already portable #else char out[PATH_MAX]; @@ -219,7 +219,7 @@ UNUSED(portable); snprintf(out, outLength, "ux0:data/%s", projectName); sceIoMkdir(out, 0777); -#elif defined(GEKKO) +#elif defined(GEKKO) || defined(__SWITCH__) UNUSED(portable); snprintf(out, outLength, "/%s", projectName); mkdir(out, 0777); @@ -331,7 +331,6 @@ _lookupIntValue(config, "frameskip", &opts->frameskip); _lookupIntValue(config, "volume", &opts->volume); _lookupIntValue(config, "rewindBufferCapacity", &opts->rewindBufferCapacity); - _lookupIntValue(config, "rewindSave", &opts->rewindSave); _lookupFloatValue(config, "fpsTarget", &opts->fpsTarget); unsigned audioBuffers; if (_lookupUIntValue(config, "audioBuffers", &audioBuffers)) { @@ -379,6 +378,7 @@ _lookupCharValue(config, "savestatePath", &opts->savestatePath); _lookupCharValue(config, "screenshotPath", &opts->screenshotPath); _lookupCharValue(config, "patchPath", &opts->patchPath); + _lookupCharValue(config, "cheatsPath", &opts->cheatsPath); } void mCoreConfigLoadDefaults(struct mCoreConfig* config, const struct mCoreOptions* opts) { @@ -390,7 +390,6 @@ ConfigurationSetIntValue(&config->defaultsTable, 0, "frameskip", opts->frameskip); ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindEnable", opts->rewindEnable); ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferCapacity", opts->rewindBufferCapacity); - ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindSave", opts->rewindSave); ConfigurationSetFloatValue(&config->defaultsTable, 0, "fpsTarget", opts->fpsTarget); ConfigurationSetUIntValue(&config->defaultsTable, 0, "audioBuffers", opts->audioBuffers); ConfigurationSetUIntValue(&config->defaultsTable, 0, "sampleRate", opts->sampleRate); @@ -443,10 +442,12 @@ free(opts->savestatePath); free(opts->screenshotPath); free(opts->patchPath); + free(opts->cheatsPath); opts->bios = 0; opts->shader = 0; opts->savegamePath = 0; opts->savestatePath = 0; opts->screenshotPath = 0; opts->patchPath = 0; + opts->cheatsPath = 0; } diff -Nru mgba-0.6.3+dfsg1/src/core/core.c mgba-0.7.0/src/core/core.c --- mgba-0.6.3+dfsg1/src/core/core.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/core.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,9 +5,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include #include #include +#include + +#ifdef USE_ELF +#include +#endif #ifdef M_CORE_GB #include @@ -160,6 +166,24 @@ core->loadPatch(core, mDirectorySetOpenSuffix(&core->dirs, core->dirs.patch, ".bps", O_RDONLY)); } +bool mCoreAutoloadCheats(struct mCore* core) { + bool success = true; + int cheatAuto; + if (!mCoreConfigGetIntValue(&core->config, "cheatAutoload", &cheatAuto) || cheatAuto) { + struct VFile* vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.cheats, ".cheats", O_RDONLY); + if (vf) { + struct mCheatDevice* device = core->cheatDevice(core); + success = mCheatParseFile(device, vf); + vf->close(vf); + } + } + if (!mCoreConfigGetIntValue(&core->config, "cheatAutosave", &cheatAuto) || cheatAuto) { + struct mCheatDevice* device = core->cheatDevice(core); + device->autosave = true; + } + return success; +} + bool mCoreSaveState(struct mCore* core, int slot, int flags) { struct VFile* vf = mCoreGetState(core, slot, true); if (!vf) { @@ -266,6 +290,10 @@ if (core->opts.audioBuffers) { core->setAudioBufferSize(core, core->opts.audioBuffers); } + + mCoreConfigCopyValue(&core->config, config, "cheatAutosave"); + mCoreConfigCopyValue(&core->config, config, "cheatAutoload"); + core->loadConfig(core, config); } @@ -273,3 +301,68 @@ core->rtc.custom = rtc; core->rtc.override = RTC_CUSTOM_START; } + +void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size) { + const struct mCoreMemoryBlock* blocks; + size_t nBlocks = core->listMemoryBlocks(core, &blocks); + size_t i; + for (i = 0; i < nBlocks; ++i) { + if (!(blocks[i].flags & mCORE_MEMORY_MAPPED)) { + continue; + } + if (start < blocks[i].start) { + continue; + } + if (start >= blocks[i].start + blocks[i].size) { + continue; + } + uint8_t* out = core->getMemoryBlock(core, blocks[i].id, size); + out += start - blocks[i].start; + *size -= start - blocks[i].start; + return out; + } + return NULL; +} + +#ifdef USE_ELF +bool mCoreLoadELF(struct mCore* core, struct ELF* elf) { + struct ELFProgramHeaders ph; + ELFProgramHeadersInit(&ph, 0); + ELFGetProgramHeaders(elf, &ph); + size_t i; + for (i = 0; i < ELFProgramHeadersSize(&ph); ++i) { + size_t bsize, esize; + Elf32_Phdr* phdr = ELFProgramHeadersGetPointer(&ph, i); + void* block = mCoreGetMemoryBlock(core, phdr->p_paddr, &bsize); + char* bytes = ELFBytes(elf, &esize); + if (block && bsize >= phdr->p_filesz && esize >= phdr->p_filesz + phdr->p_offset) { + memcpy(block, &bytes[phdr->p_offset], phdr->p_filesz); + } else { + return false; + } + } + return true; +} + +#ifdef USE_DEBUGGERS +void mCoreLoadELFSymbols(struct mDebuggerSymbols* symbols, struct ELF* elf) { + size_t symIndex = ELFFindSection(elf, ".symtab"); + size_t names = ELFFindSection(elf, ".strtab"); + Elf32_Shdr* symHeader = ELFGetSectionHeader(elf, symIndex); + char* bytes = ELFBytes(elf, NULL); + + Elf32_Sym* syms = (Elf32_Sym*) &bytes[symHeader->sh_offset]; + size_t i; + for (i = 0; i * sizeof(*syms) < symHeader->sh_size; ++i) { + if (!syms[i].st_name || ELF32_ST_TYPE(syms[i].st_info) == STT_FILE) { + continue; + } + const char* name = ELFGetString(elf, names, syms[i].st_name); + if (name[0] == '$') { + continue; + } + mDebuggerSymbolAdd(symbols, name, syms[i].st_value, -1); + } +} +#endif +#endif diff -Nru mgba-0.6.3+dfsg1/src/core/directories.c mgba-0.7.0/src/core/directories.c --- mgba-0.6.3+dfsg1/src/core/directories.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/directories.c 2019-01-27 00:06:06.000000000 +0000 @@ -16,6 +16,7 @@ dirs->patch = 0; dirs->state = 0; dirs->screenshot = 0; + dirs->cheats = 0; } void mDirectorySetDeinit(struct mDirectorySet* dirs) { @@ -34,6 +35,9 @@ if (dirs->archive == dirs->screenshot) { dirs->screenshot = NULL; } + if (dirs->archive == dirs->cheats) { + dirs->cheats = NULL; + } dirs->archive->close(dirs->archive); dirs->archive = NULL; } @@ -48,6 +52,9 @@ if (dirs->save == dirs->screenshot) { dirs->screenshot = NULL; } + if (dirs->save == dirs->cheats) { + dirs->cheats = NULL; + } dirs->save->close(dirs->save); dirs->save = NULL; } @@ -59,6 +66,9 @@ if (dirs->patch == dirs->screenshot) { dirs->screenshot = NULL; } + if (dirs->patch == dirs->cheats) { + dirs->cheats = NULL; + } dirs->patch->close(dirs->patch); dirs->patch = NULL; } @@ -67,14 +77,25 @@ if (dirs->state == dirs->screenshot) { dirs->state = NULL; } + if (dirs->state == dirs->cheats) { + dirs->cheats = NULL; + } dirs->state->close(dirs->state); dirs->state = NULL; } if (dirs->screenshot) { + if (dirs->screenshot == dirs->cheats) { + dirs->cheats = NULL; + } dirs->screenshot->close(dirs->screenshot); dirs->screenshot = NULL; } + + if (dirs->cheats) { + dirs->cheats->close(dirs->cheats); + dirs->cheats = NULL; + } } void mDirectorySetAttachBase(struct mDirectorySet* dirs, struct VDir* base) { @@ -91,6 +112,9 @@ if (!dirs->screenshot) { dirs->screenshot = dirs->base; } + if (!dirs->cheats) { + dirs->cheats = dirs->base; + } } void mDirectorySetDetachBase(struct mDirectorySet* dirs) { @@ -106,6 +130,9 @@ if (dirs->screenshot == dirs->base) { dirs->screenshot = NULL; } + if (dirs->cheats == dirs->base) { + dirs->cheats = NULL; + } if (dirs->base) { dirs->base->close(dirs->base); @@ -183,5 +210,15 @@ dirs->patch = dir; } } + + if (opts->cheatsPath) { + struct VDir* dir = VDirOpen(opts->cheatsPath); + if (dir) { + if (dirs->cheats && dirs->cheats != dirs->base) { + dirs->cheats->close(dirs->cheats); + } + dirs->cheats = dir; + } + } } #endif diff -Nru mgba-0.6.3+dfsg1/src/core/flags.h.in mgba-0.7.0/src/core/flags.h.in --- mgba-0.6.3+dfsg1/src/core/flags.h.in 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/flags.h.in 2019-01-27 00:06:06.000000000 +0000 @@ -15,7 +15,7 @@ #cmakedefine BUILD_GLES2 #endif -// COLOR flags +// Miscellaneous flags #ifndef COLOR_16_BIT #cmakedefine COLOR_16_BIT @@ -25,6 +25,14 @@ #cmakedefine COLOR_5_6_5 #endif +#ifndef DISABLE_THREADING +#cmakedefine DISABLE_THREADING +#endif + +#ifndef FIXED_ROM_BUFFER +#cmakedefine FIXED_ROM_BUFFER +#endif + // M_CORE flags #ifndef M_CORE_GBA @@ -35,9 +43,13 @@ #cmakedefine M_CORE_GB #endif -// USE flags +// ENABLE flags + +#ifndef ENABLE_SCRIPTING +#cmakedefine ENABLE_SCRIPTING +#endif -#ifndef MINIMAL_CORE +// USE flags #ifndef USE_DEBUGGERS #cmakedefine USE_DEBUGGERS @@ -47,6 +59,10 @@ #cmakedefine USE_EDITLINE #endif +#ifndef USE_ELF +#cmakedefine USE_ELF +#endif + #ifndef USE_EPOXY #cmakedefine USE_EPOXY #endif @@ -63,6 +79,14 @@ #cmakedefine USE_LIBAV #endif +#ifndef USE_LIBAVRESAMPLE +#cmakedefine USE_LIBAVRESAMPLE +#endif + +#ifndef USE_LIBSWRESAMPLE +#cmakedefine USE_LIBSWRESAMPLE +#endif + #ifndef USE_LIBZIP #cmakedefine USE_LIBZIP #endif @@ -96,5 +120,3 @@ #endif #endif - -#endif diff -Nru mgba-0.6.3+dfsg1/src/core/input.c mgba-0.7.0/src/core/input.c --- mgba-0.6.3+dfsg1/src/core/input.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/input.c 2019-01-27 00:06:06.000000000 +0000 @@ -11,7 +11,7 @@ #include -#define SECTION_NAME_MAX 50 +#define SECTION_NAME_MAX 128 #define KEY_NAME_MAX 32 #define KEY_VALUE_MAX 16 #define AXIS_INFO_MAX 12 diff -Nru mgba-0.6.3+dfsg1/src/core/library.c mgba-0.7.0/src/core/library.c --- mgba-0.6.3+dfsg1/src/core/library.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/library.c 2019-01-27 00:06:06.000000000 +0000 @@ -209,6 +209,7 @@ sqlite3_finalize(library->select); sqlite3_finalize(library->count); sqlite3_close(library->db); + free(library); } void mLibraryLoadDirectory(struct mLibrary* library, const char* base) { diff -Nru mgba-0.6.3+dfsg1/src/core/log.c mgba-0.7.0/src/core/log.c --- mgba-0.6.3+dfsg1/src/core/log.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/log.c 2019-01-27 00:06:06.000000000 +0000 @@ -128,13 +128,13 @@ } bool mLogFilterTest(struct mLogFilter* filter, int category, enum mLogLevel level) { - int value = (int) TableLookup(&filter->levels, category); + int value = (intptr_t) TableLookup(&filter->levels, category); if (value) { return value & level; } const char* cat = mLogCategoryId(category); if (cat) { - value = (int) HashTableLookup(&filter->categories, cat); + value = (intptr_t) HashTableLookup(&filter->categories, cat); if (value) { TableInsert(&filter->levels, category, (void*)(intptr_t) value); return value & level; diff -Nru mgba-0.6.3+dfsg1/src/core/map-cache.c mgba-0.7.0/src/core/map-cache.c --- mgba-0.6.3+dfsg1/src/core/map-cache.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/core/map-cache.c 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/src/core/mem-search.c mgba-0.7.0/src/core/mem-search.c --- mgba-0.6.3+dfsg1/src/core/mem-search.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/mem-search.c 2019-01-27 00:06:06.000000000 +0000 @@ -10,248 +10,113 @@ DEFINE_VECTOR(mCoreMemorySearchResults, struct mCoreMemorySearchResult); -static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint32_t value32, struct mCoreMemorySearchResults* out, size_t limit) { +static bool _op(int32_t value, int32_t match, enum mCoreMemorySearchOp op) { + switch (op) { + case mCORE_MEMORY_SEARCH_GREATER: + return value > match; + case mCORE_MEMORY_SEARCH_LESS: + return value < match; + case mCORE_MEMORY_SEARCH_EQUAL: + case mCORE_MEMORY_SEARCH_DELTA: + return value == match; + } + return false; +} + +static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint32_t value32, enum mCoreMemorySearchOp op, struct mCoreMemorySearchResults* out, size_t limit) { const uint32_t* mem32 = mem; size_t found = 0; uint32_t start = block->start; uint32_t end = size; // TODO: Segments size_t i; // TODO: Big endian - for (i = 0; (!limit || found < limit) && i < end; i += 16) { - int mask = 0; - mask |= (mem32[(i >> 2) + 0] == value32) << 0; - mask |= (mem32[(i >> 2) + 1] == value32) << 1; - mask |= (mem32[(i >> 2) + 2] == value32) << 2; - mask |= (mem32[(i >> 2) + 3] == value32) << 3; - if (!mask) { - continue; - } - if ((mask & 1) && (!limit || found < limit)) { + for (i = 0; (!limit || found < limit) && i < end; i += 4) { + if (_op(mem32[i >> 2], value32, op)) { struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); res->address = start + i; - res->type = mCORE_MEMORY_SEARCH_32; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 2) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 4; - res->type = mCORE_MEMORY_SEARCH_32; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 4) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 8; - res->type = mCORE_MEMORY_SEARCH_32; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 8) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 12; - res->type = mCORE_MEMORY_SEARCH_32; + res->type = mCORE_MEMORY_SEARCH_INT; + res->width = 4; res->segment = -1; // TODO res->guessDivisor = 1; + res->guessMultiplier = 1; + res->oldValue = value32; ++found; } } - // TODO: last 12 bytes return found; } -static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint16_t value16, struct mCoreMemorySearchResults* out, size_t limit) { +static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint16_t value16, enum mCoreMemorySearchOp op, struct mCoreMemorySearchResults* out, size_t limit) { const uint16_t* mem16 = mem; size_t found = 0; uint32_t start = block->start; uint32_t end = size; // TODO: Segments size_t i; // TODO: Big endian - for (i = 0; (!limit || found < limit) && i < end; i += 16) { - int mask = 0; - mask |= (mem16[(i >> 1) + 0] == value16) << 0; - mask |= (mem16[(i >> 1) + 1] == value16) << 1; - mask |= (mem16[(i >> 1) + 2] == value16) << 2; - mask |= (mem16[(i >> 1) + 3] == value16) << 3; - mask |= (mem16[(i >> 1) + 4] == value16) << 4; - mask |= (mem16[(i >> 1) + 5] == value16) << 5; - mask |= (mem16[(i >> 1) + 6] == value16) << 6; - mask |= (mem16[(i >> 1) + 7] == value16) << 7; - if (!mask) { - continue; - } - if ((mask & 1) && (!limit || found < limit)) { + for (i = 0; (!limit || found < limit) && i < end; i += 2) { + if (_op(mem16[i >> 1], value16, op)) { struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); res->address = start + i; - res->type = mCORE_MEMORY_SEARCH_16; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 2) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 2; - res->type = mCORE_MEMORY_SEARCH_16; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 4) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 4; - res->type = mCORE_MEMORY_SEARCH_16; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 8) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 6; - res->type = mCORE_MEMORY_SEARCH_16; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 16) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 8; - res->type = mCORE_MEMORY_SEARCH_16; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 32) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 10; - res->type = mCORE_MEMORY_SEARCH_16; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 64) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 12; - res->type = mCORE_MEMORY_SEARCH_16; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 128) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 14; - res->type = mCORE_MEMORY_SEARCH_16; + res->type = mCORE_MEMORY_SEARCH_INT; + res->width = 2; res->segment = -1; // TODO res->guessDivisor = 1; + res->guessMultiplier = 1; + res->oldValue = value16; ++found; } } - // TODO: last 14 bytes return found; } -static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint8_t value8, struct mCoreMemorySearchResults* out, size_t limit) { +static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint8_t value8, enum mCoreMemorySearchOp op, struct mCoreMemorySearchResults* out, size_t limit) { const uint8_t* mem8 = mem; size_t found = 0; uint32_t start = block->start; uint32_t end = size; // TODO: Segments size_t i; - for (i = 0; (!limit || found < limit) && i < end; i += 8) { - int mask = 0; - mask |= (mem8[i + 0] == value8) << 0; - mask |= (mem8[i + 1] == value8) << 1; - mask |= (mem8[i + 2] == value8) << 2; - mask |= (mem8[i + 3] == value8) << 3; - mask |= (mem8[i + 4] == value8) << 4; - mask |= (mem8[i + 5] == value8) << 5; - mask |= (mem8[i + 6] == value8) << 6; - mask |= (mem8[i + 7] == value8) << 7; - if (!mask) { - continue; - } - if ((mask & 1) && (!limit || found < limit)) { + for (i = 0; (!limit || found < limit) && i < end; ++i) { + if (_op(mem8[i], value8, op)) { struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); res->address = start + i; - res->type = mCORE_MEMORY_SEARCH_8; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 2) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 1; - res->type = mCORE_MEMORY_SEARCH_8; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 4) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 2; - res->type = mCORE_MEMORY_SEARCH_8; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 8) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 3; - res->type = mCORE_MEMORY_SEARCH_8; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 16) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 4; - res->type = mCORE_MEMORY_SEARCH_8; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 32) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 5; - res->type = mCORE_MEMORY_SEARCH_8; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 64) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 6; - res->type = mCORE_MEMORY_SEARCH_8; - res->segment = -1; // TODO - res->guessDivisor = 1; - ++found; - } - if ((mask & 128) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 7; - res->type = mCORE_MEMORY_SEARCH_8; + res->type = mCORE_MEMORY_SEARCH_INT; + res->width = 1; res->segment = -1; // TODO res->guessDivisor = 1; + res->guessMultiplier = 1; + res->oldValue = value8; ++found; } } - // TODO: last 7 bytes return found; } -static size_t _searchStr(const void* mem, size_t size, const struct mCoreMemoryBlock* block, const char* valueStr, struct mCoreMemorySearchResults* out, size_t limit) { +static size_t _searchInt(const void* mem, size_t size, const struct mCoreMemoryBlock* block, const struct mCoreMemorySearchParams* params, struct mCoreMemorySearchResults* out, size_t limit) { + if (params->align == params->width || params->align == -1) { + switch (params->width) { + case 4: + return _search32(mem, size, block, params->valueInt, params->op, out, limit); + case 2: + return _search16(mem, size, block, params->valueInt, params->op, out, limit); + case 1: + return _search8(mem, size, block, params->valueInt, params->op, out, limit); + } + } + return 0; +} + +static size_t _searchStr(const void* mem, size_t size, const struct mCoreMemoryBlock* block, const char* valueStr, int len, struct mCoreMemorySearchResults* out, size_t limit) { const char* memStr = mem; size_t found = 0; - size_t len = strlen(valueStr); uint32_t start = block->start; uint32_t end = size; // TODO: Segments size_t i; for (i = 0; (!limit || found < limit) && i < end - len; ++i) { - if (!strncmp(valueStr, &memStr[i], len)) { + if (!memcmp(valueStr, &memStr[i], len)) { struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); res->address = start + i; res->type = mCORE_MEMORY_SEARCH_STRING; + res->width = len; res->segment = -1; // TODO ++found; } @@ -259,11 +124,11 @@ return found; } -static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemoryBlock* block, const char* valueStr, struct mCoreMemorySearchResults* out, size_t limit) { +static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemoryBlock* block, const struct mCoreMemorySearchParams* params, struct mCoreMemorySearchResults* out, size_t limit) { // TODO: As str char* end; - uint64_t value; + int64_t value; size_t found = 0; @@ -271,14 +136,14 @@ mCoreMemorySearchResultsInit(&tmp, 0); // Decimal: - value = strtoull(valueStr, &end, 10); + value = strtoll(params->valueStr, &end, 10); if (end && !end[0]) { - if (value > 0x10000) { - found += _search32(mem, size, block, value, out, limit ? limit - found : 0); - } else if (value > 0x100) { - found += _search16(mem, size, block, value, out, limit ? limit - found : 0); + if ((params->width == -1 && value > 0x10000) || params->width == 4) { + found += _search32(mem, size, block, value, params->op, out, limit ? limit - found : 0); + } else if ((params->width == -1 && value > 0x100) || params->width == 2) { + found += _search16(mem, size, block, value, params->op, out, limit ? limit - found : 0); } else { - found += _search8(mem, size, block, value, out, limit ? limit - found : 0); + found += _search8(mem, size, block, value, params->op, out, limit ? limit - found : 0); } uint32_t divisor = 1; @@ -287,12 +152,12 @@ value /= 10; divisor *= 10; - if (value > 0x10000) { - found += _search32(mem, size, block, value, &tmp, limit ? limit - found : 0); - } else if (value > 0x100) { - found += _search16(mem, size, block, value, &tmp, limit ? limit - found : 0); + if ((params->width == -1 && value > 0x10000) || params->width == 4) { + found += _search32(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); + } else if ((params->width == -1 && value > 0x100) || params->width == 2) { + found += _search16(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } else { - found += _search8(mem, size, block, value, &tmp, limit ? limit - found : 0); + found += _search8(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } size_t i; for (i = 0; i < mCoreMemorySearchResultsSize(&tmp); ++i) { @@ -304,14 +169,14 @@ } // Hex: - value = strtoull(valueStr, &end, 16); + value = strtoll(params->valueStr, &end, 16); if (end && !end[0]) { - if (value > 0x10000) { - found += _search32(mem, size, block, value, out, limit ? limit - found : 0); - } else if (value > 0x100) { - found += _search16(mem, size, block, value, out, limit ? limit - found : 0); + if ((params->width == -1 && value > 0x10000) || params->width == 4) { + found += _search32(mem, size, block, value, params->op, out, limit ? limit - found : 0); + } else if ((params->width == -1 && value > 0x100) || params->width == 2) { + found += _search16(mem, size, block, value, params->op, out, limit ? limit - found : 0); } else { - found += _search8(mem, size, block, value, out, limit ? limit - found : 0); + found += _search8(mem, size, block, value, params->op, out, limit ? limit - found : 0); } uint32_t divisor = 1; @@ -320,12 +185,12 @@ value >>= 4; divisor <<= 4; - if (value > 0x10000) { - found += _search32(mem, size, block, value, &tmp, limit ? limit - found : 0); - } else if (value > 0x100) { - found += _search16(mem, size, block, value, &tmp, limit ? limit - found : 0); + if ((params->width == -1 && value > 0x10000) || params->width == 4) { + found += _search32(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); + } else if ((params->width == -1 && value > 0x100) || params->width == 2) { + found += _search16(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } else { - found += _search8(mem, size, block, value, &tmp, limit ? limit - found : 0); + found += _search8(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } size_t i; for (i = 0; i < mCoreMemorySearchResultsSize(&tmp); ++i) { @@ -342,17 +207,14 @@ static size_t _search(const void* mem, size_t size, const struct mCoreMemoryBlock* block, const struct mCoreMemorySearchParams* params, struct mCoreMemorySearchResults* out, size_t limit) { switch (params->type) { - case mCORE_MEMORY_SEARCH_32: - return _search32(mem, size, block, params->value32, out, limit); - case mCORE_MEMORY_SEARCH_16: - return _search16(mem, size, block, params->value16, out, limit); - case mCORE_MEMORY_SEARCH_8: - return _search8(mem, size, block, params->value8, out, limit); + case mCORE_MEMORY_SEARCH_INT: + return _searchInt(mem, size, block, params, out, limit); case mCORE_MEMORY_SEARCH_STRING: - return _searchStr(mem, size, block, params->valueStr, out, limit); + return _searchStr(mem, size, block, params->valueStr, params->width, out, limit); case mCORE_MEMORY_SEARCH_GUESS: - return _searchGuess(mem, size, block, params->valueStr, out, limit); + return _searchGuess(mem, size, block, params, out, limit); } + return 0; } void mCoreMemorySearch(struct mCore* core, const struct mCoreMemorySearchParams* params, struct mCoreMemorySearchResults* out, size_t limit) { @@ -378,34 +240,42 @@ } } -bool _testGuess(struct mCore* core, const struct mCoreMemorySearchResult* res, const struct mCoreMemorySearchParams* params) { - uint64_t value; +bool _testGuess(struct mCore* core, struct mCoreMemorySearchResult* res, const struct mCoreMemorySearchParams* params) { + int64_t value; + int32_t offset = 0; char* end; + if (params->op == mCORE_MEMORY_SEARCH_DELTA) { + offset = res->oldValue; + } - value = strtoull(params->valueStr, &end, 10); + value = strtoll(params->valueStr, &end, 10); if (end) { - if (core->rawRead8(core, res->address, res->segment) * res->guessDivisor == value) { + res->oldValue += value; + if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) { return true; } - if (!(res->address & 1) && core->rawRead16(core, res->address, res->segment) * res->guessDivisor == value) { + if (!(res->address & 1) && (res->width >= 2 || res->width == -1) && _op(core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) { return true; } - if (!(res->address & 3) && core->rawRead32(core, res->address, res->segment) * res->guessDivisor == value) { + if (!(res->address & 3) && (res->width >= 4 || res->width == -1) && _op(core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) { return true; } + res->oldValue -= value; } - value = strtoull(params->valueStr, &end, 16); + value = strtoll(params->valueStr, &end, 16); if (end) { - if (core->rawRead8(core, res->address, res->segment) * res->guessDivisor == value) { + res->oldValue += value; + if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) { return true; } - if (!(res->address & 1) && core->rawRead16(core, res->address, res->segment) * res->guessDivisor == value) { + if (!(res->address & 1) && (res->width >= 2 || res->width == -1) && _op(core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) { return true; } - if (!(res->address & 3) && core->rawRead32(core, res->address, res->segment) * res->guessDivisor == value) { + if (!(res->address & 3) && (res->width >= 4 || res->width == -1) && _op(core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) { return true; } + res->oldValue -= value; } return false; } @@ -415,76 +285,39 @@ for (i = 0; i < mCoreMemorySearchResultsSize(inout); ++i) { struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsGetPointer(inout, i); switch (res->type) { - case mCORE_MEMORY_SEARCH_8: - switch (params->type) { - case mCORE_MEMORY_SEARCH_8: - if (core->rawRead8(core, res->address, res->segment) != params->value8) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; - } - break; - case mCORE_MEMORY_SEARCH_16: - if (core->rawRead8(core, res->address, res->segment) != params->value16) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; - } - break; - case mCORE_MEMORY_SEARCH_32: - if (core->rawRead32(core, res->address, res->segment) != params->value32) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; - } - break; - case mCORE_MEMORY_SEARCH_GUESS: + case mCORE_MEMORY_SEARCH_INT: + if (params->type == mCORE_MEMORY_SEARCH_GUESS) { if (!_testGuess(core, res, params)) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; - } - break; - default: - break; - } - break; - case mCORE_MEMORY_SEARCH_16: - switch (params->type) { - case mCORE_MEMORY_SEARCH_16: - if (core->rawRead16(core, res->address, res->segment) != params->value16) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; - } - break; - case mCORE_MEMORY_SEARCH_32: - if (core->rawRead32(core, res->address, res->segment) != params->value32) { - mCoreMemorySearchResultsShift(inout, i, 1); + *res = *mCoreMemorySearchResultsGetPointer(inout, mCoreMemorySearchResultsSize(inout) - 1); + mCoreMemorySearchResultsResize(inout, -1); --i; } - break; - case mCORE_MEMORY_SEARCH_GUESS: - if (!_testGuess(core, res, params)) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; + } else if (params->type == mCORE_MEMORY_SEARCH_INT) { + int32_t oldValue = params->valueInt; + if (params->op == mCORE_MEMORY_SEARCH_DELTA) { + oldValue += res->oldValue; } - break; - default: - break; - } - break; - case mCORE_MEMORY_SEARCH_32: - switch (params->type) { - case mCORE_MEMORY_SEARCH_32: - if (core->rawRead32(core, res->address, res->segment) != params->value32) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; + int32_t value = 0; + switch (params->width) { + case 1: + value = core->rawRead8(core, res->address, res->segment); + break; + case 2: + value = core->rawRead16(core, res->address, res->segment); + break; + case 4: + value = core->rawRead32(core, res->address, res->segment); + break; + default: + break; } - break; - case mCORE_MEMORY_SEARCH_GUESS: - if (!_testGuess(core, res, params)) { - mCoreMemorySearchResultsShift(inout, i, 1); + if (!_op(value, oldValue, params->op)) { + *res = *mCoreMemorySearchResultsGetPointer(inout, mCoreMemorySearchResultsSize(inout) - 1); + mCoreMemorySearchResultsResize(inout, -1); --i; + } else { + res->oldValue = value; } - break; - default: - break; } break; case mCORE_MEMORY_SEARCH_STRING: diff -Nru mgba-0.6.3+dfsg1/src/core/rewind.c mgba-0.7.0/src/core/rewind.c --- mgba-0.6.3+dfsg1/src/core/rewind.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/rewind.c 2019-01-27 00:06:06.000000000 +0000 @@ -19,6 +19,9 @@ #endif void mCoreRewindContextInit(struct mCoreRewindContext* context, size_t entries, bool onThread) { + if (context->currentState) { + return; + } mCoreRewindPatchesInit(&context->patchMemory, entries); size_t e; for (e = 0; e < entries; ++e) { @@ -27,7 +30,6 @@ context->previousState = VFileMemChunk(0, 0); context->currentState = VFileMemChunk(0, 0); context->size = 0; - context->stateFlags = SAVESTATE_SAVEDATA; #ifndef DISABLE_THREADING context->onThread = onThread; context->ready = false; @@ -42,6 +44,9 @@ } void mCoreRewindContextDeinit(struct mCoreRewindContext* context) { + if (!context->currentState) { + return; + } #ifndef DISABLE_THREADING if (context->onThread) { MutexLock(&context->mutex); @@ -55,6 +60,8 @@ #endif context->previousState->close(context->previousState); context->currentState->close(context->currentState); + context->previousState = NULL; + context->currentState = NULL; size_t s; for (s = 0; s < mCoreRewindPatchesSize(&context->patchMemory); ++s) { deinitPatchFast(mCoreRewindPatchesGetPointer(&context->patchMemory, s)); @@ -69,7 +76,7 @@ } #endif struct VFile* nextState = context->previousState; - mCoreSaveStateNamed(core, nextState, context->stateFlags); + mCoreSaveStateNamed(core, nextState, SAVESTATE_SAVEDATA | SAVESTATE_RTC); context->previousState = context->currentState; context->currentState = nextState; #ifndef DISABLE_THREADING @@ -123,7 +130,7 @@ } --context->size; - mCoreLoadStateNamed(core, context->previousState, context->stateFlags); + mCoreLoadStateNamed(core, context->previousState, SAVESTATE_SAVEDATA | SAVESTATE_RTC); if (context->current == 0) { context->current = mCoreRewindPatchesSize(&context->patchMemory); } diff -Nru mgba-0.6.3+dfsg1/src/core/scripting.c mgba-0.7.0/src/core/scripting.c --- mgba-0.6.3+dfsg1/src/core/scripting.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/core/scripting.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,138 @@ +/* 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 + +struct mScriptBridge { + struct Table engines; + struct mDebugger* debugger; +}; + +struct mScriptInfo { + const char* name; + struct VFile* vf; + bool success; +}; + +struct mScriptSymbol { + const char* name; + int32_t* out; + bool success; +}; + +static void _seDeinit(void* value) { + struct mScriptEngine* se = value; + se->deinit(se); +} + +static void _seTryLoad(const char* key, void* value, void* user) { + UNUSED(key); + struct mScriptEngine* se = value; + struct mScriptInfo* si = user; + if (!si->success && se->isScript(se, si->name, si->vf)) { + si->success = se->loadScript(se, si->name, si->vf); + } +} + +static void _seLookupSymbol(const char* key, void* value, void* user) { + UNUSED(key); + struct mScriptEngine* se = value; + struct mScriptSymbol* si = user; + if (!si->success) { + si->success = se->lookupSymbol(se, si->name, si->out); + } +} + +static void _seRun(const char* key, void* value, void* user) { + UNUSED(key); + UNUSED(user); + struct mScriptEngine* se = value; + se->run(se); +} + +#ifdef USE_DEBUGGERS +struct mScriptDebuggerEntry { + enum mDebuggerEntryReason reason; + struct mDebuggerEntryInfo* info; +}; + +static void _seDebuggerEnter(const char* key, void* value, void* user) { + UNUSED(key); + struct mScriptEngine* se = value; + struct mScriptDebuggerEntry* entry = user; + se->debuggerEntered(se, entry->reason, entry->info); +} +#endif + +struct mScriptBridge* mScriptBridgeCreate(void) { + struct mScriptBridge* sb = malloc(sizeof(*sb)); + HashTableInit(&sb->engines, 0, _seDeinit); + sb->debugger = NULL; + return sb; +} + +void mScriptBridgeDestroy(struct mScriptBridge* sb) { + HashTableDeinit(&sb->engines); + free(sb); +} + +void mScriptBridgeInstallEngine(struct mScriptBridge* sb, struct mScriptEngine* se) { + if (!se->init(se, sb)) { + return; + } + const char* name = se->name(se); + HashTableInsert(&sb->engines, name, se); +} + +#ifdef USE_DEBUGGERS +void mScriptBridgeSetDebugger(struct mScriptBridge* sb, struct mDebugger* debugger) { + sb->debugger = debugger; + debugger->bridge = sb; +} + +struct mDebugger* mScriptBridgeGetDebugger(struct mScriptBridge* sb) { + return sb->debugger; +} + +void mScriptBridgeDebuggerEntered(struct mScriptBridge* sb, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { + struct mScriptDebuggerEntry entry = { + .reason = reason, + .info = info + }; + HashTableEnumerate(&sb->engines, _seDebuggerEnter, &entry); +} +#endif + +void mScriptBridgeRun(struct mScriptBridge* sb) { + HashTableEnumerate(&sb->engines, _seRun, NULL); +} + +bool mScriptBridgeLoadScript(struct mScriptBridge* sb, const char* name) { + struct VFile* vf = VFileOpen(name, O_RDONLY); + if (!vf) { + return false; + } + struct mScriptInfo info = { + .name = name, + .vf = vf, + .success = false + }; + HashTableEnumerate(&sb->engines, _seTryLoad, &info); + vf->close(vf); + return info.success; +} + +bool mScriptBridgeLookupSymbol(struct mScriptBridge* sb, const char* name, int32_t* out) { + struct mScriptSymbol info = { + .name = name, + .out = out, + .success = false + }; + HashTableEnumerate(&sb->engines, _seLookupSymbol, &info); + return info.success; +} diff -Nru mgba-0.6.3+dfsg1/src/core/serialize.c mgba-0.7.0/src/core/serialize.c --- mgba-0.6.3+dfsg1/src/core/serialize.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/serialize.c 2019-01-27 00:06:06.000000000 +0000 @@ -305,32 +305,37 @@ size_t stateSize = core->stateSize(core); if (flags & SAVESTATE_METADATA) { - uint64_t creationUsec; + uint64_t* creationUsec = malloc(sizeof(*creationUsec)); + if (creationUsec) { #ifndef _MSC_VER - struct timeval tv; - if (!gettimeofday(&tv, 0)) { - uint64_t usec = tv.tv_usec; - usec += tv.tv_sec * 1000000LL; - STORE_64LE(usec, 0, &creationUsec); - } + struct timeval tv; + if (!gettimeofday(&tv, 0)) { + uint64_t usec = tv.tv_usec; + usec += tv.tv_sec * 1000000LL; + STORE_64LE(usec, 0, creationUsec); + } #else - struct timespec ts; - if (timespec_get(&ts, TIME_UTC)) { - uint64_t usec = ts.tv_nsec / 1000; - usec += ts.tv_sec * 1000000LL; - STORE_64LE(usec, 0, &creationUsec); - } + struct timespec ts; + if (timespec_get(&ts, TIME_UTC)) { + uint64_t usec = ts.tv_nsec / 1000; + usec += ts.tv_sec * 1000000LL; + STORE_64LE(usec, 0, creationUsec); + } #endif - else { - creationUsec = 0; + else { + free(creationUsec); + creationUsec = 0; + } } - struct mStateExtdataItem item = { - .size = sizeof(creationUsec), - .data = &creationUsec, - .clean = NULL - }; - mStateExtdataPut(&extdata, EXTDATA_META_TIME, &item); + if (creationUsec) { + struct mStateExtdataItem item = { + .size = sizeof(*creationUsec), + .data = creationUsec, + .clean = free + }; + mStateExtdataPut(&extdata, EXTDATA_META_TIME, &item); + } } if (flags & SAVESTATE_SAVEDATA) { @@ -360,7 +365,6 @@ } } if (flags & SAVESTATE_RTC) { - mLOG(SAVESTATE, INFO, "Loading RTC"); struct mStateExtdataItem item; if (core->rtc.d.serialize) { core->rtc.d.serialize(&core->rtc.d, &item); @@ -409,11 +413,8 @@ } #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 -Nru mgba-0.6.3+dfsg1/src/core/sync.c mgba-0.7.0/src/core/sync.c --- mgba-0.6.3+dfsg1/src/core/sync.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/sync.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,6 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include + static void _changeVideoSync(struct mCoreSync* sync, bool frameOn) { // Make sure the video thread can process events while the GBA thread is paused MutexLock(&sync->videoFrameMutex); @@ -76,16 +78,20 @@ _changeVideoSync(sync, wait); } -void mCoreSyncProduceAudio(struct mCoreSync* sync, bool wait) { +bool mCoreSyncProduceAudio(struct mCoreSync* sync, const struct blip_t* buf, size_t samples) { if (!sync) { - return; + return true; } - if (sync->audioWait && wait) { - // TODO loop properly in event of spurious wakeups + size_t produced = blip_samples_avail(buf); + size_t producedNew = produced; + while (sync->audioWait && producedNew >= samples) { ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex); + produced = producedNew; + producedNew = blip_samples_avail(buf); } MutexUnlock(&sync->audioBufferMutex); + return producedNew != produced; } void mCoreSyncLockAudio(struct mCoreSync* sync) { diff -Nru mgba-0.6.3+dfsg1/src/core/test/core.c mgba-0.7.0/src/core/test/core.c --- mgba-0.6.3+dfsg1/src/core/test/core.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/test/core.c 2019-01-27 00:06:06.000000000 +0000 @@ -34,9 +34,3 @@ #endif cmocka_unit_test(findNullVF), cmocka_unit_test(findEmpty)) - -int TestRunCore(void) { - int failures = 0; - failures += M_TEST_SUITE_RUN(mCore); - return failures; -} diff -Nru mgba-0.6.3+dfsg1/src/core/thread.c mgba-0.7.0/src/core/thread.c --- mgba-0.6.3+dfsg1/src/core/thread.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/thread.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include #include #include @@ -38,7 +39,7 @@ static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args); -static void _changeState(struct mCoreThread* threadContext, enum mCoreThreadState newState, bool broadcast) { +static void _changeState(struct mCoreThreadInternal* threadContext, enum mCoreThreadState newState, bool broadcast) { MutexLock(&threadContext->stateMutex); threadContext->state = newState; if (broadcast) { @@ -47,18 +48,23 @@ MutexUnlock(&threadContext->stateMutex); } -static void _waitOnInterrupt(struct mCoreThread* threadContext) { +static void _waitOnInterrupt(struct mCoreThreadInternal* threadContext) { while (threadContext->state == THREAD_INTERRUPTED || threadContext->state == THREAD_INTERRUPTING) { ConditionWait(&threadContext->stateCond, &threadContext->stateMutex); } } -static void _waitUntilNotState(struct mCoreThread* threadContext, enum mCoreThreadState oldState) { +static void _waitUntilNotState(struct mCoreThreadInternal* threadContext, enum mCoreThreadState oldState) { MutexLock(&threadContext->sync.videoFrameMutex); bool videoFrameWait = threadContext->sync.videoFrameWait; threadContext->sync.videoFrameWait = false; MutexUnlock(&threadContext->sync.videoFrameMutex); + MutexLock(&threadContext->sync.audioBufferMutex); + bool audioWait = threadContext->sync.audioWait; + threadContext->sync.audioWait = false; + MutexUnlock(&threadContext->sync.audioBufferMutex); + while (threadContext->state == oldState) { MutexUnlock(&threadContext->stateMutex); @@ -76,12 +82,16 @@ ConditionWake(&threadContext->stateCond); } + MutexLock(&threadContext->sync.audioBufferMutex); + threadContext->sync.audioWait = audioWait; + MutexUnlock(&threadContext->sync.audioBufferMutex); + MutexLock(&threadContext->sync.videoFrameMutex); threadContext->sync.videoFrameWait = videoFrameWait; MutexUnlock(&threadContext->sync.videoFrameMutex); } -static void _pauseThread(struct mCoreThread* threadContext) { +static void _pauseThread(struct mCoreThreadInternal* threadContext) { threadContext->state = THREAD_PAUSING; _waitUntilNotState(threadContext, THREAD_PAUSING); } @@ -92,11 +102,11 @@ return; } if (thread->core->opts.rewindEnable && thread->core->opts.rewindBufferCapacity > 0) { - if (thread->state != THREAD_REWINDING) { - mCoreRewindAppend(&thread->rewind, thread->core); - } else if (thread->state == THREAD_REWINDING) { - if (!mCoreRewindRestore(&thread->rewind, thread->core)) { - mCoreRewindAppend(&thread->rewind, thread->core); + if (thread->impl->state != THREAD_REWINDING) { + mCoreRewindAppend(&thread->impl->rewind, thread->core); + } else if (thread->impl->state == THREAD_REWINDING) { + if (!mCoreRewindRestore(&thread->impl->rewind, thread->core)) { + mCoreRewindAppend(&thread->impl->rewind, thread->core); } } } @@ -117,7 +127,7 @@ if (!thread) { return; } - _changeState(thread, THREAD_CRASHED, true); + _changeState(thread->impl, THREAD_CRASHED, true); } void _coreSleep(void* context) { @@ -157,8 +167,7 @@ .context = threadContext }; core->addCoreCallbacks(core, &callbacks); - core->setSync(core, &threadContext->sync); - core->reset(core); + core->setSync(core, &threadContext->impl->sync); struct mLogFilter filter; if (!threadContext->logger.d.filter) { @@ -167,77 +176,109 @@ mLogFilterLoad(threadContext->logger.d.filter, &core->config); } - if (core->opts.rewindEnable && core->opts.rewindBufferCapacity > 0) { - mCoreRewindContextInit(&threadContext->rewind, core->opts.rewindBufferCapacity, true); - threadContext->rewind.stateFlags = core->opts.rewindSave ? SAVESTATE_SAVEDATA : 0; - } - - _changeState(threadContext, THREAD_RUNNING, true); - + mCoreThreadRewindParamsChanged(threadContext); if (threadContext->startCallback) { threadContext->startCallback(threadContext); } + + core->reset(core); + _changeState(threadContext->impl, THREAD_RUNNING, true); + if (threadContext->resetCallback) { threadContext->resetCallback(threadContext); } - while (threadContext->state < THREAD_EXITING) { + struct mCoreThreadInternal* impl = threadContext->impl; + while (impl->state < THREAD_EXITING) { #ifdef USE_DEBUGGERS struct mDebugger* debugger = core->debugger; if (debugger) { mDebuggerRun(debugger); if (debugger->state == DEBUGGER_SHUTDOWN) { - _changeState(threadContext, THREAD_EXITING, false); + _changeState(impl, THREAD_EXITING, false); } } else #endif { - while (threadContext->state <= THREAD_MAX_RUNNING) { + while (impl->state <= THREAD_MAX_RUNNING) { core->runLoop(core); } } - int resetScheduled = 0; - MutexLock(&threadContext->stateMutex); - while (threadContext->state > THREAD_MAX_RUNNING && threadContext->state < THREAD_EXITING) { - if (threadContext->state == THREAD_PAUSING) { - threadContext->state = THREAD_PAUSED; - ConditionWake(&threadContext->stateCond); - } - if (threadContext->state == THREAD_INTERRUPTING) { - threadContext->state = THREAD_INTERRUPTED; - ConditionWake(&threadContext->stateCond); - } - if (threadContext->state == THREAD_RUN_ON) { - if (threadContext->run) { - threadContext->run(threadContext); - } - threadContext->state = threadContext->savedState; - ConditionWake(&threadContext->stateCond); + enum mCoreThreadState deferred = THREAD_RUNNING; + MutexLock(&impl->stateMutex); + while (impl->state > THREAD_MAX_RUNNING && impl->state < THREAD_EXITING) { + deferred = impl->state; + + switch (deferred) { + case THREAD_INTERRUPTING: + impl->state = THREAD_INTERRUPTED; + ConditionWake(&impl->stateCond); + break; + case THREAD_PAUSING: + impl->state = THREAD_PAUSED; + break; + case THREAD_RESETING: + impl->state = THREAD_RUNNING; + break; + default: + break; } - if (threadContext->state == THREAD_RESETING) { - threadContext->state = THREAD_RUNNING; - resetScheduled = 1; + + if (deferred >= THREAD_MIN_DEFERRED && deferred <= THREAD_MAX_DEFERRED) { + break; + } + + deferred = impl->state; + if (deferred == THREAD_INTERRUPTED) { + deferred = impl->savedState; } - while (threadContext->state == THREAD_PAUSED || threadContext->state == THREAD_INTERRUPTED || threadContext->state == THREAD_WAITING) { - ConditionWait(&threadContext->stateCond, &threadContext->stateMutex); + while (impl->state >= THREAD_WAITING && impl->state <= THREAD_MAX_WAITING) { + ConditionWait(&impl->stateCond, &impl->stateMutex); + + if (impl->sync.audioWait) { + MutexUnlock(&impl->stateMutex); + mCoreSyncLockAudio(&impl->sync); + mCoreSyncProduceAudio(&impl->sync, core->getAudioChannel(core, 0), core->getAudioBufferSize(core)); + MutexLock(&impl->stateMutex); + } } } - MutexUnlock(&threadContext->stateMutex); - if (resetScheduled) { + MutexUnlock(&impl->stateMutex); + 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; } } - while (threadContext->state < THREAD_SHUTDOWN) { - _changeState(threadContext, THREAD_SHUTDOWN, false); + while (impl->state < THREAD_SHUTDOWN) { + _changeState(impl, THREAD_SHUTDOWN, false); } if (core->opts.rewindEnable) { - mCoreRewindContextDeinit(&threadContext->rewind); + mCoreRewindContextDeinit(&impl->rewind); } if (threadContext->cleanCallback) { @@ -245,33 +286,37 @@ } core->clearCoreCallbacks(core); + if (threadContext->logger.d.filter == &filter) { + mLogFilterDeinit(&filter); + } threadContext->logger.d.filter = NULL; return 0; } bool mCoreThreadStart(struct mCoreThread* threadContext) { - threadContext->state = THREAD_INITIALIZED; + threadContext->impl = calloc(sizeof(*threadContext->impl), 1); + threadContext->impl->state = THREAD_INITIALIZED; threadContext->logger.p = threadContext; if (!threadContext->logger.d.log) { threadContext->logger.d.log = _mCoreLog; threadContext->logger.d.filter = NULL; } - if (!threadContext->sync.fpsTarget) { - threadContext->sync.fpsTarget = _defaultFPSTarget; + if (!threadContext->impl->sync.fpsTarget) { + threadContext->impl->sync.fpsTarget = _defaultFPSTarget; } - MutexInit(&threadContext->stateMutex); - ConditionInit(&threadContext->stateCond); + MutexInit(&threadContext->impl->stateMutex); + ConditionInit(&threadContext->impl->stateCond); - MutexInit(&threadContext->sync.videoFrameMutex); - ConditionInit(&threadContext->sync.videoFrameAvailableCond); - ConditionInit(&threadContext->sync.videoFrameRequiredCond); - MutexInit(&threadContext->sync.audioBufferMutex); - ConditionInit(&threadContext->sync.audioRequiredCond); + MutexInit(&threadContext->impl->sync.videoFrameMutex); + ConditionInit(&threadContext->impl->sync.videoFrameAvailableCond); + ConditionInit(&threadContext->impl->sync.videoFrameRequiredCond); + MutexInit(&threadContext->impl->sync.audioBufferMutex); + ConditionInit(&threadContext->impl->sync.audioRequiredCond); - threadContext->interruptDepth = 0; + threadContext->impl->interruptDepth = 0; #ifdef USE_PTHREADS sigset_t signals; @@ -281,271 +326,298 @@ pthread_sigmask(SIG_BLOCK, &signals, 0); #endif - threadContext->sync.audioWait = threadContext->core->opts.audioSync; - threadContext->sync.videoFrameWait = threadContext->core->opts.videoSync; - threadContext->sync.fpsTarget = threadContext->core->opts.fpsTarget; - - MutexLock(&threadContext->stateMutex); - ThreadCreate(&threadContext->thread, _mCoreThreadRun, threadContext); - while (threadContext->state < THREAD_RUNNING) { - ConditionWait(&threadContext->stateCond, &threadContext->stateMutex); + threadContext->impl->sync.audioWait = threadContext->core->opts.audioSync; + threadContext->impl->sync.videoFrameWait = threadContext->core->opts.videoSync; + threadContext->impl->sync.fpsTarget = threadContext->core->opts.fpsTarget; + + MutexLock(&threadContext->impl->stateMutex); + ThreadCreate(&threadContext->impl->thread, _mCoreThreadRun, threadContext); + while (threadContext->impl->state < THREAD_RUNNING) { + ConditionWait(&threadContext->impl->stateCond, &threadContext->impl->stateMutex); } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); return true; } bool mCoreThreadHasStarted(struct mCoreThread* threadContext) { + if (!threadContext->impl) { + return false; + } bool hasStarted; - MutexLock(&threadContext->stateMutex); - hasStarted = threadContext->state > THREAD_INITIALIZED; - MutexUnlock(&threadContext->stateMutex); + MutexLock(&threadContext->impl->stateMutex); + hasStarted = threadContext->impl->state > THREAD_INITIALIZED; + MutexUnlock(&threadContext->impl->stateMutex); return hasStarted; } bool mCoreThreadHasExited(struct mCoreThread* threadContext) { + if (!threadContext->impl) { + return false; + } bool hasExited; - MutexLock(&threadContext->stateMutex); - hasExited = threadContext->state > THREAD_EXITING; - MutexUnlock(&threadContext->stateMutex); + MutexLock(&threadContext->impl->stateMutex); + hasExited = threadContext->impl->state > THREAD_EXITING; + MutexUnlock(&threadContext->impl->stateMutex); return hasExited; } bool mCoreThreadHasCrashed(struct mCoreThread* threadContext) { + if (!threadContext->impl) { + return false; + } bool hasExited; - MutexLock(&threadContext->stateMutex); - hasExited = threadContext->state == THREAD_CRASHED; - MutexUnlock(&threadContext->stateMutex); + MutexLock(&threadContext->impl->stateMutex); + hasExited = threadContext->impl->state == THREAD_CRASHED; + MutexUnlock(&threadContext->impl->stateMutex); return hasExited; } void mCoreThreadMarkCrashed(struct mCoreThread* threadContext) { - MutexLock(&threadContext->stateMutex); - threadContext->state = THREAD_CRASHED; - MutexUnlock(&threadContext->stateMutex); + MutexLock(&threadContext->impl->stateMutex); + threadContext->impl->state = THREAD_CRASHED; + MutexUnlock(&threadContext->impl->stateMutex); } void mCoreThreadEnd(struct mCoreThread* threadContext) { - MutexLock(&threadContext->stateMutex); - _waitOnInterrupt(threadContext); - threadContext->state = THREAD_EXITING; - ConditionWake(&threadContext->stateCond); - MutexUnlock(&threadContext->stateMutex); - MutexLock(&threadContext->sync.audioBufferMutex); - threadContext->sync.audioWait = 0; - ConditionWake(&threadContext->sync.audioRequiredCond); - MutexUnlock(&threadContext->sync.audioBufferMutex); - - MutexLock(&threadContext->sync.videoFrameMutex); - threadContext->sync.videoFrameWait = false; - threadContext->sync.videoFrameOn = false; - ConditionWake(&threadContext->sync.videoFrameRequiredCond); - ConditionWake(&threadContext->sync.videoFrameAvailableCond); - MutexUnlock(&threadContext->sync.videoFrameMutex); + MutexLock(&threadContext->impl->stateMutex); + _waitOnInterrupt(threadContext->impl); + threadContext->impl->state = THREAD_EXITING; + ConditionWake(&threadContext->impl->stateCond); + MutexUnlock(&threadContext->impl->stateMutex); + MutexLock(&threadContext->impl->sync.audioBufferMutex); + threadContext->impl->sync.audioWait = 0; + ConditionWake(&threadContext->impl->sync.audioRequiredCond); + MutexUnlock(&threadContext->impl->sync.audioBufferMutex); + + MutexLock(&threadContext->impl->sync.videoFrameMutex); + threadContext->impl->sync.videoFrameWait = false; + threadContext->impl->sync.videoFrameOn = false; + ConditionWake(&threadContext->impl->sync.videoFrameRequiredCond); + ConditionWake(&threadContext->impl->sync.videoFrameAvailableCond); + MutexUnlock(&threadContext->impl->sync.videoFrameMutex); } void mCoreThreadReset(struct mCoreThread* threadContext) { - MutexLock(&threadContext->stateMutex); - if (threadContext->state == THREAD_INTERRUPTED || threadContext->state == THREAD_INTERRUPTING) { - threadContext->savedState = THREAD_RESETING; + MutexLock(&threadContext->impl->stateMutex); + if (threadContext->impl->state == THREAD_INTERRUPTED || threadContext->impl->state == THREAD_INTERRUPTING) { + threadContext->impl->savedState = THREAD_RESETING; } else { - threadContext->state = THREAD_RESETING; + threadContext->impl->state = THREAD_RESETING; } - ConditionWake(&threadContext->stateCond); - MutexUnlock(&threadContext->stateMutex); + ConditionWake(&threadContext->impl->stateCond); + MutexUnlock(&threadContext->impl->stateMutex); } void mCoreThreadJoin(struct mCoreThread* threadContext) { - ThreadJoin(threadContext->thread); + if (!threadContext->impl) { + return; + } + ThreadJoin(threadContext->impl->thread); + + MutexDeinit(&threadContext->impl->stateMutex); + ConditionDeinit(&threadContext->impl->stateCond); + + MutexDeinit(&threadContext->impl->sync.videoFrameMutex); + ConditionWake(&threadContext->impl->sync.videoFrameAvailableCond); + ConditionDeinit(&threadContext->impl->sync.videoFrameAvailableCond); + ConditionWake(&threadContext->impl->sync.videoFrameRequiredCond); + ConditionDeinit(&threadContext->impl->sync.videoFrameRequiredCond); - MutexDeinit(&threadContext->stateMutex); - ConditionDeinit(&threadContext->stateCond); + ConditionWake(&threadContext->impl->sync.audioRequiredCond); + ConditionDeinit(&threadContext->impl->sync.audioRequiredCond); + MutexDeinit(&threadContext->impl->sync.audioBufferMutex); - MutexDeinit(&threadContext->sync.videoFrameMutex); - ConditionWake(&threadContext->sync.videoFrameAvailableCond); - ConditionDeinit(&threadContext->sync.videoFrameAvailableCond); - ConditionWake(&threadContext->sync.videoFrameRequiredCond); - ConditionDeinit(&threadContext->sync.videoFrameRequiredCond); - - ConditionWake(&threadContext->sync.audioRequiredCond); - ConditionDeinit(&threadContext->sync.audioRequiredCond); - MutexDeinit(&threadContext->sync.audioBufferMutex); + free(threadContext->impl); + threadContext->impl = NULL; } bool mCoreThreadIsActive(struct mCoreThread* threadContext) { - return threadContext->state >= THREAD_RUNNING && threadContext->state < THREAD_EXITING; + if (!threadContext->impl) { + return false; + } + return threadContext->impl->state >= THREAD_RUNNING && threadContext->impl->state < THREAD_EXITING; } void mCoreThreadInterrupt(struct mCoreThread* threadContext) { if (!threadContext) { return; } - MutexLock(&threadContext->stateMutex); - ++threadContext->interruptDepth; - if (threadContext->interruptDepth > 1 || !mCoreThreadIsActive(threadContext)) { - MutexUnlock(&threadContext->stateMutex); + MutexLock(&threadContext->impl->stateMutex); + ++threadContext->impl->interruptDepth; + if (threadContext->impl->interruptDepth > 1 || !mCoreThreadIsActive(threadContext)) { + MutexUnlock(&threadContext->impl->stateMutex); return; } - threadContext->savedState = threadContext->state; - _waitOnInterrupt(threadContext); - threadContext->state = THREAD_INTERRUPTING; - ConditionWake(&threadContext->stateCond); - _waitUntilNotState(threadContext, THREAD_INTERRUPTING); - MutexUnlock(&threadContext->stateMutex); + threadContext->impl->savedState = threadContext->impl->state; + _waitOnInterrupt(threadContext->impl); + threadContext->impl->state = THREAD_INTERRUPTING; + ConditionWake(&threadContext->impl->stateCond); + _waitUntilNotState(threadContext->impl, THREAD_INTERRUPTING); + MutexUnlock(&threadContext->impl->stateMutex); } void mCoreThreadInterruptFromThread(struct mCoreThread* threadContext) { if (!threadContext) { return; } - MutexLock(&threadContext->stateMutex); - ++threadContext->interruptDepth; - if (threadContext->interruptDepth > 1 || !mCoreThreadIsActive(threadContext)) { - if (threadContext->state == THREAD_INTERRUPTING) { - threadContext->state = THREAD_INTERRUPTED; + MutexLock(&threadContext->impl->stateMutex); + ++threadContext->impl->interruptDepth; + if (threadContext->impl->interruptDepth > 1 || !mCoreThreadIsActive(threadContext)) { + if (threadContext->impl->state == THREAD_INTERRUPTING) { + threadContext->impl->state = THREAD_INTERRUPTED; } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); return; } - threadContext->savedState = threadContext->state; - threadContext->state = THREAD_INTERRUPTED; - ConditionWake(&threadContext->stateCond); - MutexUnlock(&threadContext->stateMutex); + threadContext->impl->savedState = threadContext->impl->state; + threadContext->impl->state = THREAD_INTERRUPTING; + ConditionWake(&threadContext->impl->stateCond); + MutexUnlock(&threadContext->impl->stateMutex); } void mCoreThreadContinue(struct mCoreThread* threadContext) { if (!threadContext) { return; } - MutexLock(&threadContext->stateMutex); - --threadContext->interruptDepth; - if (threadContext->interruptDepth < 1 && mCoreThreadIsActive(threadContext)) { - threadContext->state = threadContext->savedState; - ConditionWake(&threadContext->stateCond); + MutexLock(&threadContext->impl->stateMutex); + --threadContext->impl->interruptDepth; + if (threadContext->impl->interruptDepth < 1 && mCoreThreadIsActive(threadContext)) { + threadContext->impl->state = threadContext->impl->savedState; + ConditionWake(&threadContext->impl->stateCond); } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); } void mCoreThreadRunFunction(struct mCoreThread* threadContext, void (*run)(struct mCoreThread*)) { - MutexLock(&threadContext->stateMutex); + MutexLock(&threadContext->impl->stateMutex); threadContext->run = run; - _waitOnInterrupt(threadContext); - threadContext->savedState = threadContext->state; - threadContext->state = THREAD_RUN_ON; - ConditionWake(&threadContext->stateCond); - _waitUntilNotState(threadContext, THREAD_RUN_ON); - MutexUnlock(&threadContext->stateMutex); + _waitOnInterrupt(threadContext->impl); + threadContext->impl->savedState = threadContext->impl->state; + threadContext->impl->state = THREAD_RUN_ON; + ConditionWake(&threadContext->impl->stateCond); + _waitUntilNotState(threadContext->impl, THREAD_RUN_ON); + MutexUnlock(&threadContext->impl->stateMutex); } void mCoreThreadPause(struct mCoreThread* threadContext) { - bool frameOn = threadContext->sync.videoFrameOn; - MutexLock(&threadContext->stateMutex); - _waitOnInterrupt(threadContext); - if (threadContext->state == THREAD_RUNNING) { - _pauseThread(threadContext); - threadContext->frameWasOn = frameOn; + bool frameOn = threadContext->impl->sync.videoFrameOn; + MutexLock(&threadContext->impl->stateMutex); + _waitOnInterrupt(threadContext->impl); + if (threadContext->impl->state == THREAD_RUNNING) { + _pauseThread(threadContext->impl); + threadContext->impl->frameWasOn = frameOn; frameOn = false; } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); - mCoreSyncSetVideoSync(&threadContext->sync, frameOn); + mCoreSyncSetVideoSync(&threadContext->impl->sync, frameOn); } void mCoreThreadUnpause(struct mCoreThread* threadContext) { - bool frameOn = threadContext->sync.videoFrameOn; - MutexLock(&threadContext->stateMutex); - _waitOnInterrupt(threadContext); - if (threadContext->state == THREAD_PAUSED || threadContext->state == THREAD_PAUSING) { - threadContext->state = THREAD_RUNNING; - ConditionWake(&threadContext->stateCond); - frameOn = threadContext->frameWasOn; + bool frameOn = threadContext->impl->sync.videoFrameOn; + MutexLock(&threadContext->impl->stateMutex); + _waitOnInterrupt(threadContext->impl); + if (threadContext->impl->state == THREAD_PAUSED || threadContext->impl->state == THREAD_PAUSING) { + threadContext->impl->state = THREAD_RUNNING; + ConditionWake(&threadContext->impl->stateCond); + frameOn = threadContext->impl->frameWasOn; } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); - mCoreSyncSetVideoSync(&threadContext->sync, frameOn); + mCoreSyncSetVideoSync(&threadContext->impl->sync, frameOn); } bool mCoreThreadIsPaused(struct mCoreThread* threadContext) { bool isPaused; - MutexLock(&threadContext->stateMutex); - if (threadContext->interruptDepth) { - isPaused = threadContext->savedState == THREAD_PAUSED; + MutexLock(&threadContext->impl->stateMutex); + if (threadContext->impl->interruptDepth) { + isPaused = threadContext->impl->savedState == THREAD_PAUSED; } else { - isPaused = threadContext->state == THREAD_PAUSED; + isPaused = threadContext->impl->state == THREAD_PAUSED; } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); return isPaused; } void mCoreThreadTogglePause(struct mCoreThread* threadContext) { - bool frameOn = threadContext->sync.videoFrameOn; - MutexLock(&threadContext->stateMutex); - _waitOnInterrupt(threadContext); - if (threadContext->state == THREAD_PAUSED || threadContext->state == THREAD_PAUSING) { - threadContext->state = THREAD_RUNNING; - ConditionWake(&threadContext->stateCond); - frameOn = threadContext->frameWasOn; - } else if (threadContext->state == THREAD_RUNNING) { - _pauseThread(threadContext); - threadContext->frameWasOn = frameOn; + bool frameOn = threadContext->impl->sync.videoFrameOn; + MutexLock(&threadContext->impl->stateMutex); + _waitOnInterrupt(threadContext->impl); + if (threadContext->impl->state == THREAD_PAUSED || threadContext->impl->state == THREAD_PAUSING) { + threadContext->impl->state = THREAD_RUNNING; + ConditionWake(&threadContext->impl->stateCond); + frameOn = threadContext->impl->frameWasOn; + } else if (threadContext->impl->state == THREAD_RUNNING) { + _pauseThread(threadContext->impl); + threadContext->impl->frameWasOn = frameOn; frameOn = false; } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); - mCoreSyncSetVideoSync(&threadContext->sync, frameOn); + mCoreSyncSetVideoSync(&threadContext->impl->sync, frameOn); } void mCoreThreadPauseFromThread(struct mCoreThread* threadContext) { bool frameOn = true; - MutexLock(&threadContext->stateMutex); - if (threadContext->state == THREAD_RUNNING || (threadContext->interruptDepth && threadContext->savedState == THREAD_RUNNING)) { - threadContext->state = THREAD_PAUSING; + MutexLock(&threadContext->impl->stateMutex); + if (threadContext->impl->state == THREAD_RUNNING || (threadContext->impl->interruptDepth && threadContext->impl->savedState == THREAD_RUNNING)) { + threadContext->impl->state = THREAD_PAUSING; frameOn = false; } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); - mCoreSyncSetVideoSync(&threadContext->sync, frameOn); + mCoreSyncSetVideoSync(&threadContext->impl->sync, frameOn); } void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool rewinding) { - MutexLock(&threadContext->stateMutex); - if (rewinding && (threadContext->state == THREAD_REWINDING || (threadContext->interruptDepth && threadContext->savedState == THREAD_REWINDING))) { - MutexUnlock(&threadContext->stateMutex); + MutexLock(&threadContext->impl->stateMutex); + if (rewinding && (threadContext->impl->state == THREAD_REWINDING || (threadContext->impl->interruptDepth && threadContext->impl->savedState == THREAD_REWINDING))) { + MutexUnlock(&threadContext->impl->stateMutex); return; } - if (!rewinding && ((!threadContext->interruptDepth && threadContext->state != THREAD_REWINDING) || (threadContext->interruptDepth && threadContext->savedState != THREAD_REWINDING))) { - MutexUnlock(&threadContext->stateMutex); + if (!rewinding && ((!threadContext->impl->interruptDepth && threadContext->impl->state != THREAD_REWINDING) || (threadContext->impl->interruptDepth && threadContext->impl->savedState != THREAD_REWINDING))) { + MutexUnlock(&threadContext->impl->stateMutex); return; } - _waitOnInterrupt(threadContext); - if (rewinding && threadContext->state == THREAD_RUNNING) { - threadContext->state = THREAD_REWINDING; + _waitOnInterrupt(threadContext->impl); + if (rewinding && threadContext->impl->state == THREAD_RUNNING) { + threadContext->impl->state = THREAD_REWINDING; } - if (!rewinding && threadContext->state == THREAD_REWINDING) { - threadContext->state = THREAD_RUNNING; + if (!rewinding && threadContext->impl->state == THREAD_REWINDING) { + threadContext->impl->state = THREAD_RUNNING; + } + MutexUnlock(&threadContext->impl->stateMutex); +} + +void mCoreThreadRewindParamsChanged(struct mCoreThread* threadContext) { + struct mCore* core = threadContext->core; + if (core->opts.rewindEnable && core->opts.rewindBufferCapacity > 0) { + mCoreRewindContextInit(&threadContext->impl->rewind, core->opts.rewindBufferCapacity, true); + } else { + mCoreRewindContextDeinit(&threadContext->impl->rewind); } - MutexUnlock(&threadContext->stateMutex); } void mCoreThreadWaitFromThread(struct mCoreThread* threadContext) { - MutexLock(&threadContext->stateMutex); - if (threadContext->interruptDepth && threadContext->savedState == THREAD_RUNNING) { - threadContext->savedState = THREAD_WAITING; - } else if (threadContext->state == THREAD_RUNNING) { - threadContext->state = THREAD_WAITING; + MutexLock(&threadContext->impl->stateMutex); + if (threadContext->impl->interruptDepth && threadContext->impl->savedState == THREAD_RUNNING) { + threadContext->impl->savedState = THREAD_WAITING; + } else if (threadContext->impl->state == THREAD_RUNNING) { + threadContext->impl->state = THREAD_WAITING; } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); } void mCoreThreadStopWaiting(struct mCoreThread* threadContext) { - MutexLock(&threadContext->stateMutex); - if (threadContext->interruptDepth && threadContext->savedState == THREAD_WAITING) { - threadContext->savedState = THREAD_RUNNING; - } else if (threadContext->state == THREAD_WAITING) { - threadContext->state = THREAD_RUNNING; - ConditionWake(&threadContext->stateCond); + MutexLock(&threadContext->impl->stateMutex); + if (threadContext->impl->interruptDepth && threadContext->impl->savedState == THREAD_WAITING) { + threadContext->impl->savedState = THREAD_RUNNING; + } else if (threadContext->impl->state == THREAD_WAITING) { + threadContext->impl->state = THREAD_RUNNING; + ConditionWake(&threadContext->impl->stateCond); } - MutexUnlock(&threadContext->stateMutex); + MutexUnlock(&threadContext->impl->stateMutex); } #ifdef USE_PTHREADS @@ -576,6 +648,12 @@ printf("%s: ", mLogCategoryName(category)); vprintf(format, args); printf("\n"); + struct mCoreThread* thread = mCoreThreadGet(); + if (thread && level == mLOG_FATAL) { +#ifndef DISABLE_THREADING + mCoreThreadMarkCrashed(thread); +#endif + } } struct mLogger* mCoreThreadLogger(void) { diff -Nru mgba-0.6.3+dfsg1/src/core/tile-cache.c mgba-0.7.0/src/core/tile-cache.c --- mgba-0.6.3+dfsg1/src/core/tile-cache.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/tile-cache.c 2019-01-27 00:06:06.000000000 +0000 @@ -12,60 +12,42 @@ 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 @@ _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 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]; - } - if (cache->globalPaletteVersion[1]) { - ++cache->globalPaletteVersion[1][address >> 1]; +void mTileCacheWritePalette(struct mTileCache* cache, uint32_t entry, color_t color) { + if (entry < cache->paletteBase) { + return; } -} - -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); + entry -= cache->paletteBase; + unsigned maxEntry = (1 << (1 << cache->bpp)) * cache->entriesPerTile; + if (entry >= maxEntry) { + return; } - cache->entries = 1 << (1 << cache->bpp); + cache->palette[entry] = color; + entry >>= (1 << mTileCacheSystemInfoGetPaletteBPP(cache->sysConfig)); + ++cache->globalPaletteVersion[entry]; } -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 @@ 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 >= 1U << 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 @@ 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 @@ 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 -Nru mgba-0.6.3+dfsg1/src/core/timing.c mgba-0.7.0/src/core/timing.c --- mgba-0.6.3+dfsg1/src/core/timing.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/core/timing.c 2019-01-27 00:06:06.000000000 +0000 @@ -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 mTimingClear(struct mTiming* timing) { timing->root = NULL; + timing->reroot = NULL; timing->masterCycles = 0; } @@ -26,12 +28,16 @@ if (nextEvent < *timing->nextEvent) { *timing->nextEvent = nextEvent; } + if (timing->reroot) { + timing->root = timing->reroot; + timing->reroot = NULL; + } struct mTimingEvent** previous = &timing->root; struct mTimingEvent* next = timing->root; unsigned priority = event->priority; while (next) { int32_t nextWhen = next->when - timing->masterCycles; - if (nextWhen > when || (nextWhen == when && next->priority > priority)) { + if (nextWhen > nextEvent || (nextWhen == nextEvent && next->priority > priority)) { break; } previous = &next->next; @@ -42,6 +48,10 @@ } void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent* event) { + if (timing->reroot) { + timing->root = timing->reroot; + timing->reroot = NULL; + } struct mTimingEvent** previous = &timing->root; struct mTimingEvent* next = timing->root; while (next) { @@ -56,6 +66,9 @@ bool mTimingIsScheduled(const struct mTiming* timing, const struct mTimingEvent* event) { const struct mTimingEvent* next = timing->root; + if (!next) { + next = timing->reroot; + } while (next) { if (next == event) { return true; @@ -77,6 +90,11 @@ 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 -Nru mgba-0.6.3+dfsg1/src/debugger/cli-debugger.c mgba-0.7.0/src/debugger/cli-debugger.c --- mgba-0.6.3+dfsg1/src/debugger/cli-debugger.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/debugger/cli-debugger.c 2019-01-27 00:06:06.000000000 +0000 @@ -12,6 +12,10 @@ #include #include +#if ENABLE_SCRIPTING +#include +#endif + #if !defined(NDEBUG) && !defined(_WIN32) #include #endif @@ -22,6 +26,7 @@ const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share const char* ERROR_OVERFLOW = "Arguments overflow"; +const char* ERROR_INVALID_ARGS = "Invalid arguments"; #if !defined(NDEBUG) && !defined(_WIN32) static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*); @@ -47,53 +52,61 @@ static void _trace(struct CLIDebugger*, struct CLIDebugVector*); static void _writeByte(struct CLIDebugger*, struct CLIDebugVector*); static void _writeHalfword(struct CLIDebugger*, struct CLIDebugVector*); +static void _writeRegister(struct CLIDebugger*, struct CLIDebugVector*); static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*); +#ifdef ENABLE_SCRIPTING +static void _source(struct CLIDebugger*, struct CLIDebugVector*); +#endif static struct CLIDebuggerCommandSummary _debuggerCommands[] = { - { "b", _setBreakpoint, CLIDVParse, "Set a breakpoint" }, - { "break", _setBreakpoint, CLIDVParse, "Set a breakpoint" }, - { "c", _continue, 0, "Continue execution" }, - { "continue", _continue, 0, "Continue execution" }, - { "d", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" }, - { "delete", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" }, - { "dis", _disassemble, CLIDVParse, "Disassemble instructions" }, - { "disasm", _disassemble, CLIDVParse, "Disassemble instructions" }, - { "disassemble", _disassemble, CLIDVParse, "Disassemble instructions" }, - { "h", _printHelp, CLIDVStringParse, "Print help" }, - { "help", _printHelp, CLIDVStringParse, "Print help" }, - { "i", _printStatus, 0, "Print the current status" }, - { "info", _printStatus, 0, "Print the current status" }, - { "n", _next, 0, "Execute next instruction" }, - { "next", _next, 0, "Execute next instruction" }, - { "p", _print, CLIDVParse, "Print a value" }, - { "p/t", _printBin, CLIDVParse, "Print a value as binary" }, - { "p/x", _printHex, CLIDVParse, "Print a value as hexadecimal" }, - { "print", _print, CLIDVParse, "Print a value" }, - { "print/t", _printBin, CLIDVParse, "Print a value as binary" }, - { "print/x", _printHex, CLIDVParse, "Print a value as hexadecimal" }, - { "q", _quit, 0, "Quit the emulator" }, - { "quit", _quit, 0, "Quit the emulator" }, - { "reset", _reset, 0, "Reset the emulation" }, - { "r/1", _readByte, CLIDVParse, "Read a byte from a specified offset" }, - { "r/2", _readHalfword, CLIDVParse, "Read a halfword from a specified offset" }, - { "r/4", _readWord, CLIDVParse, "Read a word from a specified offset" }, - { "status", _printStatus, 0, "Print the current status" }, - { "trace", _trace, CLIDVParse, "Trace a fixed number of instructions" }, - { "w", _setWatchpoint, CLIDVParse, "Set a watchpoint" }, - { "w/1", _writeByte, CLIDVParse, "Write a byte at a specified offset" }, - { "w/2", _writeHalfword, CLIDVParse, "Write a halfword at a specified offset" }, - { "w/4", _writeWord, CLIDVParse, "Write a word at a specified offset" }, - { "watch", _setWatchpoint, CLIDVParse, "Set a watchpoint" }, - { "watch/r", _setReadWatchpoint, CLIDVParse, "Set a read watchpoint" }, - { "watch/w", _setWriteWatchpoint, CLIDVParse, "Set a write watchpoint" }, - { "x/1", _dumpByte, CLIDVParse, "Examine bytes at a specified offset" }, - { "x/2", _dumpHalfword, CLIDVParse, "Examine halfwords at a specified offset" }, - { "x/4", _dumpWord, CLIDVParse, "Examine words at a specified offset" }, + { "b", _setBreakpoint, "Is", "Set a breakpoint" }, + { "break", _setBreakpoint, "Is", "Set a breakpoint" }, + { "c", _continue, "", "Continue execution" }, + { "continue", _continue, "", "Continue execution" }, + { "d", _clearBreakpoint, "I", "Delete a breakpoint or watchpoint" }, + { "delete", _clearBreakpoint, "I", "Delete a breakpoint or watchpoint" }, + { "dis", _disassemble, "Ii", "Disassemble instructions" }, + { "disasm", _disassemble, "Ii", "Disassemble instructions" }, + { "disassemble", _disassemble, "Ii", "Disassemble instructions" }, + { "h", _printHelp, "S", "Print help" }, + { "help", _printHelp, "S", "Print help" }, + { "i", _printStatus, "", "Print the current status" }, + { "info", _printStatus, "", "Print the current status" }, + { "n", _next, "", "Execute next instruction" }, + { "next", _next, "", "Execute next instruction" }, + { "p", _print, "I", "Print a value" }, + { "p/t", _printBin, "I", "Print a value as binary" }, + { "p/x", _printHex, "I", "Print a value as hexadecimal" }, + { "print", _print, "I", "Print a value" }, + { "print/t", _printBin, "I", "Print a value as binary" }, + { "print/x", _printHex, "I", "Print a value as hexadecimal" }, + { "q", _quit, "", "Quit the emulator" }, + { "quit", _quit, "", "Quit the emulator" }, + { "reset", _reset, "", "Reset the emulation" }, + { "r/1", _readByte, "I", "Read a byte from a specified offset" }, + { "r/2", _readHalfword, "I", "Read a halfword from a specified offset" }, + { "r/4", _readWord, "I", "Read a word from a specified offset" }, + { "status", _printStatus, "", "Print the current status" }, + { "trace", _trace, "I", "Trace a fixed number of instructions" }, + { "w", _setWatchpoint, "Is", "Set a watchpoint" }, + { "w/1", _writeByte, "II", "Write a byte at a specified offset" }, + { "w/2", _writeHalfword, "II", "Write a halfword at a specified offset" }, + { "w/r", _writeRegister, "SI", "Write a register" }, + { "w/4", _writeWord, "II", "Write a word at a specified offset" }, + { "watch", _setWatchpoint, "Is", "Set a watchpoint" }, + { "watch/r", _setReadWatchpoint, "Is", "Set a read watchpoint" }, + { "watch/w", _setWriteWatchpoint, "Is", "Set a write watchpoint" }, + { "x/1", _dumpByte, "Ii", "Examine bytes at a specified offset" }, + { "x/2", _dumpHalfword, "Ii", "Examine halfwords at a specified offset" }, + { "x/4", _dumpWord, "Ii", "Examine words at a specified offset" }, +#ifdef ENABLE_SCRIPTING + { "source", _source, "S", "Load a script" }, +#endif #if !defined(NDEBUG) && !defined(_WIN32) - { "!", _breakInto, 0, "Break into attached debugger (for developers)" }, + { "!", _breakInto, "", "Break into attached debugger (for developers)" }, #endif { 0, 0, 0, 0 } }; @@ -263,12 +276,12 @@ } static void _writeByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - if (!dv || dv->type != CLIDV_INT_TYPE) { + if (!dv || !dv->next) { debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } - if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + if (dv->type != CLIDV_INT_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); return; } uint32_t address = dv->intValue; @@ -285,12 +298,12 @@ } static void _writeHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - if (!dv || dv->type != CLIDV_INT_TYPE) { + if (!dv || !dv->next) { debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } - if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + if (dv->type != CLIDV_INT_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); return; } uint32_t address = dv->intValue; @@ -306,15 +319,29 @@ } } -static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - if (!dv || dv->type != CLIDV_INT_TYPE) { +static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + if (!dv || !dv->next) { debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } - if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { + if (dv->type != CLIDV_CHAR_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + return; + } + if (!debugger->d.platform->setRegister(debugger->d.platform, dv->charValue, dv->next->intValue)) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + } +} + +static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + if (!dv || !dv->next) { debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } + if (dv->type != CLIDV_INT_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + return; + } uint32_t address = dv->intValue; uint32_t value = dv->next->intValue; if (dv->segmentValue >= 0) { @@ -411,13 +438,67 @@ } } +#ifdef ENABLE_SCRIPTING +static void _source(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + if (!dv) { + debugger->backend->printf(debugger->backend, "Needs a filename\n"); + return; + } + if (debugger->d.bridge && mScriptBridgeLoadScript(debugger->d.bridge, dv->charValue)) { + mScriptBridgeRun(debugger->d.bridge); + } else { + debugger->backend->printf(debugger->backend, "Failed to load script\n"); + } +} +#endif + +static struct ParseTree* _parseTree(const char* string) { + struct LexVector lv; + bool error = false; + LexVectorInit(&lv, 0); + size_t length = strlen(string); + size_t adjusted = lexExpression(&lv, string, length, NULL); + struct ParseTree* tree = malloc(sizeof(*tree)); + if (!adjusted) { + error = true; + } else { + parseLexedExpression(tree, &lv); + + if (adjusted > length) { + error = true; + } else { + length -= adjusted; + string += adjusted; + } + } + lexFree(&lv); + LexVectorClear(&lv); + LexVectorDeinit(&lv); + if (error) { + parseFree(tree); + free(tree); + return NULL; + } else { + return tree; + } +} + static void _setBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue; - debugger->d.platform->setBreakpoint(debugger->d.platform, address, dv->segmentValue); + if (dv->next && dv->next->type == CLIDV_CHAR_TYPE) { + struct ParseTree* tree = _parseTree(dv->next->charValue); + if (tree) { + debugger->d.platform->setConditionalBreakpoint(debugger->d.platform, address, dv->segmentValue, tree); + } else { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + } + } else { + debugger->d.platform->setBreakpoint(debugger->d.platform, address, dv->segmentValue); + } } static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { @@ -430,7 +511,16 @@ return; } uint32_t address = dv->intValue; - debugger->d.platform->setWatchpoint(debugger->d.platform, address, dv->segmentValue, WATCHPOINT_RW); + if (dv->next && dv->next->type == CLIDV_CHAR_TYPE) { + struct ParseTree* tree = _parseTree(dv->next->charValue); + if (tree) { + debugger->d.platform->setConditionalWatchpoint(debugger->d.platform, address, dv->segmentValue, WATCHPOINT_RW, tree); + } else { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + } + } else { + debugger->d.platform->setWatchpoint(debugger->d.platform, address, dv->segmentValue, WATCHPOINT_RW); + } } static void _setReadWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { @@ -443,7 +533,16 @@ return; } uint32_t address = dv->intValue; - debugger->d.platform->setWatchpoint(debugger->d.platform, address, dv->segmentValue, WATCHPOINT_READ); + if (dv->next && dv->next->type == CLIDV_CHAR_TYPE) { + struct ParseTree* tree = _parseTree(dv->next->charValue); + if (tree) { + debugger->d.platform->setConditionalWatchpoint(debugger->d.platform, address, dv->segmentValue, WATCHPOINT_READ, tree); + } else { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + } + } else { + debugger->d.platform->setWatchpoint(debugger->d.platform, address, dv->segmentValue, WATCHPOINT_READ); + } } static void _setWriteWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { @@ -456,8 +555,16 @@ return; } uint32_t address = dv->intValue; - debugger->d.platform->setWatchpoint(debugger->d.platform, address, dv->segmentValue, WATCHPOINT_WRITE); -} + if (dv->next && dv->next->type == CLIDV_CHAR_TYPE) { + struct ParseTree* tree = _parseTree(dv->next->charValue); + if (tree) { + debugger->d.platform->setConditionalWatchpoint(debugger->d.platform, address, dv->segmentValue, WATCHPOINT_WRITE, tree); + } else { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + } + } else { + debugger->d.platform->setWatchpoint(debugger->d.platform, address, dv->segmentValue, WATCHPOINT_WRITE); + }} static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { @@ -497,81 +604,6 @@ debugger->system->printStatus(debugger->system); } -static uint32_t _performOperation(enum Operation operation, uint32_t current, uint32_t next, struct CLIDebugVector* dv) { - switch (operation) { - case OP_ASSIGN: - current = next; - break; - case OP_ADD: - current += next; - break; - case OP_SUBTRACT: - current -= next; - break; - case OP_MULTIPLY: - current *= next; - break; - case OP_DIVIDE: - if (next != 0) { - current /= next; - } else { - dv->type = CLIDV_ERROR_TYPE; - return 0; - } - break; - } - return current; -} - -static void _lookupIdentifier(struct mDebugger* debugger, const char* name, struct CLIDebugVector* dv) { - struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; - if (cliDebugger->system) { - uint32_t value; - if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, &dv->intValue, &dv->segmentValue)) { - return; - } - value = cliDebugger->system->lookupPlatformIdentifier(cliDebugger->system, name, dv); - if (dv->type != CLIDV_ERROR_TYPE) { - dv->intValue = value; - return; - } - dv->type = CLIDV_INT_TYPE; - value = cliDebugger->system->lookupIdentifier(cliDebugger->system, name, dv); - if (dv->type != CLIDV_ERROR_TYPE) { - dv->intValue = value; - return; - } - } - dv->type = CLIDV_ERROR_TYPE; -} - -static void _evaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, struct CLIDebugVector* dv) { - int32_t lhs, rhs; - switch (tree->token.type) { - case TOKEN_UINT_TYPE: - dv->intValue = tree->token.uintValue; - break; - case TOKEN_SEGMENT_TYPE: - _evaluateParseTree(debugger, tree->lhs, dv); - dv->segmentValue = dv->intValue; - _evaluateParseTree(debugger, tree->rhs, dv); - break; - case TOKEN_OPERATOR_TYPE: - _evaluateParseTree(debugger, tree->lhs, dv); - lhs = dv->intValue; - _evaluateParseTree(debugger, tree->rhs, dv); - rhs = dv->intValue; - dv->intValue = _performOperation(tree->token.operatorValue, lhs, rhs, dv); - break; - case TOKEN_IDENTIFIER_TYPE: - _lookupIdentifier(debugger, tree->token.identifierValue, dv); - break; - case TOKEN_ERROR_TYPE: - default: - dv->type = CLIDV_ERROR_TYPE; - } -} - struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length) { if (!string || length < 1) { return 0; @@ -579,11 +611,11 @@ struct CLIDebugVector dvTemp = { .type = CLIDV_INT_TYPE, .segmentValue = -1 }; - struct LexVector lv = { .next = 0 }; - size_t adjusted = lexExpression(&lv, string, length); + struct LexVector lv; + LexVectorInit(&lv, 0); + size_t adjusted = lexExpression(&lv, string, length, " "); if (adjusted > length) { dvTemp.type = CLIDV_ERROR_TYPE; - lexFree(lv.next); } struct ParseTree tree; @@ -591,14 +623,15 @@ if (tree.token.type == TOKEN_ERROR_TYPE) { dvTemp.type = CLIDV_ERROR_TYPE; } else { - _evaluateParseTree(&debugger->d, &tree, &dvTemp); + if (!mDebuggerEvaluateParseTree(&debugger->d, &tree, &dvTemp.intValue, &dvTemp.segmentValue)) { + dvTemp.type = CLIDV_ERROR_TYPE; + } } - parseFree(tree.lhs); - parseFree(tree.rhs); + parseFree(&tree); - length -= adjusted; - string += adjusted; + lexFree(&lv); + LexVectorDeinit(&lv); struct CLIDebugVector* dv = malloc(sizeof(struct CLIDebugVector)); if (dvTemp.type == CLIDV_ERROR_TYPE) { @@ -606,43 +639,22 @@ dv->next = 0; } else { *dv = dvTemp; - if (string[0] == ' ') { - dv->next = CLIDVParse(debugger, string + 1, length - 1); - if (dv->next && dv->next->type == CLIDV_ERROR_TYPE) { - dv->type = CLIDV_ERROR_TYPE; - } - } } return dv; } struct CLIDebugVector* CLIDVStringParse(struct CLIDebugger* debugger, const char* string, size_t length) { + UNUSED(debugger); if (!string || length < 1) { return 0; } struct CLIDebugVector dvTemp = { .type = CLIDV_CHAR_TYPE }; - size_t adjusted; - const char* next = strchr(string, ' '); - if (next) { - adjusted = next - string; - } else { - adjusted = length; - } - dvTemp.charValue = strndup(string, adjusted); - - length -= adjusted; - string += adjusted; + dvTemp.charValue = strndup(string, length); struct CLIDebugVector* dv = malloc(sizeof(struct CLIDebugVector)); *dv = dvTemp; - if (string[0] == ' ') { - dv->next = CLIDVStringParse(debugger, string + 1, length - 1); - if (dv->next && dv->next->type == CLIDV_ERROR_TYPE) { - dv->type = CLIDV_ERROR_TYPE; - } - } return dv; } @@ -658,8 +670,28 @@ } } +static struct CLIDebugVector* _parseArg(struct CLIDebugger* debugger, const char* args, size_t argsLen, char type) { + struct CLIDebugVector* dv = NULL; + switch (type) { + case 'I': + case 'i': + return CLIDVParse(debugger, args, argsLen); + case 'S': + case 's': + return CLIDVStringParse(debugger, args, argsLen); + case '*': + dv = _parseArg(debugger, args, argsLen, 'I'); + if (!dv) { + dv = _parseArg(debugger, args, argsLen, 'S'); + } + break; + } + return dv; +} + static int _tryCommands(struct CLIDebugger* debugger, struct CLIDebuggerCommandSummary* commands, const char* command, size_t commandLen, const char* args, size_t argsLen) { - struct CLIDebugVector* dv = 0; + struct CLIDebugVector* dv = NULL; + struct CLIDebugVector* dvLast = NULL; int i; const char* name; for (i = 0; (name = commands[i].name); ++i) { @@ -667,22 +699,78 @@ continue; } if (strncasecmp(name, command, commandLen) == 0) { - if (commands[i].parser) { - if (args) { - dv = commands[i].parser(debugger, args, argsLen); - if (dv && dv->type == CLIDV_ERROR_TYPE) { + if (commands[i].format && args) { + char lastArg = '\0'; + int arg; + for (arg = 0; commands[i].format[arg] && argsLen; ++arg) { + while (isspace(args[0]) && argsLen) { + ++args; + --argsLen; + } + if (!args[0] || !argsLen) { + debugger->backend->printf(debugger->backend, "Wrong number of arguments\n"); + _DVFree(dv); + return 0; + } + + size_t adjusted; + const char* next = strchr(args, ' '); + if (next) { + adjusted = next - args; + } else { + adjusted = argsLen; + } + + struct CLIDebugVector* dvNext = NULL; + bool nextArgMandatory = false; + + if (commands[i].format[arg] == '+') { + dvNext = _parseArg(debugger, args, adjusted, lastArg); + --args; + } else { + nextArgMandatory = isupper(commands[i].format[arg]) || (commands[i].format[arg] == '*'); + dvNext = _parseArg(debugger, args, adjusted, commands[i].format[arg]); + } + + args += adjusted; + argsLen -= adjusted; + + if (!dvNext) { + if (!nextArgMandatory) { + args = NULL; + } + break; + } + if (dvNext->type == CLIDV_ERROR_TYPE) { debugger->backend->printf(debugger->backend, "Parse error\n"); _DVFree(dv); - return false; + return 0; + } + + if (dvLast) { + dvLast->next = dvNext; + dvLast = dvNext; + } else { + dv = dvNext; + dvLast = dv; } } - } else if (args) { + } + + if (args) { + while (isspace(args[0]) && argsLen) { + ++args; + --argsLen; + } + } + if (args && argsLen) { debugger->backend->printf(debugger->backend, "Wrong number of arguments\n"); - return false; + _DVFree(dv); + return 0; } commands[i].command(debugger, dv); _DVFree(dv); - return true; + return 1; } } return -1; @@ -753,9 +841,9 @@ case DEBUGGER_ENTER_WATCHPOINT: if (info) { if (info->type.wp.accessType & WATCHPOINT_WRITE) { - cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (new value = 0x%08x, old value = 0x%08X)\n", info->address, info->type.wp.newValue, info->type.wp.oldValue); + cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (new value = 0x%08X, old value = 0x%08X)\n", info->address, info->type.wp.newValue, info->type.wp.oldValue); } else { - cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (value = 0x%08x)\n", info->address, info->type.wp.oldValue); + cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (value = 0x%08X)\n", info->address, info->type.wp.oldValue); } } else { cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint\n"); @@ -808,6 +896,7 @@ debugger->d.custom = _cliDebuggerCustom; debugger->d.paused = _commandLine; debugger->d.entered = _reportEntry; + debugger->d.type = DEBUGGER_CLI; debugger->system = NULL; debugger->backend = NULL; diff -Nru mgba-0.6.3+dfsg1/src/debugger/debugger.c mgba-0.7.0/src/debugger/debugger.c --- mgba-0.6.3+dfsg1/src/debugger/debugger.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/debugger/debugger.c 2019-01-27 00:06:06.000000000 +0000 @@ -8,11 +8,16 @@ #include #include +#include #ifdef USE_GDB_STUB #include #endif +#if ENABLE_SCRIPTING +#include +#endif + const uint32_t DEBUGGER_ID = 0xDEADBEEF; mLOG_DEFINE_CATEGORY(DEBUGGER, "Debugger", "core.debugger"); @@ -34,6 +39,7 @@ }; union DebugUnion* debugger = malloc(sizeof(union DebugUnion)); + memset(debugger, 0, sizeof(*debugger)); switch (type) { case DEBUGGER_CLI: @@ -109,6 +115,11 @@ if (debugger->platform->entered) { debugger->platform->entered(debugger->platform, reason, info); } +#ifdef ENABLE_SCRIPTING + if (debugger->bridge) { + mScriptBridgeDebuggerEntered(debugger->bridge, reason, info); + } +#endif } static void mDebuggerInit(void* cpu, struct mCPUComponent* component) { @@ -127,3 +138,22 @@ } debugger->platform->deinit(debugger->platform); } + +bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int32_t* value, int* segment) { + *segment = -1; +#ifdef ENABLE_SCRIPTING + if (debugger->bridge && mScriptBridgeLookupSymbol(debugger->bridge, name, value)) { + return true; + } +#endif + if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, value, segment)) { + return true; + } + if (debugger->core->lookupIdentifier(debugger->core, name, value, segment)) { + return true; + } + if (debugger->platform && debugger->platform->getRegister(debugger->platform, name, value)) { + return true; + } + return false; +} diff -Nru mgba-0.6.3+dfsg1/src/debugger/gdb-stub.c mgba-0.7.0/src/debugger/gdb-stub.c --- mgba-0.6.3+dfsg1/src/debugger/gdb-stub.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/debugger/gdb-stub.c 2019-01-27 00:06:06.000000000 +0000 @@ -658,6 +658,7 @@ stub->d.paused = _gdbStubWait; stub->d.entered = _gdbStubEntered; stub->d.custom = _gdbStubPoll; + stub->d.type = DEBUGGER_GDB; stub->untilPoll = GDB_STUB_INTERVAL; stub->lineAck = GDB_ACK_PENDING; stub->shouldBlock = false; diff -Nru mgba-0.6.3+dfsg1/src/debugger/parser.c mgba-0.7.0/src/debugger/parser.c --- mgba-0.6.3+dfsg1/src/debugger/parser.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/debugger/parser.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,39 +5,181 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include -static struct LexVector* _lexOperator(struct LexVector* lv, char operator) { - struct LexVector* lvNext = malloc(sizeof(struct LexVector)); - lvNext->token.type = TOKEN_OPERATOR_TYPE; +DEFINE_VECTOR(LexVector, struct Token); + +enum LexState { + LEX_ERROR = -1, + LEX_ROOT = 0, + LEX_EXPECT_IDENTIFIER, + LEX_EXPECT_BINARY_FIRST, + LEX_EXPECT_BINARY, + LEX_EXPECT_DECIMAL, + LEX_EXPECT_HEX_FIRST, + LEX_EXPECT_HEX, + LEX_EXPECT_PREFIX, + LEX_EXPECT_OPERATOR, + LEX_EXPECT_OPERATOR2, +}; + +static void _lexOperator(struct LexVector* lv, char operator, enum LexState* state) { + if (*state == LEX_EXPECT_OPERATOR2) { + struct Token* lvNext = LexVectorGetPointer(lv, LexVectorSize(lv) - 1); + if (lvNext->type != TOKEN_OPERATOR_TYPE) { + lvNext->type = TOKEN_ERROR_TYPE; + *state = LEX_ERROR; + return; + } + switch (lvNext->operatorValue) { + case OP_AND: + if (operator == '&') { + lvNext->operatorValue = OP_LOGICAL_AND; + *state = LEX_ROOT; + return; + } + break; + case OP_OR: + if (operator == '|') { + lvNext->operatorValue = OP_LOGICAL_OR; + *state = LEX_ROOT; + return; + } + break; + case OP_LESS: + if (operator == '=') { + lvNext->operatorValue = OP_LE; + *state = LEX_ROOT; + return; + } + if (operator == '<') { + lvNext->operatorValue = OP_SHIFT_L; + *state = LEX_ROOT; + return; + } + break; + case OP_GREATER: + if (operator == '=') { + lvNext->operatorValue = OP_GE; + *state = LEX_ROOT; + return; + } + if (operator == '>') { + lvNext->operatorValue = OP_SHIFT_R; + *state = LEX_ROOT; + return; + } + break; + case OP_ASSIGN: + if (operator == '=') { + lvNext->operatorValue = OP_EQUAL; + *state = LEX_ROOT; + return; + } + break; + case OP_NOT: + if (operator == '=') { + lvNext->operatorValue = OP_NOT_EQUAL; + *state = LEX_ROOT; + return; + } + break; + default: + break; + } + *state = LEX_ERROR; + return; + } + struct Token* lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_OPERATOR_TYPE; + *state = LEX_EXPECT_OPERATOR2; switch (operator) { + case '=': + lvNext->operatorValue = OP_ASSIGN; + break; case '+': - lvNext->token.operatorValue = OP_ADD; + lvNext->operatorValue = OP_ADD; break; case '-': - lvNext->token.operatorValue = OP_SUBTRACT; + lvNext->operatorValue = OP_SUBTRACT; break; case '*': - lvNext->token.operatorValue = OP_MULTIPLY; + lvNext->operatorValue = OP_MULTIPLY; + break; + case '/': + lvNext->operatorValue = OP_DIVIDE; + break; + case '%': + lvNext->operatorValue = OP_MODULO; + break; + case '&': + lvNext->operatorValue = OP_AND; break; + case '|': + lvNext->operatorValue = OP_OR; + break; + case '^': + lvNext->operatorValue = OP_XOR; + break; + case '<': + lvNext->operatorValue = OP_LESS; + break; + case '>': + lvNext->operatorValue = OP_GREATER; + break; + case '!': + lvNext->operatorValue = OP_NOT; + break; + default: + lvNext->type = TOKEN_ERROR_TYPE; + break; + } +} + +static void _lexValue(struct LexVector* lv, char token, uint32_t next, enum LexState* state) { + struct Token* lvNext; + + switch (token) { + case '=': + case '+': + case '-': + case '*': case '/': - lvNext->token.operatorValue = OP_DIVIDE; + case '%': + case '&': + case '|': + case '^': + case '<': + case '>': + case '!': + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_UINT_TYPE; + lvNext->uintValue = next; + _lexOperator(lv, token, state); + break; + case ')': + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_UINT_TYPE; + lvNext->uintValue = next; + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_CLOSE_PAREN_TYPE; + *state = LEX_EXPECT_OPERATOR; + break; + case ' ': + case '\t': + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_UINT_TYPE; + lvNext->uintValue = next; + *state = LEX_EXPECT_OPERATOR; break; default: - lvNext->token.type = TOKEN_ERROR_TYPE; + *state = LEX_ERROR; break; } - lvNext->next = lv->next; - lv->next = lvNext; - lv = lvNext; - lvNext = malloc(sizeof(struct LexVector)); - lvNext->next = lv->next; - lvNext->token.type = TOKEN_ERROR_TYPE; - lv->next = lvNext; - return lvNext; } -size_t lexExpression(struct LexVector* lv, const char* string, size_t length) { +size_t lexExpression(struct LexVector* lv, const char* string, size_t length, const char* eol) { if (!string || length < 1) { return 0; } @@ -47,14 +189,32 @@ enum LexState state = LEX_ROOT; const char* tokenStart = 0; - struct LexVector* lvNext; + struct Token* lvNext; + + if (!eol) { + eol = " \r\n"; + } - while (length > 0 && string[0] && string[0] != ' ' && state != LEX_ERROR) { + while (length > 0 && string[0] && !strchr(eol, string[0]) && state != LEX_ERROR) { char token = string[0]; ++string; ++adjusted; --length; switch (state) { + case LEX_EXPECT_OPERATOR2: + switch (token) { + case '&': + case '|': + case '=': + case '<': + case '>': + _lexOperator(lv, token, &state); + break; + } + if (state != LEX_EXPECT_OPERATOR2) { + break; + } + // Fall through case LEX_ROOT: tokenStart = string - 1; switch (token) { @@ -75,17 +235,20 @@ next = 0; break; case '$': - state = LEX_EXPECT_HEX; + state = LEX_EXPECT_HEX_FIRST; + next = 0; + break; + case '%': + state = LEX_EXPECT_BINARY_FIRST; next = 0; break; case '(': state = LEX_ROOT; - lv->token.type = TOKEN_OPEN_PAREN_TYPE; - lvNext = malloc(sizeof(struct LexVector)); - lvNext->next = lv->next; - lvNext->token.type = TOKEN_ERROR_TYPE; - lv->next = lvNext; - lv = lvNext; + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_OPEN_PAREN_TYPE; + break; + case ' ': + case '\t': break; default: if (tolower(token) >= 'a' && tolower(token <= 'z')) { @@ -98,24 +261,45 @@ break; case LEX_EXPECT_IDENTIFIER: switch (token) { + case '=': case '+': case '-': case '*': case '/': - lv->token.type = TOKEN_IDENTIFIER_TYPE; - lv->token.identifierValue = strndup(tokenStart, string - tokenStart - 1); - lv = _lexOperator(lv, token); - state = LEX_ROOT; + case '%': + case '&': + case '|': + case '^': + case '<': + case '>': + case '!': + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_IDENTIFIER_TYPE; + lvNext->identifierValue = strndup(tokenStart, string - tokenStart - 1); + _lexOperator(lv, token, &state); break; case ')': - lv->token.type = TOKEN_IDENTIFIER_TYPE; - lv->token.identifierValue = strndup(tokenStart, string - tokenStart - 1); + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_IDENTIFIER_TYPE; + lvNext->identifierValue = strndup(tokenStart, string - tokenStart - 1); + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_CLOSE_PAREN_TYPE; + state = LEX_EXPECT_OPERATOR; + break; + case ' ': + case '\t': + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_IDENTIFIER_TYPE; + lvNext->identifierValue = strndup(tokenStart, string - tokenStart - 1); state = LEX_EXPECT_OPERATOR; break; default: break; } break; + case LEX_EXPECT_BINARY_FIRST: + state = LEX_EXPECT_BINARY; + // Fall through case LEX_EXPECT_BINARY: switch (token) { case '0': @@ -124,22 +308,8 @@ next <<= 1; next += token - '0'; break; - case '+': - case '-': - case '*': - case '/': - lv->token.type = TOKEN_UINT_TYPE; - lv->token.uintValue = next; - lv = _lexOperator(lv, token); - state = LEX_ROOT; - break; - case ')': - lv->token.type = TOKEN_UINT_TYPE; - lv->token.uintValue = next; - state = LEX_EXPECT_OPERATOR; - break; default: - state = LEX_ERROR; + _lexValue(lv, token, next, &state); break; } break; @@ -159,24 +329,14 @@ next *= 10; next += token - '0'; break; - case '+': - case '-': - case '*': - case '/': - lv->token.type = TOKEN_UINT_TYPE; - lv->token.uintValue = next; - lv = _lexOperator(lv, token); - state = LEX_ROOT; - break; - case ')': - lv->token.type = TOKEN_UINT_TYPE; - lv->token.uintValue = next; - state = LEX_EXPECT_OPERATOR; - break; default: - state = LEX_ERROR; + _lexValue(lv, token, next, &state); + break; } break; + case LEX_EXPECT_HEX_FIRST: + state = LEX_EXPECT_HEX; + // Fall through case LEX_EXPECT_HEX: switch (token) { case '0': @@ -213,33 +373,14 @@ next *= 16; next += token - 'a' + 10; break; - case '+': - case '-': - case '*': - case '/': - lv->token.type = TOKEN_UINT_TYPE; - lv->token.uintValue = next; - lv = _lexOperator(lv, token); - state = LEX_ROOT; - break; case ':': - lv->token.type = TOKEN_SEGMENT_TYPE; - lv->token.uintValue = next; - lvNext = malloc(sizeof(struct LexVector)); - lvNext->next = lv->next; - lvNext->token.type = TOKEN_UINT_TYPE; - lv->next = lvNext; - lv = lvNext; + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_SEGMENT_TYPE; + lvNext->uintValue = next; next = 0; - state = LEX_EXPECT_HEX; - break; - case ')': - lv->token.type = TOKEN_UINT_TYPE; - lv->token.uintValue = next; - state = LEX_EXPECT_OPERATOR; break; default: - state = LEX_ERROR; + _lexValue(lv, token, next, &state); break; } break; @@ -248,26 +389,12 @@ case 'X': case 'x': next = 0; - state = LEX_EXPECT_HEX; + state = LEX_EXPECT_HEX_FIRST; break; case 'B': case 'b': next = 0; - state = LEX_EXPECT_BINARY; - break; - case '+': - case '-': - case '*': - case '/': - lv->token.type = TOKEN_UINT_TYPE; - lv->token.uintValue = next; - lv = _lexOperator(lv, token); - state = LEX_ROOT; - break; - case ')': - lv->token.type = TOKEN_UINT_TYPE; - lv->token.uintValue = next; - state = LEX_EXPECT_OPERATOR; + state = LEX_EXPECT_BINARY_FIRST; break; case '0': case '1': @@ -283,21 +410,32 @@ state = LEX_EXPECT_DECIMAL; break; default: - state = LEX_ERROR; + _lexValue(lv, token, next, &state); + break; } break; case LEX_EXPECT_OPERATOR: switch (token) { + case '=': case '+': case '-': case '*': case '/': - lvNext = malloc(sizeof(struct LexVector)); - lvNext->next = lv->next; - lvNext->token.type = TOKEN_CLOSE_PAREN_TYPE; - lv->next = lvNext; - lv = _lexOperator(lv->next, token); - state = LEX_ROOT; + case '%': + case '&': + case '|': + case '^': + case '<': + case '>': + case '!': + _lexOperator(lv, token, &state); + break; + case ')': + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_CLOSE_PAREN_TYPE; + break; + case ' ': + case '\t': break; default: state = LEX_ERROR; @@ -314,33 +452,53 @@ case LEX_EXPECT_DECIMAL: case LEX_EXPECT_HEX: case LEX_EXPECT_PREFIX: - lv->token.type = TOKEN_UINT_TYPE; - lv->token.uintValue = next; + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_UINT_TYPE; + lvNext->uintValue = next; break; case LEX_EXPECT_IDENTIFIER: - lv->token.type = TOKEN_IDENTIFIER_TYPE; - lv->token.identifierValue = strndup(tokenStart, string - tokenStart); + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_IDENTIFIER_TYPE; + lvNext->identifierValue = strndup(tokenStart, string - tokenStart); break; + case LEX_ROOT: case LEX_EXPECT_OPERATOR: - lvNext = malloc(sizeof(struct LexVector)); - lvNext->next = lv->next; - lvNext->token.type = TOKEN_CLOSE_PAREN_TYPE; - lv->next = lvNext; + case LEX_EXPECT_OPERATOR2: break; + case LEX_EXPECT_BINARY_FIRST: + case LEX_EXPECT_HEX_FIRST: case LEX_ERROR: default: - lv->token.type = TOKEN_ERROR_TYPE; + lvNext = LexVectorAppend(lv); + lvNext->type = TOKEN_ERROR_TYPE; break; } return adjusted; } static const int _operatorPrecedence[] = { - 2, - 1, - 1, - 0, - 0 + [OP_ASSIGN] = 14, + [OP_ADD] = 4, + [OP_SUBTRACT] = 4, + [OP_MULTIPLY] = 3, + [OP_DIVIDE] = 3, + [OP_MODULO] = 3, + [OP_AND] = 8, + [OP_OR] = 10, + [OP_XOR] = 9, + [OP_LESS] = 6, + [OP_GREATER] = 6, + [OP_EQUAL] = 7, + [OP_NOT_EQUAL] = 7, + [OP_LE] = 6, + [OP_GE] = 6, + [OP_LOGICAL_AND] = 11, + [OP_LOGICAL_OR] = 12, + [OP_NEGATE] = 2, + [OP_FLIP] = 2, + [OP_NOT] = 2, + [OP_SHIFT_L] = 5, + [OP_SHIFT_R] = 5, }; static struct ParseTree* _parseTreeCreate() { @@ -351,65 +509,69 @@ return tree; } -static struct LexVector* _parseExpression(struct ParseTree* tree, struct LexVector* lv, int precedence, int openParens) { +static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, size_t i, int precedence, int* openParens) { struct ParseTree* newTree = 0; - while (lv) { + while (i < LexVectorSize(lv)) { + struct Token* token = LexVectorGetPointer(lv, i); int newPrecedence; - switch (lv->token.type) { + switch (token->type) { case TOKEN_IDENTIFIER_TYPE: case TOKEN_UINT_TYPE: if (tree->token.type == TOKEN_ERROR_TYPE) { - tree->token = lv->token; - lv = lv->next; + tree->token = *token; + if (token->type == TOKEN_IDENTIFIER_TYPE) { + tree->token.identifierValue = strdup(token->identifierValue); + } + ++i; } else { tree->token.type = TOKEN_ERROR_TYPE; - return 0; + return i + 1; } break; case TOKEN_SEGMENT_TYPE: tree->lhs = _parseTreeCreate(); tree->lhs->token.type = TOKEN_UINT_TYPE; - tree->lhs->token.uintValue = lv->token.uintValue; + tree->lhs->token.uintValue = token->uintValue; tree->rhs = _parseTreeCreate(); tree->token.type = TOKEN_SEGMENT_TYPE; - lv = _parseExpression(tree->rhs, lv->next, precedence, openParens); + i = _parseExpression(tree->rhs, lv, i + 1, precedence, openParens); if (tree->token.type == TOKEN_ERROR_TYPE) { tree->token.type = TOKEN_ERROR_TYPE; } break; case TOKEN_OPEN_PAREN_TYPE: - lv = _parseExpression(tree, lv->next, INT_MAX, openParens + 1); + ++*openParens; + i = _parseExpression(tree, lv, i + 1, INT_MAX, openParens); break; case TOKEN_CLOSE_PAREN_TYPE: - if (openParens <= 0) { + if (*openParens <= 0) { tree->token.type = TOKEN_ERROR_TYPE; - return 0; } - return lv->next; - break; + --*openParens; + return i + 1; case TOKEN_OPERATOR_TYPE: - newPrecedence = _operatorPrecedence[lv->token.operatorValue]; + newPrecedence = _operatorPrecedence[token->operatorValue]; if (newPrecedence < precedence) { newTree = _parseTreeCreate(); *newTree = *tree; tree->lhs = newTree; tree->rhs = _parseTreeCreate(); - tree->token = lv->token; - lv = _parseExpression(tree->rhs, lv->next, newPrecedence, openParens); + tree->token = *token; + i = _parseExpression(tree->rhs, lv, i + 1, newPrecedence, openParens); if (tree->token.type == TOKEN_ERROR_TYPE) { tree->token.type = TOKEN_ERROR_TYPE; } } else { - return lv; + return i; } break; case TOKEN_ERROR_TYPE: tree->token.type = TOKEN_ERROR_TYPE; - return 0; + return i + 1; } } - return 0; + return i; } void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) { @@ -421,14 +583,23 @@ tree->lhs = 0; tree->rhs = 0; - _parseExpression(tree, lv, _operatorPrecedence[OP_ASSIGN], 0); + int openParens = 0; + _parseExpression(tree, lv, 0, INT_MAX, &openParens); + if (openParens) { + if (tree->token.type == TOKEN_IDENTIFIER_TYPE) { + free(tree->token.identifierValue); + } + tree->token.type = TOKEN_ERROR_TYPE; + } } void lexFree(struct LexVector* lv) { - while (lv) { - struct LexVector* lvNext = lv->next; - free(lv); - lv = lvNext; + size_t i; + for (i = 0; i < LexVectorSize(lv); ++i) { + struct Token* token = LexVectorGetPointer(lv, i); + if (token->type == TOKEN_IDENTIFIER_TYPE) { + free(token->identifierValue); + } } } @@ -437,11 +608,124 @@ return; } - parseFree(tree->lhs); - parseFree(tree->rhs); + if (tree->lhs) { + parseFree(tree->lhs); + free(tree->lhs); + } + if (tree->rhs) { + parseFree(tree->rhs); + free(tree->rhs); + } if (tree->token.type == TOKEN_IDENTIFIER_TYPE) { free(tree->token.identifierValue); } - free(tree); +} + +static bool _performOperation(enum Operation operation, int32_t current, int32_t next, int32_t* value) { + switch (operation) { + case OP_ASSIGN: + current = next; + break; + case OP_ADD: + current += next; + break; + case OP_SUBTRACT: + current -= next; + break; + case OP_MULTIPLY: + current *= next; + break; + case OP_DIVIDE: + if (next != 0) { + current /= next; + } else { + return false; + } + break; + case OP_MODULO: + if (next != 0) { + current %= next; + } else { + return false; + } + break; + case OP_AND: + current &= next; + break; + case OP_OR: + current |= next; + break; + case OP_XOR: + current ^= next; + break; + case OP_LESS: + current = current < next; + break; + case OP_GREATER: + current = current > next; + break; + case OP_EQUAL: + current = current == next; + break; + case OP_NOT_EQUAL: + current = current != next; + break; + case OP_LOGICAL_AND: + current = current && next; + break; + case OP_LOGICAL_OR: + current = current || next; + break; + case OP_LE: + current = current <= next; + break; + case OP_GE: + current = current >= next; + break; + case OP_SHIFT_L: + current <<= next; + break; + case OP_SHIFT_R: + current >>= next; + break; + default: + return false; + } + *value = current; + return true; +} + +bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, int32_t* value, int* segment) { + if (!value) { + return false; + } + int32_t lhs, rhs; + switch (tree->token.type) { + case TOKEN_UINT_TYPE: + if (segment) { + *segment = -1; + } + *value = tree->token.uintValue; + return true; + case TOKEN_SEGMENT_TYPE: + if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, value, segment)) { + return false; + } + return mDebuggerEvaluateParseTree(debugger, tree->lhs, segment, NULL); + case TOKEN_OPERATOR_TYPE: + if (!mDebuggerEvaluateParseTree(debugger, tree->lhs, &lhs, segment)) { + return false; + } + if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, &rhs, segment)) { + return false; + } + return _performOperation(tree->token.operatorValue, lhs, rhs, value); + case TOKEN_IDENTIFIER_TYPE: + return mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, value, segment); + case TOKEN_ERROR_TYPE: + default: + break; + } + return false; } diff -Nru mgba-0.6.3+dfsg1/src/debugger/symbols.c mgba-0.7.0/src/debugger/symbols.c --- mgba-0.6.3+dfsg1/src/debugger/symbols.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/debugger/symbols.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,7 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include +#include struct mDebuggerSymbol { int32_t value; @@ -47,3 +49,40 @@ void mDebuggerSymbolRemove(struct mDebuggerSymbols* st, const char* name) { HashTableRemove(&st->names, name); } + +void mDebuggerLoadARMIPSSymbols(struct mDebuggerSymbols* st, struct VFile* vf) { + char line[512]; + + while (true) { + ssize_t bytesRead = vf->readline(vf, line, sizeof(line)); + if (bytesRead <= 0) { + break; + } + if (line[bytesRead - 1] == '\n') { + line[bytesRead - 1] = '\0'; + } + uint32_t address = 0; + const char* buf = line; + buf = hex32(buf, &address); + if (!buf) { + continue; + } + bytesRead -= 8; + + while (isspace((int) buf[0]) && bytesRead > 0) { + --bytesRead; + ++buf; + } + + if (!bytesRead) { + continue; + } + + if (buf[0] == '.') { + // Directives are not handled yet + continue; + } + + mDebuggerSymbolAdd(st, buf, address, -1); + } +} diff -Nru mgba-0.6.3+dfsg1/src/debugger/test/lexer.c mgba-0.7.0/src/debugger/test/lexer.c --- mgba-0.6.3+dfsg1/src/debugger/test/lexer.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/debugger/test/lexer.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,855 @@ +/* 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 + +#define LEX(STR) \ + struct LexVector* lv = *state; \ + lexFree(lv); \ + LexVectorClear(lv); \ + size_t adjusted = lexExpression(lv, STR, strlen(STR), ""); \ + assert_false(adjusted > strlen(STR)) + +M_TEST_SUITE_SETUP(Lexer) { + struct LexVector* lv = malloc(sizeof(struct LexVector)); + LexVectorInit(lv, 0); + *state = lv; + return 0; +} + +M_TEST_SUITE_TEARDOWN(Lexer) { + struct LexVector* lv = *state; + lexFree(lv); + LexVectorDeinit(lv); + free(lv); + return 0; +} + +M_TEST_DEFINE(lexEmpty) { + LEX(""); + + assert_int_equal(LexVectorSize(lv), 0); +} + +M_TEST_DEFINE(lexInt) { + LEX("0"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 0); +} + +M_TEST_DEFINE(lexDecimal) { + LEX("10"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 10); +} + +M_TEST_DEFINE(lexBinary) { + LEX("0b10"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 2); +} + +M_TEST_DEFINE(lexSigilBinary) { + LEX("%10"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 2); +} + +M_TEST_DEFINE(lexHex) { + LEX("0x10"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 0x10); +} + +M_TEST_DEFINE(lexSigilHex) { + LEX("$10"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 0x10); +} + +M_TEST_DEFINE(lexInvalidDecimal) { + LEX("1a"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexInvalidBinary) { + LEX("0b12"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexInvalidHex) { + LEX("0x1g"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexTruncatedBinary) { + LEX("0b"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexTruncatedSigilBinary) { + LEX("%"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexTruncatedSigilHex) { + LEX("$"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexTruncatedHex) { + LEX("0x"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexSigilSegmentHex) { + LEX("$01:0010"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_SEGMENT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->uintValue, 0x10); +} + +M_TEST_DEFINE(lexIdentifier) { + LEX("x"); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); +} + +M_TEST_DEFINE(lexAddOperator) { + LEX("1+"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_ADD); +} + +M_TEST_DEFINE(lexIdentifierAddOperator) { + LEX("x+"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_ADD); +} + +M_TEST_DEFINE(lexSubOperator) { + LEX("1-"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_SUBTRACT); +} + +M_TEST_DEFINE(lexIdentifierSubOperator) { + LEX("x-"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_SUBTRACT); +} + +M_TEST_DEFINE(lexMulOperator) { + LEX("1*"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_MULTIPLY); +} + +M_TEST_DEFINE(lexIdentifierMulOperator) { + LEX("x*"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_MULTIPLY); +} + +M_TEST_DEFINE(lexDivOperator) { + LEX("1/"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_DIVIDE); +} + +M_TEST_DEFINE(lexIdentifierDivOperator) { + LEX("x/"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_DIVIDE); +} + +M_TEST_DEFINE(lexModOperator) { + LEX("1%"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_MODULO); +} + +M_TEST_DEFINE(lexIdentifierModOperator) { + LEX("x%"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_MODULO); +} + +M_TEST_DEFINE(lexAndOperator) { + LEX("1&"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_AND); +} + +M_TEST_DEFINE(lexIdentifierAndOperator) { + LEX("x&"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_AND); +} + +M_TEST_DEFINE(lexOrOperator) { + LEX("1|"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_OR); +} + +M_TEST_DEFINE(lexIdentifierOrOperator) { + LEX("x|"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_OR); +} + +M_TEST_DEFINE(lexXorOperator) { + LEX("1^"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_XOR); +} + +M_TEST_DEFINE(lexIdentifierXorOperator) { + LEX("x^"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_XOR); +} + +M_TEST_DEFINE(lexLessOperator) { + LEX("1<"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LESS); +} + +M_TEST_DEFINE(lexIdentifierLessOperator) { + LEX("x<"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LESS); +} + +M_TEST_DEFINE(lexGreaterOperator) { + LEX("1>"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_GREATER); +} + +M_TEST_DEFINE(lexIdentifierGreaterOperator) { + LEX("x>"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_GREATER); +} + +M_TEST_DEFINE(lexEqualsOperator) { + LEX("1=="); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_EQUAL); +} + +M_TEST_DEFINE(lexIdentifierEqualsOperator) { + LEX("x=="); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_EQUAL); +} + +M_TEST_DEFINE(lexNotEqualsOperator) { + LEX("1!="); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_NOT_EQUAL); +} + +M_TEST_DEFINE(lexIdentifierNotEqualsOperator) { + LEX("x!="); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_NOT_EQUAL); +} + +M_TEST_DEFINE(lexLEOperator) { + LEX("1<="); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LE); +} + +M_TEST_DEFINE(lexIdentifierLEOperator) { + LEX("x<="); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LE); +} + +M_TEST_DEFINE(lexGEOperator) { + LEX("1>="); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_GE); +} + +M_TEST_DEFINE(lexIdentifierGEOperator) { + LEX("x>="); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_GE); +} + +M_TEST_DEFINE(lexLAndOperator) { + LEX("1&&"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LOGICAL_AND); +} + +M_TEST_DEFINE(lexIdentifierLAndOperator) { + LEX("x&&"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LOGICAL_AND); +} + +M_TEST_DEFINE(lexLOrOperator) { + LEX("1||"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LOGICAL_OR); +} + +M_TEST_DEFINE(lexIdentifierLOrOperator) { + LEX("x||"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LOGICAL_OR); +} + +M_TEST_DEFINE(lexShiftLOperator) { + LEX("1<<"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_SHIFT_L); +} + +M_TEST_DEFINE(lexIdentifierShiftLOperator) { + LEX("x<<"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_SHIFT_L); +} + +M_TEST_DEFINE(lexShiftROperator) { + LEX("1>>"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_SHIFT_R); +} + +M_TEST_DEFINE(lexIdentifierShiftROperator) { + LEX("x>>"); + + assert_int_equal(LexVectorSize(lv), 2); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_SHIFT_R); +} + +M_TEST_DEFINE(lexEqualsInvalidOperator) { + LEX("1=|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_ASSIGN); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexIdentifierEqualsInvalidOperator) { + LEX("x=|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_ASSIGN); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexNotInvalidOperator) { + LEX("1!|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_NOT); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexIdentifierNotInvalidOperator) { + LEX("x!|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_NOT); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexLessInvalidOperator) { + LEX("1<|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LESS); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexIdentifierLessInvalidOperator) { + LEX("x<|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_LESS); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexGreaterInvalidOperator) { + LEX("1>|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_GREATER); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexIdentifierGreaterInvalidOperator) { + LEX("x>|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_GREATER); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexAndInvalidOperator) { + LEX("1&|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_AND); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexIdentifierAndInvalidOperator) { + LEX("x&|"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_AND); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexOrInvalidOperator) { + LEX("1|>"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_OR); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexIdentifierOrInvalidOperator) { + LEX("x|>"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_OR); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(lexSimpleExpression) { + LEX("1+1"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_ADD); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 2)->uintValue, 1); +} + +M_TEST_DEFINE(lexOpenParen) { + LEX("("); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_OPEN_PAREN_TYPE); +} + +M_TEST_DEFINE(lexCloseParen) { + LEX("(0)"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_OPEN_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->uintValue, 0); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_CLOSE_PAREN_TYPE); +} + +M_TEST_DEFINE(lexIdentifierCloseParen) { + LEX("(x)"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_OPEN_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 1)->identifierValue, "x"); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_CLOSE_PAREN_TYPE); +} + +M_TEST_DEFINE(lexParentheticalExpression) { + LEX("(1+1)"); + + assert_int_equal(LexVectorSize(lv), 5); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_OPEN_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 2)->operatorValue, OP_ADD); + assert_int_equal(LexVectorGetPointer(lv, 3)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 3)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 4)->type, TOKEN_CLOSE_PAREN_TYPE); +} + +M_TEST_DEFINE(lexNestedParentheticalExpression) { + LEX("(1+(2+3))"); + + assert_int_equal(LexVectorSize(lv), 9); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_OPEN_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 2)->operatorValue, OP_ADD); + assert_int_equal(LexVectorGetPointer(lv, 3)->type, TOKEN_OPEN_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 4)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 4)->uintValue, 2); + assert_int_equal(LexVectorGetPointer(lv, 5)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 5)->operatorValue, OP_ADD); + assert_int_equal(LexVectorGetPointer(lv, 6)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 6)->uintValue, 3); + assert_int_equal(LexVectorGetPointer(lv, 7)->type, TOKEN_CLOSE_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 8)->type, TOKEN_CLOSE_PAREN_TYPE); +} + +M_TEST_DEFINE(lexSpaceSimple) { + LEX(" 1 "); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); +} + +M_TEST_DEFINE(lexSpaceIdentifier) { + LEX(" x "); + + assert_int_equal(LexVectorSize(lv), 1); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE); + assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x"); +} + +M_TEST_DEFINE(lexSpaceOperator) { + LEX("1 + 2"); + + assert_int_equal(LexVectorSize(lv), 3); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_ADD); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 2)->uintValue, 2); +} + +M_TEST_DEFINE(lexSpaceParen) { + LEX(" ( 1 + 2 ) "); + + assert_int_equal(LexVectorSize(lv), 5); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_OPEN_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 2)->operatorValue, OP_ADD); + assert_int_equal(LexVectorGetPointer(lv, 3)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 3)->uintValue, 2); + assert_int_equal(LexVectorGetPointer(lv, 4)->type, TOKEN_CLOSE_PAREN_TYPE); +} + +M_TEST_DEFINE(lexSpaceParens) { + LEX(" ( 1 + ( 2 + 3 ) ) "); + + assert_int_equal(LexVectorSize(lv), 9); + assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_OPEN_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 1)->uintValue, 1); + assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 2)->operatorValue, OP_ADD); + assert_int_equal(LexVectorGetPointer(lv, 3)->type, TOKEN_OPEN_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 4)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 4)->uintValue, 2); + assert_int_equal(LexVectorGetPointer(lv, 5)->type, TOKEN_OPERATOR_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 5)->operatorValue, OP_ADD); + assert_int_equal(LexVectorGetPointer(lv, 6)->type, TOKEN_UINT_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 6)->uintValue, 3); + assert_int_equal(LexVectorGetPointer(lv, 7)->type, TOKEN_CLOSE_PAREN_TYPE); + assert_int_equal(LexVectorGetPointer(lv, 8)->type, TOKEN_CLOSE_PAREN_TYPE); +} + +M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(Lexer, + cmocka_unit_test(lexEmpty), + cmocka_unit_test(lexInt), + cmocka_unit_test(lexDecimal), + cmocka_unit_test(lexBinary), + cmocka_unit_test(lexSigilBinary), + cmocka_unit_test(lexHex), + cmocka_unit_test(lexSigilHex), + cmocka_unit_test(lexSigilSegmentHex), + cmocka_unit_test(lexInvalidDecimal), + cmocka_unit_test(lexInvalidHex), + cmocka_unit_test(lexInvalidBinary), + cmocka_unit_test(lexTruncatedHex), + cmocka_unit_test(lexTruncatedSigilHex), + cmocka_unit_test(lexTruncatedBinary), + cmocka_unit_test(lexTruncatedSigilBinary), + cmocka_unit_test(lexIdentifier), + cmocka_unit_test(lexAddOperator), + cmocka_unit_test(lexIdentifierAddOperator), + cmocka_unit_test(lexSubOperator), + cmocka_unit_test(lexIdentifierSubOperator), + cmocka_unit_test(lexMulOperator), + cmocka_unit_test(lexIdentifierMulOperator), + cmocka_unit_test(lexDivOperator), + cmocka_unit_test(lexIdentifierDivOperator), + cmocka_unit_test(lexModOperator), + cmocka_unit_test(lexIdentifierModOperator), + cmocka_unit_test(lexAndOperator), + cmocka_unit_test(lexIdentifierAndOperator), + cmocka_unit_test(lexOrOperator), + cmocka_unit_test(lexIdentifierOrOperator), + cmocka_unit_test(lexXorOperator), + cmocka_unit_test(lexIdentifierXorOperator), + cmocka_unit_test(lexLessOperator), + cmocka_unit_test(lexIdentifierLessOperator), + cmocka_unit_test(lexGreaterOperator), + cmocka_unit_test(lexIdentifierGreaterOperator), + cmocka_unit_test(lexEqualsOperator), + cmocka_unit_test(lexIdentifierEqualsOperator), + cmocka_unit_test(lexNotEqualsOperator), + cmocka_unit_test(lexIdentifierNotEqualsOperator), + cmocka_unit_test(lexLEOperator), + cmocka_unit_test(lexIdentifierLEOperator), + cmocka_unit_test(lexGEOperator), + cmocka_unit_test(lexIdentifierGEOperator), + cmocka_unit_test(lexLAndOperator), + cmocka_unit_test(lexIdentifierLAndOperator), + cmocka_unit_test(lexLOrOperator), + cmocka_unit_test(lexIdentifierLOrOperator), + cmocka_unit_test(lexShiftLOperator), + cmocka_unit_test(lexIdentifierShiftLOperator), + cmocka_unit_test(lexShiftROperator), + cmocka_unit_test(lexIdentifierShiftROperator), + cmocka_unit_test(lexEqualsInvalidOperator), + cmocka_unit_test(lexIdentifierEqualsInvalidOperator), + cmocka_unit_test(lexNotInvalidOperator), + cmocka_unit_test(lexIdentifierNotInvalidOperator), + cmocka_unit_test(lexLessInvalidOperator), + cmocka_unit_test(lexIdentifierLessInvalidOperator), + cmocka_unit_test(lexGreaterInvalidOperator), + cmocka_unit_test(lexIdentifierGreaterInvalidOperator), + cmocka_unit_test(lexAndInvalidOperator), + cmocka_unit_test(lexIdentifierAndInvalidOperator), + cmocka_unit_test(lexOrInvalidOperator), + cmocka_unit_test(lexIdentifierOrInvalidOperator), + cmocka_unit_test(lexSimpleExpression), + cmocka_unit_test(lexOpenParen), + cmocka_unit_test(lexCloseParen), + cmocka_unit_test(lexIdentifierCloseParen), + cmocka_unit_test(lexParentheticalExpression), + cmocka_unit_test(lexNestedParentheticalExpression), + cmocka_unit_test(lexSpaceSimple), + cmocka_unit_test(lexSpaceIdentifier), + cmocka_unit_test(lexSpaceOperator), + cmocka_unit_test(lexSpaceParen), + cmocka_unit_test(lexSpaceParens)) diff -Nru mgba-0.6.3+dfsg1/src/debugger/test/parser.c mgba-0.7.0/src/debugger/test/parser.c --- mgba-0.6.3+dfsg1/src/debugger/test/parser.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/debugger/test/parser.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,118 @@ +/* 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 + +struct LPTest { + struct LexVector lv; + struct ParseTree tree; +}; + +#define PARSE(STR) \ + struct LPTest* lp = *state; \ + lexFree(&lp->lv); \ + LexVectorClear(&lp->lv); \ + size_t adjusted = lexExpression(&lp->lv, STR, strlen(STR), ""); \ + assert_false(adjusted > strlen(STR)); \ + struct ParseTree* tree = &lp->tree; \ + parseLexedExpression(tree, &lp->lv) + +M_TEST_SUITE_SETUP(Parser) { + struct LPTest* lp = malloc(sizeof(struct LPTest)); + LexVectorInit(&lp->lv, 0); + *state = lp; + return 0; +} + +M_TEST_SUITE_TEARDOWN(Parser) { + struct LPTest* lp = *state; + parseFree(&lp->tree); \ + lexFree(&lp->lv); + LexVectorDeinit(&lp->lv); + free(lp); + return 0; +} + +M_TEST_DEFINE(parseEmpty) { + PARSE(""); + + assert_int_equal(tree->token.type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(parseInt) { + PARSE("0"); + + assert_int_equal(tree->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->token.uintValue, 0); +} + +M_TEST_DEFINE(parseLexError) { + PARSE("@"); + + assert_int_equal(tree->token.type, TOKEN_ERROR_TYPE); +} + +M_TEST_DEFINE(parseSimpleExpression) { + PARSE("1+2"); + + assert_int_equal(tree->token.type, TOKEN_OPERATOR_TYPE); + assert_int_equal(tree->token.operatorValue, OP_ADD); + assert_int_equal(tree->lhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->lhs->token.uintValue, 1); + assert_int_equal(tree->rhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->rhs->token.uintValue, 2); +} + +M_TEST_DEFINE(parseAddMultplyExpression) { + PARSE("1+2*3"); + + assert_int_equal(tree->token.type, TOKEN_OPERATOR_TYPE); + assert_int_equal(tree->token.operatorValue, OP_ADD); + assert_int_equal(tree->lhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->lhs->token.uintValue, 1); + assert_int_equal(tree->rhs->token.type, TOKEN_OPERATOR_TYPE); + assert_int_equal(tree->rhs->token.uintValue, OP_MULTIPLY); + assert_int_equal(tree->rhs->lhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->rhs->lhs->token.uintValue, 2); + assert_int_equal(tree->rhs->rhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->rhs->rhs->token.uintValue, 3); +} + +M_TEST_DEFINE(parseParentheticalExpression) { + PARSE("(1+2)"); + + assert_int_equal(tree->token.type, TOKEN_OPERATOR_TYPE); + assert_int_equal(tree->token.operatorValue, OP_ADD); + assert_int_equal(tree->lhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->lhs->token.uintValue, 1); + assert_int_equal(tree->rhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->rhs->token.uintValue, 2); +} + +M_TEST_DEFINE(parseParentheticalAddMultplyExpression) { + PARSE("(1+2)*3"); + + assert_int_equal(tree->token.type, TOKEN_OPERATOR_TYPE); + assert_int_equal(tree->token.operatorValue, OP_MULTIPLY); + assert_int_equal(tree->lhs->token.type, TOKEN_OPERATOR_TYPE); + assert_int_equal(tree->lhs->token.uintValue, OP_ADD); + assert_int_equal(tree->lhs->lhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->lhs->lhs->token.uintValue, 1); + assert_int_equal(tree->lhs->lhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->lhs->rhs->token.uintValue, 2); + assert_int_equal(tree->rhs->token.type, TOKEN_UINT_TYPE); + assert_int_equal(tree->rhs->token.uintValue, 3); +} + +M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(Parser, + cmocka_unit_test(parseEmpty), + cmocka_unit_test(parseInt), + cmocka_unit_test(parseLexError), + cmocka_unit_test(parseSimpleExpression), + cmocka_unit_test(parseAddMultplyExpression), + cmocka_unit_test(parseParentheticalExpression), + cmocka_unit_test(parseParentheticalAddMultplyExpression)) diff -Nru mgba-0.6.3+dfsg1/src/feature/commandline.c mgba-0.7.0/src/feature/commandline.c --- mgba-0.6.3+dfsg1/src/feature/commandline.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/commandline.c 2019-01-27 00:06:06.000000000 +0000 @@ -39,7 +39,7 @@ #endif { "help", no_argument, 0, 'h' }, { "log-level", required_argument, 0, 'l' }, - { "movie", required_argument, 0, 'v' }, + { "savestate", required_argument, 0, 't' }, { "patch", required_argument, 0, 'p' }, { "version", no_argument, 0, '\0' }, { 0, 0, 0, 0 } @@ -68,7 +68,7 @@ bool parseArguments(struct mArguments* args, int argc, char* const* argv, struct mSubParser* subparser) { int ch; char options[64] = - "b:c:C:hl:p:s:v:" + "b:c:C:hl:p:s:t:" #ifdef USE_EDITLINE "d" #endif @@ -132,8 +132,8 @@ case 's': args->frameskip = atoi(optarg); break; - case 'v': - args->movie = strdup(optarg); + case 't': + args->savestate = strdup(optarg); break; default: if (subparser) { @@ -179,8 +179,8 @@ free(args->patch); args->patch = 0; - free(args->movie); - args->movie = 0; + free(args->savestate); + args->savestate = 0; free(args->cheatsFile); args->cheatsFile = 0; @@ -244,7 +244,7 @@ puts(" -g, --gdb Start GDB session (default port 2345)"); #endif puts(" -l, --log-level N Log level mask"); - puts(" -v, --movie FILE Play back a movie of recorded input"); + puts(" -t, --savestate FILE Load savestate when starting"); puts(" -p, --patch FILE Apply a specified patch file when running"); puts(" -s, --frameskip N Skip every N frames"); puts(" --version Print version and exit"); diff -Nru mgba-0.6.3+dfsg1/src/feature/ffmpeg/ffmpeg-encoder.c mgba-0.7.0/src/feature/ffmpeg/ffmpeg-encoder.c --- mgba-0.6.3+dfsg1/src/feature/ffmpeg/ffmpeg-encoder.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/ffmpeg/ffmpeg-encoder.c 2019-01-27 00:06:06.000000000 +0000 @@ -19,7 +19,11 @@ #include #include +#ifdef USE_LIBAVRESAMPLE #include +#else +#include +#endif #include static void _ffmpegPostVideoFrame(struct mAVStream*, const color_t* pixels, size_t stride); @@ -201,7 +205,6 @@ encoder->currentAudioSample = 0; encoder->currentAudioFrame = 0; encoder->currentVideoFrame = 0; - encoder->nextAudioPts = 0; AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0); #ifndef USE_LIBAV @@ -248,6 +251,7 @@ encoder->audioFrame->nb_samples = encoder->audio->frame_size; encoder->audioFrame->format = encoder->audio->sample_fmt; encoder->audioFrame->pts = 0; +#ifdef USE_LIBAVRESAMPLE encoder->resampleContext = avresample_alloc_context(); av_opt_set_int(encoder->resampleContext, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(encoder->resampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); @@ -256,6 +260,11 @@ av_opt_set_int(encoder->resampleContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int(encoder->resampleContext, "out_sample_fmt", encoder->sampleFormat, 0); avresample_open(encoder->resampleContext); +#else + encoder->resampleContext = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, encoder->sampleFormat, encoder->sampleRate, + AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, PREFERRED_SAMPLE_RATE, 0, NULL); + swr_init(encoder->resampleContext); +#endif encoder->audioBufferSize = (encoder->audioFrame->nb_samples * PREFERRED_SAMPLE_RATE / encoder->sampleRate) * 4; encoder->audioBuffer = av_malloc(encoder->audioBufferSize); encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0); @@ -291,6 +300,7 @@ encoder->video->width = encoder->width; encoder->video->height = encoder->height; encoder->video->time_base = (AVRational) { VIDEO_TOTAL_LENGTH, GBA_ARM7TDMI_FREQUENCY }; + encoder->video->framerate = (AVRational) { GBA_ARM7TDMI_FREQUENCY, VIDEO_TOTAL_LENGTH }; encoder->video->pix_fmt = encoder->pixFormat; encoder->video->gop_size = 60; encoder->video->max_b_frames = 3; @@ -301,6 +311,15 @@ encoder->video->flags |= CODEC_FLAG_GLOBAL_HEADER; #endif } + + if (encoder->video->codec->id == AV_CODEC_ID_H264 && + (strcasecmp(encoder->containerFormat, "mp4") || + strcasecmp(encoder->containerFormat, "m4v") || + strcasecmp(encoder->containerFormat, "mov"))) { + // QuickTime and a few other things require YUV420 + encoder->video->pix_fmt = AV_PIX_FMT_YUV420P; + } + if (strcmp(vcodec->name, "libx264") == 0) { // Try to adaptively figure out when you can use a slower encoder if (encoder->width * encoder->height > 1000000) { @@ -310,16 +329,16 @@ } else { av_opt_set(encoder->video->priv_data, "preset", "faster", 0); } - av_opt_set(encoder->video->priv_data, "tune", "zerolatency", 0); + if (encoder->videoBitrate == 0) { + av_opt_set(encoder->video->priv_data, "crf", "0", 0); + encoder->video->pix_fmt = AV_PIX_FMT_YUV444P; + } } - - if (encoder->video->codec->id == AV_CODEC_ID_H264 && - (strcasecmp(encoder->containerFormat, "mp4") || - strcasecmp(encoder->containerFormat, "m4v") || - strcasecmp(encoder->containerFormat, "mov"))) { - // QuickTime and a few other things require YUV420 - encoder->video->pix_fmt = AV_PIX_FMT_YUV420P; + if (strcmp(vcodec->name, "libvpx-vp9") == 0 && encoder->videoBitrate == 0) { + av_opt_set(encoder->video->priv_data, "lossless", "1", 0); + encoder->video->pix_fmt = AV_PIX_FMT_YUV444P; } + avcodec_open2(encoder->video, vcodec, 0); #if LIBAVCODEC_VERSION_MAJOR >= 55 encoder->videoFrame = av_frame_alloc(); @@ -362,7 +381,11 @@ avcodec_close(encoder->audio); if (encoder->resampleContext) { +#ifdef USE_LIBAVRESAMPLE avresample_close(encoder->resampleContext); +#else + swr_free(&encoder->resampleContext); +#endif } if (encoder->absf) { @@ -414,10 +437,11 @@ } int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt); + encoder->currentAudioSample = 0; +#ifdef USE_LIBAVRESAMPLE avresample_convert(encoder->resampleContext, 0, 0, 0, (uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4); - encoder->currentAudioSample = 0; if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) { return; } @@ -425,15 +449,25 @@ av_frame_make_writable(encoder->audioFrame); #endif int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize); +#else +#if LIBAVCODEC_VERSION_MAJOR >= 55 + av_frame_make_writable(encoder->audioFrame); +#endif + if (swr_get_out_samples(encoder->resampleContext, encoder->audioBufferSize / 4) < encoder->audioFrame->nb_samples) { + swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4); + return; + } + int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize, + (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4); +#endif - encoder->audioFrame->pts = av_rescale_q(encoder->currentAudioFrame, encoder->audio->time_base, encoder->audioStream->time_base); + encoder->audioFrame->pts = encoder->currentAudioFrame; encoder->currentAudioFrame += samples; AVPacket packet; av_init_packet(&packet); packet.data = 0; packet.size = 0; - packet.pts = encoder->audioFrame->pts; int gotData; #ifdef FFMPEG_USE_PACKETS @@ -443,6 +477,9 @@ #else avcodec_encode_audio2(encoder->audio, &packet, encoder->audioFrame, &gotData); #endif + packet.pts = av_rescale_q(encoder->audioFrame->pts, encoder->audio->time_base, encoder->audioStream->time_base); + packet.dts = packet.pts; + if (gotData) { if (encoder->absf) { AVPacket tempPacket; @@ -501,7 +538,6 @@ av_frame_make_writable(encoder->videoFrame); #endif encoder->videoFrame->pts = av_rescale_q(encoder->currentVideoFrame, encoder->video->time_base, encoder->videoStream->time_base); - packet.pts = encoder->videoFrame->pts; ++encoder->currentVideoFrame; sws_scale(encoder->scaleContext, (const uint8_t* const*) &pixels, (const int*) &stride, 0, encoder->iheight, encoder->videoFrame->data, encoder->videoFrame->linesize); @@ -513,6 +549,7 @@ #else avcodec_encode_video2(encoder->video, &packet, encoder->videoFrame, &gotData); #endif + packet.pts = encoder->videoFrame->pts; if (gotData) { #ifndef FFMPEG_USE_PACKET_UNREF if (encoder->video->coded_frame->key_frame) { diff -Nru mgba-0.6.3+dfsg1/src/feature/ffmpeg/ffmpeg-encoder.h mgba-0.7.0/src/feature/ffmpeg/ffmpeg-encoder.h --- mgba-0.6.3+dfsg1/src/feature/ffmpeg/ffmpeg-encoder.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/ffmpeg/ffmpeg-encoder.h 2019-01-27 00:06:06.000000000 +0000 @@ -56,8 +56,11 @@ AVFrame* audioFrame; size_t currentAudioSample; int64_t currentAudioFrame; - int64_t nextAudioPts; // TODO (0.6): Remove +#ifdef USE_LIBAVRESAMPLE struct AVAudioResampleContext* resampleContext; +#else + struct SwrContext* resampleContext; +#endif #ifdef FFMPEG_USE_NEW_BSF struct AVBSFContext* absf; // Needed for AAC in MP4 #else diff -Nru mgba-0.6.3+dfsg1/src/feature/gui/gui-config.c mgba-0.7.0/src/feature/gui/gui-config.c --- mgba-0.6.3+dfsg1/src/feature/gui/gui-config.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/gui/gui-config.c 2019-01-27 00:06:06.000000000 +0000 @@ -10,13 +10,30 @@ #include "feature/gui/gui-runner.h" #include "feature/gui/remap.h" #include +#ifdef M_CORE_GB +#include +#endif #include #include +#include #ifndef GUI_MAX_INPUTS #define GUI_MAX_INPUTS 7 #endif +static bool _biosNamed(const char* name) { + char ext[PATH_MAX + 1] = {}; + separatePath(name, NULL, NULL, ext); + + if (strstr(name, "bios")) { + return true; + } + if (!strncmp(ext, "bin", PATH_MAX)) { + return true; + } + return false; +} + void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t nExtra) { struct GUIMenu menu = { .title = "Configure", @@ -45,6 +62,26 @@ .nStates = 2 }; *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { + .title = "Autosave state", + .data = "autosave", + .submenu = 0, + .state = true, + .validStates = (const char*[]) { + "Off", "On" + }, + .nStates = 2 + }; + *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { + .title = "Autoload state", + .data = "autoload", + .submenu = 0, + .state = true, + .validStates = (const char*[]) { + "Off", "On" + }, + .nStates = 2 + }; + *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { .title = "Use BIOS if found", .data = "useBios", .submenu = 0, @@ -55,9 +92,33 @@ .nStates = 2 }; *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { - .title = "Select BIOS path", - .data = "bios", + .title = "Select GBA BIOS path", + .data = "gba.bios", + }; +#ifdef M_CORE_GB + *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { + .title = "Select GB BIOS path", + .data = "gb.bios", + }; + *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { + .title = "Select GBC BIOS path", + .data = "gbc.bios", + }; + *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { + .title = "Select SGB BIOS path", + .data = "sgb.bios", + }; + *GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) { + .title = "Enable SGB borders", + .data = "sgb.borders", + .submenu = 0, + .state = true, + .validStates = (const char*[]) { + "Off", "On" + }, + .nStates = 2 }; +#endif size_t i; const char* mapNames[GUI_MAX_INPUTS + 1]; if (runner->keySources) { @@ -88,7 +149,12 @@ .data = 0, }; enum GUIMenuExitReason reason; - char biosPath[256] = ""; + char gbaBiosPath[256] = ""; +#ifdef M_CORE_GB + char gbBiosPath[256] = ""; + char gbcBiosPath[256] = ""; + char sgbBiosPath[256] = ""; +#endif struct GUIMenuItem* item; for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) { @@ -96,7 +162,50 @@ if (!item->validStates || !item->data) { continue; } - mCoreConfigGetUIntValue(&runner->config, item->data, &item->state); + if (item->stateMappings) { + item->state = 0; + + size_t j; + for (j = 0; j < item->nStates; ++j) { + const struct GUIVariant* v = &item->stateMappings[j]; + struct GUIVariant test; + switch (v->type) { + case GUI_VARIANT_VOID: + if (!mCoreConfigGetValue(&runner->config, item->data)) { + item->state = j; + break; + } + break; + case GUI_VARIANT_UNSIGNED: + if (mCoreConfigGetUIntValue(&runner->config, item->data, &test.v.u) && test.v.u == v->v.u) { + item->state = j; + break; + } + break; + case GUI_VARIANT_INT: + if (mCoreConfigGetIntValue(&runner->config, item->data, &test.v.i) && test.v.i == v->v.i) { + item->state = j; + break; + } + break; + case GUI_VARIANT_FLOAT: + if (mCoreConfigGetFloatValue(&runner->config, item->data, &test.v.f) && fabsf(test.v.f - v->v.f) <= 1e-3f) { + item->state = j; + break; + } + break; + case GUI_VARIANT_STRING: + test.v.s = mCoreConfigGetValue(&runner->config, item->data); + if (test.v.s && strcmp(test.v.s, v->v.s) == 0) { + item->state = j; + break; + } + break; + } + } + } else { + mCoreConfigGetUIntValue(&runner->config, item->data, &item->state); + } } while (true) { @@ -105,15 +214,45 @@ break; } if (!strcmp(item->data, "*SAVE")) { - if (biosPath[0]) { - mCoreConfigSetValue(&runner->config, "bios", biosPath); + if (gbaBiosPath[0]) { + mCoreConfigSetValue(&runner->config, "gba.bios", gbaBiosPath); + } + if (gbBiosPath[0]) { + mCoreConfigSetValue(&runner->config, "gb.bios", gbBiosPath); + } + if (gbcBiosPath[0]) { + mCoreConfigSetValue(&runner->config, "gbc.bios", gbcBiosPath); + } + if (sgbBiosPath[0]) { + mCoreConfigSetValue(&runner->config, "sgb.bios", sgbBiosPath); } for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) { item = GUIMenuItemListGetPointer(&menu.items, i); - if (!item->validStates || !item->data) { + if (!item->validStates || !item->data || ((const char*) item->data)[0] == '*') { continue; } - mCoreConfigSetUIntValue(&runner->config, item->data, item->state); + if (item->stateMappings) { + const struct GUIVariant* v = &item->stateMappings[item->state]; + switch (v->type) { + case GUI_VARIANT_VOID: + mCoreConfigSetValue(&runner->config, item->data, NULL); + break; + case GUI_VARIANT_UNSIGNED: + mCoreConfigSetUIntValue(&runner->config, item->data, v->v.u); + break; + case GUI_VARIANT_INT: + mCoreConfigSetUIntValue(&runner->config, item->data, v->v.i); + break; + case GUI_VARIANT_FLOAT: + mCoreConfigSetFloatValue(&runner->config, item->data, v->v.f); + break; + case GUI_VARIANT_STRING: + mCoreConfigSetValue(&runner->config, item->data, v->v.s); + break; + } + } else { + mCoreConfigSetUIntValue(&runner->config, item->data, item->state); + } } if (runner->keySources) { size_t i; @@ -130,13 +269,36 @@ mGUIRemapKeys(&runner->params, &runner->core->inputMap, &runner->keySources[item->state]); continue; } - if (!strcmp(item->data, "bios")) { + if (!strcmp(item->data, "gba.bios")) { + // TODO: show box if failed + if (!GUISelectFile(&runner->params, gbaBiosPath, sizeof(gbaBiosPath), _biosNamed, GBAIsBIOS)) { + gbaBiosPath[0] = '\0'; + } + continue; + } +#ifdef M_CORE_GB + if (!strcmp(item->data, "gb.bios")) { + // TODO: show box if failed + if (!GUISelectFile(&runner->params, gbBiosPath, sizeof(gbBiosPath), _biosNamed, GBIsBIOS)) { + gbBiosPath[0] = '\0'; + } + continue; + } + if (!strcmp(item->data, "gbc.bios")) { // TODO: show box if failed - if (!GUISelectFile(&runner->params, biosPath, sizeof(biosPath), GBAIsBIOS)) { - biosPath[0] = '\0'; + if (!GUISelectFile(&runner->params, gbcBiosPath, sizeof(gbcBiosPath), _biosNamed, GBIsBIOS)) { + gbcBiosPath[0] = '\0'; } continue; } + if (!strcmp(item->data, "sgb.bios")) { + // TODO: show box if failed + if (!GUISelectFile(&runner->params, sgbBiosPath, sizeof(sgbBiosPath), _biosNamed, GBIsBIOS)) { + sgbBiosPath[0] = '\0'; + } + continue; + } +#endif if (item->validStates) { ++item->state; if (item->state >= item->nStates) { diff -Nru mgba-0.6.3+dfsg1/src/feature/gui/gui-runner.c mgba-0.7.0/src/feature/gui/gui-runner.c --- mgba-0.6.3+dfsg1/src/feature/gui/gui-runner.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/gui/gui-runner.c 2019-01-27 00:06:06.000000000 +0000 @@ -18,15 +18,12 @@ #include #include -#ifdef _3DS -#include <3ds.h> -#endif - #include mLOG_DECLARE_CATEGORY(GUI_RUNNER); mLOG_DEFINE_CATEGORY(GUI_RUNNER, "GUI Runner", "gui.runner"); +#define AUTOSAVE_GRANULARITY 600 #define FPS_GRANULARITY 120 #define FPS_BUFFER_SIZE 3 @@ -38,19 +35,11 @@ RUNNER_SCREENSHOT, RUNNER_CONFIG, RUNNER_RESET, - RUNNER_COMMAND_MASK = 0xFFFF, - - RUNNER_STATE_1 = 0x10000, - RUNNER_STATE_2 = 0x20000, - RUNNER_STATE_3 = 0x30000, - RUNNER_STATE_4 = 0x40000, - RUNNER_STATE_5 = 0x50000, - RUNNER_STATE_6 = 0x60000, - RUNNER_STATE_7 = 0x70000, - RUNNER_STATE_8 = 0x80000, - RUNNER_STATE_9 = 0x90000, + RUNNER_COMMAND_MASK = 0xFFFF }; +#define RUNNER_STATE(X) ((X) << 16) + static const struct mInputPlatformInfo _mGUIKeyInfo = { .platformName = "gui", .keyId = (const char*[GUI_INPUT_MAX]) { @@ -65,7 +54,8 @@ [mGUI_INPUT_DECREASE_BRIGHTNESS] = "Decrease solar brightness", [mGUI_INPUT_SCREEN_MODE] = "Screen mode", [mGUI_INPUT_SCREENSHOT] = "Take screenshot", - [mGUI_INPUT_FAST_FORWARD] = "Fast forward", + [mGUI_INPUT_FAST_FORWARD_HELD] = "Fast forward (held)", + [mGUI_INPUT_FAST_FORWARD_TOGGLE] = "Fast forward (toggle)", }, .nKeys = GUI_INPUT_MAX }; @@ -84,6 +74,26 @@ .logLevel = 0 }; +static bool _testExtensions(const char* name) { + char ext[PATH_MAX] = {}; + separatePath(name, NULL, NULL, ext); + + if (!strncmp(ext, "sav", PATH_MAX)) { + return false; + } + if (!strncmp(ext, "png", PATH_MAX)) { + return false; + } + if (!strncmp(ext, "ini", PATH_MAX)) { + return false; + } + if (!strncmp(ext, "ss", 2)) { + return false; + } + + return true; +} + static void _drawBackground(struct GUIBackground* background, void* context) { UNUSED(context); struct mGUIBackground* gbaBackground = (struct mGUIBackground*) background; @@ -145,6 +155,27 @@ return 0xFF - value; } +static void _tryAutosave(struct mGUIRunner* runner) { + int autosave = false; + mCoreConfigGetIntValue(&runner->config, "autosave", &autosave); + if (!autosave) { + return; + } + +#ifdef DISABLE_THREADING + mCoreSaveState(runner->core, 0, SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_METADATA); +#else + if (!runner->autosave.buffer) { + runner->autosave.buffer = VFileMemChunk(NULL, 0); + } + MutexLock(&runner->autosave.mutex); + runner->autosave.core = runner->core; + mCoreSaveStateNamed(runner->core, runner->autosave.buffer, SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_METADATA); + ConditionWake(&runner->autosave.cond); + MutexUnlock(&runner->autosave.mutex); +#endif +} + void mGUIInit(struct mGUIRunner* runner, const char* port) { GUIInit(&runner->params); runner->port = port; @@ -164,6 +195,12 @@ // TODO: Do we need to load more defaults? mCoreConfigSetDefaultIntValue(&runner->config, "volume", 0x100); mCoreConfigSetDefaultValue(&runner->config, "idleOptimization", "detect"); + mCoreConfigSetDefaultIntValue(&runner->config, "autoload", true); +#ifdef DISABLE_THREADING + mCoreConfigSetDefaultIntValue(&runner->config, "autosave", false); +#else + mCoreConfigSetDefaultIntValue(&runner->config, "autosave", true); +#endif mCoreConfigLoad(&runner->config); mCoreConfigGetIntValue(&runner->config, "logLevel", &logger.logLevel); @@ -178,9 +215,34 @@ strncpy(runner->params.currentPath, lastPath, PATH_MAX - 1); runner->params.currentPath[PATH_MAX - 1] = '\0'; } + +#ifndef DISABLE_THREADING + if (!runner->autosave.running) { + runner->autosave.running = true; + MutexInit(&runner->autosave.mutex); + ConditionInit(&runner->autosave.cond); + ThreadCreate(&runner->autosave.thread, mGUIAutosaveThread, &runner->autosave); + } +#endif } void mGUIDeinit(struct mGUIRunner* runner) { +#ifndef DISABLE_THREADING + MutexLock(&runner->autosave.mutex); + runner->autosave.running = false; + ConditionWake(&runner->autosave.cond); + MutexUnlock(&runner->autosave.mutex); + + ThreadJoin(runner->autosave.thread); + + ConditionDeinit(&runner->autosave.cond); + MutexDeinit(&runner->autosave.mutex); + + if (runner->autosave.buffer) { + runner->autosave.buffer->close(runner->autosave.buffer); + } +#endif + if (runner->teardown) { runner->teardown(runner); } @@ -243,25 +305,26 @@ *GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Save state", .submenu = &stateSaveMenu }; *GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Load state", .submenu = &stateLoadMenu }; - *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 1", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE_1) }; - *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 2", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE_2) }; - *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 3", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE_3) }; - *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 4", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE_4) }; - *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 5", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE_5) }; - *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 6", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE_6) }; - *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 7", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE_7) }; - *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 8", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE_8) }; - *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE_9) }; - - *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 1", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_1) }; - *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 2", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_2) }; - *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 3", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_3) }; - *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 4", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_4) }; - *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 5", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_5) }; - *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 6", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_6) }; - *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 7", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_7) }; - *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 8", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_8) }; - *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE_9) }; + *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 1", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(1)) }; + *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 2", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(2)) }; + *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 3", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(3)) }; + *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 4", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(4)) }; + *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 5", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(5)) }; + *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 6", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(6)) }; + *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 7", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(7)) }; + *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 8", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(8)) }; + *GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(9)) }; + + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "Autosave", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(0)) }; + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 1", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(1)) }; + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 2", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(2)) }; + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 3", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(3)) }; + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 4", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(4)) }; + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 5", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(5)) }; + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 6", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(6)) }; + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 7", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(7)) }; + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 8", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(8)) }; + *GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(9)) }; *GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Take screenshot", .data = (void*) RUNNER_SCREENSHOT }; *GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Configure", .data = (void*) RUNNER_CONFIG }; @@ -306,6 +369,7 @@ mLOG(GUI_RUNNER, DEBUG, "Loading save..."); mCoreAutoloadSave(runner->core); + mCoreAutoloadCheats(runner->core); if (runner->setup) { mLOG(GUI_RUNNER, DEBUG, "Setting up runner..."); runner->setup(runner); @@ -320,7 +384,22 @@ mLOG(GUI_RUNNER, DEBUG, "Reseting..."); runner->core->reset(runner->core); mLOG(GUI_RUNNER, DEBUG, "Reset!"); + + + int autoload = false; + mCoreConfigGetIntValue(&runner->config, "autoload", &autoload); + if (autoload) { + mCoreLoadState(runner->core, 0, SAVESTATE_SCREENSHOT | SAVESTATE_RTC); + } + bool running = true; + +#ifndef DISABLE_THREADING + MutexLock(&runner->autosave.mutex); + runner->autosave.core = runner->core; + MutexUnlock(&runner->autosave.mutex); +#endif + if (runner->gameLoaded) { runner->gameLoaded(runner); } @@ -333,13 +412,15 @@ gettimeofday(&tv, 0); runner->lastFpsCheck = 1000000LL * tv.tv_sec + tv.tv_usec; - while (true) { -#ifdef _3DS - running = aptMainLoop(); - if (!running) { - break; + int frame = 0; + bool fastForward = false; + while (running) { + if (runner->running) { + running = runner->running(runner); + if (!running) { + break; + } } -#endif uint32_t guiKeys; uint32_t heldKeys; GUIPollInput(&runner->params, &guiKeys, &heldKeys); @@ -362,10 +443,15 @@ if (guiKeys & (1 << mGUI_INPUT_SCREENSHOT)) { mCoreTakeScreenshot(runner->core); } - if (heldKeys & (1 << mGUI_INPUT_FAST_FORWARD)) { - runner->setFrameLimiter(runner, false); - } else { - runner->setFrameLimiter(runner, true); + if (runner->setFrameLimiter) { + if (guiKeys & (1 << mGUI_INPUT_FAST_FORWARD_TOGGLE)) { + fastForward = !fastForward; + } + if (fastForward || (heldKeys & (1 << mGUI_INPUT_FAST_FORWARD_HELD))) { + runner->setFrameLimiter(runner, false); + } else { + runner->setFrameLimiter(runner, true); + } } uint16_t keys = runner->pollGameInput(runner); if (runner->prepareForFrame) { @@ -411,12 +497,21 @@ runner->fps = (CircleBufferSize(&runner->fpsBuffer) * FPS_GRANULARITY * 1000000.0f) / (runner->totalDelta * sizeof(uint32_t)); } } + if (frame == AUTOSAVE_GRANULARITY) { + frame = 0; + _tryAutosave(runner); + } + ++frame; } } if (runner->paused) { runner->paused(runner); } + if (runner->setFrameLimiter) { + runner->setFrameLimiter(runner, true); + } + GUIInvalidateKeys(&runner->params); uint32_t keys = 0xFFFFFFFF; // Huge hack to avoid an extra variable! struct GUIMenuItem* item; @@ -463,6 +558,18 @@ if (runner->gameUnloaded) { runner->gameUnloaded(runner); } +#ifndef DISABLE_THREADING + MutexLock(&runner->autosave.mutex); + runner->autosave.core = NULL; + MutexUnlock(&runner->autosave.mutex); +#endif + + int autosave = false; + mCoreConfigGetIntValue(&runner->config, "autosave", &autosave); + if (autosave) { + mCoreSaveState(runner->core, 0, SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_METADATA); + } + mLOG(GUI_RUNNER, DEBUG, "Unloading game..."); runner->core->unloadROM(runner->core); drawState.screenshotId = 0; @@ -486,6 +593,7 @@ mInputMapDeinit(&runner->core->inputMap); mLOG(GUI_RUNNER, DEBUG, "Deinitializing core..."); runner->core->deinit(runner->core); + runner->core = NULL; GUIMenuItemListDeinit(&pauseMenu.items); GUIMenuItemListDeinit(&stateSaveMenu.items); @@ -503,7 +611,7 @@ } while (true) { char path[PATH_MAX]; - if (!GUISelectFile(&runner->params, path, sizeof(path), 0)) { + if (!GUISelectFile(&runner->params, path, sizeof(path), _testExtensions, NULL)) { break; } mCoreConfigSetValue(&runner->config, "lastDirectory", runner->params.currentPath); @@ -511,3 +619,21 @@ mGUIRun(runner, path); } } + +#ifndef DISABLE_THREADING +THREAD_ENTRY mGUIAutosaveThread(void* context) { + struct mGUIAutosaveContext* autosave = context; + MutexLock(&autosave->mutex); + while (autosave->running) { + ConditionWait(&autosave->cond, &autosave->mutex); + if (autosave->running && autosave->core) { + struct VFile* vf = mCoreGetState(autosave->core, 0, true); + void* mem = autosave->buffer->map(autosave->buffer, autosave->buffer->size(autosave->buffer), MAP_READ); + vf->write(vf, mem, autosave->buffer->size(autosave->buffer)); + autosave->buffer->unmap(autosave->buffer, mem, autosave->buffer->size(autosave->buffer)); + vf->close(vf); + } + } + MutexUnlock(&autosave->mutex); +} +#endif diff -Nru mgba-0.6.3+dfsg1/src/feature/gui/gui-runner.h mgba-0.7.0/src/feature/gui/gui-runner.h --- mgba-0.6.3+dfsg1/src/feature/gui/gui-runner.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/gui/gui-runner.h 2019-01-27 00:06:06.000000000 +0000 @@ -15,13 +15,15 @@ #include #include #include +#include enum mGUIInput { mGUI_INPUT_INCREASE_BRIGHTNESS = GUI_INPUT_USER_START, mGUI_INPUT_DECREASE_BRIGHTNESS, mGUI_INPUT_SCREEN_MODE, mGUI_INPUT_SCREENSHOT, - mGUI_INPUT_FAST_FORWARD, + mGUI_INPUT_FAST_FORWARD_HELD, + mGUI_INPUT_FAST_FORWARD_TOGGLE }; struct mGUIBackground { @@ -38,12 +40,27 @@ int luxLevel; }; +#ifndef DISABLE_THREADING +struct VFile; +struct mGUIAutosaveContext { + struct VFile* buffer; + struct mCore* core; + Thread thread; + Mutex mutex; + Condition cond; + bool running; +}; +#endif + struct mGUIRunner { struct mCore* core; struct GUIParams params; struct mGUIBackground background; struct mGUIRunnerLux luminanceSource; +#ifndef DISABLE_THREADING + struct mGUIAutosaveContext autosave; +#endif struct mInputMap guiKeys; struct mCoreConfig config; @@ -70,6 +87,7 @@ void (*incrementScreenMode)(struct mGUIRunner*); void (*setFrameLimiter)(struct mGUIRunner*, bool limit); uint16_t (*pollGameInput)(struct mGUIRunner*); + bool (*running)(struct mGUIRunner*); }; void mGUIInit(struct mGUIRunner*, const char* port); @@ -77,6 +95,10 @@ void mGUIRun(struct mGUIRunner*, const char* path); void mGUIRunloop(struct mGUIRunner*); +#ifndef DISABLE_THREADING +THREAD_ENTRY mGUIAutosaveThread(void* context); +#endif + CXX_GUARD_END #endif diff -Nru mgba-0.6.3+dfsg1/src/feature/gui/remap.c mgba-0.7.0/src/feature/gui/remap.c --- mgba-0.6.3+dfsg1/src/feature/gui/remap.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/gui/remap.c 2019-01-27 00:06:06.000000000 +0000 @@ -69,13 +69,13 @@ if (item->data == (void*) (GUI_INPUT_MAX + map->info->nKeys + 2)) { for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) { item = GUIMenuItemListGetPointer(&menu.items, i); - if ((uint32_t) item->data < 1) { + if ((uintptr_t) item->data < 1) { continue; } - if ((uint32_t) item->data < GUI_INPUT_MAX + 1) { - mInputBindKey(¶ms->keyMap, keys->id, item->state - 1, (uint32_t) item->data - 1); - } else if ((uint32_t) item->data < GUI_INPUT_MAX + map->info->nKeys + 1) { - mInputBindKey(map, keys->id, item->state - 1, (uint32_t) item->data - GUI_INPUT_MAX - 1); + if ((uintptr_t) item->data < GUI_INPUT_MAX + 1) { + mInputBindKey(¶ms->keyMap, keys->id, item->state - 1, (uintptr_t) item->data - 1); + } else if ((uintptr_t) item->data < GUI_INPUT_MAX + map->info->nKeys + 1) { + mInputBindKey(map, keys->id, item->state - 1, (uintptr_t) item->data - GUI_INPUT_MAX - 1); } } break; diff -Nru mgba-0.6.3+dfsg1/src/feature/imagemagick/imagemagick-gif-encoder.c mgba-0.7.0/src/feature/imagemagick/imagemagick-gif-encoder.c --- mgba-0.6.3+dfsg1/src/feature/imagemagick/imagemagick-gif-encoder.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/imagemagick/imagemagick-gif-encoder.c 2019-01-27 00:06:06.000000000 +0000 @@ -98,6 +98,10 @@ static void _magickVideoDimensionsChanged(struct mAVStream* stream, unsigned width, unsigned height) { struct ImageMagickGIFEncoder* encoder = (struct ImageMagickGIFEncoder*) stream; + if (width * height > encoder->iwidth * encoder->iheight) { + free(encoder->frame); + encoder->frame = malloc(width * height * 4); + } encoder->iwidth = width; encoder->iheight = height; } diff -Nru mgba-0.6.3+dfsg1/src/feature/imagemagick/imagemagick-gif-encoder.h mgba-0.7.0/src/feature/imagemagick/imagemagick-gif-encoder.h --- mgba-0.6.3+dfsg1/src/feature/imagemagick/imagemagick-gif-encoder.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/imagemagick/imagemagick-gif-encoder.h 2019-01-27 00:06:06.000000000 +0000 @@ -12,9 +12,6 @@ #include -#define MAGICKCORE_HDRI_ENABLE 0 -#define MAGICKCORE_QUANTUM_DEPTH 8 - #if MAGICKWAND_VERSION_MAJOR >= 7 #include #else diff -Nru mgba-0.6.3+dfsg1/src/feature/thread-proxy.c mgba-0.7.0/src/feature/thread-proxy.c --- mgba-0.6.3+dfsg1/src/feature/thread-proxy.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/thread-proxy.c 2019-01-27 00:06:06.000000000 +0000 @@ -7,7 +7,6 @@ #include #include -#include #ifndef DISABLE_THREADING @@ -79,6 +78,7 @@ if (waiting) { ThreadJoin(proxyRenderer->thread); } + RingFIFODeinit(&proxyRenderer->dirtyQueue); ConditionDeinit(&proxyRenderer->fromThreadCond); ConditionDeinit(&proxyRenderer->toThreadCond); MutexDeinit(&proxyRenderer->mutex); @@ -122,7 +122,7 @@ if (!block || read) { break; } - mLOG(GBA_VIDEO, DEBUG, "Proxy thread can't read VRAM. CPU thread asleep?"); + mLOG(GBA_VIDEO, DEBUG, "Can't read %"PRIz"u bytes. CPU thread asleep?", length); MutexLock(&proxyRenderer->mutex); ConditionWake(&proxyRenderer->fromThreadCond); ConditionWait(&proxyRenderer->toThreadCond, &proxyRenderer->mutex); @@ -143,7 +143,7 @@ _proxyThreadRecover(proxyRenderer); return; } - while (proxyRenderer->threadState == PROXY_THREAD_BUSY) { + while (RingFIFOSize(&proxyRenderer->dirtyQueue)) { ConditionWake(&proxyRenderer->toThreadCond); ConditionWait(&proxyRenderer->fromThreadCond, &proxyRenderer->mutex); } diff -Nru mgba-0.6.3+dfsg1/src/feature/video-logger.c mgba-0.7.0/src/feature/video-logger.c --- mgba-0.6.3+dfsg1/src/feature/video-logger.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/feature/video-logger.c 2019-01-27 00:06:06.000000000 +0000 @@ -258,6 +258,9 @@ 0xDEADBEEF, }; logger->writeData(logger, &dirty, sizeof(dirty)); + if (logger->wait) { + logger->wait(logger); + } } void mVideoLoggerRendererFinishFrame(struct mVideoLogger* logger) { @@ -682,13 +685,33 @@ if (context->initialState) { mappedMemoryFree(context->initialState, context->initialStateSize); } + + size_t i; + for (i = 0; i < context->nChannels; ++i) { + CircleBufferDeinit(&context->channels[i].buffer); +#ifdef USE_ZLIB + if (context->channels[i].inflating) { + inflateEnd(&context->channels[i].inflateStream); + context->channels[i].inflating = false; + } +#endif + } + free(context); } 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 -Nru mgba-0.6.3+dfsg1/src/gb/audio.c mgba-0.7.0/src/gb/audio.c --- mgba-0.6.3+dfsg1/src/gb/audio.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/audio.c 2019-01-27 00:06:06.000000000 +0000 @@ -37,6 +37,8 @@ static void _updateSquareSample(struct GBAudioSquareChannel* ch); static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch); +static int8_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch); + static void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _updateChannel1(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _updateChannel2(struct mTiming* timing, void* user, uint32_t cyclesLate); @@ -93,7 +95,7 @@ audio->sampleEvent.context = audio; audio->sampleEvent.name = "GB Audio Sample"; audio->sampleEvent.callback = _sample; - audio->ch1Event.priority = 0x18; + audio->sampleEvent.priority = 0x18; } void GBAudioDeinit(struct GBAudio* audio) { @@ -109,13 +111,16 @@ mTimingDeschedule(audio->timing, &audio->ch3Fade); mTimingDeschedule(audio->timing, &audio->ch4Event); mTimingDeschedule(audio->timing, &audio->sampleEvent); - mTimingSchedule(audio->timing, &audio->frameEvent, 0); if (audio->style != GB_AUDIO_GBA) { mTimingSchedule(audio->timing, &audio->sampleEvent, 0); } + if (audio->style == GB_AUDIO_GBA) { + mTimingSchedule(audio->timing, &audio->frameEvent, 0); + } audio->ch1 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } }; audio->ch2 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } }; audio->ch3 = (struct GBAudioWaveChannel) { .bank = 0 }; + audio->ch4 = (struct GBAudioNoiseChannel) { .nSamples = 0 }; // TODO: DMG randomness audio->ch3.wavedata8[0] = 0x00; audio->ch3.wavedata8[1] = 0xFF; @@ -138,21 +143,18 @@ audio->sampleInterval = 128; audio->lastLeft = 0; audio->lastRight = 0; + audio->capLeft = 0; + audio->capRight = 0; audio->clock = 0; - audio->volumeRight = 0; - audio->volumeLeft = 0; - audio->ch1Right = false; - audio->ch2Right = false; - audio->ch3Right = false; - audio->ch4Right = false; - audio->ch1Left = false; - audio->ch2Left = false; - audio->ch3Left = false; - audio->ch4Left = false; audio->playingCh1 = false; audio->playingCh2 = false; audio->playingCh3 = false; audio->playingCh4 = false; + if (audio->p && !(audio->p->model & GB_MODEL_SGB)) { + audio->playingCh1 = true; + audio->enable = true; + *audio->nr52 |= 0x01; + } } void GBAudioResizeBuffer(struct GBAudio* audio, size_t samples) { @@ -204,12 +206,6 @@ } if (GBAudioRegisterControlIsRestart(value << 8)) { audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope); - - if (audio->playingCh1) { - audio->ch1.control.hi = 0; - _updateSquareSample(&audio->ch1); - } - audio->ch1.sweep.realFrequency = audio->ch1.control.frequency; _resetSweep(&audio->ch1.sweep); if (audio->playingCh1 && audio->ch1.sweep.shift) { @@ -221,8 +217,9 @@ --audio->ch1.control.length; } } - mTimingDeschedule(audio->timing, &audio->ch1Event); if (audio->playingCh1 && audio->ch1.envelope.dead != 2) { + _updateSquareChannel(&audio->ch1); + mTimingDeschedule(audio->timing, &audio->ch1Event); mTimingSchedule(audio->timing, &audio->ch1Event, 0); } } @@ -263,19 +260,15 @@ if (GBAudioRegisterControlIsRestart(value << 8)) { audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope); - if (audio->playingCh2) { - audio->ch2.control.hi = 0; - _updateSquareSample(&audio->ch2); - } - if (!audio->ch2.control.length) { audio->ch2.control.length = 64; if (audio->ch2.control.stop && !(audio->frame & 1)) { --audio->ch2.control.length; } } - mTimingDeschedule(audio->timing, &audio->ch2Event); if (audio->playingCh2 && audio->ch2.envelope.dead != 2) { + _updateSquareChannel(&audio->ch2); + mTimingDeschedule(audio->timing, &audio->ch2Event); mTimingSchedule(audio->timing, &audio->ch2Event, 0); } } @@ -336,6 +329,7 @@ } } audio->ch3.window = 0; + audio->ch3.sample = 0; } mTimingDeschedule(audio->timing, &audio->ch3Fade); mTimingDeschedule(audio->timing, &audio->ch3Event); @@ -381,9 +375,9 @@ audio->playingCh4 = _resetEnvelope(&audio->ch4.envelope); if (audio->ch4.power) { - audio->ch4.lfsr = 0x40; + audio->ch4.lfsr = 0x7F; } else { - audio->ch4.lfsr = 0x4000; + audio->ch4.lfsr = 0x7FFF; } if (!audio->ch4.length) { audio->ch4.length = 64; @@ -391,8 +385,8 @@ --audio->ch4.length; } } - mTimingDeschedule(audio->timing, &audio->ch4Event); if (audio->playingCh4 && audio->ch4.envelope.dead != 2) { + mTimingDeschedule(audio->timing, &audio->ch4Event); mTimingSchedule(audio->timing, &audio->ch4Event, 0); } } @@ -476,13 +470,34 @@ } *audio->nr52 &= ~0x000F; } else if (!wasEnable) { + audio->skipFrame = false; audio->frame = 7; + + if (audio->p) { + unsigned timingFactor = 0x400 >> !audio->p->doubleSpeed; + if (audio->p->timer.internalDiv & timingFactor) { + audio->skipFrame = true; + } + } } } void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBAudio* audio = user; + GBAudioUpdateFrame(audio, timing); + if (audio->style == GB_AUDIO_GBA) { + mTimingSchedule(timing, &audio->frameEvent, audio->timingFactor * FRAME_CYCLES - cyclesLate); + } +} +void GBAudioUpdateFrame(struct GBAudio* audio, struct mTiming* timing) { + if (!audio->enable) { + return; + } + if (audio->skipFrame) { + audio->skipFrame = false; + return; + } int frame = (audio->frame + 1) & 7; audio->frame = frame; @@ -562,23 +577,24 @@ if (audio->playingCh4 && !audio->ch4.envelope.dead) { --audio->ch4.envelope.nextStep; if (audio->ch4.envelope.nextStep == 0) { - int8_t sample = (audio->ch4.sample >> 7) * 0x8; + int8_t sample = audio->ch4.sample > 0; + audio->ch4.samples -= audio->ch4.sample; _updateEnvelope(&audio->ch4.envelope); if (audio->ch4.envelope.dead == 2) { mTimingDeschedule(timing, &audio->ch4Event); } audio->ch4.sample = sample * audio->ch4.envelope.currentVolume; + audio->ch4.samples += audio->ch4.sample; } } break; } - - mTimingSchedule(timing, &audio->frameEvent, audio->timingFactor * FRAME_CYCLES - cyclesLate); } void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { - int sampleLeft = 0; - int sampleRight = 0; + int dcOffset = audio->style == GB_AUDIO_GBA ? 0 : -0x8; + int sampleLeft = dcOffset; + int sampleRight = dcOffset; if (audio->playingCh1 && !audio->forceDisableCh[0]) { if (audio->ch1Left) { @@ -592,7 +608,7 @@ if (audio->playingCh2 && !audio->forceDisableCh[1]) { if (audio->ch2Left) { - sampleLeft += audio->ch2.sample; + sampleLeft += audio->ch2.sample; } if (audio->ch2Right) { @@ -611,15 +627,19 @@ } if (audio->playingCh4 && !audio->forceDisableCh[3]) { + int8_t sample = _coalesceNoiseChannel(&audio->ch4); if (audio->ch4Left) { - sampleLeft += audio->ch4.sample; + sampleLeft += sample; } if (audio->ch4Right) { - sampleRight += audio->ch4.sample; + sampleRight += sample; } } + sampleLeft <<= 3; + sampleRight <<= 3; + *left = sampleLeft * (1 + audio->volumeLeft); *right = sampleRight * (1 + audio->volumeRight); } @@ -629,11 +649,19 @@ int16_t sampleLeft = 0; int16_t sampleRight = 0; GBAudioSamplePSG(audio, &sampleLeft, &sampleRight); - sampleLeft = (sampleLeft * audio->masterVolume) >> 6; - sampleRight = (sampleRight * audio->masterVolume) >> 6; + sampleLeft = (sampleLeft * audio->masterVolume * 6) >> 7; + sampleRight = (sampleRight * audio->masterVolume * 6) >> 7; mCoreSyncLockAudio(audio->p->sync); unsigned produced; + + int16_t degradedLeft = sampleLeft - (audio->capLeft >> 16); + int16_t degradedRight = sampleRight - (audio->capRight >> 16); + audio->capLeft = (sampleLeft << 16) - degradedLeft * 65184; + audio->capRight = (sampleRight << 16) - degradedRight * 65184; + sampleLeft = degradedLeft; + sampleRight = degradedRight; + if ((size_t) blip_samples_avail(audio->left) < audio->samples) { blip_add_delta(audio->left, audio->clock, sampleLeft - audio->lastLeft); blip_add_delta(audio->right, audio->clock, sampleRight - audio->lastRight); @@ -651,7 +679,10 @@ audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight); } bool wait = produced >= audio->samples; - mCoreSyncProduceAudio(audio->p->sync, wait); + if (!mCoreSyncProduceAudio(audio->p->sync, audio->left, audio->samples)) { + // Interrupted + audio->p->earlyExit = true; + } if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) { audio->p->stream->postAudioBuffer(audio->p->stream, audio->left, audio->right); @@ -709,7 +740,7 @@ } static void _updateSquareSample(struct GBAudioSquareChannel* ch) { - ch->sample = (ch->control.hi * 2 - 1) * ch->envelope.currentVolume * 0x8; + ch->sample = ch->control.hi * ch->envelope.currentVolume; } static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch) { @@ -731,6 +762,17 @@ } } +static int8_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch) { + if (!ch->nSamples) { + return ch->sample; + } + // TODO keep track of timing + int8_t sample = ch->samples / ch->nSamples; + ch->nSamples = 0; + ch->samples = 0; + return sample; +} + static void _updateEnvelope(struct GBAudioEnvelope* envelope) { if (envelope->direction) { ++envelope->currentVolume; @@ -810,19 +852,17 @@ int volume; switch (ch->volume) { case 0: - volume = 0; + volume = 4; break; case 1: - volume = 4; + volume = 0; break; case 2: - volume = 2; - break; - case 3: volume = 1; break; default: - volume = 3; + case 3: + volume = 2; break; } int start; @@ -860,8 +900,10 @@ ch->sample = bitsCarry >> 4; break; } - ch->sample -= 8; - ch->sample *= volume * 4; + if (ch->volume > 3) { + ch->sample += ch->sample << 1; + } + ch->sample >>= volume; audio->ch3.readable = true; if (audio->style == GB_AUDIO_DMG) { mTimingDeschedule(audio->timing, &audio->ch3Fade); @@ -881,19 +923,17 @@ struct GBAudio* audio = user; struct GBAudioNoiseChannel* ch = &audio->ch4; - int32_t baseCycles = ch->ratio ? 2 * ch->ratio : 1; - baseCycles <<= ch->frequency; - baseCycles *= 8 * audio->timingFactor; - int32_t cycles = 0; - - do { - int lsb = ch->lfsr & 1; - ch->sample = lsb * 0x10 - 0x8; - ch->sample *= ch->envelope.currentVolume; - ch->lfsr >>= 1; - ch->lfsr ^= (lsb * 0x60) << (ch->power ? 0 : 8); - cycles += baseCycles; - } while (cycles + baseCycles < audio->sampleInterval); + int32_t cycles = ch->ratio ? 2 * ch->ratio : 1; + cycles <<= ch->frequency; + cycles *= 8 * audio->timingFactor; + + int lsb = ch->lfsr & 1; + ch->sample = lsb * ch->envelope.currentVolume; + ++ch->nSamples; + ch->samples += ch->sample; + ch->lfsr >>= 1; + ch->lfsr ^= (lsb * 0x60) << (ch->power ? 0 : 8); + mTimingSchedule(timing, &audio->ch4Event, cycles - cyclesLate); } @@ -904,6 +944,7 @@ uint32_t ch4Flags = 0; flags = GBSerializedAudioFlagsSetFrame(flags, audio->frame); + flags = GBSerializedAudioFlagsSetSkipFrame(flags, audio->skipFrame); STORE_32LE(audio->frameEvent.when - mTimingCurrentTime(audio->timing), 0, &state->ch1.nextFrame); flags = GBSerializedAudioFlagsSetCh1Volume(flags, audio->ch1.envelope.currentVolume); @@ -955,10 +996,15 @@ audio->playingCh4 = !!(*audio->nr52 & 0x0008); audio->enable = GBAudioEnableGetEnable(*audio->nr52); - LOAD_32LE(when, 0, &state->ch1.nextFrame); - mTimingSchedule(audio->timing, &audio->frameEvent, when); + if (audio->style == GB_AUDIO_GBA) { + LOAD_32LE(when, 0, &state->ch1.nextFrame); + mTimingSchedule(audio->timing, &audio->frameEvent, when); + } LOAD_32LE(flags, 0, flagsIn); + audio->frame = GBSerializedAudioFlagsGetFrame(flags); + audio->skipFrame = GBSerializedAudioFlagsGetSkipFrame(flags); + LOAD_32LE(ch1Flags, 0, &state->ch1.envelope); audio->ch1.envelope.currentVolume = GBSerializedAudioFlagsGetCh1Volume(flags); audio->ch1.envelope.dead = GBSerializedAudioFlagsGetCh1Dead(flags); @@ -1011,11 +1057,15 @@ void GBAudioSerialize(const struct GBAudio* audio, struct GBSerializedState* state) { GBAudioPSGSerialize(audio, &state->audio.psg, &state->audio.flags); + STORE_32LE(audio->capLeft, 0, &state->audio.capLeft); + STORE_32LE(audio->capRight, 0, &state->audio.capRight); STORE_32LE(audio->sampleEvent.when - mTimingCurrentTime(audio->timing), 0, &state->audio.nextSample); } void GBAudioDeserialize(struct GBAudio* audio, const struct GBSerializedState* state) { GBAudioPSGDeserialize(audio, &state->audio.psg, &state->audio.flags); + LOAD_32LE(audio->capLeft, 0, &state->audio.capLeft); + LOAD_32LE(audio->capRight, 0, &state->audio.capRight); uint32_t when; LOAD_32LE(when, 0, &state->audio.nextSample); mTimingSchedule(audio->timing, &audio->sampleEvent, when); diff -Nru mgba-0.6.3+dfsg1/src/gb/core.c mgba-0.7.0/src/gb/core.c --- mgba-0.6.3+dfsg1/src/gb/core.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/core.c 2019-01-27 00:06:06.000000000 +0000 @@ -26,8 +26,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[] = { @@ -179,9 +179,47 @@ 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, "allowOpposingDirections"); + + int fakeBool = 0; + mCoreConfigGetIntValue(config, "allowOpposingDirections", &fakeBool); + gb->allowOpposingDirections = fakeBool; + + if (mCoreConfigGetIntValue(config, "sgb.borders", &fakeBool)) { + gb->video.sgbBorders = fakeBool; + gb->video.renderer->enableSGBBorder(gb->video.renderer, fakeBool); + } #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 struct GBCore* gbcore = (struct GBCore*) core; @@ -190,9 +228,14 @@ } 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) { @@ -247,7 +290,9 @@ struct GB* gb = core->board; gb->stream = stream; if (stream && stream->videoDimensionsChanged) { - stream->videoDimensionsChanged(stream, GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); + unsigned width, height; + core->desiredVideoDimensions(core, &width, &height); + stream->videoDimensionsChanged(stream, width, height); } } @@ -321,6 +366,20 @@ } } + 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); + } + } + #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 if (!gb->biosVf && core->opts.useBios) { struct VFile* bios = NULL; @@ -340,9 +399,13 @@ 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"); @@ -365,9 +428,13 @@ 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)); @@ -390,6 +457,10 @@ #endif LR35902Reset(core->cpu); + + if (core->opts.skipBios) { + GBSkipBIOS(core->board); + } } static void _GBCoreRunFrame(struct mCore* core) { @@ -479,6 +550,9 @@ case mPERIPH_RUMBLE: gb->memory.rumble = periph; break; + case mPERIPH_IMAGE_SOURCE: + gb->memory.cam = periph; + break; default: return; } @@ -558,7 +632,9 @@ 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); @@ -657,6 +733,20 @@ } GBLoadSymbols(core->symbolTable, vf); } + +static bool _GBCoreLookupIdentifier(struct mCore* core, const char* name, int32_t* value, int* segment) { + UNUSED(core); + *segment = -1; + int i; + for (i = 0; i < REG_MAX; ++i) { + const char* reg = GBIORegisterNames[i]; + if (reg && strcasecmp(reg, name) == 0) { + *value = GB_BASE_IO | i; + return true; + } + } + return false; +} #endif static struct mCheatDevice* _GBCoreCheatDevice(struct mCore* core) { @@ -705,13 +795,17 @@ static size_t _GBCoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) { UNUSED(core); - *info = _GBVideoLayers; + if (info) { + *info = _GBVideoLayers; + } return sizeof(_GBVideoLayers) / sizeof(*_GBVideoLayers); } static size_t _GBCoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) { UNUSED(core); - *info = _GBAudioChannels; + if (info) { + *info = _GBAudioChannels; + } return sizeof(_GBAudioChannels) / sizeof(*_GBAudioChannels); } @@ -746,6 +840,26 @@ } } +static void _GBCoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) { + struct GBCore* gbcore = (struct GBCore*) core; + switch (id) { + case 0: + gbcore->renderer.offsetScx = x; + gbcore->renderer.offsetScy = y; + break; + case 1: + gbcore->renderer.offsetWx = x; + gbcore->renderer.offsetWy = y; + break; + case 2: + gbcore->renderer.objOffsetX = x; + gbcore->renderer.objOffsetY = y; + break; + default: + return; + } +} + #ifndef MINIMAL_CORE static void _GBCoreStartVideoLog(struct mCore* core, struct mVideoLogContext* context) { struct GBCore* gbcore = (struct GBCore*) core; @@ -839,6 +953,7 @@ core->attachDebugger = _GBCoreAttachDebugger; core->detachDebugger = _GBCoreDetachDebugger; core->loadSymbols = _GBCoreLoadSymbols; + core->lookupIdentifier = _GBCoreLookupIdentifier; #endif core->cheatDevice = _GBCoreCheatDevice; core->savedataClone = _GBCoreSavedataClone; @@ -847,6 +962,7 @@ core->listAudioChannels = _GBCoreListAudioChannels; core->enableVideoLayer = _GBCoreEnableVideoLayer; core->enableAudioChannel = _GBCoreEnableAudioChannel; + core->adjustVideoLayer = _GBCoreAdjustVideoLayer; #ifndef MINIMAL_CORE core->startVideoLog = _GBCoreStartVideoLog; core->endVideoLog = _GBCoreEndVideoLog; @@ -932,6 +1048,7 @@ gb->cpu->pc = GB_BASE_HRAM; gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc); + GBVideoReset(&gb->video); GBVideoDeserialize(&gb->video, state); GBIODeserialize(gb, state); GBAudioReset(&gb->audio); diff -Nru mgba-0.6.3+dfsg1/src/gb/debugger/cli.c mgba-0.7.0/src/gb/debugger/cli.c --- mgba-0.6.3+dfsg1/src/gb/debugger/cli.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/debugger/cli.c 2019-01-27 00:06:06.000000000 +0000 @@ -14,16 +14,15 @@ static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*); static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem*); -static uint32_t _GBCLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); static void _frame(struct CLIDebugger*, struct CLIDebugVector*); static void _load(struct CLIDebugger*, struct CLIDebugVector*); static void _save(struct CLIDebugger*, struct CLIDebugVector*); struct CLIDebuggerCommandSummary _GBCLIDebuggerCommands[] = { - { "frame", _frame, 0, "Frame advance" }, - { "load", _load, CLIDVParse, "Load a savestate" }, - { "save", _save, CLIDVParse, "Save a savestate" }, + { "frame", _frame, "", "Frame advance" }, + { "load", _load, "*", "Load a savestate" }, + { "save", _save, "*", "Save a savestate" }, { 0, 0, 0, 0 } }; @@ -34,7 +33,6 @@ debugger->d.init = _GBCLIDebuggerInit; debugger->d.deinit = NULL; debugger->d.custom = _GBCLIDebuggerCustom; - debugger->d.lookupIdentifier = _GBCLIDebuggerLookupIdentifier; debugger->d.name = "Game Boy"; debugger->d.commands = _GBCLIDebuggerCommands; @@ -65,19 +63,6 @@ return false; } -static uint32_t _GBCLIDebuggerLookupIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) { - UNUSED(debugger); - int i; - for (i = 0; i < REG_MAX; ++i) { - const char* reg = GBIORegisterNames[i]; - if (reg && strcasecmp(reg, name) == 0) { - return GB_BASE_IO | i; - } - } - dv->type = CLIDV_ERROR_TYPE; - return 0; -} - static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { UNUSED(dv); debugger->d.state = DEBUGGER_CUSTOM; diff -Nru mgba-0.6.3+dfsg1/src/gb/debugger/symbols.c mgba-0.7.0/src/gb/debugger/symbols.c --- mgba-0.6.3+dfsg1/src/gb/debugger/symbols.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/debugger/symbols.c 2019-01-27 00:06:06.000000000 +0000 @@ -25,13 +25,14 @@ uint8_t byte; const char* buf = line; - while (buf) { + while (buf && bytesRead >= 2) { buf = hex8(buf, &byte); if (!buf) { break; } address <<= 8; address += byte; + bytesRead -= 2; if (buf[0] == ':') { segment = address; @@ -42,14 +43,19 @@ break; } } - if (!buf) { + if (!buf || bytesRead < 1) { continue; } - while (isspace((int) buf[0])) { + while (isspace((int) buf[0]) && bytesRead > 0) { + --bytesRead; ++buf; } + if (!bytesRead) { + continue; + } + mDebuggerSymbolAdd(st, buf, address, segment); } } diff -Nru mgba-0.6.3+dfsg1/src/gb/extra/proxy.c mgba-0.7.0/src/gb/extra/proxy.c --- mgba-0.6.3+dfsg1/src/gb/extra/proxy.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/extra/proxy.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,21 +5,24 @@ * 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); static void GBVideoProxyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax); static void GBVideoProxyRendererFinishScanline(struct GBVideoRenderer* renderer, int y); static void GBVideoProxyRendererFinishFrame(struct GBVideoRenderer* renderer); +static void GBVideoProxyRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable); static void GBVideoProxyRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels); static void GBVideoProxyRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels); @@ -30,12 +33,14 @@ 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; renderer->d.drawRange = GBVideoProxyRendererDrawRange; renderer->d.finishScanline = GBVideoProxyRendererFinishScanline; renderer->d.finishFrame = GBVideoProxyRendererFinishFrame; + renderer->d.enableSGBBorder = GBVideoProxyRendererEnableSGBBorder; renderer->d.getPixels = GBVideoProxyRendererGetPixels; renderer->d.putPixels = GBVideoProxyRendererPutPixels; @@ -93,12 +98,12 @@ 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 +116,7 @@ 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 +160,11 @@ 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 +190,14 @@ 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 +205,7 @@ proxyRenderer->backend->writeVRAM(proxyRenderer->backend, address); } if (renderer->cache) { - mTileCacheWriteVRAM(renderer->cache, address); + mCacheSetWriteVRAM(renderer->cache, address); } } @@ -197,7 +216,7 @@ proxyRenderer->backend->writePalette(proxyRenderer->backend, address, value); } if (renderer->cache) { - mTileCacheWritePalette(renderer->cache, address); + mCacheSetWritePalette(renderer->cache, address, mColorFrom555(value)); } } @@ -233,14 +252,29 @@ struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer; if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { proxyRenderer->logger->lock(proxyRenderer->logger); - proxyRenderer->logger->wait(proxyRenderer->logger); } - proxyRenderer->backend->finishFrame(proxyRenderer->backend); + if (!proxyRenderer->logger->block) { + proxyRenderer->backend->finishFrame(proxyRenderer->backend); + } mVideoLoggerRendererFinishFrame(proxyRenderer->logger); mVideoLoggerRendererFlush(proxyRenderer->logger); if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { proxyRenderer->logger->unlock(proxyRenderer->logger); } +} + +static void GBVideoProxyRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable) { + struct GBVideoProxyRenderer* proxyRenderer = (struct GBVideoProxyRenderer*) renderer; + if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { + proxyRenderer->logger->lock(proxyRenderer->logger); + // Insert an extra item into the queue to make sure it gets flushed + mVideoLoggerRendererFlush(proxyRenderer->logger); + proxyRenderer->logger->wait(proxyRenderer->logger); + } + proxyRenderer->backend->enableSGBBorder(proxyRenderer->backend, enable); + if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { + proxyRenderer->logger->unlock(proxyRenderer->logger); + } } static void GBVideoProxyRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels) { diff -Nru mgba-0.6.3+dfsg1/src/gb/gb.c mgba-0.7.0/src/gb/gb.c --- mgba-0.6.3+dfsg1/src/gb/gb.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/gb.c 2019-01-27 00:06:06.000000000 +0000 @@ -28,6 +28,9 @@ #define DMG_BIOS_CHECKSUM 0xC2F5CC97 #define DMG_2_BIOS_CHECKSUM 0x59C8598E +#define MGB_BIOS_CHECKSUM 0xE6920754 +#define SGB_BIOS_CHECKSUM 0xEC8A83B9 +#define SGB2_BIOS_CHECKSUM 0X53D0DD63 #define CGB_BIOS_CHECKSUM 0x41884E46 mLOG_DEFINE_CATEGORY(GB, "GB", "gb"); @@ -37,12 +40,13 @@ 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); static void _enableInterrupts(struct mTiming* timing, void* user, uint32_t cyclesLate); -#ifdef _3DS +#ifdef FIXED_ROM_BUFFER extern uint32_t* romBuffer; extern size_t romBufferSize; #endif @@ -109,7 +113,7 @@ gb->pristineRomSize = vf->size(vf); vf->seek(vf, 0, SEEK_SET); gb->isPristine = true; -#ifdef _3DS +#ifdef FIXED_ROM_BUFFER if (gb->pristineRomSize <= romBufferSize) { gb->memory.rom = romBuffer; vf->read(vf, romBuffer, gb->pristineRomSize); @@ -154,6 +158,7 @@ gb->sramRealVf = vf; if (gb->sramSize) { GBResizeSram(gb, gb->sramSize); + GBMBCSwitchSramBank(gb, gb->memory.sramCurrentBank); } return vf; } @@ -245,7 +250,11 @@ } void GBSavedataMask(struct GB* gb, struct VFile* vf, bool writeback) { + struct VFile* oldVf = gb->sramVf; GBSramDeinit(gb); + if (oldVf && oldVf != gb->sramRealVf) { + oldVf->close(oldVf); + } gb->sramVf = vf; gb->sramMaskWriteback = writeback; gb->memory.sram = vf->map(vf, gb->sramSize, MAP_READ); @@ -253,7 +262,7 @@ } void GBSavedataUnmask(struct GB* gb) { - if (gb->sramVf == gb->sramRealVf) { + if (!gb->sramRealVf || gb->sramVf == gb->sramRealVf) { return; } struct VFile* vf = gb->sramVf; @@ -265,6 +274,7 @@ vf->read(vf, gb->memory.sram, gb->sramSize); gb->sramMaskWriteback = false; } + GBMBCSwitchSramBank(gb, gb->memory.sramCurrentBank); vf->close(vf); } @@ -281,7 +291,7 @@ } if (gb->romVf) { -#ifndef _3DS +#ifndef FIXED_ROM_BUFFER gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->pristineRomSize); #endif gb->romVf->close(gb->romVf); @@ -292,13 +302,15 @@ gb->isPristine = false; gb->sramMaskWriteback = false; - GBSavedataUnmask(gb); GBSramDeinit(gb); if (gb->sramRealVf) { gb->sramRealVf->close(gb->sramRealVf); } 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) { @@ -331,7 +343,7 @@ return; } if (gb->romVf) { -#ifndef _3DS +#ifndef FIXED_ROM_BUFFER gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->pristineRomSize); #endif gb->romVf->close(gb->romVf); @@ -366,6 +378,7 @@ irqh->reset = GBReset; irqh->processEvents = GBProcessEvents; irqh->setInterrupts = GBSetInterrupts; + irqh->irqVector = GBIRQVector; irqh->hitIllegal = GBIllegal; irqh->stop = GBStop; irqh->halt = GBHalt; @@ -386,6 +399,9 @@ switch (_GBBiosCRC32(vf)) { case DMG_BIOS_CHECKSUM: case DMG_2_BIOS_CHECKSUM: + case MGB_BIOS_CHECKSUM: + case SGB_BIOS_CHECKSUM: + case SGB2_BIOS_CHECKSUM: case CGB_BIOS_CHECKSUM: return true; default: @@ -425,64 +441,139 @@ cpu->b = 0; cpu->d = 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; - cpu->a = 1; - cpu->f.packed = 0xB0; - cpu->c = 0x13; - cpu->e = 0xD8; - cpu->h = 1; - cpu->l = 0x4D; - gb->timer.internalDiv = 0x2AF3; - break; - case GB_MODEL_AGB: - cpu->b = 1; - // Fall through - case GB_MODEL_CGB: - cpu->a = 0x11; - cpu->f.packed = 0x80; - cpu->c = 0; - cpu->e = 0x08; - cpu->h = 0; - cpu->l = 0x7C; - gb->timer.internalDiv = 0x7A8; - break; - } - - cpu->sp = 0xFFFE; - cpu->pc = 0x100; - } + gb->timer.internalDiv = 0; gb->cpuBlocked = false; gb->earlyExit = false; gb->doubleSpeed = 0; - cpu->memory.setActiveRegion(cpu, cpu->pc); - if (gb->yankedRomSize) { gb->memory.romSize = gb->yankedRomSize; gb->yankedRomSize = 0; } + gb->sgbBit = -1; + gb->sgbControllers = 0; + gb->sgbCurrentController = 0; + 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); + if (!gb->biosVf) { + GBSkipBIOS(gb); + } else { + mTimingSchedule(&gb->timing, &gb->timer.event, 0); + } - GBAudioReset(&gb->audio); GBIOReset(gb); + GBAudioReset(&gb->audio); GBSIOReset(&gb->sio); + cpu->memory.setActiveRegion(cpu, cpu->pc); + + gb->sramMaskWriteback = false; GBSavedataUnmask(gb); } +void GBSkipBIOS(struct GB* gb) { + struct LR35902Core* cpu = gb->cpu; + int nextDiv = 0; + + switch (gb->model) { + case GB_MODEL_AUTODETECT: // Silence warnings + gb->model = GB_MODEL_DMG; + // Fall through + 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 = 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; + 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; + cpu->c = 0; + cpu->e = 0x08; + cpu->h = 0; + cpu->l = 0x7C; + gb->timer.internalDiv = 0x1EA; + nextDiv = 0xC; + break; + } + + cpu->sp = 0xFFFE; + cpu->pc = 0x100; + + mTimingDeschedule(&gb->timing, &gb->timer.event); + mTimingSchedule(&gb->timing, &gb->timer.event, 0); + + GBIOWrite(gb, REG_LCDC, 0x91); + + if (gb->biosVf) { + GBUnmapBIOS(gb); + } +} + +void GBUnmapBIOS(struct GB* gb) { + if (gb->memory.romBase < gb->memory.rom || gb->memory.romBase > &gb->memory.rom[gb->memory.romSize - 1]) { + free(gb->memory.romBase); + gb->memory.romBase = gb->memory.rom; + } + // XXX: Force AGB registers for AGB-mode + if (gb->model == GB_MODEL_AGB && gb->cpu->pc == 0x100) { + gb->cpu->b = 1; + } +} + void GBDetectModel(struct GB* gb) { if (gb->model != GB_MODEL_AUTODETECT) { return; @@ -493,6 +584,15 @@ 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 SGB2_BIOS_CHECKSUM: + gb->model = GB_MODEL_SGB2; + break; case CGB_BIOS_CHECKSUM: gb->model = GB_MODEL_CGB; break; @@ -505,6 +605,8 @@ 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; } @@ -516,6 +618,10 @@ 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; @@ -526,38 +632,19 @@ void GBUpdateIRQs(struct GB* gb) { int irqs = gb->memory.ie & gb->memory.io[REG_IF]; if (!irqs) { + gb->cpu->irqPending = false; return; } gb->cpu->halted = false; - 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); + if (!gb->memory.ime) { + gb->cpu->irqPending = false; return; } - if (irqs & (1 << GB_IRQ_TIMER)) { - LR35902RaiseIRQ(gb->cpu, GB_VECTOR_TIMER); - gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_TIMER); + if (gb->cpu->irqPending) { 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) { @@ -575,31 +662,57 @@ } while (gb->cpuBlocked); cpu->nextEvent = nextEvent; - if (gb->earlyExit) { - gb->earlyExit = false; - break; - } if (cpu->halted) { cpu->cycles = cpu->nextEvent; if (!gb->memory.ie || !gb->memory.ime) { break; } } + if (gb->earlyExit) { + break; + } } while (cpu->cycles >= cpu->nextEvent); + gb->earlyExit = false; } void GBSetInterrupts(struct LR35902Core* cpu, bool enable) { struct GB* gb = (struct GB*) cpu->master; + mTimingDeschedule(&gb->timing, &gb->eiPending); if (!enable) { - gb->memory.ime = enable; - mTimingDeschedule(&gb->timing, &gb->eiPending); + gb->memory.ime = false; GBUpdateIRQs(gb); } else { - mTimingDeschedule(&gb->timing, &gb->eiPending); mTimingSchedule(&gb->timing, &gb->eiPending, 4); } } +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); @@ -609,16 +722,19 @@ } void GBHalt(struct LR35902Core* cpu) { - if (!cpu->irqPending) { + struct GB* gb = (struct GB*) cpu->master; + if (!(gb->memory.ie & gb->memory.io[REG_IF])) { cpu->cycles = cpu->nextEvent; cpu->halted = true; + } else if (gb->model < GB_MODEL_CGB) { + mLOG(GB, STUB, "Unimplemented HALT bug"); } } 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; @@ -644,7 +760,7 @@ 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 = { @@ -709,6 +825,18 @@ } } +void GBFrameStarted(struct GB* gb) { + GBTestKeypadIRQ(gb); + + size_t c; + for (c = 0; c < mCoreCallbacksListSize(&gb->coreCallbacks); ++c) { + struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gb->coreCallbacks, c); + if (callbacks->videoFrameStarted) { + callbacks->videoFrameStarted(callbacks->context); + } + } +} + void GBFrameEnded(struct GB* gb) { GBSramClean(gb, gb->video.frameCounter); @@ -721,5 +849,56 @@ } } - GBTestKeypadIRQ(gb); + // TODO: Move to common code + if (gb->stream && gb->stream->postVideoFrame) { + const color_t* pixels; + size_t stride; + gb->video.renderer->getPixels(gb->video.renderer, &stride, (const void**) &pixels); + gb->stream->postVideoFrame(gb->stream, pixels, stride); + } + + size_t c; + for (c = 0; c < mCoreCallbacksListSize(&gb->coreCallbacks); ++c) { + struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gb->coreCallbacks, c); + if (callbacks->videoFrameEnded) { + callbacks->videoFrameEnded(callbacks->context); + } + } +} + +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 -Nru mgba-0.6.3+dfsg1/src/gb/io.c mgba-0.7.0/src/gb/io.c --- mgba-0.6.3+dfsg1/src/gb/io.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/io.c 2019-01-27 00:06:06.000000000 +0000 @@ -101,10 +101,58 @@ [REG_BCPS] = 0x40, [REG_UNK6C] = 0xFE, [REG_SVBK] = 0xF8, - [REG_UNK75] = 0x8F, [REG_IE] = 0xE0, }; +static uint8_t _readKeys(struct GB* gb); +static uint8_t _readKeysFiltered(struct GB* gb); + +static void _writeSGBBits(struct GB* gb, int bits) { + if (!bits) { + gb->sgbBit = -1; + memset(gb->sgbPacket, 0, sizeof(gb->sgbPacket)); + } + if (bits == gb->currentSgbBits) { + return; + } + gb->currentSgbBits = bits; + if (gb->sgbBit > 128) { + switch (bits) { + case 1: + gb->sgbBit |= 2; + break; + case 2: + gb->sgbBit |= 4; + break; + case 3: + if (gb->sgbBit == 135) { + gb->sgbBit &= ~6; + gb->sgbCurrentController = (gb->sgbCurrentController + 1) & gb->sgbControllers; + } + break; + } + } + if (gb->sgbBit == 128 && bits == 2) { + GBVideoWriteSGBPacket(&gb->video, gb->sgbPacket); + ++gb->sgbBit; + } + if (gb->sgbBit >= 128) { + return; + } + switch (bits) { + case 1: + if (gb->sgbBit < 0) { + return; + } + gb->sgbPacket[gb->sgbBit >> 3] |= 1 << (gb->sgbBit & 7); + break; + case 3: + ++gb->sgbBit; + default: + break; + } +} + void GBIOInit(struct GB* gb) { memset(gb->memory.io, 0, sizeof(gb->memory.io)); } @@ -117,34 +165,43 @@ 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); GBIOWrite(gb, REG_NR50, 0x77); GBIOWrite(gb, REG_NR51, 0xF3); - GBIOWrite(gb, REG_LCDC, 0x91); + if (!gb->biosVf) { + GBIOWrite(gb, REG_LCDC, 0x91); + } else { + GBIOWrite(gb, REG_LCDC, 0x00); + } GBIOWrite(gb, REG_SCY, 0x00); GBIOWrite(gb, REG_SCX, 0x00); GBIOWrite(gb, REG_LYC, 0x00); + GBIOWrite(gb, REG_DMA, 0xFF); 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); - if (gb->model >= GB_MODEL_CGB) { + if (gb->model & GB_MODEL_CGB) { + GBIOWrite(gb, REG_UNK4C, 0); + GBIOWrite(gb, REG_JOYP, 0xFF); GBIOWrite(gb, REG_VBK, 0); GBIOWrite(gb, REG_BCPS, 0); GBIOWrite(gb, REG_OCPS, 0); @@ -154,6 +211,8 @@ 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); } @@ -343,9 +402,24 @@ } break; case REG_JOYP: + gb->memory.io[REG_JOYP] = value | 0x0F; + _readKeys(gb); + if (gb->model & GB_MODEL_SGB) { + _writeSGBBits(gb, (value >> 4) & 3); + } + return; case REG_TIMA: + if (value && mTimingUntil(&gb->timing, &gb->timer.irq) > 1) { + mTimingDeschedule(&gb->timing, &gb->timer.irq); + } + if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) { + return; + } + break; case REG_TMA: - // Handled transparently by the registers + if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) { + gb->memory.io[REG_TIMA] = value; + } break; case REG_TAC: value = GBTimerUpdateTAC(&gb->timer, value); @@ -356,7 +430,7 @@ return; case REG_LCDC: // TODO: handle GBC differences - GBVideoProcessDots(&gb->video); + GBVideoProcessDots(&gb->video, 0); value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value); GBVideoWriteLCDC(&gb->video, value); break; @@ -370,13 +444,13 @@ case REG_SCX: case REG_WY: case REG_WX: - GBVideoProcessDots(&gb->video); + GBVideoProcessDots(&gb->video, 0); value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value); break; case REG_BGP: case REG_OBP0: case REG_OBP1: - GBVideoProcessDots(&gb->video); + GBVideoProcessDots(&gb->video, 0); GBVideoWritePalette(&gb->video, address, value); break; case REG_STAT: @@ -384,9 +458,10 @@ value = gb->video.stat; break; case 0x50: - if (gb->memory.romBase < gb->memory.rom || gb->memory.romBase > &gb->memory.rom[gb->memory.romSize - 1]) { - free(gb->memory.romBase); - gb->memory.romBase = gb->memory.rom; + GBUnmapBIOS(gb); + if (gb->model >= GB_MODEL_CGB && gb->memory.io[REG_UNK4C] < 0x80) { + gb->model = GB_MODEL_DMG; + GBVideoDisableCGB(&gb->video); } break; case REG_IE: @@ -396,6 +471,8 @@ default: if (gb->model >= GB_MODEL_CGB) { switch (address) { + case REG_UNK4C: + break; case REG_KEY1: value &= 0x1; value |= gb->memory.io[address] & 0x80; @@ -418,8 +495,10 @@ gb->memory.io[REG_BCPD] = gb->video.palette[gb->video.bcpIndex >> 1] >> (8 * (gb->video.bcpIndex & 1)); break; case REG_BCPD: - GBVideoProcessDots(&gb->video); - GBVideoWritePalette(&gb->video, address, value); + if (gb->video.mode != 3) { + GBVideoProcessDots(&gb->video, 0); + GBVideoWritePalette(&gb->video, address, value); + } return; case REG_OCPS: gb->video.ocpIndex = value & 0x3F; @@ -427,8 +506,10 @@ gb->memory.io[REG_OCPD] = gb->video.palette[8 * 4 + (gb->video.ocpIndex >> 1)] >> (8 * (gb->video.ocpIndex & 1)); break; case REG_OCPD: - GBVideoProcessDots(&gb->video); - GBVideoWritePalette(&gb->video, address, value); + if (gb->video.mode != 3) { + GBVideoProcessDots(&gb->video, 0); + GBVideoWritePalette(&gb->video, address, value); + } return; case REG_SVBK: GBMemorySwitchWramBank(&gb->memory, value); @@ -452,9 +533,13 @@ static uint8_t _readKeys(struct GB* gb) { uint8_t keys = *gb->keySource; - switch (gb->memory.io[REG_JOYP] & 0x30) { - case 0x30: + if (gb->sgbCurrentController != 0) { keys = 0; + } + uint8_t joyp = gb->memory.io[REG_JOYP]; + switch (joyp & 0x30) { + case 0x30: + keys = gb->sgbCurrentController; break; case 0x20: keys >>= 4; @@ -465,13 +550,33 @@ keys |= keys >> 4; break; } - return (0xC0 | (gb->memory.io[REG_JOYP] | 0xF)) ^ (keys & 0xF); + gb->memory.io[REG_JOYP] = (0xCF | joyp) ^ (keys & 0xF); + if (joyp & ~gb->memory.io[REG_JOYP] & 0xF) { + gb->memory.io[REG_IF] |= (1 << GB_IRQ_KEYPAD); + GBUpdateIRQs(gb); + } + return gb->memory.io[REG_JOYP]; +} + +static uint8_t _readKeysFiltered(struct GB* gb) { + uint8_t keys = _readKeys(gb); + if (!gb->allowOpposingDirections && (keys & 0x30) == 0x20) { + unsigned rl = keys & 0x03; + unsigned ud = keys & 0x0C; + if (!rl) { + keys |= 0x03; + } + if (!ud) { + keys |= 0x0C; + } + } + return keys; } uint8_t GBIORead(struct GB* gb, unsigned address) { switch (address) { case REG_JOYP: - return _readKeys(gb); + return _readKeysFiltered(gb); case REG_IE: return gb->memory.ie; case REG_WAVE_0: @@ -530,6 +635,7 @@ case REG_SCX: case REG_LY: case REG_LYC: + case REG_DMA: case REG_BGP: case REG_OBP0: case REG_OBP1: @@ -566,10 +672,7 @@ } void GBTestKeypadIRQ(struct GB* gb) { - if (_readKeys(gb)) { - gb->memory.io[REG_IF] |= (1 << GB_IRQ_KEYPAD); - GBUpdateIRQs(gb); - } + _readKeys(gb); } struct GBSerializedState; @@ -581,10 +684,45 @@ 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 -Nru mgba-0.6.3+dfsg1/src/gb/mbc.c mgba-0.7.0/src/gb/mbc.c --- mgba-0.6.3+dfsg1/src/gb/mbc.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/mbc.c 2019-01-27 00:06:06.000000000 +0000 @@ -9,8 +9,11 @@ #include #include #include +#include #include +const uint32_t GB_LOGO_HASH = 0x46195417; + mLOG_DEFINE_CATEGORY(GB_MBC, "GB MBC", "gb.mbc"); static void _GBMBCNone(struct GB* gb, uint16_t address, uint8_t value) { @@ -27,12 +30,21 @@ static void _GBMBC5(struct GB*, uint16_t address, uint8_t value); static void _GBMBC6(struct GB*, uint16_t address, uint8_t value); static void _GBMBC7(struct GB*, uint16_t address, uint8_t value); +static void _GBMMM01(struct GB*, uint16_t address, uint8_t value); +static void _GBHuC1(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 _GBMBC2Read(struct GBMemory*, uint16_t address); +static uint8_t _GBMBC6Read(struct GBMemory*, uint16_t address); 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; @@ -49,7 +61,7 @@ } void GBMBCSwitchBank0(struct GB* gb, int bank) { - size_t bankStart = bank * GB_SIZE_CART_BANK0 << gb->memory.mbcState.mbc1.multicartStride; + size_t bankStart = bank * GB_SIZE_CART_BANK0; if (bankStart + GB_SIZE_CART_BANK0 > gb->memory.romSize) { mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank); bankStart &= (gb->memory.romSize - 1); @@ -60,18 +72,50 @@ } } +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; + bool success; struct VFile* vf; vf = VFileFromConstMemory(&mem[GB_SIZE_CART_BANK0 * 0x10], 1024); - success = success && GBIsROM(vf); + success = GBIsROM(vf); vf->close(vf); + if (!success) { + return false; + } + vf = VFileFromConstMemory(&mem[GB_SIZE_CART_BANK0 * 0x20], 1024); - success = success && GBIsROM(vf); + success = GBIsROM(vf); vf->close(vf); + if (!success) { + vf = VFileFromConstMemory(&mem[GB_SIZE_CART_BANK0 * 0x30], 1024); + success = GBIsROM(vf); + vf->close(vf); + } + return success; } @@ -86,9 +130,31 @@ gb->memory.sramCurrentBank = bank; } +void GBMBCSwitchSramHalfBank(struct GB* gb, int half, int bank) { + size_t bankStart = bank * GB_SIZE_EXTERNAL_RAM_HALFBANK; + if (bankStart + GB_SIZE_EXTERNAL_RAM_HALFBANK > gb->sramSize) { + mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid RAM bank: %0X", bank); + bankStart &= (gb->sramSize - 1); + bank = bankStart / GB_SIZE_EXTERNAL_RAM_HALFBANK; + } + if (!half) { + gb->memory.sramBank = &gb->memory.sram[bankStart]; + gb->memory.sramCurrentBank = bank; + } else { + gb->memory.mbcState.mbc6.sramBank1 = &gb->memory.sram[bankStart]; + gb->memory.mbcState.mbc6.currentSramBank1 = bank; + } +} + void GBMBCInit(struct GB* gb) { const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100]; if (gb->memory.rom) { + if (gb->memory.romSize >= 0x8000) { + const struct GBCartridge* cartFooter = (const struct GBCartridge*) &gb->memory.rom[gb->memory.romSize - 0x7F00]; + if (doCrc32(cartFooter->logo, sizeof(cartFooter->logo)) == GB_LOGO_HASH && cartFooter->type >= 0x0B && cartFooter->type <= 0x0D) { + cart = cartFooter; + } + } switch (cart->ramSize) { case 0: gb->sramSize = 0; @@ -122,16 +188,16 @@ case 2: case 3: gb->memory.mbcType = GB_MBC1; - if (gb->memory.romSize >= GB_SIZE_CART_BANK0 * 0x31 && _isMulticart(gb->memory.rom)) { - gb->memory.mbcState.mbc1.multicartStride = 4; - } else { - gb->memory.mbcState.mbc1.multicartStride = 5; - } break; case 5: case 6: gb->memory.mbcType = GB_MBC2; break; + case 0x0B: + case 0x0C: + case 0x0D: + gb->memory.mbcType = GB_MMM01; + break; case 0x0F: case 0x10: gb->memory.mbcType = GB_MBC3_RTC; @@ -164,11 +230,14 @@ 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 { @@ -181,6 +250,11 @@ break; case GB_MBC1: gb->memory.mbcWrite = _GBMBC1; + if (gb->memory.romSize >= GB_SIZE_CART_BANK0 * 0x31 && _isMulticart(gb->memory.rom)) { + gb->memory.mbcState.mbc1.multicartStride = 4; + } else { + gb->memory.mbcState.mbc1.multicartStride = 5; + } break; case GB_MBC2: gb->memory.mbcWrite = _GBMBC2; @@ -199,6 +273,7 @@ case GB_MBC6: mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6"); gb->memory.mbcWrite = _GBMBC6; + gb->memory.mbcRead = _GBMBC6Read; break; case GB_MBC7: gb->memory.mbcWrite = _GBMBC7; @@ -206,16 +281,21 @@ gb->sramSize = 0x100; break; case GB_MMM01: - mLOG(GB_MBC, WARN, "unimplemented MBC: MMM01"); - gb->memory.mbcWrite = _GBMBC1; + gb->memory.mbcWrite = _GBMMM01; break; case GB_HuC1: - mLOG(GB_MBC, WARN, "unimplemented MBC: HuC-1"); - gb->memory.mbcWrite = _GBMBC1; + gb->memory.mbcWrite = _GBHuC1; break; 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; @@ -226,6 +306,9 @@ 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; } @@ -334,7 +417,7 @@ case 0x2: bank &= 3; if (memory->mbcState.mbc1.mode) { - GBMBCSwitchBank0(gb, bank); + GBMBCSwitchBank0(gb, bank << gb->memory.mbcState.mbc1.multicartStride); GBMBCSwitchSramBank(gb, bank); } GBMBCSwitchBank(gb, (bank << memory->mbcState.mbc1.multicartStride) | (memory->currentBank & (stride - 1))); @@ -342,7 +425,7 @@ case 0x3: memory->mbcState.mbc1.mode = value & 1; if (memory->mbcState.mbc1.mode) { - GBMBCSwitchBank0(gb, memory->currentBank >> memory->mbcState.mbc1.multicartStride); + GBMBCSwitchBank0(gb, memory->currentBank & ~((1 << memory->mbcState.mbc1.multicartStride) - 1)); } else { GBMBCSwitchBank0(gb, 0); GBMBCSwitchSramBank(gb, 0); @@ -387,6 +470,7 @@ address &= 0x1FF; memory->sramBank[(address >> 1)] &= 0xF0 >> shift; memory->sramBank[(address >> 1)] |= (value & 0xF) << shift; + break; default: // TODO mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value); @@ -426,10 +510,10 @@ GBMBCSwitchBank(gb, bank); break; case 0x2: - if (value < 4) { + if (value < 8) { GBMBCSwitchSramBank(gb, value); memory->rtcAccess = false; - } else if (value >= 8 && value <= 0xC) { + } else if (value <= 0xC) { memory->activeRtcReg = value - 8; memory->rtcAccess = true; } @@ -489,11 +573,70 @@ } 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; + switch (address >> 10) { + case 0: + switch (value) { + case 0: + memory->mbcState.mbc6.sramAccess = false; + break; + case 0xA: + memory->mbcState.mbc6.sramAccess = true; + break; + default: + // TODO + mLOG(GB_MBC, STUB, "MBC6 unknown value %02X", value); + break; + } + break; + case 0x1: + GBMBCSwitchSramHalfBank(gb, 0, bank); + break; + case 0x2: + GBMBCSwitchSramHalfBank(gb, 1, bank); + break; + case 0x8: + case 0x9: + GBMBCSwitchHalfBank(gb, 0, bank); + break; + case 0xC: + case 0xD: + GBMBCSwitchHalfBank(gb, 1, bank); + break; + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + if (memory->mbcState.mbc6.sramAccess) { + memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value; + } + break; + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + if (memory->mbcState.mbc6.sramAccess) { + memory->mbcState.mbc6.sramBank1[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value; + } + break; + default: + mLOG(GB_MBC, STUB, "MBC6 unknown address: %04X:%02X", address, value); + break; + } +} + +uint8_t _GBMBC6Read(struct GBMemory* memory, uint16_t address) { + if (!memory->mbcState.mbc6.sramAccess) { + return 0xFF; + } + switch (address >> 12) { + case 0xA: + return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)]; + case 0xB: + return memory->mbcState.mbc6.sramBank1[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)]; + } + return 0xFF; } void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) { @@ -520,6 +663,9 @@ gb->memory.mbcState.mbc7.access &= ~2; } break; + case 0x5: + _GBMBC7Write(&gb->memory, address, value); + break; default: // TODO mLOG(GB_MBC, STUB, "MBC7 unknown address: %04X:%02X", address, value); @@ -574,7 +720,7 @@ } } -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; @@ -699,6 +845,82 @@ mbc7->eeprom = value; } +void _GBMMM01(struct GB* gb, uint16_t address, uint8_t value) { + struct GBMemory* memory = &gb->memory; + if (!memory->mbcState.mmm01.locked) { + switch (address >> 13) { + case 0x0: + memory->mbcState.mmm01.locked = true; + GBMBCSwitchBank0(gb, memory->mbcState.mmm01.currentBank0); + break; + case 0x1: + memory->mbcState.mmm01.currentBank0 &= ~0x7F; + memory->mbcState.mmm01.currentBank0 |= value & 0x7F; + break; + case 0x2: + memory->mbcState.mmm01.currentBank0 &= ~0x180; + memory->mbcState.mmm01.currentBank0 |= (value & 0x30) << 3; + break; + default: + // TODO + mLOG(GB_MBC, STUB, "MMM01 unknown address: %04X:%02X", address, value); + break; + } + return; + } + switch (address >> 13) { + case 0x0: + switch (value) { + case 0xA: + memory->sramAccess = true; + GBMBCSwitchSramBank(gb, memory->sramCurrentBank); + break; + default: + memory->sramAccess = false; + break; + } + break; + case 0x1: + GBMBCSwitchBank(gb, value + memory->mbcState.mmm01.currentBank0); + break; + case 0x2: + GBMBCSwitchSramBank(gb, value); + break; + default: + // TODO + mLOG(GB_MBC, STUB, "MMM01 unknown address: %04X:%02X", address, value); + break; + } +} + +void _GBHuC1(struct GB* gb, uint16_t address, uint8_t value) { + struct GBMemory* memory = &gb->memory; + int bank = value & 0x3F; + switch (address >> 13) { + case 0x0: + switch (value) { + case 0xE: + memory->sramAccess = false; + break; + default: + memory->sramAccess = true; + GBMBCSwitchSramBank(gb, memory->sramCurrentBank); + break; + } + break; + case 0x1: + GBMBCSwitchBank(gb, bank); + break; + case 0x2: + GBMBCSwitchSramBank(gb, value); + break; + default: + // TODO + mLOG(GB_MBC, STUB, "HuC-1 unknown address: %04X:%02X", address, value); + break; + } +} + void _GBHuC3(struct GB* gb, uint16_t address, uint8_t value) { struct GBMemory* memory = &gb->memory; int bank = value & 0x3F; @@ -761,6 +983,16 @@ 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; @@ -769,11 +1001,172 @@ 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; } 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; diff -Nru mgba-0.6.3+dfsg1/src/gb/memory.c mgba-0.7.0/src/gb/memory.c --- mgba-0.6.3+dfsg1/src/gb/memory.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/memory.c 2019-01-27 00:06:06.000000000 +0000 @@ -73,9 +73,20 @@ case GB_REGION_CART_BANK1 + 2: case GB_REGION_CART_BANK1 + 3: cpu->memory.cpuLoad8 = GBFastLoad8; - cpu->memory.activeRegion = memory->romBank; - cpu->memory.activeRegionEnd = GB_BASE_VRAM; - cpu->memory.activeMask = GB_SIZE_CART_BANK0 - 1; + if (gb->memory.mbcType != GB_MBC6) { + cpu->memory.activeRegion = memory->romBank; + cpu->memory.activeRegionEnd = GB_BASE_VRAM; + cpu->memory.activeMask = GB_SIZE_CART_BANK0 - 1; + } else { + cpu->memory.activeMask = GB_SIZE_CART_HALFBANK - 1; + if (address & 0x2000) { + cpu->memory.activeRegion = memory->mbcState.mbc6.romBank1; + cpu->memory.activeRegionEnd = GB_BASE_VRAM; + } else { + cpu->memory.activeRegion = memory->romBank; + cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1 + 0x2000; + } + } break; default: cpu->memory.cpuLoad8 = GBLoad8; @@ -107,6 +118,7 @@ gb->memory.rtc = NULL; gb->memory.rotation = NULL; gb->memory.rumble = NULL; + gb->memory.cam = NULL; GBIOInit(gb); } @@ -164,15 +176,27 @@ gb->memory.hdmaEvent.priority = 0x41; memset(&gb->memory.hram, 0, sizeof(gb->memory.hram)); + + memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState)); + GBMBCInit(gb); switch (gb->memory.mbcType) { case GB_MBC1: gb->memory.mbcState.mbc1.mode = 0; break; + case GB_MBC6: + GBMBCSwitchHalfBank(gb, 0, 2); + GBMBCSwitchHalfBank(gb, 1, 3); + gb->memory.mbcState.mbc6.sramAccess = false; + GBMBCSwitchSramHalfBank(gb, 0, 0); + GBMBCSwitchSramHalfBank(gb, 0, 1); + break; + case GB_MMM01: + GBMBCSwitchBank0(gb, gb->memory.romSize / GB_SIZE_CART_BANK0 - 2); + GBMBCSwitchBank(gb, gb->memory.romSize / GB_SIZE_CART_BANK0 - 1); + break; default: - memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState)); + break; } - - GBMBCInit(gb); gb->memory.sramBank = gb->memory.sram; if (!gb->memory.wram) { @@ -209,14 +233,21 @@ 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: - return gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)]; + if (gb->video.mode != 3) { + return gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)]; + } + return 0xFF; case GB_REGION_EXTERNAL_RAM: case GB_REGION_EXTERNAL_RAM + 1: if (memory->rtcAccess) { @@ -286,8 +317,10 @@ return; case GB_REGION_VRAM: case GB_REGION_VRAM + 1: - gb->video.renderer->writeVRAM(gb->video.renderer, (address & (GB_SIZE_VRAM_BANK0 - 1)) | (GB_SIZE_VRAM_BANK0 * gb->video.vramCurrentBank)); - gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)] = value; + if (gb->video.mode != 3) { + gb->video.renderer->writeVRAM(gb->video.renderer, (address & (GB_SIZE_VRAM_BANK0 - 1)) | (GB_SIZE_VRAM_BANK0 * gb->video.vramCurrentBank)); + gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)] = value; + } return; case GB_REGION_EXTERNAL_RAM: case GB_REGION_EXTERNAL_RAM + 1: @@ -295,8 +328,8 @@ memory->rtcRegs[memory->activeRtcReg] = value; } else if (memory->sramAccess && memory->sram && memory->mbcType != GB_MBC2) { 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; @@ -467,7 +500,7 @@ gb->memory.hdmaDest |= 0x8000; bool wasHdma = gb->memory.isHdma; gb->memory.isHdma = value & 0x80; - if ((!wasHdma && !gb->memory.isHdma) || gb->video.mode == 0) { + if ((!wasHdma && !gb->memory.isHdma) || (GBRegisterLCDCIsEnable(gb->memory.io[REG_LCDC]) && gb->video.mode == 0)) { if (gb->memory.isHdma) { gb->memory.hdmaRemaining = 0x10; } else { @@ -660,6 +693,10 @@ STORE_16LE(memory->mbcState.mbc7.sr, 0, &state->memory.mbc7.sr); STORE_32LE(memory->mbcState.mbc7.writable, 0, &state->memory.mbc7.writable); break; + case GB_MMM01: + state->memory.mmm01.locked = memory->mbcState.mmm01.locked; + state->memory.mmm01.bank0 = memory->mbcState.mmm01.currentBank0; + break; default: break; } @@ -727,6 +764,15 @@ LOAD_16LE(memory->mbcState.mbc7.sr, 0, &state->memory.mbc7.sr); LOAD_32LE(memory->mbcState.mbc7.writable, 0, &state->memory.mbc7.writable); break; + case GB_MMM01: + memory->mbcState.mmm01.locked = state->memory.mmm01.locked; + memory->mbcState.mmm01.currentBank0 = state->memory.mmm01.bank0; + if (memory->mbcState.mmm01.locked) { + GBMBCSwitchBank0(gb, memory->mbcState.mmm01.currentBank0); + } else { + GBMBCSwitchBank0(gb, gb->memory.romSize / GB_SIZE_CART_BANK0 - 2); + } + break; default: break; } diff -Nru mgba-0.6.3+dfsg1/src/gb/overrides.c mgba-0.7.0/src/gb/overrides.c --- mgba-0.6.3+dfsg1/src/gb/overrides.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/overrides.c 2019-01-27 00:06:06.000000000 +0000 @@ -12,13 +12,19 @@ #include static const struct GBCartridgeOverride _overrides[] = { - // None yet + // Pokemon Spaceworld 1997 demo + { 0x232a067d, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Gold (debug) + { 0x630ed957, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Gold (non-debug) + { 0x5aff0038, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Silver (debug) + { 0xa61856bd, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Silver (non-debug) + { 0, 0, 0, { 0 } } }; 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 +41,24 @@ 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 +70,25 @@ } } - 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 +98,46 @@ 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 +155,18 @@ 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 -Nru mgba-0.6.3+dfsg1/src/gb/renderers/cache-set.c mgba-0.7.0/src/gb/renderers/cache-set.c --- mgba-0.6.3+dfsg1/src/gb/renderers/cache-set.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/gb/renderers/cache-set.c 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/src/gb/renderers/software.c mgba-0.7.0/src/gb/renderers/software.c --- mgba-0.6.3+dfsg1/src/gb/renderers/software.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/renderers/software.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,19 +5,23 @@ * 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); static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax); static void GBVideoSoftwareRendererFinishScanline(struct GBVideoRenderer* renderer, int y); static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer); +static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable); static void GBVideoSoftwareRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels); static void GBVideoSoftwareRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels); @@ -25,9 +29,13 @@ 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) { + return; + } 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,6 +46,117 @@ } } +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 < 184) { + 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 paletteBase = SGBBgAttributesGetPalette(mapData) * 0x10; + int colorSelector; + + int flip = 0; + if (SGBBgAttributesIsXFlip(mapData)) { + flip = 7; + } + for (i = 7; i >= 0; --i) { + colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3; + renderer->outputBuffer[(base + 7 - i) ^ flip] = renderer->palette[paletteBase | colorSelector]; + } + } + } +} + +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]; + 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); + } + } + } + } +} + +static void _parseAttrLine(struct GBVideoSoftwareRenderer* renderer, int start) { + uint8_t byte = renderer->sgbPacket[start]; + unsigned line = byte & 0x1F; + int pal = (byte >> 5) & 3; + + if (byte & 0x80) { + if (line > GB_VIDEO_VERTICAL_PIXELS / 8) { + return; + } + int x; + for (x = 0; x < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++x) { + _setAttribute(renderer->d.sgbAttributes, x, line, pal); + } + } else { + if (line > GB_VIDEO_HORIZONTAL_PIXELS / 8) { + return; + } + int y; + for (y = 0; y < GB_VIDEO_VERTICAL_PIXELS / 8; ++y) { + _setAttribute(renderer->d.sgbAttributes, line, y, pal); + } + } +} + static bool _inWindow(struct GBVideoSoftwareRenderer* renderer) { return GBRegisterLCDCIsWindow(renderer->lcdc) && GB_VIDEO_HORIZONTAL_PIXELS + 7 > renderer->wx; } @@ -46,12 +165,14 @@ 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; renderer->d.drawRange = GBVideoSoftwareRendererDrawRange; renderer->d.finishScanline = GBVideoSoftwareRendererFinishScanline; renderer->d.finishFrame = GBVideoSoftwareRendererFinishFrame; + renderer->d.enableSGBBorder = GBVideoSoftwareRendererEnableSGBBorder; renderer->d.getPixels = GBVideoSoftwareRendererGetPixels; renderer->d.putPixels = GBVideoSoftwareRendererPutPixels; @@ -62,17 +183,34 @@ 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; softwareRenderer->scx = 0; softwareRenderer->wy = 0; softwareRenderer->currentWy = 0; - softwareRenderer->lastY = 0; + softwareRenderer->lastY = GB_VIDEO_VERTICAL_PIXELS; softwareRenderer->hasWindow = false; softwareRenderer->wx = 0; softwareRenderer->model = model; + softwareRenderer->sgbTransfer = 0; + softwareRenderer->sgbCommandHeader = 0; + softwareRenderer->sgbBorders = sgbBorders; + softwareRenderer->objOffsetX = 0; + softwareRenderer->objOffsetY = 0; + softwareRenderer->offsetScx = 0; + softwareRenderer->offsetScy = 0; + softwareRenderer->offsetWx = 0; + softwareRenderer->offsetWy = 0; + + 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) { @@ -90,7 +228,11 @@ renderer->hasWindow = true; } else { if (!renderer->hasWindow) { - renderer->currentWy = renderer->lastY - renderer->wy; + if (renderer->lastY > renderer->wy) { + renderer->currentWy = GB_VIDEO_VERTICAL_PIXELS; + } else { + renderer->currentWy = renderer->lastY - renderer->wy; + } } else { renderer->currentWy += renderer->lastY; } @@ -100,6 +242,9 @@ 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); + } bool wasWindow = _inWindow(softwareRenderer); switch (address) { case REG_LCDC: @@ -120,37 +265,218 @@ softwareRenderer->wx = value; GBVideoSoftwareRendererUpdateWindow(softwareRenderer, wasWindow, _inWindow(softwareRenderer)); 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; + softwareRenderer->sgbCommandHeader = data[0]; + softwareRenderer->sgbTransfer = 0; + int set; + int sets; + int attrX; + int attrY; + int attrDirection; + int pBefore; + int pAfter; + int pDiv; + 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: + sets = softwareRenderer->sgbPacket[1]; + i = 2; + for (; i < (softwareRenderer->sgbCommandHeader & 7) << 4 && sets; i += 6, --sets) { + _parseAttrBlock(softwareRenderer, i); + } + break; + case SGB_ATTR_LIN: + sets = softwareRenderer->sgbPacket[1]; + i = 2; + for (; i < (softwareRenderer->sgbCommandHeader & 7) << 4 && sets; ++i, --sets) { + _parseAttrLine(softwareRenderer, i); + } + break; + case SGB_ATTR_DIV: + pAfter = softwareRenderer->sgbPacket[1] & 3; + pBefore = (softwareRenderer->sgbPacket[1] >> 2) & 3; + pDiv = (softwareRenderer->sgbPacket[1] >> 4) & 3; + attrX = softwareRenderer->sgbPacket[2]; + if (softwareRenderer->sgbPacket[1] & 0x40) { + if (attrX > GB_VIDEO_VERTICAL_PIXELS / 8) { + attrX = GB_VIDEO_VERTICAL_PIXELS / 8; + } + int j; + for (j = 0; j < attrX; ++j) { + for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++i) { + _setAttribute(renderer->sgbAttributes, i, j, pBefore); + } + } + if (attrX < GB_VIDEO_VERTICAL_PIXELS / 8) { + for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++i) { + _setAttribute(renderer->sgbAttributes, i, attrX, pDiv); + } + + } + for (; j < GB_VIDEO_VERTICAL_PIXELS / 8; ++j) { + for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++i) { + _setAttribute(renderer->sgbAttributes, i, j, pAfter); + } + } + } else { + if (attrX > GB_VIDEO_HORIZONTAL_PIXELS / 8) { + attrX = GB_VIDEO_HORIZONTAL_PIXELS / 8; + } + int j; + for (j = 0; j < attrX; ++j) { + for (i = 0; i < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++i) { + _setAttribute(renderer->sgbAttributes, j, i, pBefore); + } + } + if (attrX < GB_VIDEO_HORIZONTAL_PIXELS / 8) { + for (i = 0; i < GB_VIDEO_VERTICAL_PIXELS / 8; ++i) { + _setAttribute(renderer->sgbAttributes, attrX, i, pDiv); + } + + } + for (; j < GB_VIDEO_HORIZONTAL_PIXELS / 8; ++j) { + for (i = 0; i < GB_VIDEO_VERTICAL_PIXELS / 8; ++i) { + _setAttribute(renderer->sgbAttributes, j, i, pAfter); + } + } + } + break; + case SGB_ATTR_CHR: + attrX = softwareRenderer->sgbPacket[1]; + attrY = softwareRenderer->sgbPacket[2]; + if (attrX >= GB_VIDEO_HORIZONTAL_PIXELS / 8) { + attrX = 0; + } + if (attrY >= GB_VIDEO_VERTICAL_PIXELS / 8) { + attrY = 0; + } + sets = softwareRenderer->sgbPacket[3]; + sets |= softwareRenderer->sgbPacket[4] << 8; + attrDirection = softwareRenderer->sgbPacket[5]; + i = 6; + for (; i < (softwareRenderer->sgbCommandHeader & 7) << 4 && sets; ++i) { + int j; + for (j = 0; j < 4 && sets; ++j, --sets) { + uint8_t p = softwareRenderer->sgbPacket[i] >> (6 - j * 2); + _setAttribute(renderer->sgbAttributes, attrX, attrY, p & 3); + if (attrDirection) { + ++attrY; + if (attrY >= GB_VIDEO_VERTICAL_PIXELS / 8) { + attrY = 0; + ++attrX; + } + if (attrX >= GB_VIDEO_HORIZONTAL_PIXELS / 8) { + attrX = 0; + } + } else { + ++attrX; + if (attrX >= GB_VIDEO_HORIZONTAL_PIXELS / 8) { + attrX = 0; + ++attrY; + } + if (attrY >= GB_VIDEO_VERTICAL_PIXELS / 8) { + attrY = 0; + } + } + } + } + + break; + case SGB_ATRC_EN: + case SGB_MASK_EN: + if (softwareRenderer->sgbBorders && !renderer->sgbRenderMode) { + _regenerateSGBBorder(softwareRenderer); + } + } +} + static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value) { struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; + color_t color = mColorFrom555(value); + if (softwareRenderer->model & GB_MODEL_SGB) { + if (index < 0x10 && index && !(index & 3)) { + color = softwareRenderer->palette[0]; + } else if (index >= 0x40 && !(index & 0xF)) { + color = softwareRenderer->palette[0]; + } + } + if (renderer->cache) { + mCacheSetWritePalette(renderer->cache, index, color); + } + if (softwareRenderer->model == GB_MODEL_AGB) { + unsigned r = M_R5(value); + unsigned g = M_G5(value); + unsigned b = M_B5(value); + r = r * r; + g = g * g; + b = b * b; #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; + r /= 31; + g /= 31; + b /= 31; + color = mColorFrom555(r | (g << 5) | (b << 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; + r >>= 2; + g >>= 2; + b >>= 2; + color = r | (g << 8) | (b << 16); #endif + } softwareRenderer->palette[index] = color; - if (renderer->cache) { - mTileCacheWritePalette(renderer->cache, index << 1); + + if (softwareRenderer->model & GB_MODEL_SGB && !index && GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) { + renderer->writePalette(renderer, 0x04, value); + renderer->writePalette(renderer, 0x08, value); + renderer->writePalette(renderer, 0x0C, value); + renderer->writePalette(renderer, 0x40, value); + renderer->writePalette(renderer, 0x50, value); + renderer->writePalette(renderer, 0x60, value); + renderer->writePalette(renderer, 0x70, value); + if (softwareRenderer->sgbBorders && !renderer->sgbRenderMode) { + _regenerateSGBBorder(softwareRenderer); + } } } static void GBVideoSoftwareRendererWriteVRAM(struct GBVideoRenderer* renderer, uint16_t address) { if (renderer->cache) { - mTileCacheWriteVRAM(renderer->cache, address); + mCacheSetWriteVRAM(renderer->cache, address); } } @@ -174,7 +500,7 @@ int wy = softwareRenderer->wy + softwareRenderer->currentWy; if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && wy <= y && endX >= softwareRenderer->wx - 7) { if (softwareRenderer->wx - 7 > 0 && !softwareRenderer->d.disableBG) { - GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx, softwareRenderer->scy + y); + GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy); } maps = &softwareRenderer->d.vram[GB_BASE_MAP]; @@ -182,10 +508,10 @@ maps += GB_SIZE_MAP; } if (!softwareRenderer->d.disableWIN) { - GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx, y - wy); + GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx - softwareRenderer->offsetWx, y - wy - softwareRenderer->offsetWy); } } else if (!softwareRenderer->d.disableBG) { - GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx, softwareRenderer->scy + y); + GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy); } } else if (!softwareRenderer->d.disableBG) { memset(&softwareRenderer->row[startX], 0, endX - startX); @@ -197,25 +523,146 @@ 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 (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) { @@ -228,11 +675,50 @@ 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 && !renderer->sgbRenderMode) { + // 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->lastY = GB_VIDEO_VERTICAL_PIXELS; softwareRenderer->currentWy = 0; softwareRenderer->hasWindow = false; } +static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable) { + struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; + if (softwareRenderer->model & GB_MODEL_SGB) { + if (enable == softwareRenderer->sgbBorders) { + return; + } + softwareRenderer->sgbBorders = enable; + if (softwareRenderer->sgbBorders && !renderer->sgbRenderMode) { + _regenerateSGBBorder(softwareRenderer); + } + } +} + static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer* renderer, uint8_t* maps, int startX, int endX, int sx, int sy) { uint8_t* data = renderer->d.vram; uint8_t* attr = &maps[GB_SIZE_VRAM_BANK0]; @@ -334,15 +820,16 @@ } static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y) { - int ix = obj->x - 8; + int objX = obj->x + renderer->objOffsetX; + int ix = objX - 8; if (endX < ix || startX >= ix + 8) { return; } - if (obj->x < endX) { - endX = obj->x; + if (objX < endX) { + endX = objX; } - if (obj->x - 8 > startX) { - startX = obj->x - 8; + if (objX - 8 > startX) { + startX = objX - 8; } if (startX < 0) { startX = 0; @@ -350,14 +837,15 @@ uint8_t* data = renderer->d.vram; int tileOffset = 0; int bottomY; + int objY = obj->y + renderer->objOffsetY; if (GBObjAttributesIsYFlip(obj->attr)) { - bottomY = 7 - ((y - obj->y - 16) & 7); - if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - obj->y < -8) { + bottomY = 7 - ((y - objY - 16) & 7); + if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - objY < -8) { ++tileOffset; } } else { - bottomY = (y - obj->y - 16) & 7; - if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - obj->y >= -8) { + bottomY = (y - objY - 16) & 7; + if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - objY >= -8) { ++tileOffset; } } @@ -381,12 +869,12 @@ } int bottomX; int x = startX; - if ((x - obj->x) & 7) { + if ((x - objX) & 7) { for (; x < endX; ++x) { if (GBObjAttributesIsXFlip(obj->attr)) { - bottomX = (x - obj->x) & 7; + bottomX = (x - objX) & 7; } else { - bottomX = 7 - ((x - obj->x) & 7); + bottomX = 7 - ((x - objX) & 7); } int objTile = obj->tile + tileOffset; uint8_t tileDataLower = data[(objTile * 8 + bottomY) * 2]; diff -Nru mgba-0.6.3+dfsg1/src/gb/renderers/tile-cache.c mgba-0.7.0/src/gb/renderers/tile-cache.c --- mgba-0.6.3+dfsg1/src/gb/renderers/tile-cache.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/renderers/tile-cache.c 1970-01-01 00:00:00.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/src/gb/serialize.c mgba-0.7.0/src/gb/serialize.c --- mgba-0.6.3+dfsg1/src/gb/serialize.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/serialize.c 2019-01-27 00:06:06.000000000 +0000 @@ -9,10 +9,15 @@ #include #include +#include + 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 +25,7 @@ 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 +49,6 @@ 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 +63,10 @@ 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 +85,15 @@ } 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 +139,7 @@ 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 +155,6 @@ 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 +163,16 @@ 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 +187,88 @@ 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); + flags = GBSerializedSGBFlagsSetBufferIndex(flags, gb->video.sgbBufferIndex); + flags = GBSerializedSGBFlagsSetReqControllers(flags, gb->sgbControllers); + flags = GBSerializedSGBFlagsSetCurrentController(flags, gb->sgbCurrentController); + STORE_32LE(flags, 0, &state->sgb.flags); + + memcpy(state->sgb.packet, gb->video.sgbPacketBuffer, sizeof(state->sgb.packet)); + memcpy(state->sgb.inProgressPacket, gb->sgbPacket, sizeof(state->sgb.inProgressPacket)); + + 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)); + } + gb->video.renderer->enableSGBBorder(gb->video.renderer, gb->video.sgbBorders); +} + +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); + gb->video.sgbBufferIndex = GBSerializedSGBFlagsGetBufferIndex(flags); + gb->sgbControllers = GBSerializedSGBFlagsGetReqControllers(flags); + gb->sgbCurrentController = GBSerializedSGBFlagsGetCurrentController(flags); + + memcpy(gb->video.sgbPacketBuffer, state->sgb.packet, sizeof(state->sgb.packet)); + memcpy(gb->sgbPacket, state->sgb.inProgressPacket, sizeof(state->sgb.inProgressPacket)); + + if (!gb->video.renderer->sgbCharRam) { + gb->video.renderer->sgbCharRam = anonymousMemoryMap(SGB_SIZE_CHAR_RAM); + } + if (!gb->video.renderer->sgbMapRam) { + gb->video.renderer->sgbMapRam = anonymousMemoryMap(SGB_SIZE_MAP_RAM); + } + if (!gb->video.renderer->sgbPalRam) { + gb->video.renderer->sgbPalRam = anonymousMemoryMap(SGB_SIZE_PAL_RAM); + } + if (!gb->video.renderer->sgbAttributeFiles) { + gb->video.renderer->sgbAttributeFiles = anonymousMemoryMap(SGB_SIZE_ATF_RAM); + } + if (!gb->video.renderer->sgbAttributes) { + gb->video.renderer->sgbAttributes = malloc(90 * 45); + } + + memcpy(gb->video.renderer->sgbCharRam, state->sgb.charRam, sizeof(state->sgb.charRam)); + memcpy(gb->video.renderer->sgbMapRam, state->sgb.mapRam, sizeof(state->sgb.mapRam)); + memcpy(gb->video.renderer->sgbPalRam, state->sgb.palRam, sizeof(state->sgb.palRam)); + memcpy(gb->video.renderer->sgbAttributeFiles, state->sgb.atfRam, sizeof(state->sgb.atfRam)); + memcpy(gb->video.renderer->sgbAttributes, state->sgb.attributes, sizeof(state->sgb.attributes)); + + GBVideoWriteSGBPacket(&gb->video, (uint8_t[16]) { (SGB_ATRC_EN << 3) | 1, 0 }); +} diff -Nru mgba-0.6.3+dfsg1/src/gb/sio/printer.c mgba-0.7.0/src/gb/sio/printer.c --- mgba-0.6.3+dfsg1/src/gb/sio/printer.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/gb/sio/printer.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,236 @@ +/* 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) { + driver->p->pendingSB = 0; + switch (printer->next) { + 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: + default: + break; + } + + driver->p->pendingSB = printer->status; + printer->next = GB_PRINTER_BYTE_MAGIC_0; + break; + } + + 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); + } + printer->printWait = -1; + } else if (printer->printWait > 0) { + --printer->printWait; + } + + printer->byte = 0; + } + return value; +} + +void GBPrinterDonePrinting(struct GBPrinter* printer) { + printer->status &= ~(GB_PRINTER_STATUS_PRINTING | GB_PRINTER_STATUS_PRINT_REQ); +} diff -Nru mgba-0.6.3+dfsg1/src/gb/test/core.c mgba-0.7.0/src/gb/test/core.c --- mgba-0.6.3+dfsg1/src/gb/test/core.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/test/core.c 2019-01-27 00:06:06.000000000 +0000 @@ -29,6 +29,7 @@ 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 @@ 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 -Nru mgba-0.6.3+dfsg1/src/gb/test/gb.c mgba-0.7.0/src/gb/test/gb.c --- mgba-0.6.3+dfsg1/src/gb/test/gb.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/test/gb.c 1970-01-01 00:00:00.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/src/gb/test/gb.h mgba-0.7.0/src/gb/test/gb.h --- mgba-0.6.3+dfsg1/src/gb/test/gb.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/test/gb.h 1970-01-01 00:00:00.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/src/gb/test/mbc.c mgba-0.7.0/src/gb/test/mbc.c --- mgba-0.6.3+dfsg1/src/gb/test/mbc.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/test/mbc.c 2019-01-27 00:06:06.000000000 +0000 @@ -16,6 +16,7 @@ GBSynthesizeROM(vf); struct mCore* core = GBCoreCreate(); core->init(core); + mCoreInitConfig(core, NULL); core->loadROM(core, vf); *state = core; return 0; diff -Nru mgba-0.6.3+dfsg1/src/gb/test/memory.c mgba-0.7.0/src/gb/test/memory.c --- mgba-0.6.3+dfsg1/src/gb/test/memory.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/test/memory.c 2019-01-27 00:06:06.000000000 +0000 @@ -16,6 +16,7 @@ GBSynthesizeROM(vf); struct mCore* core = GBCoreCreate(); core->init(core); + mCoreInitConfig(core, NULL); core->loadROM(core, vf); *state = core; return 0; diff -Nru mgba-0.6.3+dfsg1/src/gb/test/rtc.c mgba-0.7.0/src/gb/test/rtc.c --- mgba-0.6.3+dfsg1/src/gb/test/rtc.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/test/rtc.c 2019-01-27 00:06:06.000000000 +0000 @@ -48,6 +48,7 @@ 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); diff -Nru mgba-0.6.3+dfsg1/src/gb/timer.c mgba-0.7.0/src/gb/timer.c --- mgba-0.6.3+dfsg1/src/gb/timer.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/timer.c 2019-01-27 00:06:06.000000000 +0000 @@ -27,9 +27,13 @@ if (timer->timaPeriod > 0 && (timer->internalDiv & (timer->timaPeriod - 1)) == timer->timaPeriod - 1) { ++timer->p->memory.io[REG_TIMA]; if (!timer->p->memory.io[REG_TIMA]) { - mTimingSchedule(&timer->p->timing, &timer->irq, 4 - cyclesLate); + mTimingSchedule(&timer->p->timing, &timer->irq, 7 - ((timer->p->cpu->executionState - cyclesLate) & 3)); } } + unsigned timingFactor = 0x3FF >> !timer->p->doubleSpeed; + if ((timer->internalDiv & timingFactor) == timingFactor) { + GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing); + } ++timer->internalDiv; timer->p->memory.io[REG_DIV] = timer->internalDiv >> 4; } @@ -64,19 +68,22 @@ timer->nextDiv = GB_DMG_DIV_PERIOD; // TODO: GBC differences timer->timaPeriod = 1024 >> 4; - timer->internalDiv = 0; } void GBTimerDivReset(struct GBTimer* timer) { timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event); mTimingDeschedule(&timer->p->timing, &timer->event); - _GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 1) & 3); + _GBTimerDivIncrement(timer, 0); if (((timer->internalDiv << 1) | ((timer->nextDiv >> 3) & 1)) & timer->timaPeriod) { ++timer->p->memory.io[REG_TIMA]; if (!timer->p->memory.io[REG_TIMA]) { - mTimingSchedule(&timer->p->timing, &timer->irq, 4 - ((timer->p->cpu->executionState + 1) & 3)); + mTimingSchedule(&timer->p->timing, &timer->irq, 7 - (timer->p->cpu->executionState & 3)); } } + unsigned timingFactor = 0x400 >> !timer->p->doubleSpeed; + if (timer->internalDiv & timingFactor) { + GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing); + } timer->p->memory.io[REG_DIV] = 0; timer->internalDiv = 0; timer->nextDiv = GB_DMG_DIV_PERIOD; @@ -102,7 +109,7 @@ timer->nextDiv -= mTimingUntil(&timer->p->timing, &timer->event); mTimingDeschedule(&timer->p->timing, &timer->event); - _GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 1) & 3); + _GBTimerDivIncrement(timer, (timer->p->cpu->executionState + 2) & 3); timer->nextDiv += GB_DMG_DIV_PERIOD; mTimingSchedule(&timer->p->timing, &timer->event, timer->nextDiv); } else { diff -Nru mgba-0.6.3+dfsg1/src/gb/video.c mgba-0.7.0/src/gb/video.c --- mgba-0.6.3+dfsg1/src/gb/video.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gb/video.c 2019-01-27 00:06:06.000000000 +0000 @@ -7,23 +7,26 @@ #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); static void GBVideoDummyRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y, struct GBObj* obj, size_t oamMax); static void GBVideoDummyRendererFinishScanline(struct GBVideoRenderer* renderer, int y); static void GBVideoDummyRendererFinishFrame(struct GBVideoRenderer* renderer); +static void GBVideoDummyRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable); static void GBVideoDummyRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels); static void GBVideoDummyRendererPutPixels(struct GBVideoRenderer* renderer, size_t stride, const void* pixels); @@ -39,12 +42,14 @@ .init = GBVideoDummyRendererInit, .deinit = GBVideoDummyRendererDeinit, .writeVideoRegister = GBVideoDummyRendererWriteVideoRegister, + .writeSGBPacket = GBVideoDummyRendererWriteSGBPacket, .writeVRAM = GBVideoDummyRendererWriteVRAM, .writeOAM = GBVideoDummyRendererWriteOAM, .writePalette = GBVideoDummyRendererWritePalette, .drawRange = GBVideoDummyRendererDrawRange, .finishScanline = GBVideoDummyRendererFinishScanline, .finishFrame = GBVideoDummyRendererFinishFrame, + .enableSGBBorder = GBVideoDummyRendererEnableSGBBorder, .getPixels = GBVideoDummyRendererGetPixels, .putPixels = GBVideoDummyRendererPutPixels, }; @@ -52,7 +57,8 @@ void GBVideoInit(struct GBVideo* video) { video->renderer = &dummyRenderer; video->renderer->cache = NULL; - video->vram = 0; + video->renderer->sgbRenderMode = 0; + video->vram = anonymousMemoryMap(GB_SIZE_VRAM); video->frameskip = 0; video->modeEvent.context = video; @@ -68,6 +74,22 @@ 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) { @@ -79,31 +101,90 @@ video->frameCounter = 0; video->frameskipCounter = 0; - if (video->vram) { - mappedMemoryFree(video->vram, GB_SIZE_VRAM); - } - video->vram = anonymousMemoryMap(GB_SIZE_VRAM); GBVideoSwitchBank(video, 0); video->renderer->vram = video->vram; memset(&video->oam, 0, sizeof(video->oam)); 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->sgbBufferIndex = 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); + video->renderer->deinit(video->renderer); 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) { @@ -145,8 +226,7 @@ GBRegisterSTAT oldStat = video->stat; video->stat = GBRegisterSTATSetLYC(video->stat, lyc == video->ly); if (video->ly < GB_VIDEO_VERTICAL_PIXELS) { - // TODO: Cache SCX & 7 in case it changes during mode 2 - next = GB_VIDEO_MODE_2_LENGTH + (video->p->memory.io[REG_SCX] & 7); + next = GB_VIDEO_MODE_2_LENGTH; video->mode = 2; video->modeEvent.callback = _endMode2; } else { @@ -183,7 +263,7 @@ if (video->ly == GB_VIDEO_VERTICAL_TOTAL_PIXELS + 1) { video->ly = 0; video->p->memory.io[REG_LY] = video->ly; - next = GB_VIDEO_MODE_2_LENGTH + (video->p->memory.io[REG_SCX] & 7); + next = GB_VIDEO_MODE_2_LENGTH; video->mode = 2; video->modeEvent.callback = _endMode2; } else if (video->ly == GB_VIDEO_VERTICAL_TOTAL_PIXELS) { @@ -211,9 +291,9 @@ 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; - int32_t next = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 6 - (video->p->memory.io[REG_SCX] & 7); + video->x = -(video->p->memory.io[REG_SCX] & 7); + video->dotClock = mTimingCurrentTime(timing) - cyclesLate + 5 - (video->x << video->p->doubleSpeed); + int32_t next = GB_VIDEO_MODE_3_LENGTH_BASE + video->objMax * 6 - video->x; video->mode = 3; video->modeEvent.callback = _endMode3; GBRegisterSTAT oldStat = video->stat; @@ -228,7 +308,7 @@ void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate) { struct GBVideo* video = context; - GBVideoProcessDots(video); + GBVideoProcessDots(video, cyclesLate); 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; @@ -244,7 +324,8 @@ GBUpdateIRQs(video->p); } video->p->memory.io[REG_STAT] = video->stat; - int32_t next = GB_VIDEO_MODE_0_LENGTH_BASE - video->objMax * 6; + // TODO: Cache SCX & 7 in case it changes + int32_t next = GB_VIDEO_MODE_0_LENGTH_BASE - video->objMax * 6 - (video->p->memory.io[REG_SCX] & 7); mTimingSchedule(timing, &video->modeEvent, (next << video->p->doubleSpeed) - cyclesLate); } @@ -256,14 +337,6 @@ return; } - size_t c; - for (c = 0; c < mCoreCallbacksListSize(&video->p->coreCallbacks); ++c) { - struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&video->p->coreCallbacks, c); - if (callbacks->videoFrameEnded) { - callbacks->videoFrameEnded(callbacks->context); - } - } - GBFrameEnded(video->p); mCoreSyncPostFrame(video->p->sync); --video->frameskipCounter; @@ -273,24 +346,10 @@ } ++video->frameCounter; - // TODO: Move to common code - if (video->p->stream && video->p->stream->postVideoFrame) { - const color_t* pixels; - size_t stride; - video->renderer->getPixels(video->renderer, &stride, (const void**) &pixels); - video->p->stream->postVideoFrame(video->p->stream, pixels, stride); - } - if (!GBRegisterLCDCIsEnable(video->p->memory.io[REG_LCDC])) { mTimingSchedule(timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH); } - - for (c = 0; c < mCoreCallbacksListSize(&video->p->coreCallbacks); ++c) { - struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&video->p->coreCallbacks, c); - if (callbacks->videoFrameStarted) { - callbacks->videoFrameStarted(callbacks->context); - } - } + GBFrameStarted(video->p); } static void _cleanOAM(struct GBVideo* video, int y) { @@ -318,17 +377,19 @@ video->objMax = o; } -void GBVideoProcessDots(struct GBVideo* video) { +void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate) { if (video->mode != 3) { return; } int oldX = video->x; - video->x = (video->p->timing.masterCycles - video->dotClock + video->p->cpu->cycles) >> video->p->doubleSpeed; + video->x = (int32_t) (mTimingCurrentTime(&video->p->timing) - cyclesLate - video->dotClock) >> video->p->doubleSpeed; if (video->x > GB_VIDEO_HORIZONTAL_PIXELS) { video->x = GB_VIDEO_HORIZONTAL_PIXELS; } else if (video->x < 0) { - mLOG(GB, FATAL, "Video dot clock went negative!"); - video->x = oldX; + return; + } + if (oldX < 0) { + oldX = 0; } if (video->frameskipCounter <= 0) { video->renderer->drawRange(video->renderer, oldX, video->x, video->ly, video->objThisLine, video->objMax); @@ -340,6 +401,7 @@ video->mode = 2; video->modeEvent.callback = _endMode2; int32_t next = GB_VIDEO_MODE_2_LENGTH - 5; // TODO: Why is this fudge factor needed? Might be related to T-cycles for load/store differing + mTimingDeschedule(&video->p->timing, &video->modeEvent); mTimingSchedule(&video->p->timing, &video->modeEvent, next << video->p->doubleSpeed); video->ly = 0; @@ -358,6 +420,7 @@ } if (GBRegisterLCDCIsEnable(video->p->memory.io[REG_LCDC]) && !GBRegisterLCDCIsEnable(value)) { // TODO: Fix serialization; this gets internal and visible modes out of sync + video->mode = 0; video->stat = GBRegisterSTATSetMode(video->stat, 0); video->p->memory.io[REG_STAT] = video->stat; video->ly = 0; @@ -365,6 +428,7 @@ video->renderer->writePalette(video->renderer, 0, video->dmgPalette[0]); mTimingDeschedule(&video->p->timing, &video->modeEvent); + mTimingDeschedule(&video->p->timing, &video->frameEvent); mTimingSchedule(&video->p->timing, &video->frameEvent, GB_VIDEO_TOTAL_LENGTH); } video->p->memory.io[REG_STAT] = video->stat; @@ -385,16 +449,18 @@ void GBVideoWriteLYC(struct GBVideo* video, uint8_t value) { GBRegisterSTAT oldStat = video->stat; - video->stat = GBRegisterSTATSetLYC(video->stat, value == video->ly); - if (!_statIRQAsserted(video, oldStat) && _statIRQAsserted(video, video->stat)) { - video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT); - GBUpdateIRQs(video->p); + if (GBRegisterLCDCIsEnable(video->p->memory.io[REG_LCDC])) { + video->stat = GBRegisterSTATSetLYC(video->stat, value == video->ly); + if (!_statIRQAsserted(video, oldStat) && _statIRQAsserted(video, video->stat)) { + video->p->memory.io[REG_IF] |= (1 << GB_IRQ_LCDSTAT); + GBUpdateIRQs(video->p); + } } video->p->memory.io[REG_STAT] = video->stat; } 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]; @@ -407,26 +473,28 @@ 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: @@ -474,15 +542,171 @@ } 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)) { + video->sgbBufferIndex = 0; + if ((data[0] >> 3) > SGB_OBJ_TRN) { + video->sgbCommandHeader = 0; + return; + } + video->sgbCommandHeader = data[0]; + } + --video->sgbCommandHeader; + memcpy(&video->sgbPacketBuffer[video->sgbBufferIndex << 4], data, 16); + ++video->sgbBufferIndex; + if (video->sgbCommandHeader & 7) { + return; + } + switch (video->sgbCommandHeader >> 3) { + case SGB_PAL01: + video->palette[0] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8); + video->palette[1] = video->sgbPacketBuffer[3] | (video->sgbPacketBuffer[4] << 8); + video->palette[2] = video->sgbPacketBuffer[5] | (video->sgbPacketBuffer[6] << 8); + video->palette[3] = video->sgbPacketBuffer[7] | (video->sgbPacketBuffer[8] << 8); + + video->palette[4] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8); + video->palette[5] = video->sgbPacketBuffer[9] | (video->sgbPacketBuffer[10] << 8); + video->palette[6] = video->sgbPacketBuffer[11] | (video->sgbPacketBuffer[12] << 8); + video->palette[7] = video->sgbPacketBuffer[13] | (video->sgbPacketBuffer[14] << 8); + + video->palette[8] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8); + video->palette[12] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[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, 4, video->palette[4]); + video->renderer->writePalette(video->renderer, 5, video->palette[5]); + video->renderer->writePalette(video->renderer, 6, video->palette[6]); + video->renderer->writePalette(video->renderer, 7, video->palette[7]); + video->renderer->writePalette(video->renderer, 8, video->palette[8]); + video->renderer->writePalette(video->renderer, 12, video->palette[12]); + break; + case SGB_PAL23: + video->palette[9] = video->sgbPacketBuffer[3] | (video->sgbPacketBuffer[4] << 8); + video->palette[10] = video->sgbPacketBuffer[5] | (video->sgbPacketBuffer[6] << 8); + video->palette[11] = video->sgbPacketBuffer[7] | (video->sgbPacketBuffer[8] << 8); + + video->palette[13] = video->sgbPacketBuffer[9] | (video->sgbPacketBuffer[10] << 8); + video->palette[14] = video->sgbPacketBuffer[11] | (video->sgbPacketBuffer[12] << 8); + video->palette[15] = video->sgbPacketBuffer[13] | (video->sgbPacketBuffer[14] << 8); + video->renderer->writePalette(video->renderer, 9, video->palette[9]); + video->renderer->writePalette(video->renderer, 10, video->palette[10]); + video->renderer->writePalette(video->renderer, 11, video->palette[11]); + video->renderer->writePalette(video->renderer, 13, video->palette[13]); + video->renderer->writePalette(video->renderer, 14, video->palette[14]); + video->renderer->writePalette(video->renderer, 15, video->palette[15]); + break; + case SGB_PAL03: + video->palette[0] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8); + video->palette[1] = video->sgbPacketBuffer[3] | (video->sgbPacketBuffer[4] << 8); + video->palette[2] = video->sgbPacketBuffer[5] | (video->sgbPacketBuffer[6] << 8); + video->palette[3] = video->sgbPacketBuffer[7] | (video->sgbPacketBuffer[8] << 8); + + video->palette[4] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8); + video->palette[8] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8); + + video->palette[12] = video->sgbPacketBuffer[1] | (video->sgbPacketBuffer[2] << 8); + video->palette[13] = video->sgbPacketBuffer[9] | (video->sgbPacketBuffer[10] << 8); + video->palette[14] = video->sgbPacketBuffer[11] | (video->sgbPacketBuffer[12] << 8); + video->palette[15] = video->sgbPacketBuffer[13] | (video->sgbPacketBuffer[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, 4, video->palette[4]); + video->renderer->writePalette(video->renderer, 8, video->palette[8]); + video->renderer->writePalette(video->renderer, 12, video->palette[12]); + video->renderer->writePalette(video->renderer, 13, video->palette[13]); + video->renderer->writePalette(video->renderer, 14, video->palette[14]); + video->renderer->writePalette(video->renderer, 15, video->palette[15]); + break; + case SGB_PAL12: + video->palette[5] = video->sgbPacketBuffer[3] | (video->sgbPacketBuffer[4] << 8); + video->palette[6] = video->sgbPacketBuffer[5] | (video->sgbPacketBuffer[6] << 8); + video->palette[7] = video->sgbPacketBuffer[7] | (video->sgbPacketBuffer[8] << 8); + + video->palette[9] = video->sgbPacketBuffer[9] | (video->sgbPacketBuffer[10] << 8); + video->palette[10] = video->sgbPacketBuffer[11] | (video->sgbPacketBuffer[12] << 8); + video->palette[11] = video->sgbPacketBuffer[13] | (video->sgbPacketBuffer[14] << 8); + video->renderer->writePalette(video->renderer, 5, video->palette[5]); + video->renderer->writePalette(video->renderer, 6, video->palette[6]); + video->renderer->writePalette(video->renderer, 7, video->palette[7]); + video->renderer->writePalette(video->renderer, 9, video->palette[9]); + video->renderer->writePalette(video->renderer, 10, video->palette[10]); + video->renderer->writePalette(video->renderer, 11, video->palette[11]); + break; + case SGB_PAL_SET: + for (i = 0; i < 4; ++i) { + uint16_t entry = (video->sgbPacketBuffer[2 + (i * 2)] << 8) | video->sgbPacketBuffer[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[i * 4 + 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_ATTR_DIV: + case SGB_ATTR_CHR: + case SGB_ATTR_LIN: + 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_REQ: + video->p->sgbControllers = video->sgbPacketBuffer[1] & 0x3; + video->p->sgbCurrentController = 0; + return; + case SGB_MASK_EN: + video->renderer->sgbRenderMode = video->sgbPacketBuffer[1] & 0x3; + break; + default: + mLOG(GB, STUB, "Unimplemented SGB command: %02X", video->sgbPacketBuffer[0] >> 3); + return; + } + video->renderer->writeSGBPacket(video->renderer, video->sgbPacketBuffer); +} + +static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders) { UNUSED(renderer); UNUSED(model); + UNUSED(borders); // Nothing to do } @@ -492,14 +716,20 @@ } 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); } } @@ -510,9 +740,8 @@ } 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)); } } @@ -537,6 +766,12 @@ // Nothing to do } +static void GBVideoDummyRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable) { + UNUSED(renderer); + UNUSED(enable); + // Nothing to do +} + static void GBVideoDummyRendererGetPixels(struct GBVideoRenderer* renderer, size_t* stride, const void** pixels) { UNUSED(renderer); UNUSED(stride); @@ -555,6 +790,7 @@ STORE_16LE(video->x, 0, &state->video.x); STORE_16LE(video->ly, 0, &state->video.ly); STORE_32LE(video->frameCounter, 0, &state->video.frameCounter); + STORE_32LE(video->dotClock, 0, &state->video.dotCounter); state->video.vramCurrentBank = video->vramCurrentBank; GBSerializedVideoFlags flags = 0; @@ -583,6 +819,7 @@ LOAD_16LE(video->x, 0, &state->video.x); LOAD_16LE(video->ly, 0, &state->video.ly); LOAD_32LE(video->frameCounter, 0, &state->video.frameCounter); + LOAD_32LE(video->dotClock, 0, &state->video.dotCounter); video->vramCurrentBank = state->video.vramCurrentBank; GBSerializedVideoFlags flags = state->video.flags; @@ -632,5 +869,5 @@ 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 -Nru mgba-0.6.3+dfsg1/src/gba/audio.c mgba-0.7.0/src/gba/audio.c --- mgba-0.6.3+dfsg1/src/gba/audio.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/audio.c 2019-01-27 00:06:06.000000000 +0000 @@ -111,7 +111,7 @@ mLOG(GBA_AUDIO, GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest); return; } - info->reg = GBADMARegisterSetDestControl(info->reg, DMA_FIXED); + info->reg = GBADMARegisterSetDestControl(info->reg, GBA_DMA_FIXED); info->reg = GBADMARegisterSetWidth(info->reg, 1); } @@ -235,7 +235,7 @@ } if (CircleBufferSize(&channel->fifo) <= 4 * sizeof(int32_t) && channel->dmaSource > 0) { struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource]; - if (GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_CUSTOM) { + if (GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_CUSTOM) { dma->when = mTimingCurrentTime(&audio->p->timing) - cycles; dma->nextCount = 4; GBADMASchedule(audio->p, channel->dmaSource, dma); @@ -253,14 +253,14 @@ } else if (sample < 0) { sample = 0; } - return ((sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) * audio->masterVolume) >> 3; + return ((sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) * audio->masterVolume * 3) >> 4; } static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBAAudio* audio = user; int16_t sampleLeft = 0; int16_t sampleRight = 0; - int psgShift = 5 - audio->volume; + int psgShift = 4 - audio->volume; GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight); sampleLeft >>= psgShift; sampleRight >>= psgShift; @@ -307,7 +307,10 @@ audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight); } bool wait = produced >= audio->samples; - mCoreSyncProduceAudio(audio->p->sync, wait); + if (!mCoreSyncProduceAudio(audio->p->sync, audio->psg.left, audio->samples)) { + // Interrupted + audio->p->earlyExit = true; + } if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) { audio->p->stream->postAudioBuffer(audio->p->stream, audio->psg.left, audio->psg.right); diff -Nru mgba-0.6.3+dfsg1/src/gba/bios.c mgba-0.7.0/src/gba/bios.c --- mgba-0.6.3+dfsg1/src/gba/bios.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/bios.c 2019-01-27 00:06:06.000000000 +0000 @@ -251,7 +251,7 @@ uint32_t key = cpu->memory.load32(cpu, cpu->gprs[0] + 4, 0); gba->memory.activeRegion = oldRegion; - cpu->gprs[0] = key / powf(2, (180.f - cpu->gprs[1] - cpu->gprs[2] / 256.f) / 12.f); + cpu->gprs[0] = key / exp2f((180.f - cpu->gprs[1] - cpu->gprs[2] / 256.f) / 12.f); } static void _Div(struct GBA* gba, int32_t num, int32_t denom) { @@ -333,6 +333,12 @@ mLOG(GBA_BIOS, DEBUG, "SWI: %02X r0: %08X r1: %08X r2: %08X r3: %08X", immediate, cpu->gprs[0], cpu->gprs[1], cpu->gprs[2], cpu->gprs[3]); + switch (immediate) { + case 0xFA: + GBAPrintFlush(gba); + return; + } + if (gba->memory.fullBios) { ARMRaiseSWI(cpu); return; @@ -803,7 +809,7 @@ uint32_t out = 0; int bitsRemaining = 0; int bitsEaten = 0; - while (sourceLen > 0) { + while (sourceLen > 0 || bitsRemaining) { if (!bitsRemaining) { in = cpu->memory.load8(cpu, source, 0); bitsRemaining = 8; @@ -814,7 +820,6 @@ in >>= sourceWidth; if (scaled || bias & 0x80000000) { scaled += bias & 0x7FFFFFFF; - scaled &= (1 << destWidth) - 1; } bitsRemaining -= sourceWidth; out |= scaled << bitsEaten; @@ -826,4 +831,6 @@ dest += 4; } } + cpu->gprs[0] = source; + cpu->gprs[1] = dest; } diff -Nru mgba-0.6.3+dfsg1/src/gba/cheats/gameshark.c mgba-0.7.0/src/gba/cheats/gameshark.c --- mgba-0.6.3+dfsg1/src/gba/cheats/gameshark.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/cheats/gameshark.c 2019-01-27 00:06:06.000000000 +0000 @@ -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 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; } } @@ -158,9 +161,32 @@ cheats->romPatches[romPatch].exists = true; return true; case GSA_BUTTON: - // TODO: Implement button - mLOG(CHEATS, STUB, "GameShark button unimplemented"); - return false; + switch (op1 & 0x00F00000) { + case 0x00100000: + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_IF_BUTTON; + cheat->repeat = 1; + cheat->negativeRepeat = 0; + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_ASSIGN; + cheat->width = 1; + cheat->address = op1 & 0x0F0FFFFF; + break; + case 0x00200000: + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_IF_BUTTON; + cheat->repeat = 1; + cheat->negativeRepeat = 0; + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_ASSIGN; + cheat->width = 2; + cheat->address = op1 & 0x0F0FFFFF; + break; + default: + mLOG(CHEATS, STUB, "GameShark button type unimplemented"); + return false; + } + break; case GSA_IF_EQ: if (op1 == 0xDEADFACE) { GBACheatReseedGameShark(cheats->gsaSeeds, op2, _gsa1T1, _gsa1T2); @@ -206,15 +232,13 @@ 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 GBA_GS_GSAV1: GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds); // Fall through - case 2: + case GBA_GS_GSAV1_RAW: return GBACheatAddGameSharkRaw(set, o1, o2); } return false; diff -Nru mgba-0.6.3+dfsg1/src/gba/cheats/gameshark.h mgba-0.7.0/src/gba/cheats/gameshark.h --- mgba-0.6.3+dfsg1/src/gba/cheats/gameshark.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/cheats/gameshark.h 2019-01-27 00:06:06.000000000 +0000 @@ -12,10 +12,18 @@ 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 -Nru mgba-0.6.3+dfsg1/src/gba/cheats/parv3.c mgba-0.7.0/src/gba/cheats/parv3.c --- mgba-0.6.3+dfsg1/src/gba/cheats/parv3.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/cheats/parv3.c 2019-01-27 00:06:06.000000000 +0000 @@ -140,41 +140,60 @@ } static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) { + int romPatch = -1; struct mCheat* cheat; switch (op2 & 0xFF000000) { case PAR3_OTHER_SLOWDOWN: // TODO: Slowdown + mLOG(CHEATS, STUB, "Unimplemented PARv3 slowdown"); return false; case PAR3_OTHER_BUTTON_1: + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_IF_BUTTON; + cheat->repeat = 1; + cheat->negativeRepeat = 0; + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_ASSIGN; + cheat->width = 1; + cheat->repeat = 1; + cheat->address = _parAddr(op2); + cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); + break; case PAR3_OTHER_BUTTON_2: + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_IF_BUTTON; + cheat->repeat = 1; + cheat->negativeRepeat = 0; + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_ASSIGN; + cheat->width = 2; + cheat->repeat = 1; + cheat->address = _parAddr(op2); + cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); + break; case PAR3_OTHER_BUTTON_4: - // TODO: Button - mLOG(CHEATS, STUB, "GameShark button unimplemented"); - return false; - // TODO: Fix overriding existing patches + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_IF_BUTTON; + cheat->repeat = 1; + cheat->negativeRepeat = 0; + cheat = mCheatListAppend(&cheats->d.list); + cheat->type = CHEAT_ASSIGN; + cheat->width = 4; + cheat->repeat = 1; + cheat->address = _parAddr(op2); + cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); + break; case PAR3_OTHER_PATCH_1: - cheats->romPatches[0].address = BASE_CART0 | ((op2 & 0xFFFFFF) << 1); - cheats->romPatches[0].applied = false; - cheats->romPatches[0].exists = true; - cheats->incompletePatch = &cheats->romPatches[0]; + romPatch = 0; break; case PAR3_OTHER_PATCH_2: - cheats->romPatches[1].address = BASE_CART0 | ((op2 & 0xFFFFFF) << 1); - cheats->romPatches[1].applied = false; - cheats->romPatches[1].exists = true; - cheats->incompletePatch = &cheats->romPatches[1]; + romPatch = 1; break; case PAR3_OTHER_PATCH_3: - cheats->romPatches[2].address = BASE_CART0 | ((op2 & 0xFFFFFF) << 1); - cheats->romPatches[2].applied = false; - cheats->romPatches[2].exists = true; - cheats->incompletePatch = &cheats->romPatches[2]; + romPatch = 2; break; case PAR3_OTHER_PATCH_4: - cheats->romPatches[3].address = BASE_CART0 | ((op2 & 0xFFFFFF) << 1); - cheats->romPatches[3].applied = false; - cheats->romPatches[3].exists = true; - cheats->incompletePatch = &cheats->romPatches[3]; + romPatch = 3; break; case PAR3_OTHER_ENDIF: if (cheats->currentBlock != COMPLETE) { @@ -210,6 +229,18 @@ cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); break; } + if (romPatch >= 0) { + while (cheats->romPatches[romPatch].exists) { + ++romPatch; + if (romPatch >= MAX_ROM_PATCHES) { + break; + } + } + cheats->romPatches[romPatch].address = BASE_CART0 | ((op2 & 0xFFFFFF) << 1); + cheats->romPatches[romPatch].applied = false; + cheats->romPatches[romPatch].exists = true; + cheats->incompletePatch = &cheats->romPatches[romPatch]; + } return true; } @@ -222,6 +253,13 @@ if (cheats->incompleteCheat != COMPLETE) { struct mCheat* incompleteCheat = mCheatListGetPointer(&cheats->d.list, cheats->incompleteCheat); incompleteCheat->operand = op1 & (0xFFFFFFFFU >> ((4 - incompleteCheat->width) * 8)); + if (cheats->incompleteCheat > 0) { + struct mCheat* lastCheat = mCheatListGetPointer(&cheats->d.list, cheats->incompleteCheat - 1); + if (lastCheat->type == CHEAT_IF_BUTTON) { + cheats->incompleteCheat = COMPLETE; + return true; + } + } incompleteCheat->operandOffset = op2 >> 24; incompleteCheat->repeat = (op2 >> 16) & 0xFF; incompleteCheat->addressOffset = (op2 & 0xFFFF) * incompleteCheat->width; @@ -304,15 +342,13 @@ 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 GBA_GS_PARV3: GBACheatDecryptGameShark(&o1, &o2, set->gsaSeeds); // Fall through - case 4: + case GBA_GS_PARV3_RAW: return GBACheatAddProActionReplayRaw(set, o1, o2); } return false; diff -Nru mgba-0.6.3+dfsg1/src/gba/cheats.c mgba-0.7.0/src/gba/cheats.c --- mgba-0.6.3+dfsg1/src/gba/cheats.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/cheats.c 2019-01-27 00:06:06.000000000 +0000 @@ -21,7 +21,7 @@ if (cheats->hook->reentries > 1) { return; } - // TODO: Put back hooks + GBASetBreakpoint(device->p->board, &device->d, cheats->hook->address, cheats->hook->mode, &cheats->hook->patchedOpcode); } static void _removeBreakpoint(struct mCheatDevice* device, struct GBACheatSet* cheats) { @@ -32,7 +32,7 @@ if (cheats->hook->reentries > 0) { return; } - // TODO: Put back hooks + GBAClearBreakpoint(device->p->board, cheats->hook->address, cheats->hook->mode, cheats->hook->patchedOpcode); } static void _patchROM(struct mCheatDevice* device, struct GBACheatSet* cheats) { @@ -150,26 +150,26 @@ o2 = op2; if (gsaP > maxProbability) { maxProbability = gsaP; - GBACheatSetGameSharkVersion(set, 1); + GBACheatSetGameSharkVersion(set, GBA_GS_GSAV1); } GBACheatDecryptGameShark(&o1, &o2, GBACheatProActionReplaySeeds); parP = GBACheatProActionReplayProbability(o1, o2); if (parP > maxProbability) { maxProbability = parP; - GBACheatSetGameSharkVersion(set, 3); + GBACheatSetGameSharkVersion(set, GBA_GS_PARV3); } rgsaP = GBACheatGameSharkProbability(op1, op1); if (rgsaP > maxProbability) { maxProbability = rgsaP; - GBACheatSetGameSharkVersion(set, 2); + GBACheatSetGameSharkVersion(set, GBA_GS_GSAV1_RAW); } rparP = GBACheatProActionReplayProbability(op1, op1); if (rparP > maxProbability) { maxProbability = rparP; - GBACheatSetGameSharkVersion(set, 4); + GBACheatSetGameSharkVersion(set, GBA_GS_PARV3_RAW); } if (set->gsaVersion < 3) { @@ -276,6 +276,9 @@ struct GBACheatSet* gbaset = (struct GBACheatSet*) cheats; if (cheats->enabled) { _patchROM(device, gbaset); + if (gbaset->hook && !gbaset->hook->reentries) { + _addBreakpoint(device, gbaset); + } } else { _unpatchROM(device, gbaset); } @@ -308,19 +311,19 @@ 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, 2); + 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, 4); + GBACheatSetGameSharkVersion(cheats, GBA_GS_PARV3_RAW); continue; } } diff -Nru mgba-0.6.3+dfsg1/src/gba/core.c mgba-0.7.0/src/gba/core.c --- mgba-0.6.3+dfsg1/src/gba/core.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/core.c 2019-01-27 00:06:06.000000000 +0000 @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,9 @@ #include #include #include +#ifdef USE_ELF +#include +#endif #include #include #include @@ -124,7 +128,6 @@ struct mCoreCallbacks logCallbacks; #ifndef DISABLE_THREADING struct mVideoThreadProxy threadProxy; - int threadedVideo; #endif int keys; struct mCPUComponent* components[CPU_COMPONENT_MAX]; @@ -164,7 +167,6 @@ gbacore->renderer.outputBuffer = NULL; #ifndef DISABLE_THREADING - gbacore->threadedVideo = false; mVideoThreadProxyCreate(&gbacore->threadProxy); #endif gbacore->proxyRenderer.logger = NULL; @@ -237,10 +239,15 @@ } } + int fakeBool = 0; + mCoreConfigGetIntValue(config, "allowOpposingDirections", &fakeBool); + gba->allowOpposingDirections = fakeBool; + + mCoreConfigCopyValue(&core->config, config, "allowOpposingDirections"); mCoreConfigCopyValue(&core->config, config, "gba.bios"); #ifndef DISABLE_THREADING - mCoreConfigGetIntValue(config, "threadedVideo", &gbacore->threadedVideo); + mCoreConfigCopyValue(&core->config, config, "threadedVideo"); #endif } @@ -254,6 +261,7 @@ 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) { @@ -307,6 +315,15 @@ } static bool _GBACoreLoadROM(struct mCore* core, struct VFile* vf) { +#ifdef USE_ELF + struct ELF* elf = ELFOpen(vf); + if (elf) { + GBALoadNull(core->board); + bool success = mCoreLoadELF(core, elf); + ELFClose(elf); + return success; + } +#endif if (GBAIsMB(vf)) { return GBALoadMB(core->board, vf); } @@ -372,7 +389,8 @@ if (gbacore->renderer.outputBuffer) { struct GBAVideoRenderer* renderer = &gbacore->renderer.d; #ifndef DISABLE_THREADING - if (gbacore->threadedVideo) { + int fakeBool; + if (mCoreConfigGetIntValue(&core->config, "threadedVideo", &fakeBool) && fakeBool) { gbacore->proxyRenderer.logger = &gbacore->threadProxy.d; GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer); renderer = &gbacore->proxyRenderer.d; @@ -381,20 +399,8 @@ 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 (!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(gbacore->overrides, &override)) { - GBAOverrideApply(gba, &override); - } - } + GBAOverrideApplyDefaults(gba, gbacore->overrides); + #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 if (!gba->biosVf && core->opts.useBios) { struct VFile* bios = NULL; @@ -700,7 +706,52 @@ } static void _GBACoreLoadSymbols(struct mCore* core, struct VFile* vf) { - // TODO + bool closeAfter = false; + core->symbolTable = mDebuggerSymbolTableCreate(); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#ifdef USE_ELF + if (!vf) { + closeAfter = true; + vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".elf", O_RDONLY); + } +#endif + if (!vf) { + closeAfter = true; + vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".sym", O_RDONLY); + } +#endif + if (!vf) { + return; + } +#ifdef USE_ELF + struct ELF* elf = ELFOpen(vf); + if (elf) { +#ifdef USE_DEBUGGERS + mCoreLoadELFSymbols(core->symbolTable, elf); +#endif + ELFClose(elf); + } else +#endif + { + mDebuggerLoadARMIPSSymbols(core->symbolTable, vf); + } + if (closeAfter) { + vf->close(vf); + } +} + +static bool _GBACoreLookupIdentifier(struct mCore* core, const char* name, int32_t* value, int* segment) { + UNUSED(core); + *segment = -1; + int i; + for (i = 0; i < REG_MAX; i += 2) { + const char* reg = GBAIORegisterNames[i >> 1]; + if (reg && strcasecmp(reg, name) == 0) { + *value = BASE_IO | i; + return true; + } + } + return false; } #endif @@ -757,13 +808,17 @@ static size_t _GBACoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) { UNUSED(core); - *info = _GBAVideoLayers; + if (info) { + *info = _GBAVideoLayers; + } return sizeof(_GBAVideoLayers) / sizeof(*_GBAVideoLayers); } static size_t _GBACoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) { UNUSED(core); - *info = _GBAAudioChannels; + if (info) { + *info = _GBAAudioChannels; + } return sizeof(_GBAAudioChannels) / sizeof(*_GBAAudioChannels); } @@ -795,6 +850,7 @@ break; case 4: gba->audio.forceDisableChA = !enable; + break; case 5: gba->audio.forceDisableChB = !enable; break; @@ -803,6 +859,27 @@ } } +static void _GBACoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) { + struct GBACore* gbacore = (struct GBACore*) core; + switch (id) { + case 0: + case 1: + case 2: + case 3: + gbacore->renderer.bg[id].offsetX = x; + gbacore->renderer.bg[id].offsetY = y; + break; + case 4: + gbacore->renderer.objOffsetX = x; + gbacore->renderer.objOffsetY = y; + gbacore->renderer.oamDirty = 1; + break; + default: + return; + } + memset(gbacore->renderer.scanlineDirty, 0xFFFFFFFF, sizeof(gbacore->renderer.scanlineDirty)); +} + #ifndef MINIMAL_CORE static void _GBACoreStartVideoLog(struct mCore* core, struct mVideoLogContext* context) { struct GBACore* gbacore = (struct GBACore*) core; @@ -899,6 +976,7 @@ core->attachDebugger = _GBACoreAttachDebugger; core->detachDebugger = _GBACoreDetachDebugger; core->loadSymbols = _GBACoreLoadSymbols; + core->lookupIdentifier = _GBACoreLookupIdentifier; #endif core->cheatDevice = _GBACoreCheatDevice; core->savedataClone = _GBACoreSavedataClone; @@ -907,6 +985,7 @@ core->listAudioChannels = _GBACoreListAudioChannels; core->enableVideoLayer = _GBACoreEnableVideoLayer; core->enableAudioChannel = _GBACoreEnableAudioChannel; + core->adjustVideoLayer = _GBACoreAdjustVideoLayer; #ifndef MINIMAL_CORE core->startVideoLog = _GBACoreStartVideoLog; core->endVideoLog = _GBACoreEndVideoLog; diff -Nru mgba-0.6.3+dfsg1/src/gba/debugger/cli.c mgba-0.7.0/src/gba/debugger/cli.c --- mgba-0.6.3+dfsg1/src/gba/debugger/cli.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/debugger/cli.c 2019-01-27 00:06:06.000000000 +0000 @@ -14,16 +14,15 @@ static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*); static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem*); -static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); static void _frame(struct CLIDebugger*, struct CLIDebugVector*); static void _load(struct CLIDebugger*, struct CLIDebugVector*); static void _save(struct CLIDebugger*, struct CLIDebugVector*); struct CLIDebuggerCommandSummary _GBACLIDebuggerCommands[] = { - { "frame", _frame, 0, "Frame advance" }, - { "load", _load, CLIDVParse, "Load a savestate" }, - { "save", _save, CLIDVParse, "Save a savestate" }, + { "frame", _frame, "", "Frame advance" }, + { "load", _load, "*", "Load a savestate" }, + { "save", _save, "*", "Save a savestate" }, { 0, 0, 0, 0 } }; @@ -33,7 +32,6 @@ debugger->d.init = _GBACLIDebuggerInit; debugger->d.deinit = NULL; debugger->d.custom = _GBACLIDebuggerCustom; - debugger->d.lookupIdentifier = _GBACLIDebuggerLookupIdentifier; debugger->d.name = "Game Boy Advance"; debugger->d.commands = _GBACLIDebuggerCommands; @@ -64,19 +62,6 @@ return false; } -static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) { - UNUSED(debugger); - int i; - for (i = 0; i < REG_MAX; i += 2) { - const char* reg = GBAIORegisterNames[i >> 1]; - if (reg && strcasecmp(reg, name) == 0) { - return BASE_IO | i; - } - } - dv->type = CLIDV_ERROR_TYPE; - return 0; -} - static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { UNUSED(dv); debugger->d.state = DEBUGGER_CUSTOM; diff -Nru mgba-0.6.3+dfsg1/src/gba/dma.c mgba-0.7.0/src/gba/dma.c --- mgba-0.6.3+dfsg1/src/gba/dma.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/dma.c 2019-01-27 00:06:06.000000000 +0000 @@ -46,6 +46,8 @@ address &= 0x0FFFFFFE; if (_isValidDMASAD(dma, address)) { memory->dma[dma].source = address; + } else { + memory->dma[dma].source = 0; } return memory->dma[dma].source; } @@ -102,15 +104,15 @@ void GBADMASchedule(struct GBA* gba, int number, struct GBADMA* info) { switch (GBADMARegisterGetTiming(info->reg)) { - case DMA_TIMING_NOW: + case GBA_DMA_TIMING_NOW: info->when = mTimingCurrentTime(&gba->timing) + 3; // DMAs take 3 cycles to start info->nextCount = info->count; break; - case DMA_TIMING_HBLANK: - case DMA_TIMING_VBLANK: + case GBA_DMA_TIMING_HBLANK: + case GBA_DMA_TIMING_VBLANK: // Handled implicitly return; - case DMA_TIMING_CUSTOM: + case GBA_DMA_TIMING_CUSTOM: switch (number) { case 0: mLOG(GBA_MEM, WARN, "Discarding invalid DMA0 scheduling"); @@ -120,7 +122,7 @@ GBAAudioScheduleFifoDma(&gba->audio, number, info); break; case 3: - // GBAVideoScheduleVCaptureDma(dma, info); + // Handled implicitly break; } } @@ -133,7 +135,7 @@ int i; for (i = 0; i < 4; ++i) { dma = &memory->dma[i]; - if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_HBLANK && !dma->nextCount) { + if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_HBLANK && !dma->nextCount) { dma->when = mTimingCurrentTime(&gba->timing) + 3 + cycles; dma->nextCount = dma->count; } @@ -147,7 +149,7 @@ int i; for (i = 0; i < 4; ++i) { dma = &memory->dma[i]; - if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK && !dma->nextCount) { + if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_VBLANK && !dma->nextCount) { dma->when = mTimingCurrentTime(&gba->timing) + 3 + cycles; dma->nextCount = dma->count; } @@ -155,6 +157,16 @@ GBADMAUpdate(gba); } +void GBADMARunDisplayStart(struct GBA* gba, int32_t cycles) { + struct GBAMemory* memory = &gba->memory; + struct GBADMA* dma = &memory->dma[3]; + if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_CUSTOM && !dma->nextCount) { + dma->when = mTimingCurrentTime(&gba->timing) + 3 + cycles; + dma->nextCount = dma->count; + GBADMAUpdate(gba); + } +} + void _dmaEvent(struct mTiming* timing, void* context, uint32_t cyclesLate) { UNUSED(timing); UNUSED(cyclesLate); @@ -168,13 +180,16 @@ GBADMAService(gba, memory->activeDMA, dma); } else { dma->nextCount = 0; - if (!GBADMARegisterIsRepeat(dma->reg) || GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_NOW) { + bool noRepeat = !GBADMARegisterIsRepeat(dma->reg); + noRepeat |= GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_NOW; + noRepeat |= memory->activeDMA == 3 && GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_CUSTOM; + if (noRepeat) { dma->reg = GBADMARegisterClearEnable(dma->reg); // Clear the enable bit in memory memory->io[(REG_DMA0CNT_HI + memory->activeDMA * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0; } - if (GBADMARegisterGetDestControl(dma->reg) == DMA_INCREMENT_RELOAD) { + if (GBADMARegisterGetDestControl(dma->reg) == GBA_DMA_INCREMENT_RELOAD) { dma->nextDest = dma->dest; } if (GBADMARegisterIsDoIRQ(dma->reg)) { @@ -187,13 +202,17 @@ void GBADMAUpdate(struct GBA* gba) { int i; struct GBAMemory* memory = &gba->memory; - memory->activeDMA = -1; uint32_t currentTime = mTimingCurrentTime(&gba->timing); + int32_t leastTime = INT_MAX; + memory->activeDMA = -1; for (i = 0; i < 4; ++i) { struct GBADMA* dma = &memory->dma[i]; if (GBADMARegisterIsEnable(dma->reg) && dma->nextCount) { - memory->activeDMA = i; - break; + int32_t time = dma->when - currentTime; + if (memory->activeDMA == -1 || (dma->count == dma->nextCount && time < leastTime)) { + leastTime = time; + memory->activeDMA = i; + } } } @@ -238,31 +257,46 @@ info->when += cycles; gba->performingDMA = 1 | (number << 1); - uint32_t word; if (width == 4) { - word = cpu->memory.load32(cpu, source, 0); - gba->bus = word; - cpu->memory.store32(cpu, dest, word, 0); + if (source) { + memory->dmaTransferRegister = cpu->memory.load32(cpu, source, 0); + } + gba->bus = memory->dmaTransferRegister; + cpu->memory.store32(cpu, dest, memory->dmaTransferRegister, 0); + memory->dmaTransferRegister &= 0xFFFF0000; + memory->dmaTransferRegister |= memory->dmaTransferRegister >> 16; } else { if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) { - word = GBASavedataReadEEPROM(&memory->savedata); - cpu->memory.store16(cpu, dest, word, 0); - } else if (destRegion == REGION_CART2_EX) { if (memory->savedata.type == SAVEDATA_AUTODETECT) { mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); - GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming); + GBASavedataInitEEPROM(&memory->savedata); + } + memory->dmaTransferRegister = GBASavedataReadEEPROM(&memory->savedata); + } else { + if (source) { + memory->dmaTransferRegister = cpu->memory.load16(cpu, source, 0); + } + } + if (destRegion == REGION_CART2_EX) { + if (memory->savedata.type == SAVEDATA_AUTODETECT) { + mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); + GBASavedataInitEEPROM(&memory->savedata); + } + if (memory->savedata.type == SAVEDATA_EEPROM) { + GBASavedataWriteEEPROM(&memory->savedata, memory->dmaTransferRegister, wordsRemaining); } - word = cpu->memory.load16(cpu, source, 0); - GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining); } else { - word = cpu->memory.load16(cpu, source, 0); - cpu->memory.store16(cpu, dest, word, 0); + cpu->memory.store16(cpu, dest, memory->dmaTransferRegister, 0); + } - gba->bus = word | (word << 16); + memory->dmaTransferRegister |= memory->dmaTransferRegister << 16; + gba->bus = memory->dmaTransferRegister; } int sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width; int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width; - source += sourceOffset; + if (source) { + source += sourceOffset; + } dest += destOffset; --wordsRemaining; gba->performingDMA = 0; diff -Nru mgba-0.6.3+dfsg1/src/gba/extra/proxy.c mgba-0.7.0/src/gba/extra/proxy.c --- mgba-0.6.3+dfsg1/src/gba/extra/proxy.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/extra/proxy.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#include +#include #include #include @@ -103,6 +103,7 @@ struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; _init(proxyRenderer); + _reset(proxyRenderer); proxyRenderer->backend->init(proxyRenderer->backend); } @@ -136,7 +137,7 @@ } break; case DIRTY_OAM: - if (item->address < SIZE_PALETTE_RAM) { + if (item->address < SIZE_OAM) { logger->oam[item->address] = item->value; proxyRenderer->backend->writeOAM(proxyRenderer->backend, item->address); } @@ -145,6 +146,8 @@ if (item->address <= SIZE_VRAM - 0x1000) { logger->readData(logger, &logger->vram[item->address >> 1], 0x1000, true); proxyRenderer->backend->writeVRAM(proxyRenderer->backend, item->address); + } else { + logger->readData(logger, NULL, 0x1000, true); } break; case DIRTY_SCANLINE: @@ -211,7 +214,7 @@ proxyRenderer->backend->writeVRAM(proxyRenderer->backend, address); } if (renderer->cache) { - mTileCacheWriteVRAM(renderer->cache, address); + mCacheSetWriteVRAM(renderer->cache, address); } } @@ -222,7 +225,7 @@ proxyRenderer->backend->writePalette(proxyRenderer->backend, address, value); } if (renderer->cache) { - mTileCacheWritePalette(renderer->cache, address); + mCacheSetWritePalette(renderer->cache, address >> 1, mColorFrom555(value)); } } @@ -249,9 +252,10 @@ struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer; if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { proxyRenderer->logger->lock(proxyRenderer->logger); - proxyRenderer->logger->wait(proxyRenderer->logger); } - proxyRenderer->backend->finishFrame(proxyRenderer->backend); + if (!proxyRenderer->logger->block) { + proxyRenderer->backend->finishFrame(proxyRenderer->backend); + } mVideoLoggerRendererFinishFrame(proxyRenderer->logger); mVideoLoggerRendererFlush(proxyRenderer->logger); if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { @@ -265,7 +269,6 @@ proxyRenderer->logger->lock(proxyRenderer->logger); // Insert an extra item into the queue to make sure it gets flushed mVideoLoggerRendererFlush(proxyRenderer->logger); - proxyRenderer->logger->wait(proxyRenderer->logger); } proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels); if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { @@ -279,7 +282,6 @@ proxyRenderer->logger->lock(proxyRenderer->logger); // Insert an extra item into the queue to make sure it gets flushed mVideoLoggerRendererFlush(proxyRenderer->logger); - proxyRenderer->logger->wait(proxyRenderer->logger); } proxyRenderer->backend->putPixels(proxyRenderer->backend, stride, pixels); if (proxyRenderer->logger->block && proxyRenderer->logger->wait) { diff -Nru mgba-0.6.3+dfsg1/src/gba/gba.c mgba-0.7.0/src/gba/gba.c --- mgba-0.6.3+dfsg1/src/gba/gba.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/gba.c 2019-01-27 00:06:06.000000000 +0000 @@ -21,6 +21,10 @@ #include #include +#ifdef USE_ELF +#include +#endif + mLOG_DEFINE_CATEGORY(GBA, "GBA", "gba"); mLOG_DEFINE_CATEGORY(GBA_DEBUG, "GBA Debug", "gba.debug"); @@ -41,11 +45,12 @@ static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode); static void GBABreakpoint(struct ARMCore* cpu, int immediate); +#ifdef USE_DEBUGGERS static bool _setSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode); static bool _clearSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode); +#endif - -#ifdef _3DS +#ifdef FIXED_ROM_BUFFER extern uint32_t* romBuffer; extern size_t romBufferSize; #endif @@ -101,7 +106,6 @@ gba->idleOptimization = IDLE_LOOP_REMOVE; gba->idleLoop = IDLE_LOOP_NONE; - gba->realisticTiming = true; gba->hardCrash = true; gba->allowOpposingDirections = true; @@ -123,8 +127,10 @@ } if (gba->romVf) { -#ifndef _3DS - gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize); +#ifndef FIXED_ROM_BUFFER + if (gba->isPristine) { + gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize); + } #endif gba->romVf->close(gba->romVf); gba->romVf = NULL; @@ -132,6 +138,8 @@ gba->memory.rom = NULL; gba->isPristine = false; + gba->memory.savedata.maskWriteback = false; + GBASavedataUnmask(&gba->memory.savedata); GBASavedataDeinit(&gba->memory.savedata); if (gba->memory.savedata.realVf) { gba->memory.savedata.realVf->close(gba->memory.savedata.realVf); @@ -180,6 +188,7 @@ struct GBA* gba = (struct GBA*) cpu->master; if (!gba->rr || (!gba->rr->isPlaying(gba->rr) && !gba->rr->isRecording(gba->rr))) { + gba->memory.savedata.maskWriteback = false; GBASavedataUnmask(&gba->memory.savedata); } @@ -206,6 +215,13 @@ gba->debug = false; memset(gba->debugString, 0, sizeof(gba->debugString)); + if (gba->pristineRomSize > SIZE_CART0) { + GBAMatrixReset(gba); + } + + if (!gba->romVf && gba->memory.rom) { + GBASkipBIOS(gba); + } } void GBASkipBIOS(struct GBA* gba) { @@ -238,27 +254,20 @@ int32_t nextEvent = cpu->nextEvent; while (cpu->cycles >= nextEvent) { - int32_t cycles = cpu->cycles; - - cpu->cycles = 0; cpu->nextEvent = INT_MAX; - + nextEvent = 0; + do { + int32_t cycles = cpu->cycles; + cpu->cycles = 0; #ifndef NDEBUG - if (cycles < 0) { - mLOG(GBA, FATAL, "Negative cycles passed: %i", cycles); - } + if (cycles < 0) { + mLOG(GBA, FATAL, "Negative cycles passed: %i", cycles); + } #endif - nextEvent = cycles; - do { - nextEvent = mTimingTick(&gba->timing, nextEvent); + nextEvent = mTimingTick(&gba->timing, nextEvent + cycles); } while (gba->cpuBlocked); cpu->nextEvent = nextEvent; - - if (gba->earlyExit) { - gba->earlyExit = false; - break; - } if (cpu->halted) { cpu->cycles = nextEvent; if (!gba->memory.io[REG_IME >> 1] || !gba->memory.io[REG_IE >> 1]) { @@ -270,7 +279,16 @@ mLOG(GBA, FATAL, "Negative cycles will pass: %i", nextEvent); } #endif + if (gba->earlyExit) { + break; + } } + gba->earlyExit = false; +#ifndef NDEBUG + if (gba->cpuBlocked) { + mLOG(GBA, FATAL, "CPU is blocked!"); + } +#endif } #ifdef USE_DEBUGGERS @@ -291,6 +309,28 @@ } #endif +bool GBALoadNull(struct GBA* gba) { + GBAUnloadROM(gba); + gba->romVf = NULL; + gba->pristineRomSize = 0; +#ifndef FIXED_ROM_BUFFER + gba->memory.rom = anonymousMemoryMap(SIZE_CART0); +#else + gba->memory.rom = romBuffer; +#endif + gba->isPristine = false; + gba->yankedRomSize = 0; + gba->memory.romSize = SIZE_CART0; + gba->memory.romMask = SIZE_CART0 - 1; + gba->memory.mirroring = false; + gba->romCrc32 = 0; + + if (gba->cpu) { + gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]); + } + return true; +} + bool GBALoadMB(struct GBA* gba, struct VFile* vf) { GBAUnloadROM(gba); gba->romVf = vf; @@ -300,7 +340,6 @@ gba->pristineRomSize = SIZE_WORKING_RAM; } gba->isPristine = true; - gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM); memset(gba->memory.wram, 0, SIZE_WORKING_RAM); vf->read(vf, gba->memory.wram, gba->pristineRomSize); if (!gba->memory.wram) { @@ -326,28 +365,46 @@ gba->pristineRomSize = vf->size(vf); vf->seek(vf, 0, SEEK_SET); if (gba->pristineRomSize > SIZE_CART0) { - gba->pristineRomSize = SIZE_CART0; - } - gba->isPristine = true; -#ifdef _3DS - if (gba->pristineRomSize <= romBufferSize) { + gba->isPristine = false; + gba->memory.romSize = 0x01000000; +#ifdef FIXED_ROM_BUFFER gba->memory.rom = romBuffer; - vf->read(vf, romBuffer, gba->pristineRomSize); - } #else - gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ); + gba->memory.rom = anonymousMemoryMap(SIZE_CART0); #endif + } else { + gba->isPristine = true; +#ifdef FIXED_ROM_BUFFER + if (gba->pristineRomSize <= romBufferSize) { + gba->memory.rom = romBuffer; + vf->read(vf, romBuffer, gba->pristineRomSize); + } +#else + gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ); +#endif + gba->memory.romSize = gba->pristineRomSize; + } if (!gba->memory.rom) { mLOG(GBA, WARN, "Couldn't map ROM"); return false; } gba->yankedRomSize = 0; - gba->memory.romSize = gba->pristineRomSize; gba->memory.romMask = toPow2(gba->memory.romSize) - 1; gba->memory.mirroring = false; gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize); GBAHardwareInit(&gba->memory.hw, &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]); GBAVFameDetect(&gba->memory.vfame, gba->memory.rom, gba->memory.romSize); + if (popcount32(gba->memory.romSize) != 1) { + // This ROM is either a bad dump or homebrew. Emulate flash cart behavior. +#ifndef FIXED_ROM_BUFFER + void* newRom = anonymousMemoryMap(SIZE_CART0); + memcpy(newRom, gba->memory.rom, gba->pristineRomSize); + gba->memory.rom = newRom; +#endif + gba->memory.romSize = SIZE_CART0; + gba->memory.romMask = SIZE_CART0 - 1; + gba->isPristine = false; + } if (gba->cpu && gba->memory.activeRegion >= REGION_CART0) { gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]); } @@ -403,7 +460,7 @@ return; } if (gba->romVf) { -#ifndef _3DS +#ifndef FIXED_ROM_BUFFER gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize); #endif gba->romVf->close(gba->romVf); @@ -470,7 +527,8 @@ int level = 1 << GBADebugFlagsGetLevel(gba->debugFlags); level &= 0x1F; char oolBuf[0x101]; - strncpy(oolBuf, gba->debugString, sizeof(gba->debugString)); + strncpy(oolBuf, gba->debugString, sizeof(oolBuf) - 1); + memset(gba->debugString, 0, sizeof(gba->debugString)); oolBuf[0x100] = '\0'; mLog(_mLOG_CAT_GBA_DEBUG(), level, "%s", oolBuf); } @@ -478,6 +536,17 @@ } bool GBAIsROM(struct VFile* vf) { +#ifdef USE_ELF + struct ELF* elf = ELFOpen(vf); + if (elf) { + uint32_t entry = ELFEntry(elf); + bool isGBA = true; + isGBA = isGBA && ELFMachine(elf) == EM_ARM; + isGBA = isGBA && (entry == BASE_CART0 || entry == BASE_WORKING_RAM); + ELFClose(elf); + return isGBA; + } +#endif if (!vf) { return false; } @@ -529,6 +598,14 @@ if (!GBAIsROM(vf)) { return false; } +#ifdef USE_ELF + struct ELF* elf = ELFOpen(vf); + if (elf) { + bool isMB = ELFEntry(elf) == BASE_WORKING_RAM; + ELFClose(elf); + return isMB; + } +#endif if (vf->size(vf) > SIZE_WORKING_RAM) { return false; } @@ -632,6 +709,7 @@ void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) { struct GBA* gba = (struct GBA*) cpu->master; + UNUSED(gba); #ifdef USE_DEBUGGERS if (gba->debugger) { struct mDebuggerEntryInfo info = { @@ -732,7 +810,9 @@ size_t i; for (i = 0; i < mCheatSetsSize(&device->cheats); ++i) { struct GBACheatSet* cheats = (struct GBACheatSet*) *mCheatSetsGetPointer(&device->cheats, i); - mCheatRefresh(device, &cheats->d); + if (!cheats->hook) { + mCheatRefresh(device, &cheats->d); + } } } @@ -813,6 +893,7 @@ } } +#ifdef USE_DEBUGGERS static bool _setSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) { GBASetBreakpoint((struct GBA*) debugger->cpu->master, &debugger->d.p->d, address, mode, opcode); return true; @@ -822,3 +903,4 @@ GBAClearBreakpoint((struct GBA*) debugger->cpu->master, address, mode, opcode); return true; } +#endif \ No newline at end of file diff -Nru mgba-0.6.3+dfsg1/src/gba/hardware.c mgba-0.7.0/src/gba/hardware.c --- mgba-0.6.3+dfsg1/src/gba/hardware.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/hardware.c 2019-01-27 00:06:06.000000000 +0000 @@ -167,15 +167,13 @@ if ((hw->pinState & 5) == 1) { hw->rtc.transferStep = 1; } - _outputPins(hw, 1); break; case 1: if ((hw->pinState & 5) == 5) { hw->rtc.transferStep = 2; - } else { + } else if ((hw->pinState & 5) != 1) { hw->rtc.transferStep = 0; } - _outputPins(hw, 5); break; case 2: if (!(hw->pinState & 1)) { @@ -541,9 +539,9 @@ uint16_t _gbpRead(struct mKeyCallback* callback) { struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback; if (gbpCallback->p->gbpInputsPosted == 2) { - return 0x30F; + return 0xF0; } - return 0x3FF; + return 0; } uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) { diff -Nru mgba-0.6.3+dfsg1/src/gba/io.c mgba-0.7.0/src/gba/io.c --- mgba-0.6.3+dfsg1/src/gba/io.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/io.c 2019-01-27 00:06:06.000000000 +0000 @@ -293,7 +293,7 @@ 0, 0, 0, 0, 0, 0, 0, 0, // Audio 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, @@ -707,24 +707,25 @@ } switch (address) { + // Reading this takes two cycles (1N+1I), so let's remove them preemptively case REG_TM0CNT_LO: - GBATimerUpdateRegister(gba, 0); + GBATimerUpdateRegister(gba, 0, 4); break; case REG_TM1CNT_LO: - GBATimerUpdateRegister(gba, 1); + GBATimerUpdateRegister(gba, 1, 4); break; case REG_TM2CNT_LO: - GBATimerUpdateRegister(gba, 2); + GBATimerUpdateRegister(gba, 2, 4); break; case REG_TM3CNT_LO: - GBATimerUpdateRegister(gba, 3); + GBATimerUpdateRegister(gba, 3, 4); break; case REG_KEYINPUT: if (gba->rr && gba->rr->isPlaying(gba->rr)) { return 0x3FF ^ gba->rr->queryInput(gba->rr); } else { - uint16_t input = 0x3FF; + uint16_t input = 0; if (gba->keyCallback) { input = gba->keyCallback->readKeys(gba->keyCallback); if (gba->keySource) { @@ -732,16 +733,16 @@ } } else if (gba->keySource) { input = *gba->keySource; - } - if (!gba->allowOpposingDirections) { - unsigned rl = input & 0x030; - unsigned ud = input & 0x0C0; - input &= 0x30F; - if (rl != 0x030) { - input |= rl; - } - if (ud != 0x0C0) { - input |= ud; + if (!gba->allowOpposingDirections) { + unsigned rl = input & 0x030; + unsigned ud = input & 0x0C0; + input &= 0x30F; + if (rl != 0x030) { + input |= rl; + } + if (ud != 0x0C0) { + input |= ud; + } } } if (gba->rr && gba->rr->isRecording(gba->rr)) { @@ -837,7 +838,6 @@ case REG_SOUND4CNT_LO: case REG_SOUND4CNT_HI: case REG_SOUNDCNT_LO: - case REG_SOUNDCNT_HI: if (!GBAudioEnableIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) { // TODO: Is writing allowed when the circuit is disabled? return 0; @@ -854,6 +854,7 @@ case REG_WINOUT: case REG_BLDCNT: case REG_BLDALPHA: + case REG_SOUNDCNT_HI: case REG_SOUNDCNT_X: case REG_WAVE_RAM0_LO: case REG_WAVE_RAM0_HI: @@ -928,10 +929,9 @@ for (i = 0; i < 4; ++i) { STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io); STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload); - STORE_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload); STORE_32(gba->timers[i].lastEvent - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].lastEvent); STORE_32(gba->timers[i].event.when - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].nextEvent); - STORE_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval); + STORE_32(gba->timers[i].irq.when - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].nextIrq); STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags); STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource); STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest); @@ -939,6 +939,8 @@ STORE_32(gba->memory.dma[i].when, 0, &state->dma[i].when); } + state->dmaTransferRegister = gba->memory.dmaTransferRegister; + GBAHardwareSerialize(&gba->memory.hw, state); } @@ -957,8 +959,6 @@ uint32_t when; for (i = 0; i < 4; ++i) { LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload); - LOAD_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload); - LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval); LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags); if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) { // Overwrite invalid values in savestate @@ -971,17 +971,22 @@ if (GBATimerFlagsIsEnable(gba->timers[i].flags)) { mTimingSchedule(&gba->timing, &gba->timers[i].event, when); } + LOAD_32(when, 0, &state->timers[i].nextIrq); + if (GBATimerFlagsIsIrqPending(gba->timers[i].flags)) { + mTimingSchedule(&gba->timing, &gba->timers[i].irq, when); + } LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io); LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource); LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest); LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount); LOAD_32(gba->memory.dma[i].when, 0, &state->dma[i].when); - if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != DMA_TIMING_NOW) { + if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != GBA_DMA_TIMING_NOW) { GBADMASchedule(gba, i, &gba->memory.dma[i]); } } GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]); + gba->memory.dmaTransferRegister = state->dmaTransferRegister; GBADMAUpdate(gba); GBAHardwareDeserialize(&gba->memory.hw, state); } diff -Nru mgba-0.6.3+dfsg1/src/gba/matrix.c mgba-0.7.0/src/gba/matrix.c --- mgba-0.6.3+dfsg1/src/gba/matrix.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/gba/matrix.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,75 @@ +/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + +#include +#include +#include +#include + +static void _remapMatrix(struct GBA* gba) { + gba->romVf->seek(gba->romVf, gba->memory.matrix.paddr, SEEK_SET); + gba->romVf->read(gba->romVf, &gba->memory.rom[gba->memory.matrix.vaddr >> 2], gba->memory.matrix.size); +} + +void GBAMatrixReset(struct GBA* gba) { + gba->memory.matrix.paddr = 0x200; + gba->memory.matrix.size = 0x1000; + + gba->memory.matrix.vaddr = 0; + _remapMatrix(gba); + gba->memory.matrix.vaddr = 0x1000; + _remapMatrix(gba); + + gba->memory.matrix.paddr = 0; + gba->memory.matrix.vaddr = 0; + gba->memory.matrix.size = 0x100; + _remapMatrix(gba); +} + +void GBAMatrixWrite(struct GBA* gba, uint32_t address, uint32_t value) { + switch (address) { + case 0x0: + gba->memory.matrix.cmd = value; + switch (value) { + case 0x01: + case 0x11: + _remapMatrix(gba); + break; + default: + mLOG(GBA_MEM, STUB, "Unknown Matrix command: %08X", value); + break; + } + return; + case 0x4: + gba->memory.matrix.paddr = value & 0x03FFFFFF; + return; + case 0x8: + gba->memory.matrix.vaddr = value & 0x007FFFFF; + return; + case 0xC: + gba->memory.matrix.size = value << 9; + return; + } + mLOG(GBA_MEM, STUB, "Unknown Matrix write: %08X:%04X", address, value); +} + +void GBAMatrixWrite16(struct GBA* gba, uint32_t address, uint16_t value) { + switch (address) { + case 0x0: + GBAMatrixWrite(gba, address, value | (gba->memory.matrix.cmd & 0xFFFF0000)); + break; + case 0x4: + GBAMatrixWrite(gba, address, value | (gba->memory.matrix.paddr & 0xFFFF0000)); + break; + case 0x8: + GBAMatrixWrite(gba, address, value | (gba->memory.matrix.vaddr & 0xFFFF0000)); + break; + case 0xC: + GBAMatrixWrite(gba, address, value | (gba->memory.matrix.size & 0xFFFF0000)); + break; + } +} diff -Nru mgba-0.6.3+dfsg1/src/gba/memory.c mgba-0.7.0/src/gba/memory.c --- mgba-0.6.3+dfsg1/src/gba/memory.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/memory.c 2019-01-27 00:06:06.000000000 +0000 @@ -22,7 +22,10 @@ mLOG_DEFINE_CATEGORY(GBA_MEM, "GBA Memory", "gba.memory"); static void _pristineCow(struct GBA* gba); -static uint32_t _deadbeef[1] = { 0xE710B710 }; // Illegal instruction on both ARM and Thumb +static void _agbPrintStore(struct GBA* gba, uint32_t address, int16_t value); +static int16_t _agbPrintLoad(struct GBA* gba, uint32_t address); +static uint8_t _deadbeef[4] = { 0x10, 0xB7, 0x10, 0xE7 }; // Illegal instruction on both ARM and Thumb +static uint8_t _agbPrintFunc[4] = { 0xFA, 0xDF /* swi 0xFF */, 0x70, 0x47 /* bx lr */ }; static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region); static int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait); @@ -80,39 +83,44 @@ gba->memory.biosPrefetch = 0; gba->memory.mirroring = false; + gba->memory.agbPrint = 0; + memset(&gba->memory.agbPrintCtx, 0, sizeof(gba->memory.agbPrintCtx)); + gba->memory.agbPrintBuffer = NULL; + + gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM + SIZE_WORKING_IRAM); + gba->memory.iwram = &gba->memory.wram[SIZE_WORKING_RAM >> 2]; + GBADMAInit(gba); GBAVFameInit(&gba->memory.vfame); } void GBAMemoryDeinit(struct GBA* gba) { - mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM); - mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM); + mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM + SIZE_WORKING_IRAM); 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) { - gba->memory.savedata.realVf->close(gba->memory.savedata.realVf); + if (gba->memory.agbPrintBuffer) { + mappedMemoryFree(gba->memory.agbPrintBuffer, SIZE_AGB_PRINT); } } void GBAMemoryReset(struct GBA* gba) { - if (gba->memory.rom || gba->memory.fullBios || !gba->memory.wram) { - // Not multiboot - if (gba->memory.wram) { - mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM); - } - gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM); + if (gba->memory.wram && gba->memory.rom) { + memset(gba->memory.wram, 0, SIZE_WORKING_RAM); } if (gba->memory.iwram) { - mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM); + memset(gba->memory.iwram, 0, SIZE_WORKING_IRAM); } - gba->memory.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM); memset(gba->memory.io, 0, sizeof(gba->memory.io)); + GBAAdjustWaitstates(gba, 0); + + gba->memory.agbPrint = 0; + memset(&gba->memory.agbPrintCtx, 0, sizeof(gba->memory.agbPrintCtx)); + if (gba->memory.agbPrintBuffer) { + gba->memory.agbPrintBuffer = NULL; + } gba->memory.prefetch = false; gba->memory.lastPrefetchedPc = 0; @@ -123,6 +131,7 @@ } GBADMAReset(gba); + memset(&gba->memory.matrix, 0, sizeof(gba->memory.matrix)); } static void _analyzeForIdleLoop(struct GBA* gba, struct ARMCore* cpu, uint32_t address) { @@ -293,10 +302,15 @@ if ((address & (SIZE_CART0 - 1)) < memory->romSize) { break; } + if ((address & (SIZE_CART0 - 1)) == AGB_PRINT_FLUSH_ADDR && memory->agbPrint == 0x20) { + cpu->memory.activeRegion = (uint32_t*) _agbPrintFunc; + cpu->memory.activeMask = sizeof(_agbPrintFunc) - 1; + break; + } // Fall through default: memory->activeRegion = -1; - cpu->memory.activeRegion = _deadbeef; + cpu->memory.activeRegion = (uint32_t*) _deadbeef; cpu->memory.activeMask = 0; if (!gba->yankedRomSize && mCoreCallbacksListSize(&gba->coreCallbacks)) { @@ -344,6 +358,7 @@ value <<= 16; \ value |= cpu->prefetch[0]; \ } \ + break; \ default: \ value |= value << 16; \ } \ @@ -526,6 +541,16 @@ LOAD_16(value, address & memory->romMask, memory->rom); } else if (memory->vfame.cartType) { value = GBAVFameGetPatternValue(address, 16); + } else if ((address & (SIZE_CART0 - 1)) >= AGB_PRINT_BASE) { + uint32_t agbPrintAddr = address & 0x00FFFFFF; + if (agbPrintAddr == AGB_PRINT_PROTECT) { + value = memory->agbPrint; + } else if (agbPrintAddr < AGB_PRINT_TOP || (agbPrintAddr & 0x00FFFFF8) == (AGB_PRINT_STRUCT & 0x00FFFFF8)) { + value = _agbPrintLoad(gba, address); + } else { + mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address); + value = (address >> 1) & 0xFFFF; + } } else { mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address); value = (address >> 1) & 0xFFFF; @@ -683,30 +708,46 @@ 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]; \ + if (memory->matrix.size && (address & 0x01FFFF00) == 0x00800100) { \ + GBAMatrixWrite(gba, address & 0x3C, value); \ + break; \ + } \ mLOG(GBA_MEM, STUB, "Unimplemented memory Store32: 0x%08X", address); #define STORE_SRAM \ @@ -726,6 +767,7 @@ 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 +819,7 @@ 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,36 +833,70 @@ 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)) { uint32_t reg = address & 0xFFFFFE; GBAHardwareGPIOWrite(&memory->hw, reg, value); - } else { - mLOG(GBA_MEM, GAME_ERROR, "Bad cartridge Store16: 0x%08X", address); + break; } + if (memory->matrix.size && (address & 0x01FFFF00) == 0x00800100) { + GBAMatrixWrite16(gba, address & 0x3C, value); + break; + } + // Fall through + case REGION_CART0_EX: + if ((address & 0x00FFFFFF) >= AGB_PRINT_BASE) { + uint32_t agbPrintAddr = address & 0x00FFFFFF; + if (agbPrintAddr == AGB_PRINT_PROTECT) { + memory->agbPrint = value; + _agbPrintStore(gba, address, value); + break; + } + if (memory->agbPrint == 0x20 && (agbPrintAddr < AGB_PRINT_TOP || (agbPrintAddr & 0x00FFFFF8) == (AGB_PRINT_STRUCT & 0x00FFFFF8))) { + _agbPrintStore(gba, address, value); + break; + } + } + mLOG(GBA_MEM, GAME_ERROR, "Bad cartridge Store16: 0x%08X", address); break; case REGION_CART2_EX: if (memory->savedata.type == SAVEDATA_AUTODETECT) { mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); - GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming); + GBASavedataInitEEPROM(&memory->savedata); } - GBASavedataWriteEEPROM(&memory->savedata, value, 1); + if (memory->savedata.type == SAVEDATA_EEPROM) { + GBASavedataWriteEEPROM(&memory->savedata, value, 1); + break; + } + mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store16: 0x%08X", address); break; case REGION_CART_SRAM: case REGION_CART_SRAM_MIRROR: @@ -844,6 +921,7 @@ 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 +943,11 @@ mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address); break; } - gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8); - gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); + oldValue = gba->video.renderer->vram[(address & 0x1FFFE) >> 1]; + if (oldValue != (((uint8_t) value) | (value << 8))) { + gba->video.renderer->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); @@ -879,7 +960,7 @@ if (memory->savedata.type == SAVEDATA_AUTODETECT) { if (address == SAVEDATA_FLASH_BASE) { mLOG(GBA_MEM, INFO, "Detected Flash savegame"); - GBASavedataInitFlash(&memory->savedata, gba->realisticTiming); + GBASavedataInitFlash(&memory->savedata); } else { mLOG(GBA_MEM, INFO, "Detected SRAM savegame"); GBASavedataInitSRAM(&memory->savedata); @@ -1369,6 +1450,7 @@ struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; uint32_t value; + uint32_t oldValue; char* waitstatesRegion = memory->waitstatesSeq32; int i; @@ -1546,6 +1628,7 @@ if (!gba->isPristine) { return; } +#if !defined(FIXED_ROM_BUFFER) && !defined(__wii__) void* newRom = anonymousMemoryMap(SIZE_CART0); memcpy(newRom, gba->memory.rom, gba->memory.romSize); memset(((uint8_t*) newRom) + gba->memory.romSize, 0xFF, SIZE_CART0 - gba->memory.romSize); @@ -1553,13 +1636,63 @@ gba->cpu->memory.activeRegion = newRom; } if (gba->romVf) { -#ifndef _3DS gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->memory.romSize); -#endif gba->romVf->close(gba->romVf); gba->romVf = NULL; } gba->memory.rom = newRom; gba->memory.hw.gpioBase = &((uint16_t*) gba->memory.rom)[GPIO_REG_DATA >> 1]; +#endif gba->isPristine = false; } + +void GBAPrintFlush(struct GBA* gba) { + char oolBuf[0x101]; + size_t i; + for (i = 0; gba->memory.agbPrintCtx.get != gba->memory.agbPrintCtx.put && i < 0x100; ++i) { + int16_t value; + LOAD_16(value, gba->memory.agbPrintCtx.get & -2, gba->memory.agbPrintBuffer); + if (gba->memory.agbPrintCtx.get & 1) { + value >>= 8; + } else { + value &= 0xFF; + } + oolBuf[i] = value; + oolBuf[i + 1] = 0; + ++gba->memory.agbPrintCtx.get; + } + _agbPrintStore(gba, AGB_PRINT_STRUCT + 4, gba->memory.agbPrintCtx.get); + + mLOG(GBA_DEBUG, INFO, "%s", oolBuf); +} + +static void _agbPrintStore(struct GBA* gba, uint32_t address, int16_t value) { + struct GBAMemory* memory = &gba->memory; + if ((address & 0x00FFFFFF) < AGB_PRINT_TOP) { + if (!memory->agbPrintBuffer) { + memory->agbPrintBuffer = anonymousMemoryMap(SIZE_AGB_PRINT); + } + STORE_16(value, address & (SIZE_AGB_PRINT - 2), memory->agbPrintBuffer); + } else if ((address & 0x00FFFFF8) == (AGB_PRINT_STRUCT & 0x00FFFFF8)) { + (&memory->agbPrintCtx.request)[(address & 7) >> 1] = value; + } + if (memory->romSize == SIZE_CART0) { + _pristineCow(gba); + memcpy(&memory->rom[AGB_PRINT_FLUSH_ADDR >> 2], _agbPrintFunc, sizeof(_agbPrintFunc)); + STORE_16(value, address & (SIZE_CART0 - 2), memory->rom); + } else if (memory->agbPrintCtx.bank == 0xFD && memory->romSize >= SIZE_CART0 / 2) { + _pristineCow(gba); + STORE_16(value, address & (SIZE_CART0 / 2 - 2), memory->rom); + } +} + +static int16_t _agbPrintLoad(struct GBA* gba, uint32_t address) { + struct GBAMemory* memory = &gba->memory; + int16_t value = 0xFFFF; + if (address < AGB_PRINT_TOP) { + LOAD_16(value, address & (SIZE_AGB_PRINT - 1), memory->agbPrintBuffer); + } else if ((address & 0x00FFFFF8) == (AGB_PRINT_STRUCT & 0x00FFFFF8)) { + value = (&memory->agbPrintCtx.request)[(address & 7) >> 1]; + } + return value; +} diff -Nru mgba-0.6.3+dfsg1/src/gba/overrides.c mgba-0.7.0/src/gba/overrides.c --- mgba-0.6.3+dfsg1/src/gba/overrides.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/overrides.c 2019-01-27 00:06:06.000000000 +0000 @@ -296,7 +296,7 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* override) { if (override->savetype != SAVEDATA_AUTODETECT) { - GBASavedataForceType(&gba->memory.savedata, override->savetype, gba->realisticTiming); + GBASavedataForceType(&gba->memory.savedata, override->savetype); } if (override->hardware != HW_NO_OVERRIDE) { @@ -341,11 +341,19 @@ } } -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 -Nru mgba-0.6.3+dfsg1/src/gba/renderers/cache-set.c mgba-0.7.0/src/gba/renderers/cache-set.c --- mgba-0.6.3+dfsg1/src/gba/renderers/cache-set.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/gba/renderers/cache-set.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,180 @@ +/* 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) { + 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)); + if (mMapCacheSystemInfoGetPaletteBPP(cache->sysConfig) == 3) { + entry->flags = mMapCacheEntryFlagsClearPaletteId(entry->flags); + } else { + 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, + mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 0)->sysConfig) == 3); + mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, + mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 1)->sysConfig) == 3); + mMapCacheSetGetPointer(&cache->maps, 2)->tileCache = mTileCacheSetGetPointer(&cache->tiles, + mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 2)->sysConfig) == 3); + mMapCacheSetGetPointer(&cache->maps, 3)->tileCache = mTileCacheSetGetPointer(&cache->tiles, + mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 3)->sysConfig) == 3); + 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, + mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 0)->sysConfig) == 3); + mMapCacheSetGetPointer(&cache->maps, 1)->tileCache = mTileCacheSetGetPointer(&cache->tiles, + mMapCacheSystemInfoGetPaletteBPP(mMapCacheSetGetPointer(&cache->maps, 1)->sysConfig) == 3); + + 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) { + map->tileCache = mTileCacheSetGetPointer(&cache->tiles, p); + 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 - p); + } else if (map->mapParser == mapParser2) { + map->tileCache = mTileCacheSetGetPointer(&cache->tiles, 1); + 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, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 0)->context); + GBAVideoCacheWriteBGCNT(cache, 1, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 1)->context); + GBAVideoCacheWriteBGCNT(cache, 2, (uintptr_t) mMapCacheSetGetPointer(&cache->maps, 2)->context); + GBAVideoCacheWriteBGCNT(cache, 3, (uintptr_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 -Nru mgba-0.6.3+dfsg1/src/gba/renderers/software-bg.c mgba-0.7.0/src/gba/renderers/software-bg.c --- mgba-0.6.3+dfsg1/src/gba/renderers/software-bg.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/renderers/software-bg.c 2019-01-27 00:06:06.000000000 +0000 @@ -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 \ @@ -101,21 +102,7 @@ if (!mosaicWait) { LOAD_16(color, ((localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS) << 1, renderer->d.vram); -#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; @@ -192,20 +179,7 @@ if (!mosaicWait) { LOAD_16(color, offset + (localX >> 8) * 2 + (localY >> 8) * 320, renderer->d.vram); -#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 -Nru mgba-0.6.3+dfsg1/src/gba/renderers/software-mode0.c mgba-0.7.0/src/gba/renderers/software-mode0.c --- mgba-0.6.3+dfsg1/src/gba/renderers/software-mode0.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/renderers/software-mode0.c 2019-01-27 00:06:06.000000000 +0000 @@ -8,17 +8,12 @@ #include #define BACKGROUND_TEXT_SELECT_CHARACTER \ - localX = tileX * 8 + inX; \ xBase = localX & 0xF8; \ if (background->size & 1) { \ xBase += (localX & 0x100) << 5; \ } \ screenBase = yBase + (xBase >> 3); \ LOAD_16(mapData, screenBase << 1, vram); \ - localY = inY & 0x7; \ - if (GBA_TEXT_MAP_VFLIP(mapData)) { \ - localY = 7 - localY; \ - } #define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_16(BLEND, OBJWIN) \ paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \ @@ -77,11 +72,21 @@ if (baseX < 0) { \ int disturbX = (16 + baseX) >> 3; \ inX -= disturbX << 3; \ + localX = tileX * 8 + inX; \ BACKGROUND_TEXT_SELECT_CHARACTER; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ baseX -= disturbX << 3; \ inX += disturbX << 3; \ } else { \ + localX = tileX * 8 + inX; \ BACKGROUND_TEXT_SELECT_CHARACTER; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ } \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ if (UNLIKELY(charBase >= 0x10000)) { \ @@ -102,8 +107,14 @@ carryData = tileData; \ } \ } \ + localX = tileX * 8 + inX; \ for (; length; ++tileX) { \ - BACKGROUND_TEXT_SELECT_CHARACTER; \ + mapData = background->mapCache[(localX >> 3) & 0x3F]; \ + localX += 8; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ tileData = carryData; \ for (; x < 8 && length; ++x, --length) { \ @@ -136,7 +147,12 @@ #define DRAW_BACKGROUND_MODE_0_TILES_16(BLEND, OBJWIN) \ for (; tileX < tileEnd; ++tileX) { \ - BACKGROUND_TEXT_SELECT_CHARACTER; \ + mapData = background->mapCache[(localX >> 3) & 0x3F]; \ + localX += 8; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \ palette = &mainPalette[paletteData]; \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \ @@ -264,7 +280,12 @@ #define DRAW_BACKGROUND_MODE_0_TILES_256(BLEND, OBJWIN) \ for (; tileX < tileEnd; ++tileX) { \ - BACKGROUND_TEXT_SELECT_CHARACTER; \ + mapData = background->mapCache[(localX >> 3) & 0x3F]; \ + localX += 8; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \ if (UNLIKELY(charBase >= 0x10000)) { \ pixel += 8; \ @@ -308,8 +329,14 @@ } #define DRAW_BACKGROUND_MODE_0_MOSAIC_256(BLEND, OBJWIN) \ + localX = tileX * 8 + inX; \ for (; tileX < tileEnd; ++tileX) { \ - BACKGROUND_TEXT_SELECT_CHARACTER; \ + mapData = background->mapCache[(localX >> 3) & 0x3F]; \ + localX += 8; \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \ tileData = carryData; \ for (x = 0; x < 8; ++x) { \ @@ -359,8 +386,12 @@ } \ \ if (inX & 0x7) { \ + localX = tileX * 8 + inX; \ BACKGROUND_TEXT_SELECT_CHARACTER; \ - \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ int mod8 = inX & 0x7; \ int end = outX + 0x8 - mod8; \ if (end > renderer->end) { \ @@ -390,10 +421,15 @@ /*!*/ mLOG(GBA_VIDEO, FATAL, "Out of bounds background draw would occur!"); \ /*!*/ return; \ /*!*/ } \ + localX = (tileX * 8 + inX) & 0x1FF; \ DRAW_BACKGROUND_MODE_0_TILES_ ## BPP (BLEND, OBJWIN) \ if (length & 0x7) { \ + localX = tileX * 8 + inX; \ BACKGROUND_TEXT_SELECT_CHARACTER; \ - \ + localY = inY & 0x7; \ + if (GBA_TEXT_MAP_VFLIP(mapData)) { \ + localY = 7 - localY; \ + } \ int mod8 = length & 0x7; \ if (VIDEO_CHECKS && UNLIKELY(outX + mod8 != renderer->end)) { \ mLOG(GBA_VIDEO, FATAL, "Invariant doesn't hold in background draw!"); \ @@ -410,13 +446,13 @@ } void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y) { - int inX = renderer->start + background->x; + int inX = (renderer->start + background->x - background->offsetX) & 0x1FF; int length = renderer->end - renderer->start; if (background->mosaic) { int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1; y -= y % mosaicV; } - int inY = y + background->y; + int inY = y + background->y - background->offsetY; uint16_t mapData; unsigned yBase = inY & 0xF8; @@ -458,10 +494,20 @@ uint32_t current; int pixelData; int paletteData; - int tileX = 0; + int tileX; int tileEnd = ((length + inX) >> 3) - (inX >> 3); uint16_t* vram = renderer->d.vram; + if (background->yCache != inY >> 3) { + localX = 0; + for (tileX = 0; tileX < 64; ++tileX, localX += 8) { + BACKGROUND_TEXT_SELECT_CHARACTER; + background->mapCache[tileX] = mapData; + } + background->yCache = inY >> 3; + } + + tileX = 0; if (!objwinSlowPath) { if (!(flags & FLAG_TARGET_2)) { if (!background->multipalette) { diff -Nru mgba-0.6.3+dfsg1/src/gba/renderers/software-obj.c mgba-0.7.0/src/gba/renderers/software-obj.c --- mgba-0.6.3+dfsg1/src/gba/renderers/software-obj.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/renderers/software-obj.c 2019-01-27 00:06:06.000000000 +0000 @@ -9,9 +9,6 @@ SPRITE_YBASE_ ## DEPTH(inY); \ unsigned tileData; \ for (; outX < condition; ++outX, inX += xOffset) { \ - if (!(renderer->row[outX] & FLAG_UNWRITTEN)) { \ - continue; \ - } \ renderer->spriteCyclesRemaining -= 1; \ SPRITE_XBASE_ ## DEPTH(inX); \ SPRITE_DRAW_PIXEL_ ## DEPTH ## _ ## TYPE(inX); \ @@ -147,6 +144,7 @@ } int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23; x >>= 23; + x += renderer->objOffsetX; uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1]; bool align = GBAObjAttributesAIs256Color(sprite->a) && !GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt); unsigned charBase = (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x20; @@ -185,14 +183,13 @@ } } - int inY = y - (int) GBAObjAttributesAGetY(sprite->a); + int inY = y - ((int) GBAObjAttributesAGetY(sprite->a) + renderer->objOffsetY); int stride = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? (width >> !GBAObjAttributesAIs256Color(sprite->a)) : 0x80; uint32_t current; if (GBAObjAttributesAIsTransformed(sprite->a)) { int totalWidth = width << GBAObjAttributesAGetDoubleSize(sprite->a); int totalHeight = height << GBAObjAttributesAGetDoubleSize(sprite->a); - renderer->spriteCyclesRemaining -= 10; struct GBAOAMMatrix mat; LOAD_16(mat.a, 0, &renderer->d.oam->mat[GBAObjAttributesBGetMatIndex(sprite->b)].a); LOAD_16(mat.b, 0, &renderer->d.oam->mat[GBAObjAttributesBGetMatIndex(sprite->b)].b); @@ -252,6 +249,7 @@ if (outX < start || outX >= condition) { return 0; } + renderer->spriteCyclesRemaining -= 10; if (!GBAObjAttributesAIs256Color(sprite->a)) { palette = &palette[GBAObjAttributesCGetPalette(sprite->c) << 4]; @@ -272,7 +270,7 @@ SPRITE_TRANSFORMED_LOOP(256, NORMAL); } } - if (x + totalWidth > VIDEO_HORIZONTAL_PIXELS) { + if (end == VIDEO_HORIZONTAL_PIXELS && x + totalWidth > VIDEO_HORIZONTAL_PIXELS) { renderer->spriteCyclesRemaining -= (x + totalWidth - VIDEO_HORIZONTAL_PIXELS) * 2; } } else { @@ -332,7 +330,7 @@ SPRITE_NORMAL_LOOP(256, NORMAL); } } - if (x + width > VIDEO_HORIZONTAL_PIXELS) { + if (end == VIDEO_HORIZONTAL_PIXELS && x + width > VIDEO_HORIZONTAL_PIXELS) { renderer->spriteCyclesRemaining -= x + width - VIDEO_HORIZONTAL_PIXELS; } } diff -Nru mgba-0.6.3+dfsg1/src/gba/renderers/tile-cache.c mgba-0.7.0/src/gba/renderers/tile-cache.c --- mgba-0.6.3+dfsg1/src/gba/renderers/tile-cache.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/renderers/tile-cache.c 1970-01-01 00:00:00.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/src/gba/renderers/video-software.c mgba-0.7.0/src/gba/renderers/video-software.c --- mgba-0.6.3+dfsg1/src/gba/renderers/video-software.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/renderers/video-software.c 2019-01-27 00:06:06.000000000 +0000 @@ -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 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); @@ -108,9 +108,18 @@ softwareRenderer->winN[1] = (struct WindowN) { .control = { .priority = 1 } }; softwareRenderer->objwin = (struct WindowControl) { .priority = 2 }; softwareRenderer->winout = (struct WindowControl) { .priority = 3 }; + softwareRenderer->oamDirty = 1; softwareRenderer->oamMax = 0; softwareRenderer->mosaic = 0; + softwareRenderer->nextY = 0; + + softwareRenderer->objOffsetX = 0; + softwareRenderer->objOffsetY = 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]; @@ -135,6 +144,9 @@ bg->dmy = 256; bg->sx = 0; bg->sy = 0; + bg->yCache = -1; + bg->offsetX = 0; + bg->offsetY = 0; } } @@ -145,6 +157,10 @@ 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: value &= 0xFFF7; @@ -200,52 +216,76 @@ 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); @@ -343,39 +383,36 @@ 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)); + softwareRenderer->bg[0].yCache = -1; + softwareRenderer->bg[1].yCache = -1; + softwareRenderer->bg[2].yCache = -1; + softwareRenderer->bg[3].yCache = -1; } 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); @@ -383,8 +420,9 @@ 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) { @@ -474,8 +512,9 @@ height <<= GBAObjAttributesAGetDoubleSize(obj.a); } if (GBAObjAttributesAGetY(obj.a) < VIDEO_VERTICAL_PIXELS || GBAObjAttributesAGetY(obj.a) + height >= VIDEO_VERTICAL_TOTAL_PIXELS) { - renderer->sprites[oamMax].y = GBAObjAttributesAGetY(obj.a); - renderer->sprites[oamMax].endY = GBAObjAttributesAGetY(obj.a) + height; + int y = GBAObjAttributesAGetY(obj.a) + renderer->objOffsetY; + renderer->sprites[oamMax].y = y; + renderer->sprites[oamMax].endY = y + height; renderer->sprites[oamMax].obj = obj; ++oamMax; } @@ -488,6 +527,35 @@ 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; + } + + CLEAN_SCANLINE(softwareRenderer, y); + color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y]; if (GBARegisterDISPCNTIsForcedBlank(softwareRenderer->dispcnt)) { int x; @@ -519,7 +587,6 @@ softwareRenderer->windows[0].control.packed = 0xFF; } - GBAVideoSoftwareRendererUpdateDISPCNT(softwareRenderer); if (softwareRenderer->blendDirty) { _updatePalettes(softwareRenderer); softwareRenderer->blendDirty = false; @@ -601,13 +668,12 @@ } #ifdef COLOR_16_BIT -#if defined(__ARM_NEON) && !defined(__APPLE__) - _to16Bit(row, softwareRenderer->row, VIDEO_HORIZONTAL_PIXELS); -#else - for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x) { + for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; x += 4) { 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, VIDEO_HORIZONTAL_PIXELS * sizeof(*row)); #endif @@ -616,6 +682,7 @@ static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; + softwareRenderer->nextY = 0; if (softwareRenderer->temporaryBuffer) { mappedMemoryFree(softwareRenderer->temporaryBuffer, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4); softwareRenderer->temporaryBuffer = 0; @@ -624,6 +691,19 @@ softwareRenderer->bg[2].sy = softwareRenderer->bg[2].refy; softwareRenderer->bg[3].sx = softwareRenderer->bg[3].refx; softwareRenderer->bg[3].sy = softwareRenderer->bg[3].refy; + + if (softwareRenderer->bg[0].enabled > 0) { + softwareRenderer->bg[0].enabled = 4; + } + if (softwareRenderer->bg[1].enabled > 0) { + softwareRenderer->bg[1].enabled = 4; + } + if (softwareRenderer->bg[2].enabled > 0) { + softwareRenderer->bg[2].enabled = 4; + } + if (softwareRenderer->bg[3].enabled > 0) { + softwareRenderer->bg[3].enabled = 4; + } } static void GBAVideoSoftwareRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) { @@ -642,11 +722,24 @@ } } +static void _enableBg(struct GBAVideoSoftwareRenderer* renderer, int bg, bool active) { + int wasActive = renderer->bg[bg].enabled; + if (!active) { + renderer->bg[bg].enabled = 0; + } else if (!wasActive && active) { + if (renderer->nextY == 0) { + renderer->bg[bg].enabled = 4; + } else { + renderer->bg[bg].enabled = 1; + } + } +} + static void GBAVideoSoftwareRendererUpdateDISPCNT(struct GBAVideoSoftwareRenderer* renderer) { - renderer->bg[0].enabled = GBARegisterDISPCNTGetBg0Enable(renderer->dispcnt) && !renderer->d.disableBG[0]; - renderer->bg[1].enabled = GBARegisterDISPCNTGetBg1Enable(renderer->dispcnt) && !renderer->d.disableBG[1]; - renderer->bg[2].enabled = GBARegisterDISPCNTGetBg2Enable(renderer->dispcnt) && !renderer->d.disableBG[2]; - renderer->bg[3].enabled = GBARegisterDISPCNTGetBg3Enable(renderer->dispcnt) && !renderer->d.disableBG[3]; + _enableBg(renderer, 0, GBARegisterDISPCNTGetBg0Enable(renderer->dispcnt)); + _enableBg(renderer, 1, GBARegisterDISPCNTGetBg1Enable(renderer->dispcnt)); + _enableBg(renderer, 2, GBARegisterDISPCNTGetBg2Enable(renderer->dispcnt)); + _enableBg(renderer, 3, GBARegisterDISPCNTGetBg3Enable(renderer->dispcnt)); } static void GBAVideoSoftwareRendererWriteBGCNT(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* bg, uint16_t value) { @@ -660,22 +753,6 @@ bg->size = GBARegisterBGCNTGetSize(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; @@ -724,7 +801,8 @@ } #define TEST_LAYER_ENABLED(X) \ - (renderer->bg[X].enabled && \ + !renderer->d.disableBG[X] && \ + (renderer->bg[X].enabled == 4 && \ (GBAWindowControlIsBg ## X ## Enable(renderer->currentWindow.packed) || \ (GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt) && GBAWindowControlIsBg ## X ## Enable (renderer->objwin.packed))) && \ renderer->bg[X].priority == priority) @@ -822,6 +900,23 @@ renderer->bg[3].sx += renderer->bg[3].dmx; renderer->bg[3].sy += renderer->bg[3].dmy; } + + if (renderer->bg[0].enabled > 0 && renderer->bg[0].enabled < 4) { + ++renderer->bg[0].enabled; + DIRTY_SCANLINE(renderer, y); + } + if (renderer->bg[1].enabled > 0 && renderer->bg[1].enabled < 4) { + ++renderer->bg[1].enabled; + DIRTY_SCANLINE(renderer, y); + } + if (renderer->bg[2].enabled > 0 && renderer->bg[2].enabled < 4) { + ++renderer->bg[2].enabled; + DIRTY_SCANLINE(renderer, y); + } + if (renderer->bg[3].enabled > 0 && renderer->bg[3].enabled < 4) { + ++renderer->bg[3].enabled; + DIRTY_SCANLINE(renderer, y); + } } static void _updatePalettes(struct GBAVideoSoftwareRenderer* renderer) { diff -Nru mgba-0.6.3+dfsg1/src/gba/savedata.c mgba-0.7.0/src/gba/savedata.c --- mgba-0.6.3+dfsg1/src/gba/savedata.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/savedata.c 2019-01-27 00:06:06.000000000 +0000 @@ -47,6 +47,7 @@ savedata->vf = vf; savedata->realVf = vf; savedata->mapMode = MAP_WRITE; + savedata->maskWriteback = false; savedata->dirty = 0; savedata->dirtAge = 0; savedata->dust.name = "GBA Savedata Settling"; @@ -87,15 +88,19 @@ void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback) { enum SavedataType type = savedata->type; + struct VFile* oldVf = savedata->vf; GBASavedataDeinit(savedata); + if (oldVf && oldVf != savedata->realVf) { + oldVf->close(oldVf); + } savedata->vf = vf; savedata->mapMode = MAP_READ; savedata->maskWriteback = writeback; - GBASavedataForceType(savedata, type, savedata->realisticTiming); + GBASavedataForceType(savedata, type); } void GBASavedataUnmask(struct GBASavedata* savedata) { - if (savedata->vf == savedata->realVf) { + if (!savedata->realVf || savedata->vf == savedata->realVf) { return; } enum SavedataType type = savedata->type; @@ -103,7 +108,7 @@ GBASavedataDeinit(savedata); savedata->vf = savedata->realVf; savedata->mapMode = MAP_WRITE; - GBASavedataForceType(savedata, type, savedata->realisticTiming); + GBASavedataForceType(savedata, type); if (savedata->maskWriteback) { GBASavedataLoad(savedata, vf); savedata->maskWriteback = false; @@ -138,7 +143,7 @@ return true; } -size_t GBASavedataSize(struct GBASavedata* savedata) { +size_t GBASavedataSize(const struct GBASavedata* savedata) { switch (savedata->type) { case SAVEDATA_SRAM: return SIZE_CART_SRAM; @@ -193,20 +198,27 @@ return true; } -void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming) { +void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type) { + if (savedata->type == type) { + return; + } if (savedata->type != SAVEDATA_AUTODETECT) { struct VFile* vf = savedata->vf; + int mapMode = savedata->mapMode; + bool maskWriteback = savedata->maskWriteback; GBASavedataDeinit(savedata); GBASavedataInit(savedata, vf); + savedata->mapMode = mapMode; + savedata->maskWriteback = maskWriteback; } switch (type) { case SAVEDATA_FLASH512: case SAVEDATA_FLASH1M: savedata->type = type; - GBASavedataInitFlash(savedata, realisticTiming); + GBASavedataInitFlash(savedata); break; case SAVEDATA_EEPROM: - GBASavedataInitEEPROM(savedata, realisticTiming); + GBASavedataInitEEPROM(savedata); break; case SAVEDATA_SRAM: GBASavedataInitSRAM(savedata); @@ -219,7 +231,7 @@ } } -void GBASavedataInitFlash(struct GBASavedata* savedata, bool realisticTiming) { +void GBASavedataInitFlash(struct GBASavedata* savedata) { if (savedata->type == SAVEDATA_AUTODETECT) { savedata->type = SAVEDATA_FLASH512; } @@ -244,13 +256,12 @@ } savedata->currentBank = savedata->data; - savedata->realisticTiming = realisticTiming; if (end < SIZE_CART_FLASH512) { memset(&savedata->data[end], 0xFF, flashSize - end); } } -void GBASavedataInitEEPROM(struct GBASavedata* savedata, bool realisticTiming) { +void GBASavedataInitEEPROM(struct GBASavedata* savedata) { if (savedata->type == SAVEDATA_AUTODETECT) { savedata->type = SAVEDATA_EEPROM; } else { @@ -271,7 +282,6 @@ } savedata->data = savedata->vf->map(savedata->vf, eepromSize, savedata->mapMode); } - savedata->realisticTiming = realisticTiming; if (end < SIZE_CART_EEPROM512) { memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM512 - end); } @@ -327,10 +337,8 @@ savedata->dirty |= SAVEDATA_DIRT_NEW; savedata->currentBank[address] = value; savedata->command = FLASH_COMMAND_NONE; - if (savedata->realisticTiming) { - mTimingDeschedule(savedata->timing, &savedata->dust); - mTimingSchedule(savedata->timing, &savedata->dust, FLASH_PROGRAM_CYCLES); - } + mTimingDeschedule(savedata->timing, &savedata->dust); + mTimingSchedule(savedata->timing, &savedata->dust, FLASH_PROGRAM_CYCLES); break; case FLASH_COMMAND_SWITCH_BANK: if (address == 0 && value < 2) { @@ -452,10 +460,8 @@ current |= (value & 0x1) << (0x7 - (savedata->writeAddress & 0x7)); savedata->dirty |= SAVEDATA_DIRT_NEW; savedata->data[savedata->writeAddress >> 3] = current; - if (savedata->realisticTiming) { - mTimingDeschedule(savedata->timing, &savedata->dust); - mTimingSchedule(savedata->timing, &savedata->dust, EEPROM_SETTLE_CYCLES); - } + mTimingDeschedule(savedata->timing, &savedata->dust); + mTimingSchedule(savedata->timing, &savedata->dust, EEPROM_SETTLE_CYCLES); ++savedata->writeAddress; } else { mLOG(GBA_SAVE, GAME_ERROR, "Writing beyond end of EEPROM: %08X", (savedata->writeAddress >> 3)); @@ -478,7 +484,7 @@ uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) { if (savedata->command != EEPROM_COMMAND_READ) { - if (!savedata->realisticTiming || !mTimingIsScheduled(savedata->timing, &savedata->dust)) { + if (!mTimingIsScheduled(savedata->timing, &savedata->dust)) { return 1; } else { return 0; @@ -516,12 +522,14 @@ if (savedata->maskWriteback) { GBASavedataUnmask(savedata); } - size_t size = GBASavedataSize(savedata); - savedata->dirty = 0; - if (savedata->data && savedata->vf->sync(savedata->vf, savedata->data, size)) { - mLOG(GBA_SAVE, INFO, "Savedata synced"); - } else { - mLOG(GBA_SAVE, INFO, "Savedata failed to sync!"); + if (savedata->mapMode & MAP_WRITE) { + size_t size = GBASavedataSize(savedata); + savedata->dirty = 0; + if (savedata->data && savedata->vf->sync(savedata->vf, savedata->data, size)) { + mLOG(GBA_SAVE, INFO, "Savedata synced"); + } else { + mLOG(GBA_SAVE, INFO, "Savedata failed to sync!"); + } } } } @@ -549,7 +557,7 @@ void GBASavedataDeserialize(struct GBASavedata* savedata, const struct GBASerializedState* state) { if (savedata->type != state->savedata.type) { mLOG(GBA_SAVE, DEBUG, "Switching save types"); - GBASavedataForceType(savedata, state->savedata.type, savedata->realisticTiming); + GBASavedataForceType(savedata, state->savedata.type); } savedata->command = state->savedata.command; GBASerializedSavedataFlags flags = state->savedata.flags; @@ -607,9 +615,7 @@ mLOG(GBA_SAVE, DEBUG, "Performing unknown sector-size erase at 0x%04x", sectorStart); } savedata->settling = sectorStart >> 12; - if (savedata->realisticTiming) { - mTimingDeschedule(savedata->timing, &savedata->dust); - mTimingSchedule(savedata->timing, &savedata->dust, FLASH_ERASE_CYCLES); - } + mTimingDeschedule(savedata->timing, &savedata->dust); + mTimingSchedule(savedata->timing, &savedata->dust, FLASH_ERASE_CYCLES); memset(&savedata->currentBank[sectorStart & ~(size - 1)], 0xFF, size); } diff -Nru mgba-0.6.3+dfsg1/src/gba/serialize.c mgba-0.7.0/src/gba/serialize.c --- mgba-0.6.3+dfsg1/src/gba/serialize.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/serialize.c 2019-01-27 00:06:06.000000000 +0000 @@ -61,6 +61,7 @@ GBASerializedMiscFlags miscFlags = 0; miscFlags = GBASerializedMiscFlagsSetHalted(miscFlags, gba->cpu->halted); + miscFlags = GBASerializedMiscFlagsSetPOSTFLG(miscFlags, gba->memory.io[REG_POSTFLG >> 1] & 1); STORE_32(miscFlags, 0, &state->miscFlags); GBAMemorySerialize(&gba->memory, state); @@ -128,6 +129,8 @@ 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); @@ -175,6 +178,7 @@ GBASerializedMiscFlags miscFlags = 0; LOAD_32(miscFlags, 0, &state->miscFlags); gba->cpu->halted = GBASerializedMiscFlagsGetHalted(miscFlags); + gba->memory.io[REG_POSTFLG >> 1] = GBASerializedMiscFlagsGetPOSTFLG(miscFlags); GBAVideoDeserialize(&gba->video, state); GBAMemoryDeserialize(&gba->memory, state); @@ -185,5 +189,9 @@ if (gba->rr) { gba->rr->stateLoaded(gba->rr, state); } + + gba->timing.reroot = gba->timing.root; + gba->timing.root = NULL; + return true; } diff -Nru mgba-0.6.3+dfsg1/src/gba/sharkport.c mgba-0.7.0/src/gba/sharkport.c --- mgba-0.6.3+dfsg1/src/gba/sharkport.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/sharkport.c 2019-01-27 00:06:06.000000000 +0000 @@ -117,7 +117,7 @@ switch (gba->memory.savedata.type) { case SAVEDATA_FLASH512: if (copySize > SIZE_CART_FLASH512) { - GBASavedataForceType(&gba->memory.savedata, SAVEDATA_FLASH1M, gba->memory.savedata.realisticTiming); + GBASavedataForceType(&gba->memory.savedata, SAVEDATA_FLASH1M); } // Fall through default: @@ -200,22 +200,8 @@ } // Write payload - size = 0x1C; - switch (gba->memory.savedata.type) { - case SAVEDATA_SRAM: - size += SIZE_CART_SRAM; - break; - case SAVEDATA_FLASH512: - size += SIZE_CART_FLASH512; - break; - case SAVEDATA_FLASH1M: - size += SIZE_CART_FLASH1M; - break; - case SAVEDATA_EEPROM: - size += SIZE_CART_EEPROM; - break; - case SAVEDATA_FORCE_NONE: - case SAVEDATA_AUTODETECT: + size = 0x1C + GBASavedataSize(&gba->memory.savedata); + if (size == 0x1C) { return false; } STORE_32(size, 0, &buffer.i); diff -Nru mgba-0.6.3+dfsg1/src/gba/sio/joybus.c mgba-0.7.0/src/gba/sio/joybus.c --- mgba-0.6.3+dfsg1/src/gba/sio/joybus.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/gba/sio/joybus.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,76 @@ +/* Copyright (c) 2013-2017 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + +#include +#include + +static uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value); + +void GBASIOJOYCreate(struct GBASIODriver* sio) { + sio->init = NULL; + sio->deinit = NULL; + sio->load = NULL; + sio->unload = NULL; + sio->writeRegister = GBASIOJOYWriteRegister; +} + +uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value) { + switch (address) { + case REG_JOYCNT: + return (value & 0x0040) | (sio->p->p->memory.io[REG_JOYCNT >> 1] & ~(value & 0x7) & ~0x0040); + case REG_JOYSTAT: + return (value & 0x0030) | (sio->p->p->memory.io[REG_JOYSTAT >> 1] & ~0x30); + case REG_JOY_TRANS_LO: + case REG_JOY_TRANS_HI: + sio->p->p->memory.io[REG_JOYSTAT >> 1] |= 8; + break; + } + return value; +} + +int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data) { + switch (command) { + case JOY_RESET: + sio->p->p->memory.io[REG_JOYCNT >> 1] |= 1; + if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) { + GBARaiseIRQ(sio->p->p, IRQ_SIO); + } + // Fall through + case JOY_POLL: + data[0] = 0x00; + data[1] = 0x04; + data[2] = sio->p->p->memory.io[REG_JOYSTAT >> 1]; + return 3; + case JOY_RECV: + sio->p->p->memory.io[REG_JOYCNT >> 1] |= 2; + sio->p->p->memory.io[REG_JOYSTAT >> 1] |= 2; + + sio->p->p->memory.io[REG_JOY_RECV_LO >> 1] = data[0] | (data[1] << 8); + sio->p->p->memory.io[REG_JOY_RECV_HI >> 1] = data[2] | (data[3] << 8); + + data[0] = sio->p->p->memory.io[REG_JOYSTAT >> 1]; + + if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) { + GBARaiseIRQ(sio->p->p, IRQ_SIO); + } + return 1; + case JOY_TRANS: + sio->p->p->memory.io[REG_JOYCNT >> 1] |= 4; + sio->p->p->memory.io[REG_JOYSTAT >> 1] &= ~8; + data[0] = sio->p->p->memory.io[REG_JOY_TRANS_LO >> 1]; + data[1] = sio->p->p->memory.io[REG_JOY_TRANS_LO >> 1] >> 8; + data[2] = sio->p->p->memory.io[REG_JOY_TRANS_HI >> 1]; + data[3] = sio->p->p->memory.io[REG_JOY_TRANS_HI >> 1] >> 8; + data[4] = sio->p->p->memory.io[REG_JOYSTAT >> 1]; + + if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) { + GBARaiseIRQ(sio->p->p, IRQ_SIO); + } + return 5; + } + return 0; +} diff -Nru mgba-0.6.3+dfsg1/src/gba/sio.c mgba-0.7.0/src/gba/sio.c --- mgba-0.6.3+dfsg1/src/gba/sio.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/sio.c 2019-01-27 00:06:06.000000000 +0000 @@ -163,6 +163,9 @@ value &= ~0x0080; } break; + case SIO_MULTI: + value |= 0xC; + break; default: // TODO break; diff -Nru mgba-0.6.3+dfsg1/src/gba/test/cheats.c mgba-0.7.0/src/gba/test/cheats.c --- mgba-0.6.3+dfsg1/src/gba/test/cheats.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/test/cheats.c 2019-01-27 00:06:06.000000000 +0000 @@ -45,7 +45,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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); @@ -57,7 +57,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -81,7 +81,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW); assert_true(set->addLine(set, "00000000 80300000", GBA_CHEAT_PRO_ACTION_REPLAY)); assert_true(set->addLine(set, "00000001 01020002", GBA_CHEAT_PRO_ACTION_REPLAY)); @@ -110,7 +110,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW); assert_true(set->addLine(set, "00000000 82300000", GBA_CHEAT_PRO_ACTION_REPLAY)); assert_true(set->addLine(set, "00000001 01020002", GBA_CHEAT_PRO_ACTION_REPLAY)); @@ -139,7 +139,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + GBACheatSetGameSharkVersion((struct GBACheatSet*) set, GBA_GS_PARV3_RAW); assert_true(set->addLine(set, "00000000 84300000", GBA_CHEAT_PRO_ACTION_REPLAY)); assert_true(set->addLine(set, "00000001 01020002", GBA_CHEAT_PRO_ACTION_REPLAY)); @@ -168,7 +168,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -197,7 +197,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -252,7 +252,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -286,7 +286,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -354,7 +354,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -401,7 +401,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -430,7 +430,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -493,7 +493,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -528,7 +528,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -599,7 +599,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -677,7 +677,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -739,7 +739,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -809,7 +809,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -879,7 +879,7 @@ assert_non_null(device); struct mCheatSet* set = device->createSet(device, NULL); assert_non_null(set); - GBACheatSetGameSharkVersion((struct GBACheatSet*) set, 4); + 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)); @@ -1019,6 +1019,36 @@ set->deinit(set); } +M_TEST_DEFINE(doPARv3IfButton) { + 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, "00000000 10300000", GBA_CHEAT_PRO_ACTION_REPLAY)); + assert_true(set->addLine(set, "00000001 00000000", GBA_CHEAT_PRO_ACTION_REPLAY)); + + core->reset(core); + assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0); + + mCheatRefresh(device, set); + assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0); + + mCheatPressButton(device, true); + mCheatRefresh(device, set); + assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1); + + mCheatPressButton(device, false); + mCheatRefresh(device, set); + assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0x1); + + core->rawWrite8(core, 0x03000000, -1, 0); + mCheatRefresh(device, set); + assert_int_equal(core->rawRead8(core, 0x03000000, -1), 0); + set->deinit(set); +} + M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(GBACheats, cmocka_unit_test(createSet), cmocka_unit_test(addRawPARv3), @@ -1039,4 +1069,5 @@ cmocka_unit_test(doPARv3IfXContain1), cmocka_unit_test(doPARv3IfXContain1Else), cmocka_unit_test(doPARv3IfXElseContain1), - cmocka_unit_test(doPARv3IfXContain1ElseContain1)) + cmocka_unit_test(doPARv3IfXContain1ElseContain1), + cmocka_unit_test(doPARv3IfButton)) diff -Nru mgba-0.6.3+dfsg1/src/gba/test/gba.c mgba-0.7.0/src/gba/test/gba.c --- mgba-0.6.3+dfsg1/src/gba/test/gba.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/test/gba.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +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); -M_TEST_SUITE_DECLARE(GBACheats); - -int TestRunGBA(void) { - int failures = 0; - failures += M_TEST_SUITE_RUN(GBACore); - failures += M_TEST_SUITE_RUN(GBACheats); - return failures; -} diff -Nru mgba-0.6.3+dfsg1/src/gba/test/gba.h mgba-0.7.0/src/gba/test/gba.h --- mgba-0.6.3+dfsg1/src/gba/test/gba.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/test/gba.h 1970-01-01 00:00:00.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/src/gba/timer.c mgba-0.7.0/src/gba/timer.c --- mgba-0.6.3+dfsg1/src/gba/timer.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/timer.c 2019-01-27 00:06:06.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016 Jeffrey Pfau +/* Copyright (c) 2013-2018 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -8,14 +8,57 @@ #include #include -static void GBATimerUpdate(struct mTiming* timing, struct GBA* gba, int timerId, uint32_t cyclesLate) { +#define TIMER_IRQ_DELAY 7 +#define TIMER_RELOAD_DELAY 0 +#define TIMER_STARTUP_DELAY 2 + +#define REG_TMCNT_LO(X) (REG_TM0CNT_LO + ((X) << 2)) + +static void GBATimerIrq(struct GBA* gba, int timerId) { struct GBATimer* timer = &gba->timers[timerId]; - gba->memory.io[(REG_TM0CNT_LO >> 1) + (timerId << 1)] = timer->reload; - timer->oldReload = timer->reload; - timer->lastEvent = timing->masterCycles - cyclesLate; + if (GBATimerFlagsIsIrqPending(timer->flags)) { + timer->flags = GBATimerFlagsClearIrqPending(timer->flags); + GBARaiseIRQ(gba, IRQ_TIMER0 + timerId); + } +} + +static void GBATimerIrq0(struct mTiming* timing, void* context, uint32_t cyclesLate) { + UNUSED(timing); + UNUSED(cyclesLate); + GBATimerIrq(context, 0); +} + +static void GBATimerIrq1(struct mTiming* timing, void* context, uint32_t cyclesLate) { + UNUSED(timing); + UNUSED(cyclesLate); + GBATimerIrq(context, 1); +} + +static void GBATimerIrq2(struct mTiming* timing, void* context, uint32_t cyclesLate) { + UNUSED(timing); + UNUSED(cyclesLate); + GBATimerIrq(context, 2); +} + +static void GBATimerIrq3(struct mTiming* timing, void* context, uint32_t cyclesLate) { + UNUSED(timing); + UNUSED(cyclesLate); + GBATimerIrq(context, 3); +} + +static void GBATimerUpdate(struct GBA* gba, int timerId, uint32_t cyclesLate) { + struct GBATimer* timer = &gba->timers[timerId]; + if (GBATimerFlagsIsCountUp(timer->flags)) { + gba->memory.io[REG_TMCNT_LO(timerId) >> 1] = timer->reload; + } else { + GBATimerUpdateRegister(gba, timerId, TIMER_RELOAD_DELAY + cyclesLate); + } if (GBATimerFlagsIsDoIrq(timer->flags)) { - GBARaiseIRQ(gba, IRQ_TIMER0 + timerId); + timer->flags = GBATimerFlagsFillIrqPending(timer->flags); + if (!mTimingIsScheduled(&gba->timing, &timer->irq)) { + mTimingSchedule(&gba->timing, &timer->irq, TIMER_IRQ_DELAY - cyclesLate); + } } if (gba->audio.enable && timerId < 2) { @@ -31,33 +74,32 @@ if (timerId < 3) { struct GBATimer* nextTimer = &gba->timers[timerId + 1]; if (GBATimerFlagsIsCountUp(nextTimer->flags)) { // TODO: Does this increment while disabled? - ++gba->memory.io[(REG_TM1CNT_LO >> 1) + (timerId << 1)]; - if (!gba->memory.io[(REG_TM1CNT_LO >> 1) + (timerId << 1)] && GBATimerFlagsIsEnable(nextTimer->flags)) { - mTimingSchedule(timing, &nextTimer->event, -cyclesLate); + ++gba->memory.io[REG_TMCNT_LO(timerId + 1) >> 1]; + if (!gba->memory.io[REG_TMCNT_LO(timerId + 1) >> 1] && GBATimerFlagsIsEnable(nextTimer->flags)) { + GBATimerUpdate(gba, timerId + 1, cyclesLate); } } } - - if (!GBATimerFlagsIsCountUp(timer->flags)) { - uint32_t nextEvent = timer->overflowInterval - cyclesLate; - mTimingSchedule(timing, &timer->event, nextEvent); - } } static void GBATimerUpdate0(struct mTiming* timing, void* context, uint32_t cyclesLate) { - GBATimerUpdate(timing, context, 0, cyclesLate); + UNUSED(timing); + GBATimerUpdate(context, 0, cyclesLate); } static void GBATimerUpdate1(struct mTiming* timing, void* context, uint32_t cyclesLate) { - GBATimerUpdate(timing, context, 1, cyclesLate); + UNUSED(timing); + GBATimerUpdate(context, 1, cyclesLate); } static void GBATimerUpdate2(struct mTiming* timing, void* context, uint32_t cyclesLate) { - GBATimerUpdate(timing, context, 2, cyclesLate); + UNUSED(timing); + GBATimerUpdate(context, 2, cyclesLate); } static void GBATimerUpdate3(struct mTiming* timing, void* context, uint32_t cyclesLate) { - GBATimerUpdate(timing, context, 3, cyclesLate); + UNUSED(timing); + GBATimerUpdate(context, 3, cyclesLate); } void GBATimerInit(struct GBA* gba) { @@ -78,29 +120,62 @@ gba->timers[3].event.callback = GBATimerUpdate3; gba->timers[3].event.context = gba; gba->timers[3].event.priority = 0x23; + gba->timers[0].irq.name = "GBA Timer 0 IRQ"; + gba->timers[0].irq.callback = GBATimerIrq0; + gba->timers[0].irq.context = gba; + gba->timers[0].irq.priority = 0x28; + gba->timers[1].irq.name = "GBA Timer 1 IRQ"; + gba->timers[1].irq.callback = GBATimerIrq1; + gba->timers[1].irq.context = gba; + gba->timers[1].irq.priority = 0x29; + gba->timers[2].irq.name = "GBA Timer 2 IRQ"; + gba->timers[2].irq.callback = GBATimerIrq2; + gba->timers[2].irq.context = gba; + gba->timers[2].irq.priority = 0x2A; + gba->timers[3].irq.name = "GBA Timer 3 IRQ"; + gba->timers[3].irq.callback = GBATimerIrq3; + gba->timers[3].irq.context = gba; + gba->timers[3].irq.priority = 0x2B; } -void GBATimerUpdateRegister(struct GBA* gba, int timer) { +void GBATimerUpdateRegister(struct GBA* gba, int timer, int32_t cyclesLate) { struct GBATimer* currentTimer = &gba->timers[timer]; - if (GBATimerFlagsIsEnable(currentTimer->flags) && !GBATimerFlagsIsCountUp(currentTimer->flags)) { - int32_t prefetchSkew = -2; - if (gba->memory.lastPrefetchedPc > (uint32_t) gba->cpu->gprs[ARM_PC]) { - prefetchSkew += ((gba->memory.lastPrefetchedPc - gba->cpu->gprs[ARM_PC]) * gba->cpu->memory.activeSeqCycles16) / WORD_SIZE_THUMB; - } - // Reading this takes two cycles (1N+1I), so let's remove them preemptively - int32_t diff = gba->cpu->cycles - (currentTimer->lastEvent - gba->timing.masterCycles); - gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->oldReload + ((diff + prefetchSkew) >> GBATimerFlagsGetPrescaleBits(currentTimer->flags)); + if (!GBATimerFlagsIsEnable(currentTimer->flags) || GBATimerFlagsIsCountUp(currentTimer->flags)) { + return; } + + // Align timer + int prescaleBits = GBATimerFlagsGetPrescaleBits(currentTimer->flags); + int32_t currentTime = mTimingCurrentTime(&gba->timing) - cyclesLate; + int32_t tickMask = (1 << prescaleBits) - 1; + currentTime &= ~tickMask; + + // Update register + int32_t tickIncrement = currentTime - currentTimer->lastEvent; + currentTimer->lastEvent = currentTime; + tickIncrement >>= prescaleBits; + tickIncrement += gba->memory.io[REG_TMCNT_LO(timer) >> 1]; + while (tickIncrement >= 0x10000) { + tickIncrement -= 0x10000 - currentTimer->reload; + } + gba->memory.io[REG_TMCNT_LO(timer) >> 1] = tickIncrement; + + // Schedule next update + tickIncrement = (0x10000 - tickIncrement) << prescaleBits; + currentTime += tickIncrement; + currentTime &= ~tickMask; + currentTime -= mTimingCurrentTime(&gba->timing); + mTimingDeschedule(&gba->timing, ¤tTimer->event); + mTimingSchedule(&gba->timing, ¤tTimer->event, currentTime); } void GBATimerWriteTMCNT_LO(struct GBA* gba, int timer, uint16_t reload) { gba->timers[timer].reload = reload; - gba->timers[timer].overflowInterval = (0x10000 - gba->timers[timer].reload) << GBATimerFlagsGetPrescaleBits(gba->timers[timer].flags); } void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) { struct GBATimer* currentTimer = &gba->timers[timer]; - GBATimerUpdateRegister(gba, timer); + GBATimerUpdateRegister(gba, timer, 0); unsigned oldPrescale = GBATimerFlagsGetPrescaleBits(currentTimer->flags); unsigned prescaleBits; @@ -121,21 +196,20 @@ currentTimer->flags = GBATimerFlagsSetPrescaleBits(currentTimer->flags, prescaleBits); currentTimer->flags = GBATimerFlagsTestFillCountUp(currentTimer->flags, timer > 0 && (control & 0x0004)); currentTimer->flags = GBATimerFlagsTestFillDoIrq(currentTimer->flags, control & 0x0040); - currentTimer->overflowInterval = (0x10000 - currentTimer->reload) << GBATimerFlagsGetPrescaleBits(currentTimer->flags); bool wasEnabled = GBATimerFlagsIsEnable(currentTimer->flags); currentTimer->flags = GBATimerFlagsTestFillEnable(currentTimer->flags, control & 0x0080); if (!wasEnabled && GBATimerFlagsIsEnable(currentTimer->flags)) { mTimingDeschedule(&gba->timing, ¤tTimer->event); - if (!GBATimerFlagsIsCountUp(currentTimer->flags)) { - mTimingSchedule(&gba->timing, ¤tTimer->event, currentTimer->overflowInterval + 7 - 6 * prescaleBits); - } - gba->memory.io[(REG_TM0CNT_LO + (timer << 2)) >> 1] = currentTimer->reload; - currentTimer->oldReload = currentTimer->reload; - currentTimer->lastEvent = gba->timing.masterCycles + gba->cpu->cycles; + gba->memory.io[REG_TMCNT_LO(timer) >> 1] = currentTimer->reload; + int32_t tickMask = (1 << prescaleBits) - 1; + currentTimer->lastEvent = (mTimingCurrentTime(&gba->timing) - TIMER_STARTUP_DELAY) & ~tickMask; + GBATimerUpdateRegister(gba, timer, TIMER_STARTUP_DELAY); } else if (wasEnabled && !GBATimerFlagsIsEnable(currentTimer->flags)) { mTimingDeschedule(&gba->timing, ¤tTimer->event); } else if (GBATimerFlagsIsEnable(currentTimer->flags) && GBATimerFlagsGetPrescaleBits(currentTimer->flags) != oldPrescale && !GBATimerFlagsIsCountUp(currentTimer->flags)) { mTimingDeschedule(&gba->timing, ¤tTimer->event); - mTimingSchedule(&gba->timing, ¤tTimer->event, currentTimer->overflowInterval - currentTimer->lastEvent); + int32_t tickMask = (1 << prescaleBits) - 1; + currentTimer->lastEvent = (mTimingCurrentTime(&gba->timing) - TIMER_STARTUP_DELAY) & ~tickMask; + GBATimerUpdateRegister(gba, timer, TIMER_STARTUP_DELAY); } } diff -Nru mgba-0.6.3+dfsg1/src/gba/vfame.c mgba-0.7.0/src/gba/vfame.c --- mgba-0.6.3+dfsg1/src/gba/vfame.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/vfame.c 2019-01-27 00:06:06.000000000 +0000 @@ -246,10 +246,8 @@ // if mode has been set - the address and value of the SRAM write will be modified address = _modifySramAddress(cart->cartType, address, cart->sramMode); value = _modifySramValue(cart->cartType, value, cart->sramMode); - // these writes are mirrored - address &= 0x7FFF; + address &= (SIZE_CART_SRAM - 1); sramData[address] = value; - sramData[address + 0x8000] = value; } static uint32_t _modifySramAddress(enum GBAVFameCartType type, uint32_t address, int mode) { diff -Nru mgba-0.6.3+dfsg1/src/gba/video.c mgba-0.7.0/src/gba/video.c --- mgba-0.6.3+dfsg1/src/gba/video.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/gba/video.c 2019-01-27 00:06:06.000000000 +0000 @@ -6,11 +6,12 @@ #include #include -#include +#include #include #include #include #include +#include #include #include @@ -68,7 +69,7 @@ void GBAVideoInit(struct GBAVideo* video) { video->renderer = &dummyRenderer; video->renderer->cache = NULL; - video->vram = 0; + video->vram = anonymousMemoryMap(SIZE_VRAM); video->frameskip = 0; video->event.name = "GBA Video"; video->event.callback = NULL; @@ -77,24 +78,21 @@ } void GBAVideoReset(struct GBAVideo* video) { + int32_t nextEvent = VIDEO_HDRAW_LENGTH; if (video->p->memory.fullBios) { video->vcount = 0; } else { - // TODO: Verify exact scanline hardware + // TODO: Verify exact scanline on hardware video->vcount = 0x7E; + nextEvent = 170; } video->p->memory.io[REG_VCOUNT >> 1] = video->vcount; video->event.callback = _startHblank; - mTimingSchedule(&video->p->timing, &video->event, VIDEO_HDRAW_LENGTH); + mTimingSchedule(&video->p->timing, &video->event, nextEvent); video->frameCounter = 0; video->frameskipCounter = 0; - - if (video->vram) { - mappedMemoryFree(video->vram, SIZE_VRAM); - } - video->vram = anonymousMemoryMap(SIZE_VRAM); video->renderer->vram = video->vram; memset(video->palette, 0, sizeof(video->palette)); @@ -105,7 +103,7 @@ } void GBAVideoDeinit(struct GBAVideo* video) { - GBAVideoAssociateRenderer(video, &dummyRenderer); + video->renderer->deinit(video->renderer); mappedMemoryFree(video->vram, SIZE_VRAM); } @@ -186,6 +184,9 @@ if (video->vcount < VIDEO_VERTICAL_PIXELS) { GBADMARunHblank(video->p, -cyclesLate); } + if (video->vcount >= 2 && video->vcount < VIDEO_VERTICAL_PIXELS + 2) { + GBADMARunDisplayStart(video->p, -cyclesLate); + } if (GBARegisterDISPSTATIsHblankIRQ(dispstat)) { GBARaiseIRQ(video->p, IRQ_HBLANK); } @@ -214,7 +215,9 @@ } 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_DISPCNT: value &= 0xFFF7; @@ -255,14 +258,13 @@ 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)); } } @@ -321,7 +323,7 @@ uint32_t when; LOAD_32(when, 0, &state->video.nextEvent); - GBARegisterDISPSTAT dispstat = video->p->memory.io[REG_DISPSTAT >> 1]; + GBARegisterDISPSTAT dispstat = state->io[REG_DISPSTAT >> 1]; if (GBARegisterDISPSTATIsInHblank(dispstat)) { video->event.callback = _startHdraw; } else { diff -Nru mgba-0.6.3+dfsg1/src/lr35902/debugger/cli-debugger.c mgba-0.7.0/src/lr35902/debugger/cli-debugger.c --- mgba-0.6.3+dfsg1/src/lr35902/debugger/cli-debugger.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/lr35902/debugger/cli-debugger.c 2019-01-27 00:06:06.000000000 +0000 @@ -21,7 +21,7 @@ }; static inline void _printFlags(struct CLIDebuggerBackend* be, union FlagRegister f) { - be->printf(be, "[%c%c%c%c]\n", + be->printf(be, "F: [%c%c%c%c]\n", f.z ? 'Z' : '-', f.n ? 'N' : '-', f.h ? 'H' : '-', @@ -82,16 +82,16 @@ static void _printStatus(struct CLIDebuggerSystem* debugger) { struct CLIDebuggerBackend* be = debugger->p->backend; struct LR35902Core* cpu = debugger->p->d.core->cpu; - be->printf(be, "A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af); - be->printf(be, "B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc); - be->printf(be, "D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de); - be->printf(be, "H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl); - be->printf(be, "PC: %04X SP: %04X\n", cpu->pc, cpu->sp); + be->printf(be, "A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af); + be->printf(be, "B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc); + be->printf(be, "D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de); + be->printf(be, "H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl); + be->printf(be, "PC: %04X SP: %04X\n", cpu->pc, cpu->sp); struct LR35902Debugger* platDebugger = (struct LR35902Debugger*) debugger->p->d.platform; size_t i; for (i = 0; platDebugger->segments[i].name; ++i) { - be->printf(be, "%s%s: %02X", i ? " " : "", platDebugger->segments[i].name, cpu->memory.currentSegment(cpu, platDebugger->segments[i].start)); + be->printf(be, "%s%s: %02X", i ? " " : "", platDebugger->segments[i].name, cpu->memory.currentSegment(cpu, platDebugger->segments[i].start)); } if (i) { be->printf(be, "\n"); @@ -100,58 +100,9 @@ _printLine(debugger->p, cpu->pc, cpu->memory.currentSegment(cpu, cpu->pc)); } -static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) { - struct LR35902Core* cpu = debugger->p->d.core->cpu; - if (strcmp(name, "a") == 0) { - return cpu->a; - } - if (strcmp(name, "b") == 0) { - return cpu->b; - } - if (strcmp(name, "c") == 0) { - return cpu->c; - } - if (strcmp(name, "d") == 0) { - return cpu->d; - } - if (strcmp(name, "e") == 0) { - return cpu->e; - } - if (strcmp(name, "h") == 0) { - return cpu->h; - } - if (strcmp(name, "l") == 0) { - return cpu->l; - } - if (strcmp(name, "bc") == 0) { - return cpu->bc; - } - if (strcmp(name, "de") == 0) { - return cpu->de; - } - if (strcmp(name, "hl") == 0) { - return cpu->hl; - } - if (strcmp(name, "af") == 0) { - return cpu->af; - } - if (strcmp(name, "pc") == 0) { - return cpu->pc; - } - if (strcmp(name, "sp") == 0) { - return cpu->sp; - } - if (strcmp(name, "f") == 0) { - return cpu->f.packed; - } - dv->type = CLIDV_ERROR_TYPE; - return 0; -} - void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger) { debugger->printStatus = _printStatus; debugger->disassemble = _disassemble; - debugger->lookupPlatformIdentifier = _lookupPlatformIdentifier; debugger->platformName = "GB-Z80"; debugger->platformCommands = _lr35902Commands; } diff -Nru mgba-0.6.3+dfsg1/src/lr35902/debugger/debugger.c mgba-0.7.0/src/lr35902/debugger/debugger.c --- mgba-0.6.3+dfsg1/src/lr35902/debugger/debugger.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/lr35902/debugger/debugger.c 2019-01-27 00:06:06.000000000 +0000 @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -23,6 +24,20 @@ return 0; } +static void _destroyBreakpoint(struct LR35902DebugBreakpoint* breakpoint) { + if (breakpoint->condition) { + parseFree(breakpoint->condition); + free(breakpoint->condition); + } +} + +static void _destroyWatchpoint(struct LR35902DebugWatchpoint* watchpoint) { + if (watchpoint->condition) { + parseFree(watchpoint->condition); + free(watchpoint->condition); + } +} + static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) { struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; struct LR35902DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->pc); @@ -32,6 +47,13 @@ if (breakpoint->segment >= 0 && debugger->cpu->memory.currentSegment(debugger->cpu, breakpoint->address) != breakpoint->segment) { return; } + if (breakpoint->condition) { + int32_t value; + int segment; + if (!mDebuggerEvaluateParseTree(d->p, breakpoint->condition, &value, &segment) || !(value || segment >= 0)) { + return; + } + } struct mDebuggerEntryInfo info = { .address = breakpoint->address }; @@ -44,12 +66,16 @@ static void LR35902DebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info); static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment); +static void LR35902DebuggerSetConditionalBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment, struct ParseTree* condition); static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment); static void LR35902DebuggerSetWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment, enum mWatchpointType type); +static void LR35902DebuggerSetConditionalWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment, enum mWatchpointType type, struct ParseTree* condition); static void LR35902DebuggerClearWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment); static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform*); static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform*); static void LR35902DebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length); +static bool LR35902DebuggerGetRegister(struct mDebuggerPlatform*, const char* name, int32_t* value); +static bool LR35902DebuggerSetRegister(struct mDebuggerPlatform*, const char* name, int32_t value); struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void) { struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct LR35902Debugger)); @@ -57,25 +83,38 @@ platform->init = LR35902DebuggerInit; platform->deinit = LR35902DebuggerDeinit; platform->setBreakpoint = LR35902DebuggerSetBreakpoint; + platform->setConditionalBreakpoint = LR35902DebuggerSetConditionalBreakpoint; platform->clearBreakpoint = LR35902DebuggerClearBreakpoint; platform->setWatchpoint = LR35902DebuggerSetWatchpoint; + platform->setConditionalWatchpoint = LR35902DebuggerSetConditionalWatchpoint; platform->clearWatchpoint = LR35902DebuggerClearWatchpoint; platform->checkBreakpoints = LR35902DebuggerCheckBreakpoints; platform->hasBreakpoints = LR35902DebuggerHasBreakpoints; platform->trace = LR35902DebuggerTrace; + platform->getRegister = LR35902DebuggerGetRegister; + platform->setRegister = LR35902DebuggerSetRegister; return platform; } void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform) { struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform; debugger->cpu = cpu; + debugger->originalMemory = debugger->cpu->memory; LR35902DebugBreakpointListInit(&debugger->breakpoints, 0); LR35902DebugWatchpointListInit(&debugger->watchpoints, 0); } void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform) { struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform; + size_t i; + for (i = 0; i < LR35902DebugBreakpointListSize(&debugger->breakpoints); ++i) { + _destroyBreakpoint(LR35902DebugBreakpointListGetPointer(&debugger->breakpoints, i)); + } LR35902DebugBreakpointListDeinit(&debugger->breakpoints); + + for (i = 0; i < LR35902DebugWatchpointListSize(&debugger->watchpoints); ++i) { + _destroyWatchpoint(LR35902DebugWatchpointListGetPointer(&debugger->watchpoints, i)); + } LR35902DebugWatchpointListDeinit(&debugger->watchpoints); } @@ -92,10 +131,15 @@ } static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) { + LR35902DebuggerSetConditionalBreakpoint(d, address, segment, NULL); +} + +static void LR35902DebuggerSetConditionalBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment, struct ParseTree* condition) { struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListAppend(&debugger->breakpoints); breakpoint->address = address; breakpoint->segment = segment; + breakpoint->condition = condition; } static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) { @@ -105,6 +149,7 @@ for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) { struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListGetPointer(breakpoints, i); if (breakpoint->address == address && breakpoint->segment == segment) { + _destroyBreakpoint(LR35902DebugBreakpointListGetPointer(breakpoints, i)); LR35902DebugBreakpointListShift(breakpoints, i, 1); } } @@ -116,6 +161,10 @@ } static void LR35902DebuggerSetWatchpoint(struct mDebuggerPlatform* d, uint32_t address, int segment, enum mWatchpointType type) { + LR35902DebuggerSetConditionalWatchpoint(d, address, segment, type, NULL); +} + +static void LR35902DebuggerSetConditionalWatchpoint(struct mDebuggerPlatform* d, uint32_t address, int segment, enum mWatchpointType type, struct ParseTree* condition) { struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; if (!LR35902DebugWatchpointListSize(&debugger->watchpoints)) { LR35902DebuggerInstallMemoryShim(debugger); @@ -124,6 +173,7 @@ watchpoint->address = address; watchpoint->type = type; watchpoint->segment = segment; + watchpoint->condition = condition; } static void LR35902DebuggerClearWatchpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) { @@ -163,8 +213,136 @@ disPtr += 2; LR35902Disassemble(&info, disPtr, sizeof(disassembly) - (disPtr - disassembly)); - *length = snprintf(out, *length, "A: %02X F: %02X B: %02X C: %02X D: %02X E: %02X H: %02X L: %02X SP: %04X PC: %04X | %s", + *length = snprintf(out, *length, "A: %02X F: %02X B: %02X C: %02X D: %02X E: %02X H: %02X L: %02X SP: %04X PC: %02X:%04X | %s", cpu->a, cpu->f.packed, cpu->b, cpu->c, cpu->d, cpu->e, cpu->h, cpu->l, - cpu->sp, cpu->pc, disassembly); + cpu->sp, cpu->memory.currentSegment(cpu, cpu->pc), cpu->pc, disassembly); +} + +bool LR35902DebuggerGetRegister(struct mDebuggerPlatform* d, const char* name, int32_t* value) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; + struct LR35902Core* cpu = debugger->cpu; + + if (strcmp(name, "a") == 0) { + *value = cpu->a; + return true; + } + if (strcmp(name, "b") == 0) { + *value = cpu->b; + return true; + } + if (strcmp(name, "c") == 0) { + *value = cpu->c; + return true; + } + if (strcmp(name, "d") == 0) { + *value = cpu->d; + return true; + } + if (strcmp(name, "e") == 0) { + *value = cpu->e; + return true; + } + if (strcmp(name, "h") == 0) { + *value = cpu->h; + return true; + } + if (strcmp(name, "l") == 0) { + *value = cpu->l; + return true; + } + if (strcmp(name, "bc") == 0) { + *value = cpu->bc; + return true; + } + if (strcmp(name, "de") == 0) { + *value = cpu->de; + return true; + } + if (strcmp(name, "hl") == 0) { + *value = cpu->hl; + return true; + } + if (strcmp(name, "af") == 0) { + *value = cpu->af; + return true; + } + if (strcmp(name, "pc") == 0) { + *value = cpu->pc; + return true; + } + if (strcmp(name, "sp") == 0) { + *value = cpu->sp; + return true; + } + if (strcmp(name, "f") == 0) { + *value = cpu->f.packed; + return true; + } + return false; +} + +bool LR35902DebuggerSetRegister(struct mDebuggerPlatform* d, const char* name, int32_t value) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; + struct LR35902Core* cpu = debugger->cpu; + + if (strcmp(name, "a") == 0) { + cpu->a = value; + return true; + } + if (strcmp(name, "b") == 0) { + cpu->b = value; + return true; + } + if (strcmp(name, "c") == 0) { + cpu->c = value; + return true; + } + if (strcmp(name, "d") == 0) { + cpu->d = value; + return true; + } + if (strcmp(name, "e") == 0) { + cpu->e = value; + return true; + } + if (strcmp(name, "h") == 0) { + cpu->h = value; + return true; + } + if (strcmp(name, "l") == 0) { + cpu->l = value; + return true; + } + if (strcmp(name, "bc") == 0) { + cpu->bc = value; + return true; + } + if (strcmp(name, "de") == 0) { + cpu->de = value; + return true; + } + if (strcmp(name, "hl") == 0) { + cpu->hl = value; + return true; + } + if (strcmp(name, "af") == 0) { + cpu->af = value; + cpu->f.packed &= 0xF0; + return true; + } + if (strcmp(name, "pc") == 0) { + cpu->pc = value; + cpu->memory.setActiveRegion(cpu, cpu->pc); + return true; + } + if (strcmp(name, "sp") == 0) { + cpu->sp = value; + return true; + } + if (strcmp(name, "f") == 0) { + cpu->f.packed = value & 0xF0; + return true; + } + return false; } diff -Nru mgba-0.6.3+dfsg1/src/lr35902/debugger/memory-debugger.c mgba-0.7.0/src/lr35902/debugger/memory-debugger.c --- mgba-0.6.3+dfsg1/src/lr35902/debugger/memory-debugger.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/lr35902/debugger/memory-debugger.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include #include @@ -47,6 +48,13 @@ for (i = 0; i < LR35902DebugWatchpointListSize(&debugger->watchpoints); ++i) { watchpoint = LR35902DebugWatchpointListGetPointer(&debugger->watchpoints, i); if (watchpoint->address == address && (watchpoint->segment < 0 || watchpoint->segment == debugger->originalMemory.currentSegment(debugger->cpu, address)) && watchpoint->type & type) { + if (watchpoint->condition) { + int32_t value; + int segment; + if (!mDebuggerEvaluateParseTree(debugger->d.p, watchpoint->condition, &value, &segment) || !(value || segment >= 0)) { + return false; + } + } info->type.wp.oldValue = debugger->originalMemory.load8(debugger->cpu, address); info->type.wp.newValue = newValue; info->address = address; diff -Nru mgba-0.6.3+dfsg1/src/lr35902/decoder.c mgba-0.7.0/src/lr35902/decoder.c --- mgba-0.6.3+dfsg1/src/lr35902/decoder.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/lr35902/decoder.c 2019-01-27 00:06:06.000000000 +0000 @@ -409,7 +409,7 @@ } #define ADVANCE(AMOUNT) \ - if (AMOUNT > blen) { \ + if (AMOUNT >= blen) { \ buffer[blen - 1] = '\0'; \ return total; \ } \ diff -Nru mgba-0.6.3+dfsg1/src/lr35902/lr35902.c mgba-0.7.0/src/lr35902/lr35902.c --- mgba-0.6.3+dfsg1/src/lr35902/lr35902.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/lr35902/lr35902.c 2019-01-27 00:06:06.000000000 +0000 @@ -70,9 +70,8 @@ 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 _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; } @@ -137,22 +137,22 @@ } void LR35902Tick(struct LR35902Core* cpu) { + while (cpu->cycles >= cpu->nextEvent) { + cpu->irqh.processEvents(cpu); + } _LR35902Step(cpu); if (cpu->cycles + 2 >= cpu->nextEvent) { int32_t diff = cpu->nextEvent - cpu->cycles; cpu->cycles = cpu->nextEvent; cpu->executionState += diff; cpu->irqh.processEvents(cpu); - cpu->cycles += 2 - diff; + cpu->cycles += LR35902_CORE_EXECUTE - cpu->executionState; } else { cpu->cycles += 2; } cpu->executionState = LR35902_CORE_FETCH; cpu->instruction(cpu); ++cpu->cycles; - if (cpu->cycles >= cpu->nextEvent) { - cpu->irqh.processEvents(cpu); - } } void LR35902Run(struct LR35902Core* cpu) { @@ -168,7 +168,7 @@ cpu->cycles = cpu->nextEvent; cpu->executionState += diff; cpu->irqh.processEvents(cpu); - cpu->cycles += 2 - diff; + cpu->cycles += LR35902_CORE_EXECUTE - cpu->executionState; running = false; } else { cpu->cycles += 2; diff -Nru mgba-0.6.3+dfsg1/src/platform/3ds/cia.rsf.in mgba-0.7.0/src/platform/3ds/cia.rsf.in --- mgba-0.6.3+dfsg1/src/platform/3ds/cia.rsf.in 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/3ds/cia.rsf.in 2019-01-27 00:06:06.000000000 +0000 @@ -174,7 +174,6 @@ - ldr:ro - ir:USER - ir:u - - csnd:SND SystemControlInfo: @@ -195,7 +194,6 @@ cecd: 0x0004013000002602L cfg: 0x0004013000001702L codec: 0x0004013000001802L - csnd: 0x0004013000002702L dlp: 0x0004013000002802L dsp: 0x0004013000001a02L friends: 0x0004013000003202L diff -Nru mgba-0.6.3+dfsg1/src/platform/3ds/CMakeLists.txt mgba-0.7.0/src/platform/3ds/CMakeLists.txt --- mgba-0.6.3+dfsg1/src/platform/3ds/CMakeLists.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/3ds/CMakeLists.txt 2019-01-27 00:06:06.000000000 +0000 @@ -109,10 +109,12 @@ DEPENDS ${BINARY_NAME}-perf ${BINARY_NAME}.smdh) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}-perf.3dsx - DESTINATION . COMPONENT ${BINARY_NAME}-3ds) + DESTINATION . COMPONENT ${BINARY_NAME}-perf) endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cia.rsf.in ${CMAKE_CURRENT_BINARY_DIR}/cia.rsf) + +install(TARGETS ${BINARY_NAME}.elf DESTINATION . COMPONENT ${BINARY_NAME}-dbg) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.3dsx ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.smdh diff -Nru mgba-0.6.3+dfsg1/src/platform/3ds/CMakeToolchain.txt mgba-0.7.0/src/platform/3ds/CMakeToolchain.txt --- mgba-0.6.3+dfsg1/src/platform/3ds/CMakeToolchain.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/3ds/CMakeToolchain.txt 2019-01-27 00:06:06.000000000 +0000 @@ -23,9 +23,9 @@ set(CMAKE_PROGRAM_PATH ${DEVKITARM}/bin) set(cross_prefix arm-none-eabi-) -set(arch_flags "-march=armv6k -mtune=mpcore -mfpu=vfp -mfloat-abi=hard") +set(arch_flags "-march=armv6k -mtune=mpcore -mfloat-abi=hard -ffunction-sections") set(inc_flags "-I${CTRULIB}/include ${arch_flags} -mword-relocations") -set(link_flags "-L${CTRULIB}/lib -lctru -specs=3dsx.specs ${arch_flags}") +set(link_flags "-L${CTRULIB}/lib -lctru -specs=3dsx.specs ${arch_flags} -Wl,--gc-sections") set(CMAKE_SYSTEM_NAME Generic CACHE INTERNAL "system name") set(CMAKE_SYSTEM_PROCESSOR arm CACHE INTERNAL "processor") @@ -45,7 +45,7 @@ set(CMAKE_MODULE_LINKER_FLAGS ${link_flags} CACHE INTERNAL "module link flags") set(CMAKE_SHARED_LINKER_FLAGS ${link_flags} CACHE INTERNAL "shared link flags") -set(CMAKE_FIND_ROOT_PATH ${DEVKITARM}/arm-none-eabi) +set(CMAKE_FIND_ROOT_PATH ${DEVKITARM}/arm-none-eabi ${DEVKITPRO}/portlibs/3ds) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE INTERNAL "") set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY CACHE INTERNAL "") set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY CACHE INTERNAL "") diff -Nru mgba-0.6.3+dfsg1/src/platform/3ds/ctr-gpu.c mgba-0.7.0/src/platform/3ds/ctr-gpu.c --- mgba-0.6.3+dfsg1/src/platform/3ds/ctr-gpu.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/3ds/ctr-gpu.c 2019-01-27 00:06:06.000000000 +0000 @@ -133,7 +133,7 @@ C3D_TexBind(0, activeTexture); C3D_TexEnv* env = C3D_GetTexEnv(0); - C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); + C3D_TexEnvInit(env); if (texture->fmt < GPU_LA8) { C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0); C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); @@ -144,11 +144,11 @@ C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE); } env = C3D_GetTexEnv(1); - C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); + C3D_TexEnvInit(env); C3D_TexEnvSrc(env, C3D_Both, GPU_PREVIOUS, 0, 0); C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); env = C3D_GetTexEnv(2); - C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); + C3D_TexEnvInit(env); C3D_TexEnvSrc(env, C3D_Both, GPU_PREVIOUS, 0, 0); C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); @@ -164,14 +164,14 @@ void ctrTextureMultiply(void) { C3D_TexEnv* env = C3D_GetTexEnv(1); - C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); + C3D_TexEnvInit(env); C3D_TexEnvSrc(env, C3D_Both, GPU_PREVIOUS, GPU_TEXTURE0, 0); C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); } void ctrTextureBias(u32 color) { C3D_TexEnv* env = C3D_GetTexEnv(2); - C3D_TexEnvOp(env, C3D_Both, 0, 0, 0); + C3D_TexEnvInit(env); C3D_TexEnvSrc(env, C3D_Both, GPU_PREVIOUS, GPU_CONSTANT, 0); C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); C3D_TexEnvColor(env, color); diff -Nru mgba-0.6.3+dfsg1/src/platform/3ds/main.c mgba-0.7.0/src/platform/3ds/main.c --- mgba-0.6.3+dfsg1/src/platform/3ds/main.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/3ds/main.c 2019-01-27 00:06:06.000000000 +0000 @@ -6,6 +6,7 @@ #include #include +#include #ifdef M_CORE_GBA #include #include @@ -22,11 +23,15 @@ #include #include +#include #include "ctr-gpu.h" #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,23 +63,30 @@ #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, - CSND_SUPPORTED + DSP_SUPPORTED } hasSound; // TODO: Move into context static void* outputBuffer; static struct mAVStream stream; static int16_t* audioLeft = 0; -static int16_t* audioRight = 0; static size_t audioPos = 0; static C3D_Tex outputTexture; static ndspWaveBuf dspBuffer[DSP_BUFFERS]; @@ -115,8 +127,6 @@ return false; } - C3D_RenderTargetSetClear(upscaleBuffer, C3D_CLEAR_COLOR, 0, 0); - return ctrInitGpu(); } @@ -142,36 +152,19 @@ linearFree(audioLeft); } - if (hasSound == CSND_SUPPORTED) { - linearFree(audioRight); - csndExit(); - } - if (hasSound == DSP_SUPPORTED) { ndspExit(); } - csndExit(); + camExit(); + ndspExit(); ptmuExit(); } static void _aptHook(APT_HookType hook, void* user) { UNUSED(user); switch (hook) { - case APTHOOK_ONSUSPEND: - case APTHOOK_ONSLEEP: - if (hasSound == CSND_SUPPORTED) { - CSND_SetPlayState(8, 0); - CSND_SetPlayState(9, 0); - csndExecCmds(false); - } - break; case APTHOOK_ONEXIT: - if (hasSound == CSND_SUPPORTED) { - CSND_SetPlayState(8, 0); - CSND_SetPlayState(9, 0); - csndExecCmds(false); - } _cleanup(); exit(0); break; @@ -184,39 +177,9 @@ mInputBindKey(map, _3DS_INPUT, __builtin_ctz(ctrKey), key); } -static void _csndPlaySound(u32 flags, u32 sampleRate, float vol, void* left, void* right, u32 size) { - u32 pleft = 0, pright = 0; - - int loopMode = (flags >> 10) & 3; - if (!loopMode) { - flags |= SOUND_ONE_SHOT; - } - - pleft = osConvertVirtToPhys(left); - pright = osConvertVirtToPhys(right); - - u32 timer = CSND_TIMER(sampleRate); - if (timer < 0x0042) { - timer = 0x0042; - } - else if (timer > 0xFFFF) { - timer = 0xFFFF; - } - flags &= ~0xFFFF001F; - flags |= SOUND_ENABLE | (timer << 16); - - u32 volumes = CSND_VOL(vol, -1.0); - CSND_SetChnRegs(flags | SOUND_CHANNEL(8), pleft, pleft, size, volumes, volumes); - volumes = CSND_VOL(vol, 1.0); - CSND_SetChnRegs(flags | SOUND_CHANNEL(9), pright, pright, size, volumes, volumes); -} - static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right); static void _drawStart(void) { -} - -static void _frameStart(void) { if (frameStarted) { return; } @@ -225,15 +188,16 @@ if (!frameLimiter) { if (tickCounter + 4481000 > svcGetSystemTick()) { flags = C3D_FRAME_NONBLOCK; - } else { - tickCounter = svcGetSystemTick(); } + tickCounter = svcGetSystemTick(); } C3D_FrameBegin(flags); - // Mark both buffers used to make sure they get cleared - C3D_FrameDrawOn(topScreen[doubleBuffer]); - C3D_FrameDrawOn(bottomScreen[doubleBuffer]); ctrStartFrame(); + + C3D_FrameDrawOn(bottomScreen[doubleBuffer]); + C3D_RenderTargetClear(bottomScreen[doubleBuffer], C3D_CLEAR_COLOR, 0, 0); + C3D_FrameDrawOn(topScreen[doubleBuffer]); + C3D_RenderTargetClear(topScreen[doubleBuffer], C3D_CLEAR_COLOR, 0, 0); } static void _drawEnd(void) { @@ -243,12 +207,10 @@ 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); + C3D_FrameEnd(0); 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) { @@ -267,7 +229,6 @@ } static void _guiPrepare(void) { - _frameStart(); C3D_FrameDrawOn(bottomScreen[doubleBuffer]); ctrSetViewportSize(320, 240, true); } @@ -276,14 +237,30 @@ 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) { - uint8_t mask; - if (R_SUCCEEDED(svcGetProcessAffinityMask(&mask, CUR_PROCESS_HANDLE, 4)) && mask >= 4) { + bool n3ds = false; + APT_CheckNew3DS(&n3ds); + if (n3ds) { 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); } @@ -299,7 +276,7 @@ _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; @@ -325,6 +302,7 @@ 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(); @@ -352,12 +330,7 @@ if (hasSound != NO_SOUND) { audioPos = 0; } - if (hasSound == CSND_SUPPORTED) { - memset(audioLeft, 0, AUDIO_SAMPLE_BUFFER * sizeof(int16_t)); - memset(audioRight, 0, AUDIO_SAMPLE_BUFFER * sizeof(int16_t)); - _csndPlaySound(SOUND_REPEAT | SOUND_FORMAT_16BIT, 32768, 1.0, audioLeft, audioRight, AUDIO_SAMPLE_BUFFER * sizeof(int16_t)); - csndExecCmds(false); - } else if (hasSound == DSP_SUPPORTED) { + if (hasSound == DSP_SUPPORTED) { memset(audioLeft, 0, AUDIO_SAMPLE_BUFFER * 2 * sizeof(int16_t)); } unsigned mode; @@ -375,19 +348,36 @@ 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) { - if (hasSound == CSND_SUPPORTED) { - CSND_SetPlayState(8, 0); - CSND_SetPlayState(9, 0); - csndExecCmds(false); - } osSetSpeedupEnable(false); frameLimiter = true; 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(); @@ -410,7 +400,6 @@ } static void _drawTex(struct mCore* core, bool faded) { - _frameStart(); unsigned screen_w, screen_h; switch (screenMode) { case SM_PA_BOTTOM: @@ -554,11 +543,10 @@ static void _drawFrame(struct mGUIRunner* runner, bool faded) { UNUSED(runner); - C3D_Tex* tex = &outputTexture; GSPGPU_FlushDataCache(outputBuffer, 256 * VIDEO_VERTICAL_PIXELS * 2); - C3D_SafeDisplayTransfer( + C3D_SyncDisplayTransfer( outputBuffer, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), tex->data, GX_BUFFER_DIM(256, 256), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) | @@ -570,12 +558,10 @@ blip_clear(runner->core->getAudioChannel(runner->core, 1)); } - gspWaitForPPF(); _drawTex(runner->core, faded); } static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, unsigned width, unsigned height, bool faded) { - C3D_Tex* tex = &outputTexture; color_t* newPixels = linearMemAlign(256 * height * sizeof(color_t), 0x100); @@ -587,13 +573,12 @@ } GSPGPU_FlushDataCache(newPixels, 256 * height * sizeof(u32)); - C3D_SafeDisplayTransfer( + C3D_SyncDisplayTransfer( (u32*) newPixels, GX_BUFFER_DIM(256, height), tex->data, GX_BUFFER_DIM(256, 256), GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB565) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_FLIP_VERT(1)); - gspWaitForPPF(); linearFree(newPixels); _drawTex(runner->core, faded); @@ -613,9 +598,6 @@ UNUSED(runner); screenMode = (screenMode + 1) % SM_MAX; mCoreConfigSetUIntValue(&runner->config, "screenMode", screenMode); - - 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) { @@ -627,6 +609,11 @@ tickCounter = svcGetSystemTick(); } +static bool _running(struct mGUIRunner* runner) { + UNUSED(runner); + return aptMainLoop(); +} + static uint32_t _pollInput(const struct mInputMap* map) { hidScanInput(); int activeKeys = hidKeysHeld(); @@ -646,45 +633,99 @@ } 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) { - blip_read_samples(left, &audioLeft[audioPos], AUDIO_SAMPLES, false); - blip_read_samples(right, &audioRight[audioPos], AUDIO_SAMPLES, false); - GSPGPU_FlushDataCache(&audioLeft[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); - GSPGPU_FlushDataCache(&audioRight[audioPos], AUDIO_SAMPLES * sizeof(int16_t)); - audioPos = (audioPos + AUDIO_SAMPLES) % AUDIO_SAMPLE_BUFFER; - if (audioPos == AUDIO_SAMPLES * 3) { - u8 playing = 0; - csndIsPlaying(0x8, &playing); - if (!playing) { - CSND_SetPlayState(0x8, 1); - CSND_SetPlayState(0x9, 1); - csndExecCmds(false); - } - } - } else if (hasSound == DSP_SUPPORTED) { + if (hasSound == DSP_SUPPORTED) { int startId = bufferId; while (dspBuffer[bufferId].status == NDSP_WBUF_QUEUED || dspBuffer[bufferId].status == NDSP_WBUF_PLAYING) { bufferId = (bufferId + 1) & (DSP_BUFFERS - 1); @@ -716,6 +757,13 @@ stream.postAudioFrame = 0; stream.postAudioBuffer = _postAudioBuffer; + 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; } @@ -723,6 +771,8 @@ aptHook(&cookie, _aptHook, 0); ptmuInit(); + camInit(); + hasSound = NO_SOUND; if (!ndspInit()) { hasSound = DSP_SUPPORTED; @@ -742,12 +792,6 @@ } } - if (hasSound == NO_SOUND && !csndInit()) { - hasSound = CSND_SUPPORTED; - audioLeft = linearMemAlign(AUDIO_SAMPLE_BUFFER * sizeof(int16_t), 0x80); - audioRight = linearMemAlign(AUDIO_SAMPLE_BUFFER * sizeof(int16_t), 0x80); - } - gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, true); if (!_initGpu()) { @@ -865,9 +909,21 @@ "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, @@ -879,9 +935,17 @@ .unpaused = _gameLoaded, .incrementScreenMode = _incrementScreenMode, .setFrameLimiter = _setFrameLimiter, - .pollGameInput = _pollGameInput + .pollGameInput = _pollGameInput, + .running = _running }; + runner.autosave.running = true; + MutexInit(&runner.autosave.mutex); + ConditionInit(&runner.autosave.cond); + + APT_SetAppCpuTimeLimit(20); + runner.autosave.thread = threadCreate(mGUIAutosaveThread, &runner.autosave, 0x4000, 0x1F, 1, true); + mGUIInit(&runner, "3ds"); _map3DSKey(&runner.params.keyMap, KEY_X, GUI_INPUT_CANCEL); diff -Nru mgba-0.6.3+dfsg1/src/platform/example/client-server/client.c mgba-0.7.0/src/platform/example/client-server/client.c --- mgba-0.6.3+dfsg1/src/platform/example/client-server/client.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/example/client-server/client.c 2019-01-27 00:06:06.000000000 +0000 @@ -29,19 +29,19 @@ SocketRecv(server, &bpp, sizeof(bpp)); width = ntohl(width); height = ntohl(height); - if (ntohl(bpp) != BYTES_PER_PIXEL) { + bpp = ntohl(bpp); + ssize_t bufferSize = width * height * bpp; + +#if !SDL_VERSION_ATLEAST(2, 0, 0) + if (bpp == 2) { + SDL_SetVideoMode(width, height, 16, SDL_DOUBLEBUF | SDL_HWSURFACE); + } else if (bpp == 4) { + SDL_SetVideoMode(width, height, 32, SDL_DOUBLEBUF | SDL_HWSURFACE); + } else { SocketClose(server); SocketSubsystemDeinit(); return 1; } - ssize_t bufferSize = width * height * BYTES_PER_PIXEL; - -#if !SDL_VERSION_ATLEAST(2, 0, 0) -#ifdef COLOR_16_BIT - SDL_SetVideoMode(width, height, 16, SDL_DOUBLEBUF | SDL_HWSURFACE); -#else - SDL_SetVideoMode(width, height, 32, SDL_DOUBLEBUF | SDL_HWSURFACE); -#endif #endif #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -49,15 +49,16 @@ SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); Uint32 pixfmt; -#ifdef COLOR_16_BIT -#ifdef COLOR_5_6_5 - pixfmt = SDL_PIXELFORMAT_RGB565; -#else - pixfmt = SDL_PIXELFORMAT_ABGR1555; -#endif -#else - pixfmt = SDL_PIXELFORMAT_ABGR8888; -#endif + if (bpp == 2) { + pixfmt = SDL_PIXELFORMAT_RGB565; + } else if (bpp == 4) { + pixfmt = SDL_PIXELFORMAT_ABGR8888; + } else { + SocketClose(server); + SocketSubsystemDeinit(); + return 1; + } + SDL_Texture* sdlTex = SDL_CreateTexture(renderer, pixfmt, SDL_TEXTUREACCESS_STREAMING, width, height); #endif diff -Nru mgba-0.6.3+dfsg1/src/platform/libretro/libretro.c mgba-0.7.0/src/platform/libretro/libretro.c --- mgba-0.6.3+dfsg1/src/platform/libretro/libretro.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/libretro/libretro.c 2019-01-27 00:06:06.000000000 +0000 @@ -11,17 +11,18 @@ #include #include #include +#include #include #ifdef M_CORE_GB #include #include +#include #endif #ifdef M_CORE_GBA #include #include #include #endif -#include #include #include @@ -42,6 +43,10 @@ static void _setRumble(struct mRumble* rumble, int enable); static uint8_t _readLux(struct GBALuminanceSource* lux); static void _updateLux(struct GBALuminanceSource* lux); +static void _updateCamera(const uint32_t* buffer, unsigned width, unsigned height, size_t pitch); +static void _startImage(struct mImageSource*, unsigned w, unsigned h, int colorFormats); +static void _stopImage(struct mImageSource*); +static void _requestImage(struct mImageSource*, const void** buffer, size_t* stride, enum mColorFormat* colorFormat); static struct mCore* core; static void* outputBuffer; @@ -49,12 +54,20 @@ static size_t dataSize; static void* savedata; static struct mAVStream stream; -static int rumbleLevel; -static struct CircleBuffer rumbleHistory; +static int rumbleUp; +static int rumbleDown; static struct mRumble rumble; static struct GBALuminanceSource lux; static int luxLevel; static struct mLogger logger; +static struct retro_camera_callback cam; +static struct mImageSource imageSource; +static uint32_t* camData = NULL; +static unsigned camWidth; +static unsigned camHeight; +static unsigned imcapWidth; +static unsigned imcapHeight; +static size_t camStride; static void _reloadSettings(void) { struct mCoreOptions opts = { @@ -63,6 +76,29 @@ }; struct retro_variable var; + enum GBModel model; + const char* modelName; + + var.key = "mgba_gb_model"; + var.value = 0; + if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "Game Boy") == 0) { + model = GB_MODEL_DMG; + } else if (strcmp(var.value, "Super Game Boy") == 0) { + model = GB_MODEL_SGB; + } else if (strcmp(var.value, "Game Boy Color") == 0) { + model = GB_MODEL_CGB; + } else if (strcmp(var.value, "Game Boy Advance") == 0) { + model = GB_MODEL_AGB; + } else { + model = GB_MODEL_AUTODETECT; + } + + modelName = GBModelToName(model); + mCoreConfigSetDefaultValue(&core->config, "gb.model", modelName); + mCoreConfigSetDefaultValue(&core->config, "sgb.model", modelName); + mCoreConfigSetDefaultValue(&core->config, "cgb.model", modelName); + } var.key = "mgba_use_bios"; var.value = 0; @@ -76,6 +112,16 @@ opts.skipBios = strcmp(var.value, "ON") == 0; } + var.key = "mgba_sgb_borders"; + var.value = 0; + if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "ON") == 0) { + mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", true); + } else { + mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", false); + } + } + var.key = "mgba_idle_optimization"; var.value = 0; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { @@ -88,6 +134,13 @@ } } + var.key = "mgba_frameskip"; + var.value = 0; + if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + opts.frameskip = strtol(var.value, NULL, 10); + + } + mCoreConfigLoadDefaults(&core->config, &opts); mCoreLoadConfig(core); } @@ -102,9 +155,12 @@ 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_gb_model", "Game Boy model (requires restart); Autodetect|Game Boy|Super Game Boy|Game Boy Color|Game Boy Advance" }, + { "mgba_use_bios", "Use BIOS file if found (requires restart); ON|OFF" }, + { "mgba_skip_bios", "Skip BIOS intro (requires restart); OFF|ON" }, + { "mgba_sgb_borders", "Use Super Game Boy borders (requires restart); ON|OFF" }, { "mgba_idle_optimization", "Idle loop removal; Remove Known|Detect and Remove|Don't Remove" }, + { "mgba_frameskip", "Frameskip; 0|1|2|3|4|5|6|7|8|9|10" }, { 0, 0 } }; @@ -144,8 +200,17 @@ core->desiredVideoDimensions(core, &width, &height); info->geometry.base_width = width; info->geometry.base_height = height; - info->geometry.max_width = width; - info->geometry.max_height = height; +#ifdef M_CORE_GB + if (core->platform(core) == PLATFORM_GB) { + info->geometry.max_width = 256; + info->geometry.max_height = 224; + } else +#endif + { + info->geometry.max_width = width; + info->geometry.max_height = height; + } + info->geometry.aspect_ratio = width / (double) height; info->timing.fps = core->frequency(core) / (float) core->frameCycles(core); info->timing.sample_rate = 32768; @@ -188,7 +253,6 @@ struct retro_rumble_interface rumbleInterface; if (environCallback(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumbleInterface)) { rumbleCallback = rumbleInterface.set_rumble_state; - CircleBufferInit(&rumbleHistory, RUMBLE_PWM); rumble.setRumble = _setRumble; } else { rumbleCallback = 0; @@ -212,6 +276,10 @@ stream.postAudioFrame = 0; stream.postAudioBuffer = _postAudioBuffer; stream.postVideoFrame = 0; + + imageSource.startRequestImage = _startImage; + imageSource.stopRequestImage = _stopImage; + imageSource.requestImage = _requestImage; } void retro_deinit(void) { @@ -222,16 +290,22 @@ uint16_t keys; inputPollCallback(); - struct retro_variable var = { - .key = "mgba_allow_opposing_directions", - .value = 0 - }; - bool updated = false; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) { + struct retro_variable var = { + .key = "mgba_allow_opposing_directions", + .value = 0 + }; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { ((struct GBA*) core->board)->allowOpposingDirections = strcmp(var.value, "yes") == 0; } + + var.key = "mgba_frameskip"; + var.value = 0; + if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + mCoreConfigSetUIntValue(&core->config, "frameskip", strtol(var.value, NULL, 10)); + mCoreLoadConfig(core); + } } keys = 0; @@ -271,9 +345,21 @@ unsigned width, height; core->desiredVideoDimensions(core, &width, &height); videoCallback(outputBuffer, width, height, BYTES_PER_PIXEL * 256); + + if (rumbleCallback) { + if (rumbleUp) { + rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); + rumbleCallback(0, RETRO_RUMBLE_WEAK, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); + } else { + rumbleCallback(0, RETRO_RUMBLE_STRONG, 0); + rumbleCallback(0, RETRO_RUMBLE_WEAK, 0); + } + rumbleUp = 0; + rumbleDown = 0; + } } -void static _setupMaps(struct mCore* core) { +static void _setupMaps(struct mCore* core) { #ifdef M_CORE_GBA if (core->platform(core) == PLATFORM_GBA) { struct GBA* gba = core->board; @@ -361,9 +447,8 @@ core->reset(core); _setupMaps(core); - if (rumbleCallback) { - CircleBufferClear(&rumbleHistory); - } + rumbleUp = 0; + rumbleDown = 0; } bool retro_load_game(const struct retro_game_info* game) { @@ -391,7 +476,9 @@ core->init(core); core->setAVStream(core, &stream); - outputBuffer = malloc(256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); + size_t size = 256 * 224 * BYTES_PER_PIXEL; + outputBuffer = malloc(size); + memset(outputBuffer, 0xFF, size); core->setVideoBuffer(core, outputBuffer, 256); core->setAudioBufferSize(core, SAMPLES); @@ -408,22 +495,62 @@ core->loadROM(core, rom); core->loadSave(core, save); + const char* sysDir = 0; + const char* biosName = 0; + char biosPath[PATH_MAX]; + environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir); + #ifdef M_CORE_GBA if (core->platform(core) == PLATFORM_GBA) { core->setPeripheral(core, mPERIPH_GBA_LUMINANCE, &lux); + biosName = "gba_bios.bin"; - const char* sysDir = 0; - if (core->opts.useBios && environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir)) { - char biosPath[PATH_MAX]; - snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, "gba_bios.bin"); - struct VFile* bios = VFileOpen(biosPath, O_RDONLY); - if (bios) { - core->loadBIOS(core, bios, 0); - } + } +#endif + +#ifdef M_CORE_GB + if (core->platform(core) == PLATFORM_GB) { + memset(&cam, 0, sizeof(cam)); + cam.height = GBCAM_HEIGHT; + cam.width = GBCAM_WIDTH; + cam.caps = 1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER; + cam.frame_raw_framebuffer = _updateCamera; + core->setPeripheral(core, mPERIPH_IMAGE_SOURCE, &imageSource); + + environCallback(RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE, &cam); + const char* modelName = mCoreConfigGetValue(&core->config, "gb.model"); + struct GB* gb = core->board; + + if (modelName) { + gb->model = GBNameToModel(modelName); + } else { + GBDetectModel(gb); + } + + switch (gb->model) { + case GB_MODEL_AGB: + case GB_MODEL_CGB: + biosName = "gbc_bios.bin"; + break; + case GB_MODEL_SGB: + biosName = "sgb_bios.bin"; + break; + case GB_MODEL_DMG: + default: + biosName = "gb_bios.bin"; + break; } } #endif + if (core->opts.useBios && sysDir && biosName) { + snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, biosName); + struct VFile* bios = VFileOpen(biosPath, O_RDONLY); + if (bios) { + core->loadBIOS(core, bios, 0); + } + } + core->reset(core); _setupMaps(core); @@ -439,27 +566,36 @@ data = 0; mappedMemoryFree(savedata, SIZE_CART_FLASH1M); savedata = 0; - CircleBufferDeinit(&rumbleHistory); } size_t retro_serialize_size(void) { - return core->stateSize(core); + struct VFile* vfm = VFileMemChunk(NULL, 0); + mCoreSaveStateNamed(core, vfm, SAVESTATE_SAVEDATA | SAVESTATE_RTC); + size_t size = vfm->size(vfm); + vfm->close(vfm); + return size; } bool retro_serialize(void* data, size_t size) { - if (size != retro_serialize_size()) { + struct VFile* vfm = VFileMemChunk(NULL, 0); + mCoreSaveStateNamed(core, vfm, SAVESTATE_SAVEDATA | SAVESTATE_RTC); + if ((ssize_t) size > vfm->size(vfm)) { + size = vfm->size(vfm); + } else if ((ssize_t) size < vfm->size(vfm)) { + vfm->close(vfm); return false; } - core->saveState(core, data); + vfm->seek(vfm, 0, SEEK_SET); + vfm->read(vfm, data, size); + vfm->close(vfm); return true; } bool retro_unserialize(const void* data, size_t size) { - if (size != retro_serialize_size()) { - return false; - } - core->loadState(core, data); - return true; + struct VFile* vfm = VFileFromConstMemory(data, size); + bool success = mCoreLoadStateNamed(core, vfm, SAVESTATE_RTC); + vfm->close(vfm); + return success; } void retro_cheat_reset(void) { @@ -477,24 +613,50 @@ cheatSet = device->createSet(device, NULL); mCheatAddSet(device, cheatSet); } - // Convert the super wonky unportable libretro format to something normal - char realCode[] = "XXXXXXXX XXXXXXXX"; - size_t len = strlen(code) + 1; // Include null terminator - size_t i, pos; - for (i = 0, pos = 0; i < len; ++i) { - if (isspace((int) code[i]) || code[i] == '+') { - realCode[pos] = ' '; - } else { - realCode[pos] = code[i]; +// Convert the super wonky unportable libretro format to something normal +#ifdef M_CORE_GBA + if (core->platform(core) == PLATFORM_GBA) { + char realCode[] = "XXXXXXXX XXXXXXXX"; + size_t len = strlen(code) + 1; // Include null terminator + size_t i, pos; + for (i = 0, pos = 0; i < len; ++i) { + if (isspace((int) code[i]) || code[i] == '+') { + realCode[pos] = ' '; + } else { + realCode[pos] = code[i]; + } + if ((pos == 13 && (realCode[pos] == ' ' || !realCode[pos])) || pos == 17) { + realCode[pos] = '\0'; + mCheatAddLine(cheatSet, realCode, 0); + pos = 0; + continue; + } + ++pos; } - if ((pos == 13 && (realCode[pos] == ' ' || !realCode[pos])) || pos == 17) { - realCode[pos] = '\0'; - mCheatAddLine(cheatSet, realCode, 0); - pos = 0; - continue; + } +#endif +#ifdef M_CORE_GB + if (core->platform(core) == PLATFORM_GB) { + char realCode[] = "XXX-XXX-XXX"; + size_t len = strlen(code) + 1; // Include null terminator + size_t i, pos; + for (i = 0, pos = 0; i < len; ++i) { + if (isspace((int) code[i]) || code[i] == '+') { + realCode[pos] = '\0'; + } else { + realCode[pos] = code[i]; + } + if (pos == 11 || !realCode[pos]) { + realCode[pos] = '\0'; + mCheatAddLine(cheatSet, realCode, 0); + pos = 0; + continue; + } + ++pos; } - ++pos; } +#endif + cheatSet->refresh(cheatSet, device); } unsigned retro_get_region(void) { @@ -601,15 +763,11 @@ if (!rumbleCallback) { return; } - rumbleLevel += enable; - if (CircleBufferSize(&rumbleHistory) == RUMBLE_PWM) { - int8_t oldLevel; - CircleBufferRead8(&rumbleHistory, &oldLevel); - rumbleLevel -= oldLevel; - } - CircleBufferWrite8(&rumbleHistory, enable); - rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleLevel * 0xFFFF / RUMBLE_PWM); - rumbleCallback(0, RETRO_RUMBLE_WEAK, rumbleLevel * 0xFFFF / RUMBLE_PWM); + if (enable) { + ++rumbleUp; + } else { + ++rumbleDown; + } } static void _updateLux(struct GBALuminanceSource* lux) { @@ -648,3 +806,66 @@ } return 0xFF - value; } + +static void _updateCamera(const uint32_t* buffer, unsigned width, unsigned height, size_t pitch) { + if (!camData || width > camWidth || height > camHeight) { + if (camData) { + free(camData); + } + unsigned bufPitch = pitch / sizeof(*buffer); + unsigned bufHeight = height; + if (imcapWidth > bufPitch) { + bufPitch = imcapWidth; + } + if (imcapHeight > bufHeight) { + bufHeight = imcapHeight; + } + camData = malloc(sizeof(*buffer) * bufHeight * bufPitch); + memset(camData, 0xFF, sizeof(*buffer) * bufHeight * bufPitch); + camWidth = width; + camHeight = bufHeight; + camStride = bufPitch; + } + size_t i; + for (i = 0; i < height; ++i) { + memcpy(&camData[camStride * i], &buffer[pitch * i / sizeof(*buffer)], pitch); + } +} + +static void _startImage(struct mImageSource* image, unsigned w, unsigned h, int colorFormats) { + UNUSED(image); + UNUSED(colorFormats); + + if (camData) { + free(camData); + } + camData = NULL; + imcapWidth = w; + imcapHeight = h; + cam.start(); +} + +static void _stopImage(struct mImageSource* image) { + UNUSED(image); + cam.stop(); +} + +static void _requestImage(struct mImageSource* image, const void** buffer, size_t* stride, enum mColorFormat* colorFormat) { + UNUSED(image); + if (!camData) { + cam.start(); + *buffer = NULL; + return; + } + size_t offset = 0; + if (imcapWidth < camWidth) { + offset += (camWidth - imcapWidth) / 2; + } + if (imcapHeight < camHeight) { + offset += (camHeight - imcapHeight) / 2 * camStride; + } + + *buffer = &camData[offset]; + *stride = camStride; + *colorFormat = mCOLOR_XRGB8; +} diff -Nru mgba-0.6.3+dfsg1/src/platform/openemu/mGBAGameCore.m mgba-0.7.0/src/platform/openemu/mGBAGameCore.m --- mgba-0.6.3+dfsg1/src/platform/openemu/mGBAGameCore.m 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/openemu/mGBAGameCore.m 2019-01-27 00:06:06.000000000 +0000 @@ -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 -Nru mgba-0.6.3+dfsg1/src/platform/opengl/gles2.c mgba-0.7.0/src/platform/opengl/gles2.c --- mgba-0.6.3+dfsg1/src/platform/opengl/gles2.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/opengl/gles2.c 2019-01-27 00:06:06.000000000 +0000 @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -192,13 +193,6 @@ 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; @@ -224,6 +218,14 @@ 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 -Nru mgba-0.6.3+dfsg1/src/platform/psp2/CMakeLists.txt mgba-0.7.0/src/platform/psp2/CMakeLists.txt --- mgba-0.6.3+dfsg1/src/platform/psp2/CMakeLists.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/psp2/CMakeLists.txt 2019-01-27 00:06:06.000000000 +0000 @@ -17,6 +17,7 @@ -lSceAppMgr_stub -lSceAppUtil_stub -lSceAudio_stub + -lSceCamera_stub -lSceCommonDialog_stub -lSceCtrl_stub -lSceDisplay_stub @@ -60,4 +61,5 @@ FILE ${CMAKE_CURRENT_SOURCE_DIR}/startup.png sce_sys/livearea/contents/startup.png FILE ${CMAKE_CURRENT_BINARY_DIR}/template.xml sce_sys/livearea/contents/template.xml) +install(TARGETS ${BINARY_NAME}.elf DESTINATION . COMPONENT ${BINARY_NAME}-dbg) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.vpk DESTINATION . COMPONENT ${BINARY_NAME}-psp2) diff -Nru mgba-0.6.3+dfsg1/src/platform/psp2/main.c mgba-0.7.0/src/platform/psp2/main.c --- mgba-0.6.3+dfsg1/src/platform/psp2/main.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/psp2/main.c 2019-01-27 00:06:06.000000000 +0000 @@ -25,18 +25,18 @@ #include static void _drawStart(void) { - vita2d_set_vblank_wait(false); + static int vcount = 0; + extern bool frameLimiter; + int oldVCount = vcount; + vcount = sceDisplayGetVcount(); + vita2d_set_vblank_wait(frameLimiter && vcount + 1 >= oldVCount); vita2d_start_drawing(); vita2d_clear_screen(); } static void _drawEnd(void) { - static int vcount = 0; - extern bool frameLimiter; - int oldVCount = vcount; vita2d_end_drawing(); - vcount = sceDisplayGetVcount(); - vita2d_set_vblank_wait(frameLimiter && vcount + 1 >= oldVCount); + vita2d_wait_rendering_done(); vita2d_swap_buffers(); } @@ -89,7 +89,8 @@ struct mGUIRunner runner = { .params = { PSP2_HORIZONTAL_PIXELS, PSP2_VERTICAL_PIXELS, - font, "ux0:data", _drawStart, _drawEnd, + font, "", + _drawStart, _drawEnd, _pollInput, _pollCursor, _batteryState, 0, 0, @@ -107,6 +108,18 @@ "Fit Aspect Ratio", }, .nStates = 4 + }, + { + .title = "Camera", + .data = "camera", + .submenu = 0, + .state = 1, + .validStates = (const char*[]) { + "None", + "Front", + "Back", + }, + .nStates = 3 } }, .keySources = (struct GUIInputKeys[]) { @@ -135,7 +148,7 @@ }, { .id = 0 } }, - .nConfigExtra = 1, + .nConfigExtra = 2, .setup = mPSP2Setup, .teardown = mPSP2Teardown, .gameLoaded = mPSP2LoadROM, diff -Nru mgba-0.6.3+dfsg1/src/platform/psp2/psp2-context.c mgba-0.7.0/src/platform/psp2/psp2-context.c --- mgba-0.6.3+dfsg1/src/platform/psp2/psp2-context.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/psp2/psp2-context.c 2019-01-27 00:06:06.000000000 +0000 @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #define RUMBLE_PWM 8 +#define CDRAM_ALIGN 0x40000 static enum ScreenMode { SM_BACKDROP, @@ -48,16 +50,26 @@ 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; + static struct mAVStream stream; bool frameLimiter = true; @@ -85,18 +97,23 @@ static THREAD_ENTRY _audioThread(void* context) { struct mPSP2AudioContext* audio = (struct mPSP2AudioContext*) context; uint32_t zeroBuffer[PSP2_SAMPLES] = {0}; + void* buffer = zeroBuffer; int audioPort = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, PSP2_SAMPLES, 48000, SCE_AUDIO_OUT_MODE_STEREO); while (audio->running) { MutexLock(&audio->mutex); - void* buffer; + if (buffer != zeroBuffer) { + // Can only happen in successive iterations + audio->samples -= PSP2_SAMPLES; + ConditionWake(&audio->cond); + } if (audio->samples >= PSP2_SAMPLES) { buffer = &audio->buffer[audio->readOffset]; - audio->samples -= PSP2_SAMPLES; audio->readOffset += PSP2_SAMPLES; if (audio->readOffset >= PSP2_AUDIO_BUFFER_SIZE) { audio->readOffset = 0; } - ConditionWake(&audio->cond); + // Don't mark samples as read until the next loop iteration to prevent + // writing to the buffer while being read (see above) } else { buffer = zeroBuffer; } @@ -146,11 +163,83 @@ 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); +} + static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { UNUSED(stream); MutexLock(&audioContext.mutex); - struct GBAStereoSample* samples = &audioContext.buffer[audioContext.writeOffset]; - while (audioContext.samples == PSP2_AUDIO_BUFFER_SIZE) { + while (audioContext.samples + PSP2_SAMPLES >= PSP2_AUDIO_BUFFER_SIZE) { if (!frameLimiter) { blip_clear(left); blip_clear(right); @@ -159,6 +248,7 @@ } ConditionWait(&audioContext.cond, &audioContext.mutex); } + struct GBAStereoSample* samples = &audioContext.buffer[audioContext.writeOffset]; blip_read_samples(left, &samples[0].left, PSP2_SAMPLES, true); blip_read_samples(right, &samples[0].right, PSP2_SAMPLES, true); audioContext.samples += PSP2_SAMPLES; @@ -195,6 +285,13 @@ void mPSP2SetFrameLimiter(struct mGUIRunner* runner, bool limit) { UNUSED(runner); + if (!frameLimiter && limit) { + MutexLock(&audioContext.mutex); + while (audioContext.samples) { + ConditionWait(&audioContext.cond, &audioContext.mutex); + } + MutexUnlock(&audioContext.mutex); + } frameLimiter = limit; } @@ -237,6 +334,14 @@ 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); + + stream.videoDimensionsChanged = NULL; stream.postAudioFrame = NULL; stream.postAudioBuffer = _postAudioBuffer; @@ -250,6 +355,9 @@ 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) { @@ -307,6 +415,8 @@ default: break; } + audioContext.running = false; + ThreadJoin(audioThread); } void mPSP2Paused(struct mGUIRunner* runner) { @@ -324,6 +434,19 @@ 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 -Nru mgba-0.6.3+dfsg1/src/platform/psp2/sce-vfs.c mgba-0.7.0/src/platform/psp2/sce-vfs.c --- mgba-0.6.3+dfsg1/src/platform/psp2/sce-vfs.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/psp2/sce-vfs.c 2019-01-27 00:06:06.000000000 +0000 @@ -52,6 +52,16 @@ static const char* _vdesceName(struct VDirEntry* vde); static enum VFSType _vdesceType(struct VDirEntry* vde); +static bool _vdlsceClose(struct VDir* vd); +static void _vdlsceRewind(struct VDir* vd); +static struct VDirEntry* _vdlsceListNext(struct VDir* vd); +static struct VFile* _vdlsceOpenFile(struct VDir* vd, const char* path, int mode); +static struct VDir* _vdlsceOpenDir(struct VDir* vd, const char* path); +static bool _vdlsceDeleteFile(struct VDir* vd, const char* path); + +static const char* _vdlesceName(struct VDirEntry* vde); +static enum VFSType _vdlesceType(struct VDirEntry* vde); + struct VFile* VFileOpenSce(const char* path, int flags, SceMode mode) { struct VFileSce* vfsce = malloc(sizeof(struct VFileSce)); if (!vfsce) { @@ -148,6 +158,10 @@ } struct VDir* VDirOpen(const char* path) { + if (!path || !path[0]) { + return VDeviceList(); + } + SceUID dir = sceIoDopen(path); if (dir < 0) { return 0; @@ -250,3 +264,96 @@ } return VFS_FILE; } + +struct VDirEntrySceDevList { + struct VDirEntry d; + ssize_t index; + const char* name; +}; + +struct VDirSceDevList { + struct VDir d; + struct VDirEntrySceDevList vde; +}; + +static const char* _devs[] = { + "ux0:", + "ur0:", + "uma0:" +}; + +struct VDir* VDeviceList() { + struct VDirSceDevList* vd = malloc(sizeof(struct VDirSceDevList)); + if (!vd) { + return 0; + } + + vd->d.close = _vdlsceClose; + vd->d.rewind = _vdlsceRewind; + vd->d.listNext = _vdlsceListNext; + vd->d.openFile = _vdlsceOpenFile; + vd->d.openDir = _vdlsceOpenDir; + vd->d.deleteFile = _vdlsceDeleteFile; + + vd->vde.d.name = _vdlesceName; + vd->vde.d.type = _vdlesceType; + vd->vde.index = -1; + vd->vde.name = 0; + + return &vd->d; +} + +static bool _vdlsceClose(struct VDir* vd) { + struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd; + free(vdl); + return true; +} + +static void _vdlsceRewind(struct VDir* vd) { + struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd; + vdl->vde.name = NULL; + vdl->vde.index = -1; +} + +static struct VDirEntry* _vdlsceListNext(struct VDir* vd) { + struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd; + while (vdl->vde.index < 3) { + ++vdl->vde.index; + vdl->vde.name = _devs[vdl->vde.index]; + SceUID dir = sceIoDopen(vdl->vde.name); + if (dir < 0) { + continue; + } + sceIoDclose(dir); + return &vdl->vde.d; + } + return 0; +} + +static struct VFile* _vdlsceOpenFile(struct VDir* vd, const char* path, int mode) { + UNUSED(vd); + UNUSED(path); + UNUSED(mode); + return NULL; +} + +static struct VDir* _vdlsceOpenDir(struct VDir* vd, const char* path) { + UNUSED(vd); + return VDirOpen(path); +} + +static bool _vdlsceDeleteFile(struct VDir* vd, const char* path) { + UNUSED(vd); + UNUSED(path); + return false; +} + +static const char* _vdlesceName(struct VDirEntry* vde) { + struct VDirEntrySceDevList* vdle = (struct VDirEntrySceDevList*) vde; + return vdle->name; +} + +static enum VFSType _vdlesceType(struct VDirEntry* vde) { + UNUSED(vde); + return VFS_DIRECTORY; +} diff -Nru mgba-0.6.3+dfsg1/src/platform/python/_builder.h mgba-0.7.0/src/platform/python/_builder.h --- mgba-0.6.3+dfsg1/src/platform/python/_builder.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/_builder.h 2019-01-27 00:06:06.000000000 +0000 @@ -1,5 +1,6 @@ #define COMMON_H #define PNG_H +#define OPAQUE_THREADING #define _SYS_TIME_H #define _SYS_TIME_H_ #define _TIME_H @@ -7,12 +8,20 @@ #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 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; @@ -23,16 +32,19 @@ void free(void*); #include -#undef const #include "flags.h" +#include +#include #include +#include #include -#include +#include #include #define PYEXPORT extern "Python+C" +#include "platform/python/core.h" #include "platform/python/log.h" #include "platform/python/sio.h" #include "platform/python/vfs-py.h" @@ -42,14 +54,19 @@ #include #endif #ifdef M_CORE_GBA +#include #include #include #include -#include +#include #endif #ifdef M_CORE_GB #include #include #include -#include +#include +#endif +#ifdef USE_DEBUGGERS +#include +#include #endif diff -Nru mgba-0.6.3+dfsg1/src/platform/python/_builder.py mgba-0.7.0/src/platform/python/_builder.py --- mgba-0.6.3+dfsg1/src/platform/python/_builder.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/_builder.py 2019-01-27 00:06:06.000000000 +0000 @@ -9,32 +9,41 @@ srcdir = os.path.join(pydir, "..", "..") incdir = os.path.join(pydir, "..", "..", "..", "include") bindir = os.environ.get("BINDIR", os.path.join(os.getcwd(), "..")) +libdir = os.environ.get("LIBDIR") cpp = shlex.split(os.environ.get("CPP", "cc -E")) cppflags = shlex.split(os.environ.get("CPPFLAGS", "")) -if __name__ == "__main__": - cppflags.extend(sys.argv[1:]) 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 +#include #include +#include #include #include -#include +#include #include #include -#include +#include #include #include #define PYEXPORT +#include "platform/python/core.h" #include "platform/python/log.h" #include "platform/python/sio.h" #include "platform/python/vfs-py.h" @@ -43,7 +52,8 @@ extra_compile_args=cppflags, libraries=["mgba"], library_dirs=[bindir], - sources=[os.path.join(pydir, path) for path in ["vfs-py.c", "log.c", "sio.c"]]) + runtime_library_dirs=[libdir], + sources=[os.path.join(pydir, path) for path in ["vfs-py.c", "core.c", "log.c", "sio.c"]]) preprocessed = subprocess.check_output(cpp + ["-fno-inline", "-P"] + cppflags + [os.path.join(pydir, "_builder.h")], universal_newlines=True) @@ -55,5 +65,92 @@ lines.append(line) ffi.cdef('\n'.join(lines)) +preprocessed = subprocess.check_output(cpp + ["-fno-inline", "-P"] + cppflags + [os.path.join(pydir, "lib.h")], universal_newlines=True) + +lines = [] +for line in preprocessed.splitlines(): + line = line.strip() + if line.startswith('#'): + continue + lines.append(line) +ffi.embedding_api('\n'.join(lines)) + +ffi.embedding_init_code(""" + import os, os.path + from mgba._pylib import ffi, lib + symbols = {} + globalSyms = { + 'symbols': symbols + } + pendingCode = [] + + @ffi.def_extern() + def mPythonSetDebugger(debugger): + from mgba.debugger import NativeDebugger, CLIDebugger + oldDebugger = globalSyms.get('debugger') + if oldDebugger and oldDebugger._native == debugger: + return + if oldDebugger and not debugger: + del globalSyms['debugger'] + return + if debugger.type == lib.DEBUGGER_CLI: + debugger = CLIDebugger(debugger) + else: + debugger = NativeDebugger(debugger) + globalSyms['debugger'] = debugger + + @ffi.def_extern() + def mPythonLoadScript(name, vf): + from mgba.vfs import VFile + vf = VFile(vf) + name = ffi.string(name) + source = vf.read_all().decode('utf-8') + try: + code = compile(source, name, 'exec') + pendingCode.append(code) + except: + return False + return True + + @ffi.def_extern() + def mPythonRunPending(): + global pendingCode + for code in pendingCode: + exec(code, globalSyms, {}) + pendingCode = [] + + @ffi.def_extern() + def mPythonDebuggerEntered(reason, info): + debugger = globalSyms['debugger'] + if not debugger: + return + if info == ffi.NULL: + info = None + for cb in debugger._cbs: + cb(reason, info) + + @ffi.def_extern() + def mPythonLookupSymbol(name, outptr): + name = ffi.string(name).decode('utf-8') + if name not in symbols: + return False + sym = symbols[name] + val = None + try: + val = int(sym) + except: + try: + val = sym() + except: + pass + if val is None: + return False + try: + outptr[0] = ffi.cast('int32_t', val) + return True + except: + return False +""") + if __name__ == "__main__": - ffi.compile() + ffi.emit_c_code("lib.c") diff -Nru mgba-0.6.3+dfsg1/src/platform/python/cinema/__init__.py mgba-0.7.0/src/platform/python/cinema/__init__.py --- mgba-0.6.3+dfsg1/src/platform/python/cinema/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/cinema/__init__.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,24 @@ +from PIL.ImageChops import difference +from PIL.ImageOps import autocontrast +from PIL.Image import open as PIOpen + + +class VideoFrame(object): + def __init__(self, pil_image): + self.image = pil_image.convert('RGB') + + @staticmethod + def diff(a, b): + diff = difference(a.image, b.image) + diff_normalized = autocontrast(diff) + return (VideoFrame(diff), VideoFrame(diff_normalized)) + + @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 -Nru mgba-0.6.3+dfsg1/src/platform/python/cinema/movie.py mgba-0.7.0/src/platform/python/cinema/movie.py --- mgba-0.6.3+dfsg1/src/platform/python/cinema/movie.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/cinema/movie.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,41 @@ +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.framebuffer = Image(*core.desired_video_dimensions()) + self.core.set_video_buffer(self.framebuffer) + self._video_fifo = [] + + def yield_frames(self, skip=0, limit=None): + self.core.reset() + skip = (skip or 0) + 1 + while skip > 0: + frame = self.core.frame_counter + self.core.run_frame() + skip -= 1 + while frame <= self.core.frame_counter and limit != 0: + self._video_fifo.append(VideoFrame(self.framebuffer.to_pil())) + yield frame + frame = self.core.frame_counter + self.core.run_frame() + if limit is not None: + assert limit >= 0 + limit -= 1 + + def video(self, generator=None, **kwargs): + if not generator: + generator = self.yield_frames(**kwargs) + try: + while True: + if self._video_fifo: + yield self._video_fifo.pop(0) + else: + next(generator) + except StopIteration: + return diff -Nru mgba-0.6.3+dfsg1/src/platform/python/cinema/test.py mgba-0.7.0/src/platform/python/cinema/test.py --- mgba-0.6.3+dfsg1/src/platform/python/cinema/test.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/cinema/test.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,101 @@ +import os +import os.path +import mgba.core +import 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 dict_merge + + +class CinemaTest(object): + TEST = 'test.(mvl|gb|gba|nds)' + + def __init__(self, path, root, settings={}): + self.full_path = path or [] + self.path = os.path.abspath(os.path.join(root, *self.full_path)) + self.root = root + self.name = '.'.join(path) + self.settings = settings + try: + with open(os.path.join(self.path, 'manifest.yml'), 'r') as f: + dict_merge(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.load_path(results[0]) + if 'config' in self.settings: + self.config = mgba.core.Config(defaults=self.settings['config']) + self.core.load_config(self.config) + self.core.reset() + + def add_test(self, name, cls=None, settings={}): + cls = cls or self.__class__ + new_settings = deepcopy(self.settings) + dict_merge(new_settings, settings) + self.tests[name] = cls(self.full_path + [name], self.root, new_settings) + return self.tests[name] + + def output_settings(self): + output_settings = {} + if 'frames' in self.settings: + output_settings['limit'] = self.settings['frames'] + if 'skip' in self.settings: + output_settings['skip'] = self.settings['skip'] + return output_settings + + 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 generate_frames(self): + for i, frame in zip(itertools.count(), self.tracer.video(**self.output_settings())): + 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.generate_frames()) + assert not any(any(diffs[0].image.convert("L").point(bool).getdata()) for diffs in self.diffs) + + def generate_baseline(self): + for i, frame in zip(itertools.count(), self.tracer.video(**self.output_settings())): + frame.save(os.path.join(self.path, self.BASELINE % i)) + + +def gather_tests(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:] + test_path = suffix.split(os.sep) + test_root = tests + for component in test_path[:-1]: + new_test = test_root.tests.get(component) + if not new_test: + new_test = test_root.add_test(component) + test_root = new_test + test_root.add_test(test_path[-1], VideoTest) + return tests diff -Nru mgba-0.6.3+dfsg1/src/platform/python/cinema/util.py mgba-0.7.0/src/platform/python/cinema/util.py --- mgba-0.6.3+dfsg1/src/platform/python/cinema/util.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/cinema/util.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,9 @@ +def dict_merge(a, b): + for key, value in b.items(): + if isinstance(value, dict): + if key in a: + dict_merge(a[key], value) + else: + a[key] = dict(value) + else: + a[key] = value diff -Nru mgba-0.6.3+dfsg1/src/platform/python/CMakeLists.txt mgba-0.7.0/src/platform/python/CMakeLists.txt --- mgba-0.6.3+dfsg1/src/platform/python/CMakeLists.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/CMakeLists.txt 2019-01-27 00:06:06.000000000 +0000 @@ -1,17 +1,70 @@ -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) +set(INCLUDE_FLAGS_STR "") foreach(DIR IN LISTS INCLUDE_DIRECTORIES) - list(APPEND INCLUDE_FLAGS "-I${DIR}") + list(APPEND INCLUDE_FLAGS "-I${DIR}") + set(INCLUDE_FLAGS_STR "${INCLUDE_FLAGS_STR} \"-I${DIR}\"") endforeach() -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 ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py) +file(GLOB PYTHON_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) -add_custom_target(${BINARY_NAME}-py ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/build/lib/${BINARY_NAME}/__init__.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) + +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}") + +add_custom_target(${BINARY_NAME}-py ALL + COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. LIBDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON_EXECUTABLE} setup.py build -b ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${BINARY_NAME} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/setup.py + DEPENDS ${PYTHON_HEADERS} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py + DEPENDS ${BINARY_NAME}-pylib) + +add_custom_target(${BINARY_NAME}-py-install + COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. LIBDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON_EXECUTABLE} setup.py install -b ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${BINARY_NAME}-py) + +add_custom_target(${BINARY_NAME}-py-develop + COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. LIBDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON_EXECUTABLE} setup.py develop -b ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${BINARY_NAME}-py) + +add_custom_target(${BINARY_NAME}-py-bdist + COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. LIBDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON_EXECUTABLE} setup.py bdist_wheel -b ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${BINARY_NAME}-py) + +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(NAME python-${TEST_NAME} + COMMAND ${PYTHON_EXECUTABLE} setup.py build -b ${CMAKE_CURRENT_BINARY_DIR} pytest --extras --addopts ${TEST} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + set_tests_properties(python-${TEST_NAME} PROPERTIES ENVIRONMENT "${PATH}=${CMAKE_CURRENT_BINARY_DIR}/..;BINDIR=${CMAKE_CURRENT_BINARY_DIR}/..;LIBDIR=${CMAKE_CURRENT_BINARY_DIR}/..;CPPFLAGS=${INCLUDE_FLAGS_STR}") +endforeach() diff -Nru mgba-0.6.3+dfsg1/src/platform/python/conftest.py mgba-0.7.0/src/platform/python/conftest.py --- mgba-0.6.3+dfsg1/src/platform/python/conftest.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/conftest.py 2019-01-27 00:06:06.000000000 +0000 @@ -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.full_path) + 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 -Nru mgba-0.6.3+dfsg1/src/platform/python/core.c mgba-0.7.0/src/platform/python/core.c --- mgba-0.6.3+dfsg1/src/platform/python/core.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/core.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,19 @@ +/* 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 "core.h" + +#include + +struct mCoreCallbacks* mCorePythonCallbackCreate(void* pyobj) { + struct mCoreCallbacks* callbacks = malloc(sizeof(*callbacks)); + callbacks->videoFrameStarted = _mCorePythonCallbacksVideoFrameStarted; + callbacks->videoFrameEnded = _mCorePythonCallbacksVideoFrameEnded; + callbacks->coreCrashed = _mCorePythonCallbacksCoreCrashed; + callbacks->sleep = _mCorePythonCallbacksSleep; + + callbacks->context = pyobj; + return callbacks; +} diff -Nru mgba-0.6.3+dfsg1/src/platform/python/core.h mgba-0.7.0/src/platform/python/core.h --- mgba-0.6.3+dfsg1/src/platform/python/core.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/core.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,15 @@ +/* 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 "pycommon.h" + +struct mCoreCallbacks* mCorePythonCallbackCreate(void* pyobj); + +PYEXPORT void _mCorePythonCallbacksVideoFrameStarted(void* user); +PYEXPORT void _mCorePythonCallbacksVideoFrameEnded(void* user); +PYEXPORT void _mCorePythonCallbacksCoreCrashed(void* user); +PYEXPORT void _mCorePythonCallbacksSleep(void* user); diff -Nru mgba-0.6.3+dfsg1/src/platform/python/engine.c mgba-0.7.0/src/platform/python/engine.c --- mgba-0.6.3+dfsg1/src/platform/python/engine.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/engine.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,112 @@ +/* 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 "engine.h" + +#include +#include +#include + +#ifdef USE_DEBUGGERS +#include +#endif + +#include "lib.h" + +static const char* mPythonScriptEngineName(struct mScriptEngine*); +static bool mPythonScriptEngineInit(struct mScriptEngine*, struct mScriptBridge*); +static void mPythonScriptEngineDeinit(struct mScriptEngine*); +static bool mPythonScriptEngineIsScript(struct mScriptEngine*, const char* name, struct VFile* vf); +static bool mPythonScriptEngineLoadScript(struct mScriptEngine*, const char* name, struct VFile* vf); +static void mPythonScriptEngineRun(struct mScriptEngine*); +static bool mPythonScriptEngineLookupSymbol(struct mScriptEngine*, const char* name, int32_t* out); + +#ifdef USE_DEBUGGERS +static void mPythonScriptDebuggerEntered(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); +#endif + +struct mPythonScriptEngine { + struct mScriptEngine d; + struct mScriptBridge* sb; +}; + +struct mPythonScriptEngine* mPythonCreateScriptEngine(void) { + struct mPythonScriptEngine* engine = malloc(sizeof(*engine)); + engine->d.name = mPythonScriptEngineName; + engine->d.init = mPythonScriptEngineInit; + engine->d.deinit = mPythonScriptEngineDeinit; + engine->d.isScript = mPythonScriptEngineIsScript; + engine->d.loadScript = mPythonScriptEngineLoadScript; + engine->d.run = mPythonScriptEngineRun; + engine->d.lookupSymbol = mPythonScriptEngineLookupSymbol; +#ifdef USE_DEBUGGERS + engine->d.debuggerEntered = mPythonScriptDebuggerEntered; +#endif + engine->sb = NULL; + return engine; +} + +void mPythonSetup(struct mScriptBridge* sb) { + struct mPythonScriptEngine* se = mPythonCreateScriptEngine(); + mScriptBridgeInstallEngine(sb, &se->d); +} + +const char* mPythonScriptEngineName(struct mScriptEngine* se) { + UNUSED(se); + return "python"; +} + +bool mPythonScriptEngineInit(struct mScriptEngine* se, struct mScriptBridge* sb) { + struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se; + engine->sb = sb; + return true; +} + +void mPythonScriptEngineDeinit(struct mScriptEngine* se) { + free(se); +} + +bool mPythonScriptEngineIsScript(struct mScriptEngine* se, const char* name, struct VFile* vf) { + UNUSED(se); + UNUSED(vf); + return endswith(name, ".py"); +} + +bool mPythonScriptEngineLoadScript(struct mScriptEngine* se, const char* name, struct VFile* vf) { + UNUSED(se); + return mPythonLoadScript(name, vf); +} + +void mPythonScriptEngineRun(struct mScriptEngine* se) { + struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se; + +#ifdef USE_DEBUGGERS + struct mDebugger* debugger = mScriptBridgeGetDebugger(engine->sb); + if (debugger) { + mPythonSetDebugger(debugger); + } +#endif + + mPythonRunPending(); +} + +bool mPythonScriptEngineLookupSymbol(struct mScriptEngine* se, const char* name, int32_t* out) { + UNUSED(se); + return mPythonLookupSymbol(name, out); +} + +#ifdef USE_DEBUGGERS +void mPythonScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { + struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se; + + struct mDebugger* debugger = mScriptBridgeGetDebugger(engine->sb); + if (!debugger) { + return; + } + + mPythonSetDebugger(debugger); + mPythonDebuggerEntered(reason, info); +} +#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/python/engine.h mgba-0.7.0/src/platform/python/engine.h --- mgba-0.6.3+dfsg1/src/platform/python/engine.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/engine.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,20 @@ +/* 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 PYTHON_ENGINE_H +#define PYTHON_ENGINE_H + +#include + +CXX_GUARD_START + +struct mScriptBridge; +struct mPythonScriptEngine; +struct mPythonScriptEngine* mPythonCreateScriptEngine(void); +void mPythonSetup(struct mScriptBridge* sb); + +CXX_GUARD_END + +#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/python/.gitignore mgba-0.7.0/src/platform/python/.gitignore --- mgba-0.6.3+dfsg1/src/platform/python/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/.gitignore 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,5 @@ +/build +/dist +.eggs +.cache +*.egg-info* diff -Nru mgba-0.6.3+dfsg1/src/platform/python/lib.h mgba-0.7.0/src/platform/python/lib.h --- mgba-0.6.3+dfsg1/src/platform/python/lib.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/lib.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,12 @@ +#include "flags.h" + +struct VFile; + +extern bool mPythonLoadScript(const char*, struct VFile*); +extern void mPythonRunPending(); +extern bool mPythonLookupSymbol(const char* name, int32_t* out); + +#ifdef USE_DEBUGGERS +extern void mPythonSetDebugger(struct mDebugger*); +extern void mPythonDebuggerEntered(enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); +#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/python/log.c mgba-0.7.0/src/platform/python/log.c --- mgba-0.6.3+dfsg1/src/platform/python/log.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/log.c 2019-01-27 00:06:06.000000000 +0000 @@ -3,14 +3,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include - -struct mLoggerPy { - struct mLogger d; - void* pyobj; -}; - -void _pyLog(void* logger, int category, enum mLogLevel level, const char* message); +#include "log.h" static void _pyLogShim(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { struct mLoggerPy* pylogger = (struct mLoggerPy*) logger; diff -Nru mgba-0.6.3+dfsg1/src/platform/python/log.h mgba-0.7.0/src/platform/python/log.h --- mgba-0.6.3+dfsg1/src/platform/python/log.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/log.h 2019-01-27 00:06:06.000000000 +0000 @@ -5,6 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include "pycommon.h" + struct mLoggerPy { struct mLogger d; void* pyobj; diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/arm.py mgba-0.7.0/src/platform/python/mgba/arm.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/arm.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/arm.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,21 +3,23 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -from ._pylib import ffi, lib +from ._pylib import ffi, lib # pylint: disable=no-name-in-module + class _ARMRegisters: def __init__(self, cpu): self._cpu = cpu - def __getitem__(self, r): - if r > lib.ARM_PC: + def __getitem__(self, reg): + if reg > lib.ARM_PC: raise IndexError("Register out of range") - return self._cpu._native.gprs[r] + return self._cpu._native.gprs[reg] - def __setitem__(self, r, value): - if r >= lib.ARM_PC: + def __setitem__(self, reg, value): + if reg >= lib.ARM_PC: raise IndexError("Register out of range") - self._cpu._native.gprs[r] = value + self._cpu._native.gprs[reg] = value + class ARMCore: def __init__(self, native): @@ -25,4 +27,3 @@ self.gprs = _ARMRegisters(self) self.cpsr = self._native.cpsr self.spsr = self._native.spsr - diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/audio.py mgba-0.7.0/src/platform/python/mgba/audio.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/audio.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/audio.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,57 @@ +# Copyright (c) 2013-2018 Jeffrey Pfau +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +from ._pylib import ffi, lib # pylint: disable=no-name-in-module + + +class Buffer(object): + def __init__(self, native, internal_rate): + self._native = native + self._internal_rate = internal_rate + + @property + def available(self): + return lib.blip_samples_avail(self._native) + + def set_rate(self, rate): + lib.blip_set_rates(self._native, self._internal_rate, rate) + + def read(self, samples): + buffer = ffi.new("short[%i]" % samples) + count = self.read_into(buffer, samples, 1, 0) + return buffer[:count] + + def read_into(self, buffer, samples, channels=1, interleave=0): + return lib.blip_read_samples(self._native, ffi.addressof(buffer, interleave), samples, channels == 2) + + def clear(self): + lib.blip_clear(self._native) + + +class StereoBuffer(object): + def __init__(self, left, right): + self._left = left + self._right = right + + @property + def available(self): + return min(self._left.available, self._right.available) + + def set_rate(self, rate): + self._left.set_rate(rate) + self._right.set_rate(rate) + + def read(self, samples): + buffer = ffi.new("short[%i]" % (2 * samples)) + count = self.read_into(buffer, samples) + return buffer[0:2 * count] + + def read_into(self, buffer, samples): + samples = self._left.read_into(buffer, samples, 2, 0) + return self._right.read_into(buffer, samples, 2, 1) + + def clear(self): + self._left.clear() + self._right.clear() diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/core.py mgba-0.7.0/src/platform/python/mgba/core.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/core.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/core.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,9 +3,11 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -from ._pylib import ffi, lib -from . import tile +from ._pylib import ffi, lib # pylint: disable=no-name-in-module +from . import tile, audio from cached_property import cached_property +from functools import wraps + def find(path): core = lib.mCoreFind(path.encode('UTF-8')) @@ -13,31 +15,96 @@ return None return Core._init(core) -def findVF(vf): - core = lib.mCoreFindVF(vf.handle) + +def find_vf(vfile): + core = lib.mCoreFindVF(vfile.handle) if core == ffi.NULL: return None return Core._init(core) -def loadPath(path): + +def load_path(path): core = find(path) - if not core or not core.loadFile(path): + if not core or not core.load_file(path): return None return core -def loadVF(vf): - core = findVF(vf) - if not core or not core.loadROM(vf): + +def load_vf(vfile): + core = find_vf(vfile) + if not core or not core.load_rom(vfile): return None return core -def needsReset(f): + +def needs_reset(func): + @wraps(func) def wrapper(self, *args, **kwargs): - if not self._wasReset: + if not self._was_reset: raise RuntimeError("Core must be reset first") - return f(self, *args, **kwargs) + return func(self, *args, **kwargs) + return wrapper + + +def protected(func): + @wraps(func) + def wrapper(self, *args, **kwargs): + if self._protected: + raise RuntimeError("Core is protected") + return func(self, *args, **kwargs) return wrapper + +@ffi.def_extern() +def _mCorePythonCallbacksVideoFrameStarted(user): # pylint: disable=invalid-name + context = ffi.from_handle(user) + context._video_frame_started() + + +@ffi.def_extern() +def _mCorePythonCallbacksVideoFrameEnded(user): # pylint: disable=invalid-name + context = ffi.from_handle(user) + context._video_frame_ended() + + +@ffi.def_extern() +def _mCorePythonCallbacksCoreCrashed(user): # pylint: disable=invalid-name + context = ffi.from_handle(user) + context._core_crashed() + + +@ffi.def_extern() +def _mCorePythonCallbacksSleep(user): # pylint: disable=invalid-name + context = ffi.from_handle(user) + context._sleep() + + +class CoreCallbacks(object): + def __init__(self): + self._handle = ffi.new_handle(self) + self.video_frame_started = [] + self.video_frame_ended = [] + self.core_crashed = [] + self.sleep = [] + self.context = lib.mCorePythonCallbackCreate(self._handle) + + def _video_frame_started(self): + for callback in self.video_frame_started: + callback() + + def _video_frame_ended(self): + for callback in self.video_frame_ended: + callback() + + def _core_crashed(self): + for callback in self.core_crashed: + callback() + + def _sleep(self): + for callback in self.sleep: + callback() + + class Core(object): if hasattr(lib, 'PLATFORM_GBA'): PLATFORM_GBA = lib.PLATFORM_GBA @@ -47,18 +114,48 @@ def __init__(self, native): self._core = native - self._wasReset = False + self._was_reset = False + 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._was_reset = False + + @cached_property + def graphics_cache(self): + if not self._was_reset: + raise RuntimeError("Core must be reset first") + return tile.CacheSet(self) @cached_property def tiles(self): - return tile.TileView(self) + tiles = [] + native_tiles = ffi.addressof(self.graphics_cache.cache.tiles) + for i in range(lib.mTileCacheSetSize(native_tiles)): + tiles.append(tile.TileView(lib.mTileCacheSetGetPointer(native_tiles, i))) + return tiles + + @cached_property + def maps(self): + maps = [] + native_maps = ffi.addressof(self.graphics_cache.cache.maps) + for i in range(lib.mMapCacheSetSize(native_maps)): + maps.append(tile.MapView(lib.mMapCacheSetGetPointer(native_maps, i))) + return maps @classmethod def _init(cls, native): core = ffi.gc(native, native.deinit) success = bool(core.init(core)) + lib.mCoreInitConfig(core, ffi.NULL) if not success: raise RuntimeError("Failed to initialize core") + return cls._detect(core) + + @classmethod + def _detect(cls, core): if hasattr(cls, 'PLATFORM_GBA') and core.platform(core) == cls.PLATFORM_GBA: from .gba import GBA return GBA(core) @@ -67,63 +164,120 @@ return GB(core) return Core(core) - def _deinit(self): - self._core.deinit(self._core) + def _load(self): + self._was_reset = True - def loadFile(self, path): + @protected + def load_file(self, path): return bool(lib.mCoreLoadFile(self._core, path.encode('UTF-8'))) - def isROM(self, vf): - return bool(self._core.isROM(vf.handle)) + def is_rom(self, vfile): + return bool(self._core.isROM(vfile.handle)) - def loadROM(self, vf): - return bool(self._core.loadROM(self._core, vf.handle)) + @protected + def load_rom(self, vfile): + return bool(self._core.loadROM(self._core, vfile.handle)) + + @protected + def load_bios(self, vfile, id=0): + return bool(self._core.loadBIOS(self._core, vfile.handle, id)) + + @protected + def load_save(self, vfile): + return bool(self._core.loadSave(self._core, vfile.handle)) + + @protected + def load_temporary_save(self, vfile): + return bool(self._core.loadTemporarySave(self._core, vfile.handle)) + + @protected + def load_patch(self, vfile): + return bool(self._core.loadPatch(self._core, vfile.handle)) + + @protected + def load_config(self, config): + lib.mCoreLoadForeignConfig(self._core, config._native) - def loadSave(self, vf): - return bool(self._core.loadSave(self._core, vf.handle)) - - def loadTemporarySave(self, vf): - return bool(self._core.loadTemporarySave(self._core, vf.handle)) - - def loadPatch(self, vf): - return bool(self._core.loadPatch(self._core, vf.handle)) - - def autoloadSave(self): + @protected + def autoload_save(self): return bool(lib.mCoreAutoloadSave(self._core)) - def autoloadPatch(self): + @protected + def autoload_patch(self): return bool(lib.mCoreAutoloadPatch(self._core)) + @protected + def autoload_cheats(self): + return bool(lib.mCoreAutoloadCheats(self._core)) + + @property def platform(self): return self._core.platform(self._core) - def desiredVideoDimensions(self): + @protected + def desired_video_dimensions(self): width = ffi.new("unsigned*") height = ffi.new("unsigned*") self._core.desiredVideoDimensions(self._core, width, height) return width[0], height[0] - def setVideoBuffer(self, image): + @protected + def set_video_buffer(self, image): self._core.setVideoBuffer(self._core, image.buffer, image.stride) + @protected + def set_audio_buffer_size(self, size): + self._core.setAudioBufferSize(self._core, size) + + @property + def audio_buffer_size(self): + return self._core.getAudioBufferSize(self._core) + + @protected + def get_audio_channels(self): + return audio.StereoBuffer(self.get_audio_channel(0), self.get_audio_channel(1)); + + @protected + def get_audio_channel(self, channel): + return audio.Buffer(self._core.getAudioChannel(self._core, channel), self.frequency) + + @protected def reset(self): self._core.reset(self._core) - self._wasReset = True + self._load() - @needsReset - def runFrame(self): + @needs_reset + @protected + def run_frame(self): self._core.runFrame(self._core) - @needsReset - def runLoop(self): + @needs_reset + @protected + def run_loop(self): self._core.runLoop(self._core) - @needsReset + @needs_reset + @protected def step(self): self._core.step(self._core) + @needs_reset + @protected + def load_raw_state(self, state): + if len(state) < self._core.stateSize(self._core): + return False + return self._core.loadState(self._core, state) + + @needs_reset + @protected + def save_raw_state(self): + state = ffi.new('unsigned char[%i]' % self._core.stateSize(self._core)) + if self._core.saveState(self._core, state): + return state + return None + @staticmethod - def _keysToInt(*args, **kwargs): + def _keys_to_int(*args, **kwargs): keys = 0 if 'raw' in kwargs: keys = kwargs['raw'] @@ -131,31 +285,108 @@ keys |= 1 << key return keys - def setKeys(self, *args, **kwargs): - self._core.setKeys(self._core, self._keysToInt(*args, **kwargs)) - - def addKeys(self, *args, **kwargs): - self._core.addKeys(self._core, self._keysToInt(*args, **kwargs)) - - def clearKeys(self, *args, **kwargs): - self._core.clearKeys(self._core, self._keysToInt(*args, **kwargs)) - - @needsReset - def frameCounter(self): + @protected + def set_keys(self, *args, **kwargs): + self._core.setKeys(self._core, self._keys_to_int(*args, **kwargs)) + + @protected + def add_keys(self, *args, **kwargs): + self._core.addKeys(self._core, self._keys_to_int(*args, **kwargs)) + + @protected + def clear_keys(self, *args, **kwargs): + self._core.clearKeys(self._core, self._keys_to_int(*args, **kwargs)) + + @property + @needs_reset + def frame_counter(self): return self._core.frameCounter(self._core) - def frameCycles(self): + @property + def frame_cycles(self): return self._core.frameCycles(self._core) + @property def frequency(self): return self._core.frequency(self._core) - def getGameTitle(self): + @property + def game_title(self): title = ffi.new("char[16]") self._core.getGameTitle(self._core, title) return ffi.string(title, 16).decode("ascii") - def getGameCode(self): + @property + def game_code(self): code = ffi.new("char[12]") self._core.getGameCode(self._core, code) return ffi.string(code, 12).decode("ascii") + + def add_frame_callback(self, callback): + self._callbacks.video_frame_ended.append(callback) + + @property + def crc32(self): + return self._native.romCrc32 + + +class ICoreOwner(object): + def claim(self): + raise NotImplementedError + + def release(self): + raise NotImplementedError + + def __enter__(self): + self.core = self.claim() + self.core._protected = True + return self.core + + def __exit__(self, type, value, traceback): + self.core._protected = False + self.release() + + +class IRunner(object): + def pause(self): + raise NotImplementedError + + def unpause(self): + raise NotImplementedError + + def use_core(self): + raise NotImplementedError + + @property + def running(self): + raise NotImplementedError + + @property + def paused(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 -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/debugger.py mgba-0.7.0/src/platform/python/mgba/debugger.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/debugger.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/debugger.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,106 @@ +# 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/. +from ._pylib import ffi, lib # pylint: disable=no-name-in-module +from .core import IRunner, ICoreOwner, Core +import sys + + +class DebuggerCoreOwner(ICoreOwner): + def __init__(self, debugger): + self.debugger = debugger + self.was_paused = False + + def claim(self): + if self.debugger.isRunning(): + self.was_paused = True + self.debugger.pause() + return self.debugger._core + + def release(self): + if self.was_paused: + self.debugger.unpause() + + +class NativeDebugger(IRunner): + WATCHPOINT_WRITE = lib.WATCHPOINT_WRITE + WATCHPOINT_READ = lib.WATCHPOINT_READ + WATCHPOINT_RW = lib.WATCHPOINT_RW + + BREAKPOINT_HARDWARE = lib.BREAKPOINT_HARDWARE + BREAKPOINT_SOFTWARE = lib.BREAKPOINT_SOFTWARE + + ENTER_MANUAL = lib.DEBUGGER_ENTER_MANUAL + ENTER_ATTACHED = lib.DEBUGGER_ENTER_ATTACHED + ENTER_BREAKPOINT = lib.DEBUGGER_ENTER_BREAKPOINT + ENTER_WATCHPOINT = lib.DEBUGGER_ENTER_WATCHPOINT + ENTER_ILLEGAL_OP = lib.DEBUGGER_ENTER_ILLEGAL_OP + + def __init__(self, native): + self._native = native + self._cbs = [] + self._core = Core._detect(native.core) + self._core._load() + + def pause(self): + lib.mDebuggerEnter(self._native, lib.DEBUGGER_ENTER_MANUAL, ffi.NULL) + + def unpause(self): + self._native.state = lib.DEBUGGER_RUNNING + + @property + def running(self): + return self._native.state == lib.DEBUGGER_RUNNING + + @property + def paused(self): + return self._native.state in (lib.DEBUGGER_PAUSED, lib.DEBUGGER_CUSTOM) + + def use_core(self): + return DebuggerCoreOwner(self) + + def set_breakpoint(self, address): + if not self._native.platform.setBreakpoint: + raise RuntimeError("Platform does not support breakpoints") + self._native.platform.setBreakpoint(self._native.platform, address) + + def clear_breakpoint(self, address): + if not self._native.platform.setBreakpoint: + raise RuntimeError("Platform does not support breakpoints") + self._native.platform.clearBreakpoint(self._native.platform, address) + + def set_watchpoint(self, address): + if not self._native.platform.setWatchpoint: + raise RuntimeError("Platform does not support watchpoints") + self._native.platform.setWatchpoint(self._native.platform, address) + + def clear_watchpoint(self, address): + if not self._native.platform.clearWatchpoint: + raise RuntimeError("Platform does not support watchpoints") + self._native.platform.clearWatchpoint(self._native.platform, address) + + def add_callback(self, callback): + self._cbs.append(callback) + + +class CLIBackend(object): + def __init__(self, backend): + self.backend = backend + + def write(self, string): + self.backend.printf(string) + + +class CLIDebugger(NativeDebugger): + def __init__(self, native): + super(CLIDebugger, self).__init__(native) + self._cli = ffi.cast("struct CLIDebugger*", native) + + def printf(self, message, *args, **kwargs): + message = message.format(*args, **kwargs) + self._cli.backend.printf(ffi.new("char []", b"%s"), ffi.new("char []", message.encode('utf-8'))) + + def install_print(self): + sys.stdout = CLIBackend(self) diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/gamedata.py mgba-0.7.0/src/platform/python/mgba/gamedata.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/gamedata.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/gamedata.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,23 @@ +# 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/. +try: + import mgba_gamedata +except ImportError: + pass + + +def search(core): + crc32 = None + if hasattr(core, 'PLATFORM_GBA') and core.platform == core.PLATFORM_GBA: + platform = 'GBA' + crc32 = core.crc32 + if hasattr(core, 'PLATFORM_GB') and core.platform == core.PLATFORM_GB: + platform = 'GB' + crc32 = core.crc32 + cls = mgba_gamedata.registry.search(platform, {'crc32': crc32}) + if not cls: + return None + return cls(core.memory.u8) diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/gba.py mgba-0.7.0/src/platform/python/mgba/gba.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/gba.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/gba.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,12 +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/. -from ._pylib import ffi, lib +from ._pylib import ffi, lib # pylint: disable=no-name-in-module from .arm import ARMCore -from .core import Core, needsReset +from .core import Core, needs_reset from .tile import Sprite from .memory import Memory -from . import createCallback +from . import create_callback + class GBA(Core): KEY_A = lib.GBA_KEY_A @@ -26,6 +27,7 @@ SIO_NORMAL_32 = lib.SIO_NORMAL_32 SIO_MULTI = lib.SIO_MULTI SIO_UART = lib.SIO_UART + SIO_JOYBUS = lib.SIO_JOYBUS SIO_GPIO = lib.SIO_GPIO def __init__(self, native): @@ -33,31 +35,43 @@ self._native = ffi.cast("struct GBA*", native.board) self.sprites = GBAObjs(self) self.cpu = ARMCore(self._core.cpu) + self.memory = None + self._sio = set() - @needsReset - def _initTileCache(self, cache): - lib.GBAVideoTileCacheInit(cache) - lib.GBAVideoTileCacheAssociate(cache, ffi.addressof(self._native.video)) - - def _deinitTileCache(self, cache): - self._native.video.renderer.cache = ffi.NULL - lib.mTileCacheDeinit(cache) + @needs_reset + def _init_cache(self, cache): + lib.GBAVideoCacheInit(cache) + lib.GBAVideoCacheAssociate(cache, ffi.addressof(self._native.video)) + + def _deinit_cache(self, cache): + lib.mCacheSetDeinit(cache) + if self._was_reset: + self._native.video.renderer.cache = ffi.NULL - def reset(self): - super(GBA, self).reset() + def _load(self): + super(GBA, self)._load() self.memory = GBAMemory(self._core, self._native.memory.romSize) - def attachSIO(self, link, mode=lib.SIO_MULTI): + def attach_sio(self, link, mode=lib.SIO_MULTI): + self._sio.add(mode) lib.GBASIOSetDriver(ffi.addressof(self._native.sio), link._native, mode) -createCallback("GBASIOPythonDriver", "init") -createCallback("GBASIOPythonDriver", "deinit") -createCallback("GBASIOPythonDriver", "load") -createCallback("GBASIOPythonDriver", "unload") -createCallback("GBASIOPythonDriver", "writeRegister") + def __del__(self): + for mode in self._sio: + lib.GBASIOSetDriver(ffi.addressof(self._native.sio), ffi.NULL, mode) + + +create_callback("GBASIOPythonDriver", "init") +create_callback("GBASIOPythonDriver", "deinit") +create_callback("GBASIOPythonDriver", "load") +create_callback("GBASIOPythonDriver", "unload") +create_callback("GBASIOPythonDriver", "writeRegister") + class GBASIODriver(object): def __init__(self): + super(GBASIODriver, self).__init__() + self._handle = ffi.new_handle(self) self._native = ffi.gc(lib.GBASIOPythonDriverCreate(self._handle), lib.free) @@ -73,9 +87,38 @@ def unload(self): return True - def writeRegister(self, address, value): + def write_register(self, address, value): return value + +class GBASIOJOYDriver(GBASIODriver): + RESET = lib.JOY_RESET + POLL = lib.JOY_POLL + TRANS = lib.JOY_TRANS + RECV = lib.JOY_RECV + + def __init__(self): + super(GBASIOJOYDriver, self).__init__() + + self._native = ffi.gc(lib.GBASIOJOYPythonDriverCreate(self._handle), lib.free) + + def send_command(self, cmd, data): + buffer = ffi.new('uint8_t[5]') + try: + buffer[0] = data[0] + buffer[1] = data[1] + buffer[2] = data[2] + buffer[3] = data[3] + buffer[4] = data[4] + except IndexError: + pass + + outlen = lib.GBASIOJOYSendCommand(self._native, cmd, buffer) + if outlen > 0 and outlen <= 5: + return bytes(buffer[0:outlen]) + return None + + class GBAMemory(Memory): def __init__(self, core, romSize=lib.SIZE_CART0): super(GBAMemory, self).__init__(core, 0x100000000) @@ -83,7 +126,7 @@ self.bios = Memory(core, lib.SIZE_BIOS, lib.BASE_BIOS) self.wram = Memory(core, lib.SIZE_WORKING_RAM, lib.BASE_WORKING_RAM) self.iwram = Memory(core, lib.SIZE_WORKING_IRAM, lib.BASE_WORKING_IRAM) - self.io = Memory(core, lib.SIZE_IO, lib.BASE_IO) + self.io = Memory(core, lib.SIZE_IO, lib.BASE_IO) # pylint: disable=invalid-name self.palette = Memory(core, lib.SIZE_PALETTE_RAM, lib.BASE_PALETTE_RAM) self.vram = Memory(core, lib.SIZE_VRAM, lib.BASE_VRAM) self.oam = Memory(core, lib.SIZE_OAM, lib.BASE_OAM) @@ -94,6 +137,7 @@ self.rom = self.cart0 self.sram = Memory(core, lib.SIZE_CART_SRAM, lib.BASE_CART_SRAM) + class GBASprite(Sprite): TILE_BASE = 0x800, 0x400 PALETTE_BASE = 0x10, 1 @@ -102,18 +146,19 @@ self._a = obj.a self._b = obj.b self._c = obj.c - self.x = self._b & 0x1FF - self.y = self._a & 0xFF + self.x = self._b & 0x1FF # pylint: disable=invalid-name + self.y = self._a & 0xFF # pylint: disable=invalid-name self._shape = self._a >> 14 self._size = self._b >> 14 - self._256Color = bool(self._a & 0x2000) + self._256_color = bool(self._a & 0x2000) self.width, self.height = lib.GBAVideoObjSizes[self._shape * 4 + self._size] self.tile = self._c & 0x3FF - if self._256Color: - self.paletteId = 0 + if self._256_color: + self.palette_id = 0 self.tile >>= 1 else: - self.paletteId = self._c >> 12 + self.palette_id = self._c >> 12 + class GBAObjs: def __init__(self, core): @@ -127,6 +172,7 @@ if index >= len(self): raise IndexError() sprite = GBASprite(self._obj[index]) - map1D = bool(self._core._native.memory.io[0] & 0x40) - sprite.constitute(self._core.tiles, 0 if map1D else 0x20, int(sprite._256Color)) + tiles = self._core.tiles[3 if sprite._256_color else 2] + map_1d = bool(self._core._native.memory.io[0] & 0x40) + sprite.constitute(tiles, 0 if map_1d else 0x20) return sprite diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/gb.py mgba-0.7.0/src/platform/python/mgba/gb.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/gb.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/gb.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,12 +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/. -from ._pylib import ffi, lib +from ._pylib import ffi, lib # pylint: disable=no-name-in-module from .lr35902 import LR35902Core -from .core import Core, needsReset +from .core import Core, needs_reset from .memory import Memory from .tile import Sprite -from . import createCallback +from . import create_callback + class GB(Core): KEY_A = lib.GBA_KEY_A @@ -25,27 +26,34 @@ self._native = ffi.cast("struct GB*", native.board) self.sprites = GBObjs(self) self.cpu = LR35902Core(self._core.cpu) + self.memory = None - @needsReset - def _initTileCache(self, cache): - lib.GBVideoTileCacheInit(cache) - lib.GBVideoTileCacheAssociate(cache, ffi.addressof(self._native.video)) - - def _deinitTileCache(self, cache): - self._native.video.renderer.cache = ffi.NULL - lib.mTileCacheDeinit(cache) + @needs_reset + def _init_cache(self, cache): + lib.GBVideoCacheInit(cache) + lib.GBVideoCacheAssociate(cache, ffi.addressof(self._native.video)) + + def _deinit_cache(self, cache): + lib.mCacheSetDeinit(cache) + if self._was_reset: + self._native.video.renderer.cache = ffi.NULL - def reset(self): - super(GB, self).reset() + def _load(self): + super(GB, self)._load() self.memory = GBMemory(self._core) - def attachSIO(self, link): + def attach_sio(self, link): lib.GBSIOSetDriver(ffi.addressof(self._native.sio), link._native) -createCallback("GBSIOPythonDriver", "init") -createCallback("GBSIOPythonDriver", "deinit") -createCallback("GBSIOPythonDriver", "writeSB") -createCallback("GBSIOPythonDriver", "writeSC") + def __del__(self): + lib.GBSIOSetDriver(ffi.addressof(self._native.sio), ffi.NULL) + + +create_callback("GBSIOPythonDriver", "init") +create_callback("GBSIOPythonDriver", "deinit") +create_callback("GBSIOPythonDriver", "writeSB") +create_callback("GBSIOPythonDriver", "writeSC") + class GBSIODriver(object): def __init__(self): @@ -58,53 +66,55 @@ def deinit(self): pass - def writeSB(self, value): + def write_sb(self, value): pass - def writeSC(self, value): + def write_sc(self, value): return value + class GBSIOSimpleDriver(GBSIODriver): def __init__(self, period=0x100): super(GBSIOSimpleDriver, self).__init__() - self.rx = 0x00 + self.rx = 0x00 # pylint: disable=invalid-name self._period = period def init(self): self._native.p.period = self._period return True - def writeSB(self, value): - self.rx = value + def write_sb(self, value): + self.rx = value # pylint: disable=invalid-name - def writeSC(self, value): + def write_sc(self, value): self._native.p.period = self._period if value & 0x80: lib.mTimingDeschedule(ffi.addressof(self._native.p.p.timing), ffi.addressof(self._native.p.event)) lib.mTimingSchedule(ffi.addressof(self._native.p.p.timing), ffi.addressof(self._native.p.event), self._native.p.period) return value - def isReady(self): + def is_ready(self): return not self._native.p.remainingBits @property - def tx(self): - self._native.p.pendingSB + def tx(self): # pylint: disable=invalid-name + return self._native.p.pendingSB @property def period(self): return self._native.p.period @tx.setter - def tx(self, newTx): + def tx(self, newTx): # pylint: disable=invalid-name self._native.p.pendingSB = newTx self._native.p.remainingBits = 8 @period.setter - def period(self, newPeriod): - self._period = newPeriod + def period(self, new_period): + self._period = new_period if self._native.p: - self._native.p.period = newPeriod + self._native.p.period = new_period + class GBMemory(Memory): def __init__(self, core): @@ -115,15 +125,16 @@ self.sram = Memory(core, lib.GB_SIZE_EXTERNAL_RAM, lib.GB_REGION_EXTERNAL_RAM) self.iwram = Memory(core, lib.GB_SIZE_WORKING_RAM_BANK0, lib.GB_BASE_WORKING_RAM_BANK0) self.oam = Memory(core, lib.GB_SIZE_OAM, lib.GB_BASE_OAM) - self.io = Memory(core, lib.GB_SIZE_IO, lib.GB_BASE_IO) + self.io = Memory(core, lib.GB_SIZE_IO, lib.GB_BASE_IO) # pylint: disable=invalid-name self.hram = Memory(core, lib.GB_SIZE_HRAM, lib.GB_BASE_HRAM) + class GBSprite(Sprite): - PALETTE_BASE = 8, + PALETTE_BASE = (8,) def __init__(self, obj, core): - self.x = obj.x - self.y = obj.y + self.x = obj.x # pylint: disable=invalid-name + self.y = obj.y # pylint: disable=invalid-name self.tile = obj.tile self._attr = obj.attr self.width = 8 @@ -132,9 +143,10 @@ if core._native.model >= lib.GB_MODEL_CGB: if self._attr & 8: self.tile += 512 - self.paletteId = self._attr & 7 + self.palette_id = self._attr & 7 else: - self.paletteId = (self._attr >> 4) & 1 + self.palette_id = (self._attr >> 4) & 1 + self.palette_id += 8 class GBObjs: @@ -149,5 +161,5 @@ 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 -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/image.py mgba-0.7.0/src/platform/python/mgba/image.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/image.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/image.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,7 +3,7 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -from ._pylib import ffi, lib +from ._pylib import ffi # pylint: disable=no-name-in-module from . import png try: @@ -11,11 +11,13 @@ 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): @@ -23,57 +25,63 @@ self.stride = self.width self.buffer = ffi.new("color_t[{}]".format(self.stride * self.height)) - def savePNG(self, f): - p = png.PNG(f) - success = p.writeHeader(self) - success = success and p.writePixels(self) - p.writeClose() + def save_png(self, fileobj): + png_file = png.PNG(fileobj, mode=png.MODE_RGBA if self.alpha else png.MODE_RGB) + success = png_file.write_header(self) + success = success and png_file.write_pixels(self) + png_file.write_close() return success if 'PImage' in globals(): - def toPIL(self): - return PImage.frombytes("RGBX", (self.width, self.height), ffi.buffer(self.buffer), "raw", - "RGBX", self.stride * 4) - -def u16ToU32(c): - r = c & 0x1F - g = (c >> 5) & 0x1F - b = (c >> 10) & 0x1F - a = (c >> 15) & 1 + def to_pil(self): + colorspace = "RGBA" if self.alpha else "RGBX" + return PImage.frombytes(colorspace, (self.width, self.height), ffi.buffer(self.buffer), "raw", + colorspace, self.stride * 4) + + +def u16_to_u32(color): + # pylint: disable=invalid-name + r = color & 0x1F + g = (color >> 5) & 0x1F + b = (color >> 10) & 0x1F + a = (color >> 15) & 1 abgr = r << 3 abgr |= g << 11 abgr |= b << 19 abgr |= (a * 0xFF) << 24 return abgr -def u32ToU16(c): - r = (c >> 3) & 0x1F - g = (c >> 11) & 0x1F - b = (c >> 19) & 0x1F - a = c >> 31 + +def u32_to_u16(color): + # pylint: disable=invalid-name + r = (color >> 3) & 0x1F + g = (color >> 11) & 0x1F + b = (color >> 19) & 0x1F + a = color >> 31 abgr = r abgr |= g << 5 abgr |= b << 10 abgr |= a << 15 return abgr + if ffi.sizeof("color_t") == 2: - def colorToU16(c): - return c + def color_to_u16(color): + return color - colorToU32 = u16ToU32 + color_to_u32 = u16_to_u32 # pylint: disable=invalid-name - def u16ToColor(c): - return c + def u16_to_color(color): + return color - u32ToColor = u32ToU16 + u32_to_color = u32_to_u16 # pylint: disable=invalid-name else: - def colorToU32(c): - return c + def color_to_u32(color): + return color - colorToU16 = u32ToU16 + color_to_u16 = u32_to_u16 # pylint: disable=invalid-name - def u32ToColor(c): - return c + def u32_to_color(color): + return color - u16ToColor = u16ToU32 + u16_to_color = u16_to_u32 # pylint: disable=invalid-name diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/__init__.py mgba-0.7.0/src/platform/python/mgba/__init__.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/__init__.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/__init__.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,31 +3,34 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -from ._pylib import ffi, lib +from ._pylib import ffi, lib # pylint: disable=no-name-in-module from collections import namedtuple -def createCallback(structName, cbName, funcName=None): - funcName = funcName or "_py{}{}".format(structName, cbName[0].upper() + cbName[1:]) - fullStruct = "struct {}*".format(structName) - def cb(handle, *args): - h = ffi.cast(fullStruct, handle) - return getattr(ffi.from_handle(h.pyobj), cbName)(*args) - return ffi.def_extern(name=funcName)(cb) +def create_callback(struct_name, cb_name, func_name=None): + func_name = func_name or "_py{}{}".format(struct_name, cb_name[0].upper() + cb_name[1:]) + full_struct = "struct {}*".format(struct_name) -version = ffi.string(lib.projectVersion).decode('utf-8') + def callback(handle, *args): + handle = ffi.cast(full_struct, handle) + return getattr(ffi.from_handle(handle.pyobj), cb_name)(*args) + + return ffi.def_extern(name=func_name)(callback) + + +__version__ = ffi.string(lib.projectVersion).decode('utf-8') GitInfo = namedtuple("GitInfo", "commit commitShort branch revision") -git = {} +GIT = {} if lib.gitCommit and lib.gitCommit != "(unknown)": - git['commit'] = ffi.string(lib.gitCommit).decode('utf-8') + GIT['commit'] = ffi.string(lib.gitCommit).decode('utf-8') if lib.gitCommitShort and lib.gitCommitShort != "(unknown)": - git['commitShort'] = ffi.string(lib.gitCommitShort).decode('utf-8') + GIT['commitShort'] = ffi.string(lib.gitCommitShort).decode('utf-8') if lib.gitBranch and lib.gitBranch != "(unknown)": - git['branch'] = ffi.string(lib.gitBranch).decode('utf-8') + GIT['branch'] = ffi.string(lib.gitBranch).decode('utf-8') if lib.gitRevision > 0: - git['revision'] = lib.gitRevision + GIT['revision'] = lib.gitRevision -git = GitInfo(**git) +GIT = GitInfo(**GIT) diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/log.py mgba-0.7.0/src/platform/python/mgba/log.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/log.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/log.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,17 +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/. -from ._pylib import ffi, lib -from . import createCallback +from ._pylib import ffi, lib # pylint: disable=no-name-in-module +from . import create_callback -createCallback("mLoggerPy", "log", "_pyLog") +create_callback("mLoggerPy", "log", "_pyLog") -defaultLogger = None -def installDefault(logger): - global defaultLogger - defaultLogger = logger - lib.mLogSetDefaultLogger(logger._native) +def install_default(logger): + Logger.install_default(logger) + + +def silence(): + Logger.install_default(NullLogger()) + class Logger(object): FATAL = lib.mLOG_FATAL @@ -24,16 +26,24 @@ STUB = lib.mLOG_STUB GAME_ERROR = lib.mLOG_GAME_ERROR + _DEFAULT_LOGGER = None + def __init__(self): self._handle = ffi.new_handle(self) self._native = ffi.gc(lib.mLoggerPythonCreate(self._handle), lib.free) @staticmethod - def categoryName(category): + def category_name(category): return ffi.string(lib.mLogCategoryName(category)).decode('UTF-8') + @classmethod + def install_default(cls, logger): + cls._DEFAULT_LOGGER = logger + lib.mLogSetDefaultLogger(logger._native) + def log(self, category, level, message): - print("{}: {}".format(self.categoryName(category), message)) + print("{}: {}".format(self.category_name(category), message)) + class NullLogger(Logger): def log(self, category, level, message): diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/lr35902.py mgba-0.7.0/src/platform/python/mgba/lr35902.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/lr35902.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/lr35902.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,9 +3,11 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -from ._pylib import ffi, lib +from ._pylib import ffi # pylint: disable=no-name-in-module + class LR35902Core: + # pylint: disable=invalid-name def __init__(self, native): self._native = ffi.cast("struct LR35902Core*", native) diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/memory.py mgba-0.7.0/src/platform/python/mgba/memory.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/memory.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/memory.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,7 +3,8 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -from ._pylib import ffi, lib +from ._pylib import ffi, lib # pylint: disable=no-name-in-module + class MemoryView(object): def __init__(self, core, width, size, base=0, sign="u"): @@ -11,11 +12,11 @@ self._width = width self._size = size self._base = base - self._busRead = getattr(self._core, "busRead" + str(width * 8)) - self._busWrite = getattr(self._core, "busWrite" + str(width * 8)) - self._rawRead = getattr(self._core, "rawRead" + str(width * 8)) - self._rawWrite = getattr(self._core, "rawWrite" + str(width * 8)) - self._mask = (1 << (width * 8)) - 1 # Used to force values to fit within range so that negative values work + self._bus_read = getattr(self._core, "busRead" + str(width * 8)) + self._bus_write = getattr(self._core, "busWrite" + str(width * 8)) + self._raw_read = getattr(self._core, "rawRead" + str(width * 8)) + self._raw_write = getattr(self._core, "rawWrite" + str(width * 8)) + self._mask = (1 << (width * 8)) - 1 # Used to force values to fit within range so that negative values work if sign == "u" or sign == "unsigned": self._type = "uint{}_t".format(width * 8) elif sign == "i" or sign == "s" or sign == "signed": @@ -23,7 +24,7 @@ else: raise ValueError("Invalid sign type: '{}'".format(sign)) - def _addrCheck(self, address): + def _addr_check(self, address): if isinstance(address, slice): start = address.start or 0 stop = self._size - self._width if address.stop is None else address.stop @@ -39,33 +40,32 @@ return self._size def __getitem__(self, address): - self._addrCheck(address) + self._addr_check(address) if isinstance(address, slice): start = address.start or 0 stop = self._size - self._width if address.stop is None else address.stop step = address.step or self._width - return [int(ffi.cast(self._type, self._busRead(self._core, self._base + a))) for a in range(start, stop, step)] - else: - return int(ffi.cast(self._type, self._busRead(self._core, self._base + address))) + return [int(ffi.cast(self._type, self._bus_read(self._core, self._base + a))) for a in range(start, stop, step)] + return int(ffi.cast(self._type, self._bus_read(self._core, self._base + address))) def __setitem__(self, address, value): - self._addrCheck(address) + self._addr_check(address) if isinstance(address, slice): start = address.start or 0 stop = self._size - self._width if address.stop is None else address.stop step = address.step or self._width - for a in range(start, stop, step): - self._busWrite(self._core, self._base + a, value[a] & self._mask) + for addr in range(start, stop, step): + self._bus_write(self._core, self._base + addr, value[addr] & self._mask) else: - self._busWrite(self._core, self._base + address, value & self._mask) + self._bus_write(self._core, self._base + address, value & self._mask) - def rawRead(self, address, segment=-1): - self._addrCheck(address) - return int(ffi.cast(self._type, self._rawRead(self._core, self._base + address, segment))) - - def rawWrite(self, address, value, segment=-1): - self._addrCheck(address) - self._rawWrite(self._core, self._base + address, segment, value & self._mask) + def raw_read(self, address, segment=-1): + self._addr_check(address) + return int(ffi.cast(self._type, self._raw_read(self._core, self._base + address, segment))) + + def raw_write(self, address, value, segment=-1): + self._addr_check(address) + self._raw_write(self._core, self._base + address, segment, value & self._mask) class MemorySearchResult(object): @@ -75,12 +75,13 @@ self.guessDivisor = result.guessDivisor self.type = result.type - if result.type == Memory.SEARCH_8: - self._memory = memory.u8 - elif result.type == Memory.SEARCH_16: - self._memory = memory.u16 - elif result.type == Memory.SEARCH_32: - self._memory = memory.u32 + if result.type == Memory.SEARCH_INT: + if result.width == 1: + self._memory = memory.u8 + elif result.width == 2: + self._memory = memory.u16 + elif result.width == 4: + self._memory = memory.u32 elif result.type == Memory.SEARCH_STRING: self._memory = memory.u8 else: @@ -100,12 +101,12 @@ class Memory(object): - SEARCH_32 = lib.mCORE_MEMORY_SEARCH_32 - SEARCH_16 = lib.mCORE_MEMORY_SEARCH_16 - SEARCH_8 = lib.mCORE_MEMORY_SEARCH_8 + SEARCH_INT = lib.mCORE_MEMORY_SEARCH_INT SEARCH_STRING = lib.mCORE_MEMORY_SEARCH_STRING SEARCH_GUESS = lib.mCORE_MEMORY_SEARCH_GUESS + SEARCH_EQUAL = lib.mCORE_MEMORY_SEARCH_EQUAL + READ = lib.mCORE_MEMORY_READ WRITE = lib.mCORE_MEMORY_READ RW = lib.mCORE_MEMORY_RW @@ -123,7 +124,7 @@ self.s32 = MemoryView(core, 4, size, base, "s") def __len__(self): - return self._size + return self.size def search(self, value, type=SEARCH_GUESS, flags=RW, limit=10000, old_results=[]): results = ffi.new("struct mCoreMemorySearchResults*") @@ -131,21 +132,18 @@ params = ffi.new("struct mCoreMemorySearchParams*") params.memoryFlags = flags params.type = type - if type == self.SEARCH_8: - params.value8 = int(value) - elif type == self.SEARCH_16: - params.value16 = int(value) - elif type == self.SEARCH_32: - params.value32 = int(value) + params.op = self.SEARCH_EQUAL + if type == self.SEARCH_INT: + params.valueInt = int(value) else: params.valueStr = ffi.new("char[]", str(value).encode("ascii")) for result in old_results: - r = lib.mCoreMemorySearchResultsAppend(results) - r.address = result.address - r.segment = result.segment - r.guessDivisor = result.guessDivisor - r.type = result.type + native_result = lib.mCoreMemorySearchResultsAppend(results) + native_result.address = result.address + native_result.segment = result.segment + native_result.guessDivisor = result.guessDivisor + native_result.type = result.type if old_results: lib.mCoreMemorySearchRepeat(self._core, params, results) else: @@ -153,3 +151,8 @@ new_results = [MemorySearchResult(self, lib.mCoreMemorySearchResultsGetPointer(results, i)) for i in range(lib.mCoreMemorySearchResultsSize(results))] lib.mCoreMemorySearchResultsDeinit(results) return new_results + + def __getitem__(self, address): + if isinstance(address, slice): + return bytearray(self.u8[address]) + return self.u8[address] diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/png.py mgba-0.7.0/src/platform/python/mgba/png.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/png.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/png.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,22 +3,41 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -from ._pylib import ffi, lib +from ._pylib import ffi, lib # pylint: disable=no-name-in-module from . import vfs +MODE_RGB = 0 +MODE_RGBA = 1 +MODE_INDEX = 2 + + class PNG: - def __init__(self, f): - self.vf = vfs.open(f) + def __init__(self, f, mode=MODE_RGB): + self._vfile = vfs.open(f) + self._png = None + self._info = None + self.mode = mode + + def write_header(self, image): + self._png = lib.PNGWriteOpen(self._vfile.handle) + 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 write_pixels(self, image): + 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) + return False - def writeHeader(self, image): - self._png = lib.PNGWriteOpen(self.vf.handle) - self._info = lib.PNGWriteHeader(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) - - def writeClose(self): - lib.PNGWriteClose(self._png, self._info) - del self._png - del self._info + def write_close(self): + lib.PNGWriteClose(self._png, self._info) + self._png = None + self._info = None diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/thread.py mgba-0.7.0/src/platform/python/mgba/thread.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/thread.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/thread.py 2019-01-27 00:06:06.000000000 +0000 @@ -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/. +from ._pylib import ffi, lib # pylint: disable=no-name-in-module +from .core import IRunner, ICoreOwner, Core + + +class ThreadCoreOwner(ICoreOwner): + def __init__(self, thread): + self.thread = thread + + def claim(self): + if not self.thread.isRunning(): + raise ValueError + lib.mCoreThreadInterrupt(self.thread._native) + return self.thread._core + + def release(self): + lib.mCoreThreadContinue(self.thread._native) + + +class Thread(IRunner): + def __init__(self, native=None): + if native: + self._native = native + self._core = Core(native.core) + self._core._was_reset = lib.mCoreThreadHasStarted(self._native) + else: + self._native = ffi.new("struct mCoreThread*") + + def start(self, core): + if lib.mCoreThreadHasStarted(self._native): + raise ValueError + self._core = core + self._native.core = core._core + lib.mCoreThreadStart(self._native) + self._core._was_reset = lib.mCoreThreadHasStarted(self._native) + + def end(self): + if not lib.mCoreThreadHasStarted(self._native): + raise ValueError + lib.mCoreThreadEnd(self._native) + lib.mCoreThreadJoin(self._native) + + def pause(self): + lib.mCoreThreadPause(self._native) + + def unpause(self): + lib.mCoreThreadUnpause(self._native) + + @property + def running(self): + return bool(lib.mCoreThreadIsActive(self._native)) + + @property + def paused(self): + return bool(lib.mCoreThreadIsPaused(self._native)) + + def use_core(self): + return ThreadCoreOwner(self) diff -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/tile.py mgba-0.7.0/src/platform/python/mgba/tile.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/tile.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/tile.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,55 +3,71 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -from ._pylib import ffi, lib +from ._pylib import ffi, lib # pylint: disable=no-name-in-module from . import image + class Tile: def __init__(self, data): self.buffer = data - def toImage(self): + def to_image(self): i = image.Image(8, 8) self.composite(i, 0, 0) return i 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._deinit_cache) + core._init_cache(self.cache) + + +class TileView: + def __init__(self, cache): + self.cache = cache - def getTile(self, tile, palette): + def get_tile(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 Sprite(object): - TILE_BASE = 0, 0 - PALETTE_BASE = 0, 0 +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 - 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] + +class Sprite(object): + 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 -Nru mgba-0.6.3+dfsg1/src/platform/python/mgba/vfs.py mgba-0.7.0/src/platform/python/mgba/vfs.py --- mgba-0.6.3+dfsg1/src/platform/python/mgba/vfs.py 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/mgba/vfs.py 2019-01-27 00:06:06.000000000 +0000 @@ -3,128 +3,152 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -from ._pylib import ffi, lib -import mmap +# pylint: disable=invalid-name,unused-argument +from ._pylib import ffi, lib # pylint: disable=no-name-in-module import os + @ffi.def_extern() def _vfpClose(vf): - vfp = ffi.cast("struct VFilePy*", vf) - ffi.from_handle(vfp.fileobj).close() + vfp = ffi.cast("struct VFilePy*", vf) + ffi.from_handle(vfp.fileobj).close() + return True + @ffi.def_extern() def _vfpSeek(vf, offset, whence): - vfp = ffi.cast("struct VFilePy*", vf) - f = ffi.from_handle(vfp.fileobj) - f.seek(offset, whence) - return f.tell() + vfp = ffi.cast("struct VFilePy*", vf) + f = ffi.from_handle(vfp.fileobj) + f.seek(offset, whence) + return f.tell() + @ffi.def_extern() def _vfpRead(vf, buffer, size): - vfp = ffi.cast("struct VFilePy*", vf) - pybuf = ffi.buffer(buffer, size) - ffi.from_handle(vfp.fileobj).readinto(pybuf) - return size + vfp = ffi.cast("struct VFilePy*", vf) + pybuf = ffi.buffer(buffer, size) + ffi.from_handle(vfp.fileobj).readinto(pybuf) + return size + @ffi.def_extern() def _vfpWrite(vf, buffer, size): - vfp = ffi.cast("struct VFilePy*", vf) - pybuf = ffi.buffer(buffer, size) - ffi.from_handle(vfp.fileobj).write(pybuf) - return size + vfp = ffi.cast("struct VFilePy*", vf) + pybuf = ffi.buffer(buffer, size) + ffi.from_handle(vfp.fileobj).write(pybuf) + return size + @ffi.def_extern() def _vfpMap(vf, size, flags): - pass + pass + @ffi.def_extern() def _vfpUnmap(vf, memory, size): - pass + pass + @ffi.def_extern() def _vfpTruncate(vf, size): - vfp = ffi.cast("struct VFilePy*", vf) - ffi.from_handle(vfp.fileobj).truncate(size) + vfp = ffi.cast("struct VFilePy*", vf) + ffi.from_handle(vfp.fileobj).truncate(size) + @ffi.def_extern() def _vfpSize(vf): - vfp = ffi.cast("struct VFilePy*", vf) - f = ffi.from_handle(vfp.fileobj) - pos = f.tell() - f.seek(0, os.SEEK_END) - size = f.tell() - f.seek(pos, os.SEEK_SET) - return size + vfp = ffi.cast("struct VFilePy*", vf) + f = ffi.from_handle(vfp.fileobj) + pos = f.tell() + f.seek(0, os.SEEK_END) + size = f.tell() + f.seek(pos, os.SEEK_SET) + return size + @ffi.def_extern() def _vfpSync(vf, buffer, size): - vfp = ffi.cast("struct VFilePy*", vf) - f = ffi.from_handle(vfp.fileobj) - if buffer and size: - pos = f.tell() - f.seek(0, os.SEEK_SET) - _vfpWrite(vf, buffer, size) - f.seek(pos, os.SEEK_SET) - f.flush() - os.fsync() - return True - -def open(f): - handle = ffi.new_handle(f) - vf = VFile(lib.VFileFromPython(handle)) - # Prevent garbage collection - vf._fileobj = f - vf._handle = handle - return vf - -def openPath(path, mode="r"): - flags = 0 - if mode.startswith("r"): - flags |= os.O_RDONLY - elif mode.startswith("w"): - flags |= os.O_WRONLY | os.O_CREAT | os.O_TRUNC - elif mode.startswith("a"): - flags |= os.O_WRONLY | os.O_CREAT | os.O_APPEND - else: - return None - - if "+" in mode[1:]: - flags |= os.O_RDWR - if "x" in mode[1:]: - flags |= os.O_EXCL + vfp = ffi.cast("struct VFilePy*", vf) + f = ffi.from_handle(vfp.fileobj) + if buffer and size: + pos = f.tell() + f.seek(0, os.SEEK_SET) + _vfpWrite(vf, buffer, size) + f.seek(pos, os.SEEK_SET) + f.flush() + os.fsync() + return True + + +def open(f): # pylint: disable=redefined-builtin + handle = ffi.new_handle(f) + vf = VFile(lib.VFileFromPython(handle), _no_gc=(f, handle)) + return vf + + +def open_path(path, mode="r"): + flags = 0 + if mode.startswith("r"): + flags |= os.O_RDONLY + elif mode.startswith("w"): + flags |= os.O_WRONLY | os.O_CREAT | os.O_TRUNC + elif mode.startswith("a"): + flags |= os.O_WRONLY | os.O_CREAT | os.O_APPEND + else: + return None + + if "+" in mode[1:]: + flags |= os.O_RDWR + if "x" in mode[1:]: + flags |= os.O_EXCL + + vf = lib.VFileOpen(path.encode("UTF-8"), flags) + if vf == ffi.NULL: + return None + return VFile(vf) - return VFile(lib.VFileOpen(path.encode("UTF-8"), flags)) class VFile: - def __init__(self, vf): - self.handle = vf + def __init__(self, vf, _no_gc=None): + self.handle = vf + self._no_gc = _no_gc + + def __del__(self): + self.close() + + def close(self): + return bool(self.handle.close(self.handle)) - def close(self): - return self.handle.close(self.handle) + def seek(self, offset, whence): + return self.handle.seek(self.handle, offset, whence) - def seek(self, offset, whence): - return self.handle.seek(self.handle, offset, whence) + def read(self, buffer, size): + return self.handle.read(self.handle, buffer, size) - def read(self, buffer, size): - return self.handle.read(self.handle, buffer, size) + def read_all(self, size=0): + if not size: + size = self.size() + buffer = ffi.new("char[%i]" % size) + size = self.handle.read(self.handle, buffer, size) + return ffi.unpack(buffer, size) - def readline(self, buffer, size): - return self.handle.readline(self.handle, buffer, size) + def readline(self, buffer, size): + return self.handle.readline(self.handle, buffer, size) - def write(self, buffer, size): - return self.handle.write(self.handle, buffer, size) + def write(self, buffer, size): + return self.handle.write(self.handle, buffer, size) - def map(self, size, flags): - return self.handle.map(self.handle, size, flags) + def map(self, size, flags): + return self.handle.map(self.handle, size, flags) - def unmap(self, memory, size): - self.handle.unmap(self.handle, memory, size) + def unmap(self, memory, size): + self.handle.unmap(self.handle, memory, size) - def truncate(self, size): - self.handle.truncate(self.handle, size) + def truncate(self, size): + self.handle.truncate(self.handle, size) - def size(self): - return self.handle.size(self.handle) + def size(self): + return self.handle.size(self.handle) - def sync(self, buffer, size): - return self.handle.sync(self.handle, buffer, size) + def sync(self, buffer, size): + return self.handle.sync(self.handle, buffer, size) diff -Nru mgba-0.6.3+dfsg1/src/platform/python/pycommon.h mgba-0.7.0/src/platform/python/pycommon.h --- mgba-0.6.3+dfsg1/src/platform/python/pycommon.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/pycommon.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,15 @@ +/* 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 PYTHON_COMMON_H +#define PYTHON_COMMON_H + +#include + +#ifndef PYEXPORT +#define PYEXPORT extern +#endif + +#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/python/.pylintrc mgba-0.7.0/src/platform/python/.pylintrc --- mgba-0.6.3+dfsg1/src/platform/python/.pylintrc 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/.pylintrc 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,2 @@ +[MESSAGES CONTROL] +disable=line-too-long,missing-docstring,too-few-public-methods,too-many-instance-attributes,too-many-public-methods,wrong-import-order diff -Nru mgba-0.6.3+dfsg1/src/platform/python/setup.cfg mgba-0.7.0/src/platform/python/setup.cfg --- mgba-0.6.3+dfsg1/src/platform/python/setup.cfg 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/setup.cfg 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,6 @@ +[aliases] +test=pytest + +[pycodestyle] +exclude = .eggs +ignore = E501,E741,E743 diff -Nru mgba-0.6.3+dfsg1/src/platform/python/setup.py mgba-0.7.0/src/platform/python/setup.py --- mgba-0.6.3+dfsg1/src/platform/python/setup.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/setup.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,38 @@ +from setuptools import setup +import re +import os +import os.path +import sys +import subprocess + + +def get_version_component(piece): + return subprocess.check_output(['cmake', '-DPRINT_STRING={}'.format(piece), '-P', '../../../version.cmake']).decode('utf-8').strip() + + +version = '{}.{}.{}'.format(*(get_version_component(p) for p in ('LIB_VERSION_MAJOR', 'LIB_VERSION_MINOR', 'LIB_VERSION_PATCH'))) +if not get_version_component('GIT_TAG'): + version += '.{}+g{}'.format(*(get_version_component(p) for p in ('GIT_REV', 'GIT_COMMIT_SHORT'))) + +setup( + name="mgba", + version=version, + author="Jeffrey Pfau", + author_email="jeffrey@endrift.com", + url="http://github.com/mgba-emu/mgba/", + packages=["mgba"], + setup_requires=['cffi>=1.6', 'pytest-runner'], + install_requires=['cffi>=1.6', 'cached-property'], + extras_require={'pil': ['Pillow>=2.3'], 'cinema': ['pyyaml', 'pytest']}, + tests_require=['pytest'], + cffi_modules=["_builder.py:ffi"], + license="MPL 2.0", + classifiers=[ + "Programming Language :: C", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 3", + "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", + "Topic :: Games/Entertainment", + "Topic :: System :: Emulators" + ] +) diff -Nru mgba-0.6.3+dfsg1/src/platform/python/setup.py.in mgba-0.7.0/src/platform/python/setup.py.in --- mgba-0.6.3+dfsg1/src/platform/python/setup.py.in 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/setup.py.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -from setuptools import setup -import re -import os - -os.environ["BINDIR"] = "${CMAKE_BINARY_DIR}" -os.environ["CPPFLAGS"] = " ".join([d for d in "${INCLUDE_FLAGS}".split(";") if d]) - -classifiers = [ - "Programming Language :: C", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 3", - "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", - "Topic :: Games/Entertainment", - "Topic :: System :: Emulators" -] - -setup(name="${BINARY_NAME}", - version=re.sub("/", "-", "${VERSION_STRING}"), - author="Jeffrey Pfau", - author_email="jeffrey@endrift.com", - url="http://github.com/mgba-emu/mgba/", - packages=["mgba"], - package_dir={ - "mgba": "${CMAKE_CURRENT_SOURCE_DIR}/mgba" - }, - setup_requires=['cffi>=1.6'], - install_requires=['cffi>=1.6', 'cached-property'], - extras_require={'pil': ['Pillow>=2.3']}, - cffi_modules=["${CMAKE_CURRENT_SOURCE_DIR}/_builder.py:ffi"], - license="MPL 2.0", - classifiers=classifiers - ) diff -Nru mgba-0.6.3+dfsg1/src/platform/python/sio.c mgba-0.7.0/src/platform/python/sio.c --- mgba-0.6.3+dfsg1/src/platform/python/sio.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/sio.c 2019-01-27 00:06:06.000000000 +0000 @@ -46,6 +46,18 @@ return &driver->d; } +struct GBASIODriver* GBASIOJOYPythonDriverCreate(void* pyobj) { + struct GBASIOPythonDriver* driver = malloc(sizeof(*driver)); + GBASIOJOYCreate(&driver->d); + driver->d.init = _pyGBASIOPythonDriverInitShim; + driver->d.deinit = _pyGBASIOPythonDriverDeinitShim; + driver->d.load = _pyGBASIOPythonDriverLoadShim; + driver->d.unload = _pyGBASIOPythonDriverUnloadShim; + + driver->pyobj = pyobj; + return &driver->d; +} + #endif #ifdef M_CORE_GB diff -Nru mgba-0.6.3+dfsg1/src/platform/python/sio.h mgba-0.7.0/src/platform/python/sio.h --- mgba-0.6.3+dfsg1/src/platform/python/sio.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/sio.h 2019-01-27 00:06:06.000000000 +0000 @@ -13,6 +13,7 @@ }; struct GBASIODriver* GBASIOPythonDriverCreate(void* pyobj); +struct GBASIODriver* GBASIOJOYPythonDriverCreate(void* pyobj); PYEXPORT bool _pyGBASIOPythonDriverInit(void* driver); PYEXPORT void _pyGBASIOPythonDriverDeinit(void* driver); diff -Nru mgba-0.6.3+dfsg1/src/platform/python/test_cinema.py mgba-0.7.0/src/platform/python/test_cinema.py --- mgba-0.6.3+dfsg1/src/platform/python/test_cinema.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/test_cinema.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,61 @@ +import pytest +import cinema.test +import mgba.log +import os.path +import yaml + +mgba.log.install_default(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.gather_tests(os.path.join(os.path.dirname(__file__), '..', '..', '..', '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.generate_baseline() + 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 -Nru mgba-0.6.3+dfsg1/src/platform/python/tests/mgba/test_core.py mgba-0.7.0/src/platform/python/tests/mgba/test_core.py --- mgba-0.6.3+dfsg1/src/platform/python/tests/mgba/test_core.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/tests/mgba/test_core.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,7 @@ +import pytest + +def test_core_import(): + try: + import mgba.core + except: + raise AssertionError diff -Nru mgba-0.6.3+dfsg1/src/platform/python/tests/mgba/test_vfs.py mgba-0.7.0/src/platform/python/tests/mgba/test_vfs.py --- mgba-0.6.3+dfsg1/src/platform/python/tests/mgba/test_vfs.py 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/python/tests/mgba/test_vfs.py 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,64 @@ +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_open_path(): + vf = vfs.open_path(__file__) + assert vf + assert vf.close() + + +def test_vfs_read(): + vf = vfs.open_path(__file__) + buffer = ffi.new('char[13]') + assert vf.read(buffer, 13) == 13 + assert ffi.string(buffer) == b'import pytest' + vf.close() + + +def test_vfs_readline(): + vf = vfs.open_path(__file__) + buffer = ffi.new('char[16]') + linelen = vf.readline(buffer, 16) + assert linelen in (14, 15) + if linelen == 14: + assert ffi.string(buffer) == b'import pytest\n' + elif linelen == 15: + assert ffi.string(buffer) == b'import pytest\r\n' + vf.close() + + +def test_vfs_read_all_size(): + vf = vfs.open_path(__file__) + buffer = vf.read_all() + assert buffer + assert len(buffer) + assert len(buffer) == vf.size() + vf.close() + + +def test_vfs_seek(): + vf = vfs.open_path(__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_open_path_invalid(): + vf = vfs.open_path('.invalid') + assert not vf diff -Nru mgba-0.6.3+dfsg1/src/platform/python/vfs-py.c mgba-0.7.0/src/platform/python/vfs-py.c --- mgba-0.6.3+dfsg1/src/platform/python/vfs-py.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/vfs-py.c 2019-01-27 00:06:06.000000000 +0000 @@ -3,22 +3,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include - -struct VFilePy { - struct VFile d; - void* fileobj; -}; - -bool _vfpClose(struct VFile* vf); -off_t _vfpSeek(struct VFile* vf, off_t offset, int whence); -ssize_t _vfpRead(struct VFile* vf, void* buffer, size_t size); -ssize_t _vfpWrite(struct VFile* vf, const void* buffer, size_t size); -void* _vfpMap(struct VFile* vf, size_t size, int flags); -void _vfpUnmap(struct VFile* vf, void* memory, size_t size); -void _vfpTruncate(struct VFile* vf, size_t size); -ssize_t _vfpSize(struct VFile* vf); -bool _vfpSync(struct VFile* vf, const void* buffer, size_t size); +#include "vfs-py.h" struct VFile* VFileFromPython(void* fileobj) { if (!fileobj) { diff -Nru mgba-0.6.3+dfsg1/src/platform/python/vfs-py.h mgba-0.7.0/src/platform/python/vfs-py.h --- mgba-0.6.3+dfsg1/src/platform/python/vfs-py.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/python/vfs-py.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,9 +3,10 @@ * 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 "pycommon.h" + struct VFilePy { struct VFile d; void* fileobj; diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AboutScreen.h mgba-0.7.0/src/platform/qt/AboutScreen.h --- mgba-0.6.3+dfsg1/src/platform/qt/AboutScreen.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AboutScreen.h 2019-01-27 00:06:06.000000000 +0000 @@ -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 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ArchiveInspector.h mgba-0.7.0/src/platform/qt/ArchiveInspector.h --- mgba-0.6.3+dfsg1/src/platform/qt/ArchiveInspector.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ArchiveInspector.h 2019-01-27 00:06:06.000000000 +0000 @@ -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 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AssetTile.cpp mgba-0.7.0/src/platform/qt/AssetTile.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/AssetTile.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AssetTile.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,9 +5,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AssetTile.h" +#include "CoreController.h" #include "GBAApp.h" #include +#include #include #ifdef M_CORE_GBA @@ -33,14 +35,27 @@ 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::setController(GameController* controller) { - m_tileCache = controller->tileCache(); +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_cacheSet = controller->graphicCaches(); switch (controller->platform()) { #ifdef M_CORE_GBA case PLATFORM_GBA: @@ -69,68 +84,76 @@ 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.get(), 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.get(), 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.get(), 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.get(), 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 -Nru mgba-0.6.3+dfsg1/src/platform/qt/AssetTile.h mgba-0.7.0/src/platform/qt/AssetTile.h --- mgba-0.6.3+dfsg1/src/platform/qt/AssetTile.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AssetTile.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,44 +3,50 @@ * 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 - -#include "GameController.h" +#pragma once #include "ui_AssetTile.h" -#include +#include + +#include namespace QGBA { +class CoreController; + class AssetTile : public QGroupBox { Q_OBJECT public: AssetTile(QWidget* parent = nullptr); - void setController(GameController*); + 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; - std::shared_ptr 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 -Nru mgba-0.6.3+dfsg1/src/platform/qt/AssetTile.ui mgba-0.7.0/src/platform/qt/AssetTile.ui --- mgba-0.6.3+dfsg1/src/platform/qt/AssetTile.ui 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AssetTile.ui 2019-01-27 00:06:06.000000000 +0000 @@ -2,6 +2,14 @@ AssetTile + + + 0 + 0 + 171 + 355 + + 0 @@ -47,6 +55,27 @@ + + + + + + + + Palette # + + + + + + + 0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AssetView.cpp mgba-0.7.0/src/platform/qt/AssetView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/AssetView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AssetView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,32 +5,32 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AssetView.h" -#include +#include "CoreController.h" -#include +#include using namespace QGBA; -AssetView::AssetView(GameController* controller, QWidget* parent) +AssetView::AssetView(std::shared_ptr controller, QWidget* parent) : QWidget(parent) - , m_tileCache(controller->tileCache()) + , m_cacheSet(controller->graphicCaches()) , m_controller(controller) { m_updateTimer.setSingleShot(true); m_updateTimer.setInterval(1); - connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateTiles())); + connect(&m_updateTimer, &QTimer::timeout, this, static_cast(&AssetView::updateTiles)); - connect(m_controller, &GameController::frameAvailable, &m_updateTimer, + connect(controller.get(), &CoreController::frameAvailable, &m_updateTimer, static_cast(&QTimer::start)); - connect(m_controller, &GameController::gameStopped, this, &AssetView::close); - connect(m_controller, &GameController::gameStopped, &m_updateTimer, &QTimer::stop); + connect(controller.get(), &CoreController::stopping, this, &AssetView::close); + connect(controller.get(), &CoreController::stopping, &m_updateTimer, &QTimer::stop); } -void AssetView::updateTiles(bool force) { - if (!m_controller->isLoaded()) { - return; - } +void AssetView::updateTiles() { + updateTiles(false); +} +void AssetView::updateTiles(bool force) { switch (m_controller->platform()) { #ifdef M_CORE_GBA case PLATFORM_GBA: @@ -55,8 +55,8 @@ updateTiles(true); } -void AssetView::compositeTile(unsigned tileId, void* buffer, size_t stride, size_t x, size_t y, int depth) { - const uint8_t* tile = mTileCacheGetRawTile(m_tileCache.get(), tileId); +void AssetView::compositeTile(const void* tBuffer, void* buffer, size_t stride, size_t x, size_t y, int depth) { + const uint8_t* tile = static_cast(tBuffer); uint8_t* pixels = static_cast(buffer); size_t base = stride * y + x; switch (depth) { diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AssetView.h mgba-0.7.0/src/platform/qt/AssetView.h --- mgba-0.6.3+dfsg1/src/platform/qt/AssetView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AssetView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,25 +3,30 @@ * 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_VIEW -#define QGBA_ASSET_VIEW +#pragma once +#include #include -#include "GameController.h" +#include + +#include namespace QGBA { +class CoreController; + class AssetView : public QWidget { Q_OBJECT public: - AssetView(GameController* controller, QWidget* parent = nullptr); + AssetView(std::shared_ptr controller, QWidget* parent = nullptr); - void compositeTile(unsigned tileId, void* image, size_t stride, size_t x, size_t y, int depth = 8); + static void compositeTile(const void* tile, void* image, size_t stride, size_t x, size_t y, int depth = 8); protected slots: - void updateTiles(bool force = false); + void updateTiles(); + void updateTiles(bool force); protected: #ifdef M_CORE_GBA @@ -34,13 +39,11 @@ void resizeEvent(QResizeEvent*) override; void showEvent(QShowEvent*) override; - const std::shared_ptr m_tileCache; + mCacheSet* const m_cacheSet; private: - GameController* m_controller; + std::shared_ptr m_controller; QTimer m_updateTimer; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AudioDevice.cpp mgba-0.7.0/src/platform/qt/AudioDevice.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/AudioDevice.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AudioDevice.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -26,13 +26,13 @@ LOG(QT, INFO) << tr("Can't set format of context-less audio device"); return; } - double fauxClock = GBAAudioCalculateRatio(1, m_context->sync.fpsTarget, 1); - mCoreSyncLockAudio(&m_context->sync); + double fauxClock = GBAAudioCalculateRatio(1, m_context->impl->sync.fpsTarget, 1); + mCoreSyncLockAudio(&m_context->impl->sync); blip_set_rates(m_context->core->getAudioChannel(m_context->core, 0), m_context->core->frequency(m_context->core), format.sampleRate() * fauxClock); blip_set_rates(m_context->core->getAudioChannel(m_context->core, 1), m_context->core->frequency(m_context->core), format.sampleRate() * fauxClock); - mCoreSyncUnlockAudio(&m_context->sync); + mCoreSyncUnlockAudio(&m_context->impl->sync); } void AudioDevice::setInput(mCoreThread* input) { @@ -49,14 +49,14 @@ return 0; } - mCoreSyncLockAudio(&m_context->sync); + mCoreSyncLockAudio(&m_context->impl->sync); int available = blip_samples_avail(m_context->core->getAudioChannel(m_context->core, 0)); if (available > maxSize / sizeof(GBAStereoSample)) { available = maxSize / sizeof(GBAStereoSample); } blip_read_samples(m_context->core->getAudioChannel(m_context->core, 0), &reinterpret_cast(data)->left, available, true); blip_read_samples(m_context->core->getAudioChannel(m_context->core, 1), &reinterpret_cast(data)->right, available, true); - mCoreSyncConsumeAudio(&m_context->sync); + mCoreSyncConsumeAudio(&m_context->impl->sync); return available * sizeof(GBAStereoSample); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AudioDevice.h mgba-0.7.0/src/platform/qt/AudioDevice.h --- mgba-0.6.3+dfsg1/src/platform/qt/AudioDevice.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AudioDevice.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_AUDIO_DEVICE -#define QGBA_AUDIO_DEVICE +#pragma once #include #include @@ -31,5 +30,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessor.cpp mgba-0.7.0/src/platform/qt/AudioProcessor.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessor.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AudioProcessor.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -47,10 +47,18 @@ { } -void AudioProcessor::setInput(mCoreThread* input) { +AudioProcessor::~AudioProcessor() { + stop(); +} + +void AudioProcessor::setInput(std::shared_ptr input) { m_context = input; } +void AudioProcessor::stop() { + m_context.reset(); +} + void AudioProcessor::setBufferSamples(int samples) { m_samples = samples; } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessor.h mgba-0.7.0/src/platform/qt/AudioProcessor.h --- mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessor.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AudioProcessor.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,10 +3,14 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef QGBA_AUDIO_PROCESSOR -#define QGBA_AUDIO_PROCESSOR +#pragma once + #include +#include + +#include "CoreController.h" + struct mCoreThread; namespace QGBA { @@ -28,12 +32,14 @@ static void setDriver(Driver driver) { s_driver = driver; } AudioProcessor(QObject* parent = nullptr); + ~AudioProcessor(); int getBufferSamples() const { return m_samples; } virtual unsigned sampleRate() const = 0; public slots: - virtual void setInput(mCoreThread* input); + virtual void setInput(std::shared_ptr); + virtual void stop(); virtual bool start() = 0; virtual void pause() = 0; @@ -44,14 +50,12 @@ virtual void requestSampleRate(unsigned) = 0; protected: - mCoreThread* input() { return m_context; } + mCoreThread* input() { return m_context ? m_context->thread() : nullptr; } private: - mCoreThread* m_context = nullptr; + std::shared_ptr m_context; int m_samples = 2048; static Driver s_driver; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessorQt.cpp mgba-0.7.0/src/platform/qt/AudioProcessorQt.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessorQt.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AudioProcessorQt.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -20,16 +20,24 @@ { } -void AudioProcessorQt::setInput(mCoreThread* input) { - AudioProcessor::setInput(input); +void AudioProcessorQt::setInput(std::shared_ptr controller) { + AudioProcessor::setInput(controller); if (m_device) { - m_device->setInput(input); + m_device->setInput(input()); if (m_audioOutput) { m_device->setFormat(m_audioOutput->format()); } } } +void AudioProcessorQt::stop() { + if (m_device) { + m_device.reset(); + } + pause(); + AudioProcessor::stop(); +} + bool AudioProcessorQt::start() { if (!input()) { LOG(QT, WARN) << tr("Can't start an audio processor without input"); @@ -37,7 +45,7 @@ } if (!m_device) { - m_device = new AudioDevice(this); + m_device = std::make_unique(this); } if (!m_audioOutput) { @@ -56,7 +64,7 @@ m_device->setInput(input()); m_device->setFormat(m_audioOutput->format()); - m_audioOutput->start(m_device); + m_audioOutput->start(m_device.get()); return m_audioOutput->state() == QAudio::ActiveState; } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessorQt.h mgba-0.7.0/src/platform/qt/AudioProcessorQt.h --- mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessorQt.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AudioProcessorQt.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,8 +3,8 @@ * 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_AUDIO_PROCESSOR_QT -#define QGBA_AUDIO_PROCESSOR_QT +#pragma once + #include "AudioProcessor.h" class QAudioOutput; @@ -22,7 +22,8 @@ virtual unsigned sampleRate() const override; public slots: - virtual void setInput(mCoreThread* input) override; + virtual void setInput(std::shared_ptr input) override; + virtual void stop() override; virtual bool start() override; virtual void pause() override; @@ -33,10 +34,8 @@ private: QAudioOutput* m_audioOutput = nullptr; - AudioDevice* m_device = nullptr; + std::unique_ptr m_device; unsigned m_sampleRate = 44100; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessorSDL.cpp mgba-0.7.0/src/platform/qt/AudioProcessorSDL.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessorSDL.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AudioProcessorSDL.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -16,18 +16,19 @@ { } -AudioProcessorSDL::~AudioProcessorSDL() { - mSDLDeinitAudio(&m_audio); -} - -void AudioProcessorSDL::setInput(mCoreThread* input) { - AudioProcessor::setInput(input); - if (m_audio.core && input->core != m_audio.core) { +void AudioProcessorSDL::setInput(std::shared_ptr controller) { + AudioProcessor::setInput(controller); + if (m_audio.core && input()->core != m_audio.core) { mSDLDeinitAudio(&m_audio); - mSDLInitAudio(&m_audio, input); + mSDLInitAudio(&m_audio, input()); } } +void AudioProcessorSDL::stop() { + mSDLDeinitAudio(&m_audio); + AudioProcessor::stop(); +} + bool AudioProcessorSDL::start() { if (!input()) { LOG(QT, WARN) << tr("Can't start an audio processor without input"); @@ -51,10 +52,12 @@ void AudioProcessorSDL::setBufferSamples(int samples) { AudioProcessor::setBufferSamples(samples); - m_audio.samples = samples; - if (m_audio.core) { - mSDLDeinitAudio(&m_audio); - mSDLInitAudio(&m_audio, input()); + if (m_audio.samples != samples) { + m_audio.samples = samples; + if (m_audio.core) { + mSDLDeinitAudio(&m_audio); + mSDLInitAudio(&m_audio, input()); + } } } @@ -62,10 +65,12 @@ } void AudioProcessorSDL::requestSampleRate(unsigned rate) { - m_audio.sampleRate = rate; - if (m_audio.core) { - mSDLDeinitAudio(&m_audio); - mSDLInitAudio(&m_audio, input()); + if (m_audio.sampleRate != rate) { + m_audio.sampleRate = rate; + if (m_audio.core) { + mSDLDeinitAudio(&m_audio); + mSDLInitAudio(&m_audio, input()); + } } } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessorSDL.h mgba-0.7.0/src/platform/qt/AudioProcessorSDL.h --- mgba-0.6.3+dfsg1/src/platform/qt/AudioProcessorSDL.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/AudioProcessorSDL.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,8 +3,8 @@ * 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_AUDIO_PROCESSOR_SDL -#define QGBA_AUDIO_PROCESSOR_SDL +#pragma once + #include "AudioProcessor.h" #ifdef BUILD_SDL @@ -18,12 +18,12 @@ public: AudioProcessorSDL(QObject* parent = nullptr); - ~AudioProcessorSDL(); virtual unsigned sampleRate() const override; public slots: - virtual void setInput(mCoreThread* input) override; + virtual void setInput(std::shared_ptr input) override; + virtual void stop() override; virtual bool start() override; virtual void pause() override; @@ -39,5 +39,3 @@ } #endif - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/CheatsModel.cpp mgba-0.7.0/src/platform/qt/CheatsModel.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/CheatsModel.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/CheatsModel.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -70,10 +70,12 @@ case Qt::DisplayRole: case Qt::EditRole: mCheatSetRename(cheats, value.toString().toUtf8().constData()); + mCheatAutosave(m_device); emit dataChanged(index, index); return true; case Qt::CheckStateRole: cheats->enabled = value == Qt::Checked; + mCheatAutosave(m_device); emit dataChanged(index, index); return true; default: @@ -154,7 +156,8 @@ beginRemoveRows(QModelIndex(), row, row); mCheatRemoveSet(m_device, set); mCheatSetDeinit(set); - endInsertRows(); + endRemoveRows(); + mCheatAutosave(m_device); } QString CheatsModel::toString(const QModelIndexList& indices) const { @@ -201,6 +204,7 @@ void CheatsModel::endAppendRow() { endInsertRows(); + mCheatAutosave(m_device); } void CheatsModel::loadFile(const QString& path) { @@ -232,6 +236,7 @@ } mCheatAddSet(m_device, set); endInsertRows(); + mCheatAutosave(m_device); } void CheatsModel::invalidated() { diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/CheatsModel.h mgba-0.7.0/src/platform/qt/CheatsModel.h --- mgba-0.6.3+dfsg1/src/platform/qt/CheatsModel.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/CheatsModel.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_CHEATS_MODEL -#define QGBA_CHEATS_MODEL +#pragma once #include #include @@ -51,5 +50,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/CheatsView.cpp mgba-0.7.0/src/platform/qt/CheatsView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/CheatsView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/CheatsView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -6,7 +6,7 @@ #include "CheatsView.h" #include "GBAApp.h" -#include "GameController.h" +#include "CoreController.h" #include #include @@ -21,7 +21,7 @@ using namespace QGBA; -CheatsView::CheatsView(GameController* controller, QWidget* parent) +CheatsView::CheatsView(std::shared_ptr controller, QWidget* parent) : QWidget(parent) , m_controller(controller) , m_model(controller->cheatDevice()) @@ -35,8 +35,8 @@ connect(m_ui.save, &QPushButton::clicked, this, &CheatsView::save); connect(m_ui.addSet, &QPushButton::clicked, this, &CheatsView::addSet); connect(m_ui.remove, &QPushButton::clicked, this, &CheatsView::removeSet); - connect(controller, &GameController::gameStopped, this, &CheatsView::close); - connect(controller, &GameController::stateLoaded, &m_model, &CheatsModel::invalidated); + connect(controller.get(), &CoreController::stopping, this, &CheatsView::close); + connect(controller.get(), &CoreController::stateLoaded, &m_model, &CheatsModel::invalidated); QPushButton* add; switch (controller->platform()) { @@ -109,21 +109,21 @@ } void CheatsView::load() { - QString filename = GBAApp::app()->getOpenFileName(this, tr("Select cheats file")); + QString filename = GBAApp::app()->getOpenFileName(this, tr("Select cheats file"), tr(("Cheats file (*.cheats *.cht *.clt)"))); if (!filename.isEmpty()) { m_model.loadFile(filename); } } void CheatsView::save() { - QString filename = GBAApp::app()->getSaveFileName(this, tr("Select cheats file")); + QString filename = GBAApp::app()->getSaveFileName(this, tr("Select cheats file"), tr(("Cheats file (*.cheats *.cht *.clt)"))); if (!filename.isEmpty()) { m_model.saveFile(filename); } } void CheatsView::addSet() { - GameController::Interrupter interrupter(m_controller); + CoreController::Interrupter interrupter(m_controller); mCheatSet* set = m_controller->cheatDevice()->createSet(m_controller->cheatDevice(), nullptr); m_model.addSet(set); } @@ -134,7 +134,7 @@ if (selection.count() < 1) { return; } - GameController::Interrupter interrupter(m_controller); + CoreController::Interrupter interrupter(m_controller); for (const QModelIndex& index : selection) { m_model.removeAt(selection[0]); } @@ -154,7 +154,7 @@ if (!set) { return; } - m_controller->threadInterrupt(); + CoreController::Interrupter interrupter(m_controller); if (selection.count() == 0) { m_model.addSet(set); index = m_model.index(m_model.rowCount() - 1, 0, QModelIndex()); @@ -167,6 +167,5 @@ m_model.endAppendRow(); } set->refresh(set, m_controller->cheatDevice()); - m_controller->threadContinue(); m_ui.codeEntry->clear(); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/CheatsView.h mgba-0.7.0/src/platform/qt/CheatsView.h --- mgba-0.6.3+dfsg1/src/platform/qt/CheatsView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/CheatsView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,12 +3,12 @@ * 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_CHEATS_VIEW -#define QGBA_CHEATS_VIEW +#pragma once #include #include +#include #include "CheatsModel.h" @@ -18,13 +18,13 @@ namespace QGBA { -class GameController; +class CoreController; class CheatsView : public QWidget { Q_OBJECT public: - CheatsView(GameController* controller, QWidget* parent = nullptr); + CheatsView(std::shared_ptr controller, QWidget* parent = nullptr); virtual bool eventFilter(QObject*, QEvent*) override; @@ -38,10 +38,8 @@ void enterCheat(int codeType); Ui::CheatsView m_ui; - GameController* m_controller; + std::shared_ptr m_controller; CheatsModel m_model; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/CMakeLists.txt mgba-0.7.0/src/platform/qt/CMakeLists.txt --- mgba-0.6.3+dfsg1/src/platform/qt/CMakeLists.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/CMakeLists.txt 2019-01-27 00:06:06.000000000 +0000 @@ -1,14 +1,12 @@ -if(NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -endif() +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) set(PLATFORM_SRC) set(QT_STATIC OFF) if(BUILD_SDL) - if(NOT SDL_FOUND AND NOT SDL2_FOUND) - find_package(SDL 1.2 REQUIRED) - endif() + add_definitions(-DBUILD_SDL) if(SDL2_FOUND) link_directories(${SDL2_LIBDIR}) endif() @@ -32,9 +30,9 @@ message(WARNING "OpenGL is recommended to build the Qt port") endif() +set(FOUND_QT ${Qt5Widgets_FOUND} PARENT_SCOPE) if(NOT Qt5Widgets_FOUND) message(WARNING "Cannot find Qt modules") - set(BUILD_QT OFF PARENT_SCOPE) return() endif() @@ -74,13 +72,15 @@ CheatsModel.cpp CheatsView.cpp ConfigController.cpp + ColorPicker.cpp + CoreManager.cpp + CoreController.cpp Display.cpp DisplayGL.cpp DisplayQt.cpp GBAApp.cpp GBAKeyEditor.cpp GIFView.cpp - GameController.cpp GamepadAxisEvent.cpp GamepadButtonEvent.cpp GamepadHatEvent.cpp @@ -91,6 +91,7 @@ LoadSaveState.cpp LogController.cpp LogView.cpp + MapView.cpp MemoryModel.cpp MemorySearch.cpp MemoryView.cpp @@ -99,6 +100,9 @@ ObjView.cpp OverrideView.cpp PaletteView.cpp + PlacementControl.cpp + PrinterView.cpp + RegisterView.cpp ROMInfo.cpp SavestateButton.cpp SensorView.cpp @@ -124,11 +128,14 @@ IOViewer.ui LoadSaveState.ui LogView.ui + MapView.ui MemorySearch.ui MemoryView.ui ObjView.ui OverrideView.ui PaletteView.ui + PlacementControl.ui + PrinterView.ui ROMInfo.ui SensorView.ui SettingsView.ui @@ -164,8 +171,11 @@ list(APPEND AUDIO_SRC AudioProcessorQt.cpp AudioDevice.cpp) + list(APPEND SOURCE_FILES + VideoDumper.cpp) if (WIN32 AND QT_STATIC) - list(APPEND QT_LIBRARIES qtaudio_windows strmiids) + list(APPEND QT_LIBRARIES Qt5::QWindowsAudioPlugin Qt5::DSServicePlugin + strmiids mfuuid mfplat mf ksguid dxva2 evr d3d9) endif() list(APPEND QT_LIBRARIES Qt5::Multimedia) list(APPEND QT_DEFINES BUILD_QT_MULTIMEDIA) @@ -259,15 +269,27 @@ qt5_wrap_ui(UI_SRC ${UI_FILES}) add_executable(${BINARY_NAME}-qt WIN32 MACOSX_BUNDLE main.cpp ${CMAKE_SOURCE_DIR}/res/mgba.icns ${SOURCE_FILES} ${PLATFORM_SRC} ${UI_SRC} ${AUDIO_SRC} ${RESOURCES}) -set_target_properties(${BINARY_NAME}-qt PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/res/info.plist.in COMPILE_DEFINITIONS "${FEATURE_DEFINES};${FUNCTION_DEFINES};${OS_DEFINES};${QT_DEFINES}") +set_target_properties(${BINARY_NAME}-qt PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/res/info.plist.in COMPILE_DEFINITIONS "${FEATURE_DEFINES};${FUNCTION_DEFINES};${OS_DEFINES};${QT_DEFINES}" COMPILE_OPTIONS "${FEATURE_FLAGS}") list(APPEND QT_LIBRARIES Qt5::Widgets) if(BUILD_GL OR BUILD_GLES2) list(APPEND QT_LIBRARIES Qt5::OpenGL ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) endif() -if(WIN32 AND QT_STATIC) - list(APPEND QT_LIBRARIES qwindows dwmapi imm32 uxtheme Qt5EventDispatcherSupport Qt5FontDatabaseSupport Qt5ThemeSupport) - set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "qtpcre2;version;winmm;ws2_32") +if(QT_STATIC) + find_library(QTPCRE NAMES qtpcre2 qtpcre) + if(WIN32) + list(APPEND QT_LIBRARIES qwindows dwmapi imm32 uxtheme Qt5EventDispatcherSupport Qt5FontDatabaseSupport Qt5ThemeSupport) + set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE};version;winmm;ws2_32") + elseif(APPLE) + find_package(Cups) + find_package(Qt5PrintSupport) + find_library(QTFREETYPE NAMES qtfreetype) + find_library(QTHARFBUZZ NAMES qtharfbuzzng qtharfbuzz) + find_library(QTPLATFORMSUPPORT NAMES Qt5PlatformSupport) + list(APPEND QT_LIBRARIES Cups Qt5::PrintSupport Qt5::QCocoaIntegrationPlugin Qt5::CoreAudioPlugin Qt5::AVFServicePlugin Qt5::QCocoaPrinterSupportPlugin ${QTPLATFORMSUPPORT} "-framework AVFoundation" "-framework CoreMedia") + set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE};${QTHARFBUZZ};${QTFREETYPE}") + link_directories() + endif() endif() target_link_libraries(${BINARY_NAME}-qt ${PLATFORM_LIBRARY} ${BINARY_NAME} ${QT_LIBRARIES}) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}" PARENT_SCOPE) @@ -278,7 +300,7 @@ if(UNIX AND NOT APPLE) find_program(DESKTOP_FILE_INSTALL desktop-file-install) if(DESKTOP_FILE_INSTALL) - install(CODE "execute_process(COMMAND ${DESKTOP_FILE_INSTALL} \"${CMAKE_SOURCE_DIR}/res/mgba-qt.desktop\" --dir \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/applications/\")") + install(CODE "execute_process(COMMAND ${DESKTOP_FILE_INSTALL} \"${CMAKE_SOURCE_DIR}/res/mgba-qt.desktop\" --dir \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/applications/\")" COMPONENT ${BINARY_NAME}-qt) endif() endif() if(UNIX) @@ -291,10 +313,12 @@ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") get_target_property(QTCOCOA Qt5::QCocoaIntegrationPlugin LOCATION) get_target_property(COREAUDIO Qt5::CoreAudioPlugin LOCATION) - get_target_property(BUNDLE_PATH ${BINARY_NAME}-qt LOCATION) + get_target_property(QTAVFSERVICE Qt5::AVFServicePlugin LOCATION) + set(BUNDLE_PATH ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.app) target_sources(${BINARY_NAME}-qt PRIVATE "${PLUGINS}") set_source_files_properties("${QTCOCOA}" PROPERTIES MACOSX_PACKAGE_LOCATION Contents/PlugIns) set_source_files_properties("${COREAUDIO}" PROPERTIES MACOSX_PACKAGE_LOCATION Contents/PlugIns) + set_source_files_properties("${QTAVFSERVICE}" PROPERTIES MACOSX_PACKAGE_LOCATION Contents/PlugIns) install(CODE " include(BundleUtilities) set(BU_CHMOD_BUNDLE_ITEMS ON) @@ -302,7 +326,7 @@ fixup_bundle(\"${BUNDLE_PATH}\" \"${PLUGINS}\" \"\") " COMPONENT ${BINARY_NAME}-qt) else() - set(DEPLOY_OPTIONS -p platforms/libqcocoa.dylib,audio/libqtaudio_coreaudio.dylib) + set(DEPLOY_OPTIONS -p platforms/libqcocoa.dylib,audio/libqtaudio_coreaudio.dylib,mediaservice/libqavfcamera.dylib) if(NOT CMAKE_INSTALL_NAME_TOOL EQUAL "install_name_tool") set(DEPLOY_OPTIONS ${DEPLOY_OPTIONS} -I "${CMAKE_INSTALL_NAME_TOOL}") endif() @@ -323,4 +347,16 @@ find_program(BASH bash) install(CODE "execute_process(COMMAND \"${BASH}\" \"${CMAKE_SOURCE_DIR}/tools/deploy-win.sh\" \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.exe\" \"\${CMAKE_INSTALL_PREFIX}\" \"\$ENV{PWD}\" WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}\")" COMPONENT ${BINARY_NAME}-qt) endif() + if(DISTBUILD) + file(WRITE "${CMAKE_BINARY_DIR}/portable.ini" "") + install(FILES "${CMAKE_BINARY_DIR}/portable.ini" DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT ${BINARY_NAME}-qt) + endif() +endif() + +if(DISTBUILD AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + if(NOT APPLE) + add_custom_command(TARGET ${BINARY_NAME}-qt POST_BUILD COMMAND "${OBJCOPY}" --only-keep-debug "$" "$.dSYM") + add_custom_command(TARGET ${BINARY_NAME}-qt POST_BUILD COMMAND "${STRIP}" -S "$") + install(FILES "$.dSYM" DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-qt-dbg) + endif() endif() diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ColorPicker.cpp mgba-0.7.0/src/platform/qt/ColorPicker.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/ColorPicker.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ColorPicker.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,60 @@ +/* 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 "ColorPicker.h" + +#include +#include + +using namespace QGBA; + +ColorPicker::ColorPicker() { +} + +ColorPicker::ColorPicker(QWidget* parent, const QColor& defaultColor) + : m_parent(parent) + , m_defaultColor(defaultColor) +{ + QPalette palette = parent->palette(); + palette.setColor(parent->backgroundRole(), defaultColor); + parent->setPalette(palette); + parent->installEventFilter(this); +} + +ColorPicker& ColorPicker::operator=(const ColorPicker& other) { + if (m_parent) { + m_parent->removeEventFilter(this); + } + m_parent = other.m_parent; + m_defaultColor = other.m_defaultColor; + m_parent->installEventFilter(this); + + return *this; +} + +bool ColorPicker::eventFilter(QObject* obj, QEvent* event) { + if (event->type() != QEvent::MouseButtonRelease) { + return false; + } + int colorId; + if (obj != m_parent) { + return false; + } + + QWidget* swatch = static_cast(obj); + + QColorDialog* colorPicker = new QColorDialog; + colorPicker->setAttribute(Qt::WA_DeleteOnClose); + colorPicker->setCurrentColor(m_defaultColor); + colorPicker->open(); + connect(colorPicker, &QColorDialog::colorSelected, [this, swatch](const QColor& color) { + m_defaultColor = color; + QPalette palette = swatch->palette(); + palette.setColor(swatch->backgroundRole(), color); + swatch->setPalette(palette); + emit colorChanged(color); + }); + return true; +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ColorPicker.h mgba-0.7.0/src/platform/qt/ColorPicker.h --- mgba-0.6.3+dfsg1/src/platform/qt/ColorPicker.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ColorPicker.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,35 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + +#include +#include + +class QWidget; + +namespace QGBA { + +class ColorPicker : public QObject { +Q_OBJECT + +public: + ColorPicker(); + ColorPicker(QWidget* parent, const QColor& defaultColor); + + ColorPicker& operator=(const ColorPicker&); + +signals: + void colorChanged(const QColor&); + +protected: + bool eventFilter(QObject* obj, QEvent* event) override; + +private: + QWidget* m_parent = nullptr; + QColor m_defaultColor; +}; + +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ConfigController.cpp mgba-0.7.0/src/platform/qt/ConfigController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/ConfigController.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ConfigController.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ConfigController.h" -#include "GameController.h" +#include "CoreController.h" #include #include @@ -98,8 +98,8 @@ mCoreConfigInit(&m_config, PORT); - m_opts.audioSync = GameController::AUDIO_SYNC; - m_opts.videoSync = GameController::VIDEO_SYNC; + m_opts.audioSync = CoreController::AUDIO_SYNC; + m_opts.videoSync = CoreController::VIDEO_SYNC; m_opts.fpsTarget = 60; m_opts.audioBuffers = 1536; m_opts.sampleRate = 44100; @@ -107,7 +107,6 @@ m_opts.logLevel = mLOG_WARN | mLOG_ERROR | mLOG_FATAL; m_opts.rewindEnable = false; m_opts.rewindBufferCapacity = 300; - m_opts.rewindSave = true; m_opts.useBios = true; m_opts.suspendScreensaver = true; m_opts.lockAspectRatio = true; @@ -158,12 +157,16 @@ m_optionSet[optionName]->setValue(mCoreConfigGetValue(&m_config, key)); } -QString ConfigController::getOption(const char* key) const { - return QString(mCoreConfigGetValue(&m_config, key)); +QString ConfigController::getOption(const char* key, const QVariant& defaultVal) const { + const char* val = mCoreConfigGetValue(&m_config, key); + if (val) { + return QString(val); + } + return defaultVal.toString(); } -QString ConfigController::getOption(const QString& key) const { - return getOption(key.toUtf8().constData()); +QString ConfigController::getOption(const QString& key, const QVariant& defaultVal) const { + return getOption(key.toUtf8().constData(), defaultVal); } QVariant ConfigController::getQtOption(const QString& key, const QString& group) const { diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ConfigController.h mgba-0.7.0/src/platform/qt/ConfigController.h --- mgba-0.6.3+dfsg1/src/platform/qt/ConfigController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ConfigController.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_CONFIG_CONTROLLER -#define QGBA_CONFIG_CONTROLLER +#pragma once #include "Override.h" @@ -70,8 +69,8 @@ ConfigOption* addOption(const char* key); void updateOption(const char* key); - QString getOption(const char* key) const; - QString getOption(const QString& key) const; + QString getOption(const char* key, const QVariant& defaultVal = QVariant()) const; + QString getOption(const QString& key, const QVariant& defaultVal = QVariant()) const; QVariant getQtOption(const QString& key, const QString& group = QString()) const; @@ -110,5 +109,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/CoreController.cpp mgba-0.7.0/src/platform/qt/CoreController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/CoreController.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/CoreController.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,882 @@ +/* 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 "CoreController.h" + +#include "ConfigController.h" +#include "InputController.h" +#include "LogController.h" +#include "MultiplayerController.h" +#include "Override.h" + +#include +#include + +#include +#include +#ifdef M_CORE_GBA +#include +#include +#include +#endif +#ifdef M_CORE_GB +#include +#include +#endif +#include +#include + +#define AUTOSAVE_GRANULARITY 600 + +using namespace QGBA; + +CoreController::CoreController(mCore* core, QObject* parent) + : QObject(parent) + , m_saveStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS | SAVESTATE_RTC) + , m_loadStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_RTC) +{ + m_threadContext.core = core; + m_threadContext.userData = this; + + QSize size(256, 512); + m_buffers[0].resize(size.width() * size.height() * sizeof(color_t)); + m_buffers[1].resize(size.width() * size.height() * sizeof(color_t)); + m_buffers[0].fill(0xFF); + m_buffers[1].fill(0xFF); + m_activeBuffer = &m_buffers[0]; + m_completeBuffer = m_buffers[0]; + + m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer->data()), size.width()); + + m_resetActions.append([this]() { + if (m_autoload) { + mCoreLoadState(m_threadContext.core, 0, m_loadStateFlags); + } + }); + + m_threadContext.startCallback = [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + + switch (context->core->platform(context->core)) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: + context->core->setPeripheral(context->core, mPERIPH_GBA_LUMINANCE, controller->m_inputController->luminance()); + break; +#endif + default: + break; + } + + controller->updateFastForward(); + + if (controller->m_multiplayer) { + controller->m_multiplayer->attachGame(controller); + } + + QMetaObject::invokeMethod(controller, "started"); + }; + + m_threadContext.resetCallback = [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + for (auto action : controller->m_resetActions) { + action(); + } + + if (controller->m_override) { + controller->m_override->identify(context->core); + controller->m_override->apply(context->core); + } + + controller->m_resetActions.clear(); + + controller->m_activeBuffer = &controller->m_buffers[0]; + context->core->setVideoBuffer(context->core, reinterpret_cast(controller->m_activeBuffer->data()), controller->screenDimensions().width()); + + controller->finishFrame(); + }; + + m_threadContext.frameCallback = [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + + if (controller->m_autosaveCounter == AUTOSAVE_GRANULARITY) { + if (controller->m_autosave) { + mCoreSaveState(context->core, 0, controller->m_saveStateFlags); + } + controller->m_autosaveCounter = 0; + } + ++controller->m_autosaveCounter; + + controller->finishFrame(); + }; + + m_threadContext.cleanCallback = [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + + if (controller->m_autosave) { + mCoreSaveState(context->core, 0, controller->m_saveStateFlags); + } + + controller->clearMultiplayerController(); + QMetaObject::invokeMethod(controller, "stopping"); + }; + + m_threadContext.pauseCallback = [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + + QMetaObject::invokeMethod(controller, "paused"); + }; + + m_threadContext.unpauseCallback = [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + + QMetaObject::invokeMethod(controller, "unpaused"); + }; + + m_threadContext.logger.d.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { + mThreadLogger* logContext = reinterpret_cast(logger); + mCoreThread* context = logContext->p; + + static const char* savestateMessage = "State %i saved"; + static const char* loadstateMessage = "State %i loaded"; + static const char* savestateFailedMessage = "State %i failed to load"; + static int biosCat = -1; + static int statusCat = -1; + if (!context) { + return; + } + CoreController* controller = static_cast(context->userData); + QString message; + if (biosCat < 0) { + biosCat = mLogCategoryById("gba.bios"); + } + if (statusCat < 0) { + statusCat = mLogCategoryById("core.status"); + } +#ifdef M_CORE_GBA + if (level == mLOG_STUB && category == biosCat) { + va_list argc; + va_copy(argc, args); + int immediate = va_arg(argc, int); + va_end(argc); + QMetaObject::invokeMethod(controller, "unimplementedBiosCall", Q_ARG(int, immediate)); + } else +#endif + if (category == statusCat) { + // Slot 0 is reserved for suspend points + if (strncmp(loadstateMessage, format, strlen(loadstateMessage)) == 0) { + va_list argc; + va_copy(argc, args); + int slot = va_arg(argc, int); + va_end(argc); + if (slot == 0) { + format = "Loaded suspend state"; + } + } else if (strncmp(savestateFailedMessage, format, strlen(savestateFailedMessage)) == 0 || strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) { + va_list argc; + va_copy(argc, args); + int slot = va_arg(argc, int); + va_end(argc); + if (slot == 0) { + return; + } + } + message = QString().vsprintf(format, args); + QMetaObject::invokeMethod(controller, "statusPosted", Q_ARG(const QString&, message)); + } + message = QString().vsprintf(format, args); + QMetaObject::invokeMethod(controller, "logPosted", Q_ARG(int, level), Q_ARG(int, category), Q_ARG(const QString&, message)); + if (level == mLOG_FATAL) { + mCoreThreadMarkCrashed(controller->thread()); + QMetaObject::invokeMethod(controller, "crashed", Q_ARG(const QString&, QString().vsprintf(format, args))); + } + }; +} + +CoreController::~CoreController() { + endVideoLog(); + stop(); + disconnect(); + + mCoreThreadJoin(&m_threadContext); + + if (m_cacheSet) { + mCacheSetDeinit(m_cacheSet.get()); + m_cacheSet.reset(); + } + + mCoreConfigDeinit(&m_threadContext.core->config); + m_threadContext.core->deinit(m_threadContext.core); +} + +const color_t* CoreController::drawContext() { + QMutexLocker locker(&m_mutex); + return reinterpret_cast(m_completeBuffer.constData()); +} + +bool CoreController::isPaused() { + return mCoreThreadIsPaused(&m_threadContext); +} + +bool CoreController::hasStarted() { + return mCoreThreadHasStarted(&m_threadContext); +} + +mPlatform CoreController::platform() const { + return m_threadContext.core->platform(m_threadContext.core); +} + +QSize CoreController::screenDimensions() const { + unsigned width, height; + m_threadContext.core->desiredVideoDimensions(m_threadContext.core, &width, &height); + + return QSize(width, height); +} + +void CoreController::loadConfig(ConfigController* config) { + Interrupter interrupter(this); + m_loadStateFlags = config->getOption("loadStateExtdata", m_loadStateFlags).toInt(); + m_saveStateFlags = config->getOption("saveStateExtdata", m_saveStateFlags).toInt(); + m_fastForwardRatio = config->getOption("fastForwardRatio", m_fastForwardRatio).toFloat(); + m_videoSync = config->getOption("videoSync", m_videoSync).toInt(); + m_audioSync = config->getOption("audioSync", m_audioSync).toInt(); + m_fpsTarget = config->getOption("fpsTarget").toFloat(); + m_autosave = config->getOption("autosave", false).toInt(); + m_autoload = config->getOption("autoload", true).toInt(); + m_autofireThreshold = config->getOption("autofireThreshold", m_autofireThreshold).toInt(); + m_fastForwardVolume = config->getOption("fastForwardVolume", -1).toInt(); + m_fastForwardMute = config->getOption("fastForwardMute", -1).toInt(); + mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "volume"); + mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "mute"); + mCoreLoadForeignConfig(m_threadContext.core, config->config()); + if (hasStarted()) { + updateFastForward(); + mCoreThreadRewindParamsChanged(&m_threadContext); + } +} + +#ifdef USE_DEBUGGERS +void CoreController::setDebugger(mDebugger* debugger) { + Interrupter interrupter(this); + if (debugger) { + mDebuggerAttach(debugger, m_threadContext.core); + } else { + m_threadContext.core->detachDebugger(m_threadContext.core); + } +} +#endif + +void CoreController::setMultiplayerController(MultiplayerController* controller) { + if (controller == m_multiplayer) { + return; + } + clearMultiplayerController(); + m_multiplayer = controller; + if (!mCoreThreadHasStarted(&m_threadContext)) { + return; + } + mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* thread) { + CoreController* controller = static_cast(thread->userData); + controller->m_multiplayer->attachGame(controller); + }); +} + +void CoreController::clearMultiplayerController() { + if (!m_multiplayer) { + return; + } + m_multiplayer->detachGame(this); + m_multiplayer = nullptr; +} + +mCacheSet* CoreController::graphicCaches() { + if (m_cacheSet) { + return m_cacheSet.get(); + } + Interrupter interrupter(this); + switch (platform()) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: { + GBA* gba = static_cast(m_threadContext.core->board); + m_cacheSet = std::make_unique(); + GBAVideoCacheInit(m_cacheSet.get()); + GBAVideoCacheAssociate(m_cacheSet.get(), &gba->video); + break; + } +#endif +#ifdef M_CORE_GB + case PLATFORM_GB: { + GB* gb = static_cast(m_threadContext.core->board); + m_cacheSet = std::make_unique(); + GBVideoCacheInit(m_cacheSet.get()); + GBVideoCacheAssociate(m_cacheSet.get(), &gb->video); + break; + } +#endif + default: + return nullptr; + } + return m_cacheSet.get(); +} + +void CoreController::setOverride(std::unique_ptr override) { + Interrupter interrupter(this); + m_override = std::move(override); + m_override->identify(m_threadContext.core); +} + +void CoreController::setInputController(InputController* inputController) { + m_inputController = inputController; + m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_ROTATION, m_inputController->rotationSource()); + m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_RUMBLE, m_inputController->rumble()); + m_threadContext.core->setPeripheral(m_threadContext.core, mPERIPH_IMAGE_SOURCE, m_inputController->imageSource()); +} + +void CoreController::setLogger(LogController* logger) { + disconnect(m_log); + m_log = logger; + m_threadContext.logger.d.filter = logger->filter(); + connect(this, &CoreController::logPosted, m_log, &LogController::postLog); +} + +void CoreController::start() { + if (!m_patched) { + mCoreAutoloadPatch(m_threadContext.core); + } + if (!mCoreThreadStart(&m_threadContext)) { + emit failed(); + emit stopping(); + } +} + +void CoreController::stop() { + setSync(false); +#ifdef USE_DEBUGGERS + setDebugger(nullptr); +#endif + setPaused(false); + mCoreThreadEnd(&m_threadContext); + emit stopping(); +} + +void CoreController::reset() { + bool wasPaused = isPaused(); + setPaused(false); + Interrupter interrupter(this); + mCoreThreadReset(&m_threadContext); + if (wasPaused) { + setPaused(true); + } +} + +void CoreController::setPaused(bool paused) { + if (paused == isPaused()) { + return; + } + if (paused) { + QMutexLocker locker(&m_mutex); + m_frameActions.append([this]() { + mCoreThreadPauseFromThread(&m_threadContext); + }); + } else { + mCoreThreadUnpause(&m_threadContext); + } +} + +void CoreController::frameAdvance() { + QMutexLocker locker(&m_mutex); + m_frameActions.append([this]() { + mCoreThreadPauseFromThread(&m_threadContext); + }); + setPaused(false); +} + +void CoreController::setSync(bool sync) { + if (sync) { + m_threadContext.impl->sync.audioWait = m_audioSync; + m_threadContext.impl->sync.videoFrameWait = m_videoSync; + } else { + m_threadContext.impl->sync.audioWait = false; + m_threadContext.impl->sync.videoFrameWait = false; + } +} + +void CoreController::setRewinding(bool rewind) { + if (!m_threadContext.core->opts.rewindEnable) { + return; + } + if (rewind && m_multiplayer && m_multiplayer->attached() > 1) { + return; + } + + if (rewind && isPaused()) { + setPaused(false); + // TODO: restore autopausing + } + mCoreThreadSetRewinding(&m_threadContext, rewind); +} + +void CoreController::rewind(int states) { + { + Interrupter interrupter(this); + if (!states) { + states = INT_MAX; + } + for (int i = 0; i < states; ++i) { + if (!mCoreRewindRestore(&m_threadContext.impl->rewind, m_threadContext.core)) { + break; + } + } + } + emit frameAvailable(); + emit rewound(); +} + +void CoreController::setFastForward(bool enable) { + m_fastForward = enable; + updateFastForward(); +} + +void CoreController::forceFastForward(bool enable) { + m_fastForwardForced = enable; + updateFastForward(); +} + +void CoreController::loadState(int slot) { + if (slot > 0 && slot != m_stateSlot) { + m_stateSlot = slot; + m_backupSaveState.clear(); + } + mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + if (!controller->m_backupLoadState.isOpen()) { + controller->m_backupLoadState = VFileMemChunk(nullptr, 0); + } + mCoreSaveStateNamed(context->core, controller->m_backupLoadState, controller->m_saveStateFlags); + if (mCoreLoadState(context->core, controller->m_stateSlot, controller->m_loadStateFlags)) { + emit controller->frameAvailable(); + emit controller->stateLoaded(); + } + }); +} + +void CoreController::loadState(const QString& path) { + m_statePath = path; + mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + VFile* vf = VFileDevice::open(controller->m_statePath, O_RDONLY); + if (!vf) { + return; + } + if (!controller->m_backupLoadState.isOpen()) { + controller->m_backupLoadState = VFileMemChunk(nullptr, 0); + } + mCoreSaveStateNamed(context->core, controller->m_backupLoadState, controller->m_saveStateFlags); + if (mCoreLoadStateNamed(context->core, vf, controller->m_loadStateFlags)) { + emit controller->frameAvailable(); + emit controller->stateLoaded(); + } + vf->close(vf); + }); +} + +void CoreController::saveState(int slot) { + if (slot > 0) { + m_stateSlot = slot; + } + mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + VFile* vf = mCoreGetState(context->core, controller->m_stateSlot, false); + if (vf) { + controller->m_backupSaveState.resize(vf->size(vf)); + vf->read(vf, controller->m_backupSaveState.data(), controller->m_backupSaveState.size()); + vf->close(vf); + } + mCoreSaveState(context->core, controller->m_stateSlot, controller->m_saveStateFlags); + }); +} + +void CoreController::saveState(const QString& path) { + m_statePath = path; + mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + VFile* vf = VFileDevice::open(controller->m_statePath, O_RDONLY); + if (vf) { + controller->m_backupSaveState.resize(vf->size(vf)); + vf->read(vf, controller->m_backupSaveState.data(), controller->m_backupSaveState.size()); + vf->close(vf); + } + vf = VFileDevice::open(controller->m_statePath, O_WRONLY | O_CREAT | O_TRUNC); + if (!vf) { + return; + } + mCoreSaveStateNamed(context->core, vf, controller->m_saveStateFlags); + vf->close(vf); + }); +} + +void CoreController::loadBackupState() { + if (!m_backupLoadState.isOpen()) { + return; + } + + mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + controller->m_backupLoadState.seek(0); + if (mCoreLoadStateNamed(context->core, controller->m_backupLoadState, controller->m_loadStateFlags)) { + mLOG(STATUS, INFO, "Undid state load"); + controller->frameAvailable(); + controller->stateLoaded(); + } + controller->m_backupLoadState.close(); + }); +} + +void CoreController::saveBackupState() { + if (m_backupSaveState.isEmpty()) { + return; + } + + mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { + CoreController* controller = static_cast(context->userData); + VFile* vf = mCoreGetState(context->core, controller->m_stateSlot, true); + if (vf) { + vf->write(vf, controller->m_backupSaveState.constData(), controller->m_backupSaveState.size()); + vf->close(vf); + mLOG(STATUS, INFO, "Undid state save"); + } + controller->m_backupSaveState.clear(); + }); +} + +void CoreController::loadSave(const QString& path, bool temporary) { + m_resetActions.append([this, path, temporary]() { + VFile* vf = VFileDevice::open(path, temporary ? O_RDONLY : O_RDWR); + if (!vf) { + LOG(QT, ERROR) << tr("Failed to open save file: %1").arg(path); + return; + } + + if (temporary) { + m_threadContext.core->loadTemporarySave(m_threadContext.core, vf); + } else { + m_threadContext.core->loadSave(m_threadContext.core, vf); + } + }); + reset(); +} + +void CoreController::loadPatch(const QString& patchPath) { + Interrupter interrupter(this); + VFile* patch = VFileDevice::open(patchPath, O_RDONLY); + if (patch) { + m_threadContext.core->loadPatch(m_threadContext.core, patch); + m_patched = true; + patch->close(patch); + } + if (mCoreThreadHasStarted(&m_threadContext)) { + reset(); + } +} + +void CoreController::replaceGame(const QString& path) { + QFileInfo info(path); + if (!info.isReadable()) { + LOG(QT, ERROR) << tr("Failed to open game file: %1").arg(path); + return; + } + QString fname = info.canonicalFilePath(); + Interrupter interrupter(this); + mDirectorySetDetachBase(&m_threadContext.core->dirs); + mCoreLoadFile(m_threadContext.core, fname.toUtf8().constData()); +} + +void CoreController::yankPak() { +#ifdef M_CORE_GBA + if (platform() != PLATFORM_GBA) { + return; + } + Interrupter interrupter(this); + GBAYankROM(static_cast(m_threadContext.core->board)); +#endif +} + +void CoreController::addKey(int key) { + m_activeKeys |= 1 << key; +} + +void CoreController::clearKey(int key) { + m_activeKeys &= ~(1 << key); +} + +void CoreController::setAutofire(int key, bool enable) { + if (key >= 32 || key < 0) { + return; + } + + m_autofire[key] = enable; + m_autofireStatus[key] = 0; +} + +#ifdef USE_PNG +void CoreController::screenshot() { + mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { + mCoreTakeScreenshot(context->core); + }); +} +#endif + +void CoreController::setRealTime() { + m_threadContext.core->rtc.override = RTC_NO_OVERRIDE; +} + +void CoreController::setFixedTime(const QDateTime& time) { + m_threadContext.core->rtc.override = RTC_FIXED; + m_threadContext.core->rtc.value = time.toMSecsSinceEpoch(); +} + +void CoreController::setFakeEpoch(const QDateTime& time) { + m_threadContext.core->rtc.override = RTC_FAKE_EPOCH; + m_threadContext.core->rtc.value = time.toMSecsSinceEpoch(); +} + +void CoreController::importSharkport(const QString& path) { +#ifdef M_CORE_GBA + if (platform() != PLATFORM_GBA) { + return; + } + VFile* vf = VFileDevice::open(path, O_RDONLY); + if (!vf) { + LOG(QT, ERROR) << tr("Failed to open snapshot file for reading: %1").arg(path); + return; + } + Interrupter interrupter(this); + GBASavedataImportSharkPort(static_cast(m_threadContext.core->board), vf, false); + vf->close(vf); +#endif +} + +void CoreController::exportSharkport(const QString& path) { +#ifdef M_CORE_GBA + if (platform() != PLATFORM_GBA) { + return; + } + VFile* vf = VFileDevice::open(path, O_WRONLY | O_CREAT | O_TRUNC); + if (!vf) { + LOG(QT, ERROR) << tr("Failed to open snapshot file for writing: %1").arg(path); + return; + } + Interrupter interrupter(this); + GBASavedataExportSharkPort(static_cast(m_threadContext.core->board), vf); + vf->close(vf); +#endif +} + +void CoreController::attachPrinter() { +#ifdef M_CORE_GB + if (platform() != PLATFORM_GB) { + return; + } + GB* gb = static_cast(m_threadContext.core->board); + clearMultiplayerController(); + GBPrinterCreate(&m_printer.d); + m_printer.parent = this; + m_printer.d.print = [](GBPrinter* printer, int height, const uint8_t* data) { + QGBPrinter* qPrinter = reinterpret_cast(printer); + QImage image(GB_VIDEO_HORIZONTAL_PIXELS, height, QImage::Format_Indexed8); + QVector colors; + colors.append(qRgb(0xF8, 0xF8, 0xF8)); + colors.append(qRgb(0xA8, 0xA8, 0xA8)); + colors.append(qRgb(0x50, 0x50, 0x50)); + colors.append(qRgb(0x00, 0x00, 0x00)); + image.setColorTable(colors); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < GB_VIDEO_HORIZONTAL_PIXELS; x += 4) { + uint8_t byte = data[(x + y * GB_VIDEO_HORIZONTAL_PIXELS) / 4]; + image.setPixel(x + 0, y, (byte & 0xC0) >> 6); + image.setPixel(x + 1, y, (byte & 0x30) >> 4); + image.setPixel(x + 2, y, (byte & 0x0C) >> 2); + image.setPixel(x + 3, y, (byte & 0x03) >> 0); + } + } + QMetaObject::invokeMethod(qPrinter->parent, "imagePrinted", Q_ARG(const QImage&, image)); + }; + Interrupter interrupter(this); + GBSIOSetDriver(&gb->sio, &m_printer.d.d); +#endif +} + +void CoreController::detachPrinter() { +#ifdef M_CORE_GB + if (platform() != PLATFORM_GB) { + return; + } + Interrupter interrupter(this); + GB* gb = static_cast(m_threadContext.core->board); + GBPrinterDonePrinting(&m_printer.d); + GBSIOSetDriver(&gb->sio, nullptr); +#endif +} + +void CoreController::endPrint() { +#ifdef M_CORE_GB + if (platform() != PLATFORM_GB) { + return; + } + Interrupter interrupter(this); + GBPrinterDonePrinting(&m_printer.d); +#endif +} + +void CoreController::setAVStream(mAVStream* stream) { + Interrupter interrupter(this); + m_threadContext.core->setAVStream(m_threadContext.core, stream); +} + +void CoreController::clearAVStream() { + Interrupter interrupter(this); + m_threadContext.core->setAVStream(m_threadContext.core, nullptr); +} + +void CoreController::clearOverride() { + m_override.reset(); +} + +void CoreController::startVideoLog(const QString& path) { + if (m_vl) { + return; + } + + Interrupter interrupter(this); + m_vl = mVideoLogContextCreate(m_threadContext.core); + m_vlVf = VFileDevice::open(path, O_WRONLY | O_CREAT | O_TRUNC); + mVideoLogContextSetOutput(m_vl, m_vlVf); + mVideoLogContextWriteHeader(m_vl, m_threadContext.core); +} + +void CoreController::endVideoLog() { + if (!m_vl) { + return; + } + + Interrupter interrupter(this); + mVideoLogContextDestroy(m_threadContext.core, m_vl); + if (m_vlVf) { + m_vlVf->close(m_vlVf); + m_vlVf = nullptr; + } + m_vl = nullptr; +} + +void CoreController::updateKeys() { + int activeKeys = m_activeKeys | updateAutofire() | m_inputController->pollEvents(); + m_threadContext.core->setKeys(m_threadContext.core, activeKeys); +} + +int CoreController::updateAutofire() { + int active = 0; + for (int k = 0; k < 32; ++k) { + if (!m_autofire[k]) { + continue; + } + ++m_autofireStatus[k]; + if (m_autofireStatus[k] >= 2 * m_autofireThreshold) { + m_autofireStatus[k] = 0; + } else if (m_autofireStatus[k] >= m_autofireThreshold) { + active |= 1 << k; + } + } + return active; +} + +void CoreController::finishFrame() { + QMutexLocker locker(&m_mutex); + memcpy(m_completeBuffer.data(), m_activeBuffer->constData(), m_activeBuffer->size()); + + // TODO: Generalize this to triple buffering? + m_activeBuffer = &m_buffers[0]; + if (m_activeBuffer == m_completeBuffer) { + m_activeBuffer = &m_buffers[1]; + } + // Copy contents to avoid issues when doing frameskip + memcpy(m_activeBuffer->data(), m_completeBuffer.constData(), m_activeBuffer->size()); + m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer->data()), screenDimensions().width()); + + for (auto& action : m_frameActions) { + action(); + } + m_frameActions.clear(); + updateKeys(); + + QMetaObject::invokeMethod(this, "frameAvailable"); +} + +void CoreController::updateFastForward() { + if (m_fastForward || m_fastForwardForced) { + if (m_fastForwardVolume >= 0) { + m_threadContext.core->opts.volume = m_fastForwardVolume; + } + if (m_fastForwardMute >= 0) { + m_threadContext.core->opts.mute = m_fastForwardMute; + } + if (m_fastForwardRatio > 0) { + m_threadContext.impl->sync.fpsTarget = m_fpsTarget * m_fastForwardRatio; + } else { + setSync(false); + } + } else { + if (!mCoreConfigGetIntValue(&m_threadContext.core->config, "volume", &m_threadContext.core->opts.volume)) { + m_threadContext.core->opts.volume = 0x100; + } + int fakeBool = 0; + mCoreConfigGetIntValue(&m_threadContext.core->config, "mute", &fakeBool); + m_threadContext.core->opts.mute = fakeBool; + m_threadContext.impl->sync.fpsTarget = m_fpsTarget; + setSync(true); + } + // XXX: Have a way of just updating opts + m_threadContext.core->loadConfig(m_threadContext.core, &m_threadContext.core->config); +} + +CoreController::Interrupter::Interrupter(CoreController* parent, bool fromThread) + : m_parent(parent) +{ + if (!m_parent->thread()->impl) { + return; + } + if (!fromThread) { + mCoreThreadInterrupt(m_parent->thread()); + } else { + mCoreThreadInterruptFromThread(m_parent->thread()); + } +} + +CoreController::Interrupter::Interrupter(std::shared_ptr parent, bool fromThread) + : m_parent(parent.get()) +{ + if (!m_parent->thread()->impl) { + return; + } + if (!fromThread) { + mCoreThreadInterrupt(m_parent->thread()); + } else { + mCoreThreadInterruptFromThread(m_parent->thread()); + } +} + +CoreController::Interrupter::Interrupter(const Interrupter& other) + : m_parent(other.m_parent) +{ + if (!m_parent->thread()->impl) { + return; + } + mCoreThreadInterrupt(m_parent->thread()); +} + +CoreController::Interrupter::~Interrupter() { + if (!m_parent->thread()->impl) { + return; + } + mCoreThreadContinue(m_parent->thread()); +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/CoreController.h mgba-0.7.0/src/platform/qt/CoreController.h --- mgba-0.6.3+dfsg1/src/platform/qt/CoreController.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/CoreController.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,227 @@ +/* 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/. */ +#pragma once + +#include +#include +#include +#include +#include + +#include "VFileDevice.h" + +#include +#include + +#include +#include +#include +#include + +#ifdef M_CORE_GB +#include +#endif + +struct mCore; + +namespace QGBA { + +class ConfigController; +class InputController; +class LogController; +class MultiplayerController; +class Override; + +class CoreController : public QObject { +Q_OBJECT + +public: + static const bool VIDEO_SYNC = false; + static const bool AUDIO_SYNC = true; + + class Interrupter { + public: + Interrupter(CoreController*, bool fromThread = false); + Interrupter(std::shared_ptr, bool fromThread = false); + Interrupter(const Interrupter&); + ~Interrupter(); + + private: + CoreController* m_parent; + }; + + CoreController(mCore* core, QObject* parent = nullptr); + ~CoreController(); + + mCoreThread* thread() { return &m_threadContext; } + + const color_t* drawContext(); + + bool isPaused(); + bool hasStarted(); + + mPlatform platform() const; + QSize screenDimensions() const; + + void loadConfig(ConfigController*); + + mCheatDevice* cheatDevice() { return m_threadContext.core->cheatDevice(m_threadContext.core); } + +#ifdef USE_DEBUGGERS + mDebugger* debugger() { return m_threadContext.core->debugger; } + void setDebugger(mDebugger*); +#endif + + void setMultiplayerController(MultiplayerController*); + void clearMultiplayerController(); + MultiplayerController* multiplayerController() { return m_multiplayer; } + + mCacheSet* graphicCaches(); + int stateSlot() const { return m_stateSlot; } + + void setOverride(std::unique_ptr override); + Override* override() { return m_override.get(); } + + void setInputController(InputController*); + void setLogger(LogController*); + +public slots: + void start(); + void stop(); + void reset(); + void setPaused(bool paused); + void frameAdvance(); + void setSync(bool enable); + + void setRewinding(bool); + void rewind(int count = 0); + + void setFastForward(bool); + void forceFastForward(bool); + + void loadState(int slot = 0); + void loadState(const QString& path); + void saveState(int slot = 0); + void saveState(const QString& path); + void loadBackupState(); + void saveBackupState(); + + void loadSave(const QString&, bool temporary); + void loadPatch(const QString&); + void replaceGame(const QString&); + void yankPak(); + + void addKey(int key); + void clearKey(int key); + void setAutofire(int key, bool enable); + +#ifdef USE_PNG + void screenshot(); +#endif + + void setRealTime(); + void setFixedTime(const QDateTime& time); + void setFakeEpoch(const QDateTime& time); + + void importSharkport(const QString& path); + void exportSharkport(const QString& path); + + void attachPrinter(); + void detachPrinter(); + void endPrint(); + + void setAVStream(mAVStream*); + void clearAVStream(); + + void clearOverride(); + + void startVideoLog(const QString& path); + void endVideoLog(); + +signals: + void started(); + void paused(); + void unpaused(); + void stopping(); + void crashed(const QString& errorMessage); + void failed(); + void frameAvailable(); + void stateLoaded(); + void rewound(); + + void rewindChanged(bool); + void fastForwardChanged(bool); + + void unimplementedBiosCall(int); + void statusPosted(const QString& message); + void logPosted(int level, int category, const QString& log); + + void imagePrinted(const QImage&); + +private: + void updateKeys(); + int updateAutofire(); + void finishFrame(); + + void updateFastForward(); + + mCoreThread m_threadContext{}; + + bool m_patched = false; + + QByteArray m_buffers[2]; + QByteArray* m_activeBuffer; + QByteArray m_completeBuffer; + + std::unique_ptr m_cacheSet; + std::unique_ptr m_override; + + QList> m_resetActions; + QList> m_frameActions; + QMutex m_mutex; + + int m_activeKeys = 0; + bool m_autofire[32] = {}; + int m_autofireStatus[32] = {}; + int m_autofireThreshold = 1; + + VFileDevice m_backupLoadState; + QByteArray m_backupSaveState{nullptr}; + int m_stateSlot = 1; + QString m_statePath; + int m_loadStateFlags; + int m_saveStateFlags; + + bool m_audioSync = AUDIO_SYNC; + bool m_videoSync = VIDEO_SYNC; + + bool m_autosave; + bool m_autoload; + int m_autosaveCounter; + + int m_fastForward = false; + int m_fastForwardForced = false; + int m_fastForwardVolume = -1; + int m_fastForwardMute = -1; + float m_fastForwardRatio = -1.f; + float m_fpsTarget; + + InputController* m_inputController = nullptr; + LogController* m_log = nullptr; + MultiplayerController* m_multiplayer = nullptr; + + mVideoLogContext* m_vl = nullptr; + VFile* m_vlVf = nullptr; + +#ifdef M_CORE_GB + struct QGBPrinter { + GBPrinter d; + CoreController* parent; + } m_printer; +#endif +}; + +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/CoreManager.cpp mgba-0.7.0/src/platform/qt/CoreManager.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/CoreManager.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/CoreManager.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,169 @@ +/* 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 "CoreManager.h" + +#include "CoreController.h" +#include "LogController.h" + +#include + +#ifdef M_CORE_GBA +#include +#endif + +#include +#include + +using namespace QGBA; + +void CoreManager::setConfig(const mCoreConfig* config) { + m_config = config; +} + +void CoreManager::setMultiplayerController(MultiplayerController* multiplayer) { + m_multiplayer = multiplayer; +} + +CoreController* CoreManager::loadGame(const QString& path) { + QFileInfo info(path); + if (!info.isReadable()) { + QString fname = info.fileName(); + QString base = info.path(); + if (base.endsWith("/") || base.endsWith(QDir::separator())) { + base.chop(1); + } + VDir* dir = VDirOpenArchive(base.toUtf8().constData()); + if (dir) { + VFile* vf = dir->openFile(dir, fname.toUtf8().constData(), O_RDONLY); + if (vf) { + struct VFile* vfclone = VFileMemChunk(NULL, vf->size(vf)); + uint8_t buffer[2048]; + ssize_t read; + while ((read = vf->read(vf, buffer, sizeof(buffer))) > 0) { + vfclone->write(vfclone, buffer, read); + } + vf->close(vf); + vf = vfclone; + } + dir->close(dir); + loadGame(vf, fname, base); + } else { + LOG(QT, ERROR) << tr("Failed to open game file: %1").arg(path); + } + return nullptr; + } + VFile* vf = nullptr; + VDir* archive = VDirOpenArchive(path.toUtf8().constData()); + if (archive) { + VFile* vfOriginal = VDirFindFirst(archive, [](VFile* vf) { + return mCoreIsCompatible(vf) != PLATFORM_NONE; + }); + ssize_t size; + if (vfOriginal && (size = vfOriginal->size(vfOriginal)) > 0) { + void* mem = vfOriginal->map(vfOriginal, size, MAP_READ); + vf = VFileMemChunk(mem, size); + vfOriginal->unmap(vfOriginal, mem, (size_t) read); + vfOriginal->close(vfOriginal); + } + } + QDir dir(info.dir()); + if (!vf) { + vf = VFileOpen(info.canonicalFilePath().toUtf8().constData(), O_RDONLY); + } + return loadGame(vf, info.fileName(), dir.canonicalPath()); +} + +CoreController* CoreManager::loadGame(VFile* vf, const QString& path, const QString& base) { + if (!vf) { + return nullptr; + } + + mCore* core = mCoreFindVF(vf); + if (!core) { + return nullptr; + } + + core->init(core); + mCoreInitConfig(core, nullptr); + + if (m_config) { + mCoreLoadForeignConfig(core, m_config); + } + + if (m_preload) { + mCorePreloadVF(core, vf); + } else { + core->loadROM(core, vf); + } + + QByteArray bytes(path.toUtf8()); + separatePath(bytes.constData(), nullptr, core->dirs.baseName, nullptr); + + QFileInfo info(base); + if (info.isDir()) { + info = QFileInfo(base + "/" + path); + } + bytes = info.dir().canonicalPath().toUtf8(); + mDirectorySetAttachBase(&core->dirs, VDirOpen(bytes.constData())); + mCoreAutoloadSave(core); + mCoreAutoloadCheats(core); + + CoreController* cc = new CoreController(core); + if (m_multiplayer) { + cc->setMultiplayerController(m_multiplayer); + } + emit coreLoaded(cc); + return cc; +} + +CoreController* CoreManager::loadBIOS(int platform, const QString& path) { + QFileInfo info(path); + VFile* vf = VFileOpen(info.canonicalFilePath().toUtf8().constData(), O_RDONLY); + if (!vf) { + return nullptr; + } + + mCore* core = nullptr; + switch (platform) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: + core = GBACoreCreate(); + break; +#endif + default: + vf->close(vf); + return nullptr; + } + if (!core) { + vf->close(vf); + return nullptr; + } + + core->init(core); + mCoreInitConfig(core, nullptr); + + if (m_config) { + mCoreLoadForeignConfig(core, m_config); + } + + core->loadBIOS(core, vf, 0); + + mCoreConfigSetOverrideIntValue(&core->config, "useBios", 1); + mCoreConfigSetOverrideIntValue(&core->config, "skipBios", 0); + + QByteArray bytes(info.baseName().toUtf8()); + strncpy(core->dirs.baseName, bytes.constData(), sizeof(core->dirs.baseName)); + + bytes = info.dir().canonicalPath().toUtf8(); + mDirectorySetAttachBase(&core->dirs, VDirOpen(bytes.constData())); + + CoreController* cc = new CoreController(core); + if (m_multiplayer) { + cc->setMultiplayerController(m_multiplayer); + } + emit coreLoaded(cc); + return cc; +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/CoreManager.h mgba-0.7.0/src/platform/qt/CoreManager.h --- mgba-0.6.3+dfsg1/src/platform/qt/CoreManager.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/CoreManager.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,42 @@ +/* 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/. */ +#pragma once + +#include +#include +#include + +struct mCoreConfig; +struct VFile; + +namespace QGBA { + +class CoreController; +class MultiplayerController; + +class CoreManager : public QObject { +Q_OBJECT + +public: + void setConfig(const mCoreConfig*); + void setMultiplayerController(MultiplayerController*); + void setPreload(bool preload) { m_preload = preload; } + +public slots: + CoreController* loadGame(const QString& path); + CoreController* loadGame(VFile* vf, const QString& path, const QString& base); + CoreController* loadBIOS(int platform, const QString& path); + +signals: + void coreLoaded(CoreController*); + +private: + const mCoreConfig* m_config = nullptr; + MultiplayerController* m_multiplayer = nullptr; + bool m_preload = false; +}; + +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DebuggerConsoleController.cpp mgba-0.7.0/src/platform/qt/DebuggerConsoleController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/DebuggerConsoleController.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DebuggerConsoleController.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "DebuggerConsoleController.h" -#include "GameController.h" +#include "CoreController.h" #include @@ -13,8 +13,8 @@ using namespace QGBA; -DebuggerConsoleController::DebuggerConsoleController(GameController* controller, QObject* parent) - : DebuggerController(controller, &m_cliDebugger.d, parent) +DebuggerConsoleController::DebuggerConsoleController(QObject* parent) + : DebuggerController(&m_cliDebugger.d, parent) { m_backend.d.printf = printf; m_backend.d.init = init; @@ -79,7 +79,7 @@ const char* DebuggerConsoleController::readLine(struct CLIDebuggerBackend* be, size_t* len) { Backend* consoleBe = reinterpret_cast(be); DebuggerConsoleController* self = consoleBe->self; - GameController::Interrupter interrupter(self->m_gameController, true); + CoreController::Interrupter interrupter(self->m_gameController, true); QMutexLocker lock(&self->m_mutex); while (self->m_lines.isEmpty()) { self->m_cond.wait(&self->m_mutex); @@ -103,7 +103,7 @@ const char* DebuggerConsoleController::historyLast(struct CLIDebuggerBackend* be, size_t* len) { Backend* consoleBe = reinterpret_cast(be); DebuggerConsoleController* self = consoleBe->self; - GameController::Interrupter interrupter(self->m_gameController, true); + CoreController::Interrupter interrupter(self->m_gameController, true); QMutexLocker lock(&self->m_mutex); if (self->m_history.isEmpty()) { return "i"; @@ -115,7 +115,7 @@ void DebuggerConsoleController::historyAppend(struct CLIDebuggerBackend* be, const char* line) { Backend* consoleBe = reinterpret_cast(be); DebuggerConsoleController* self = consoleBe->self; - GameController::Interrupter interrupter(self->m_gameController, true); + CoreController::Interrupter interrupter(self->m_gameController, true); QMutexLocker lock(&self->m_mutex); self->m_history.append(QString::fromUtf8(line)); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DebuggerConsoleController.h mgba-0.7.0/src/platform/qt/DebuggerConsoleController.h --- mgba-0.6.3+dfsg1/src/platform/qt/DebuggerConsoleController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DebuggerConsoleController.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_DEBUGGER_CONSOLE_CONTROLLER -#define QGBA_DEBUGGER_CONSOLE_CONTROLLER +#pragma once #include "DebuggerController.h" @@ -16,13 +15,13 @@ namespace QGBA { -class GameController; +class CoreController; class DebuggerConsoleController : public DebuggerController { Q_OBJECT public: - DebuggerConsoleController(GameController* controller, QObject* parent = nullptr); + DebuggerConsoleController(QObject* parent = nullptr); signals: void log(const QString&); @@ -44,7 +43,7 @@ static const char* historyLast(struct CLIDebuggerBackend* be, size_t* len); static void historyAppend(struct CLIDebuggerBackend* be, const char* line); - CLIDebugger m_cliDebugger; + CLIDebugger m_cliDebugger{}; QMutex m_mutex; QWaitCondition m_cond; @@ -59,5 +58,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DebuggerConsole.cpp mgba-0.7.0/src/platform/qt/DebuggerConsole.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/DebuggerConsole.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DebuggerConsole.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -17,6 +17,8 @@ { m_ui.setupUi(this); + m_ui.prompt->installEventFilter(this); + connect(m_ui.prompt, &QLineEdit::returnPressed, this, &DebuggerConsole::postLine); connect(controller, &DebuggerConsoleController::log, this, &DebuggerConsole::log); connect(m_ui.breakpoint, &QAbstractButton::clicked, controller, &DebuggerController::attach); @@ -36,7 +38,47 @@ if (line.isEmpty()) { m_consoleController->enterLine(QString("\n")); } else { + m_history.append(line); + m_historyOffset = 0; log(QString("> %1\n").arg(line)); m_consoleController->enterLine(line); } } + +bool DebuggerConsole::eventFilter(QObject*, QEvent* event) { + if (event->type() != QEvent::KeyPress) { + return false; + } + if (m_history.isEmpty()) { + return false; + } + QKeyEvent* keyEvent = static_cast(event); + switch (keyEvent->key()) { + case Qt::Key_Down: + if (m_historyOffset <= 0) { + return false; + } + --m_historyOffset; + break; + case Qt::Key_Up: + if (m_historyOffset >= m_history.size()) { + return false; + } + ++m_historyOffset; + break; + case Qt::Key_End: + m_historyOffset = 0; + break; + case Qt::Key_Home: + m_historyOffset = m_history.size(); + break; + default: + return false; + } + if (m_historyOffset == 0) { + m_ui.prompt->clear(); + } else { + m_ui.prompt->setText(m_history[m_history.size() - m_historyOffset]); + } + return true; +} \ No newline at end of file diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DebuggerConsole.h mgba-0.7.0/src/platform/qt/DebuggerConsole.h --- mgba-0.6.3+dfsg1/src/platform/qt/DebuggerConsole.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DebuggerConsole.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_DEBUGGER_CONSOLE -#define QGBA_DEBUGGER_CONSOLE +#pragma once #include "ui_DebuggerConsole.h" @@ -22,12 +21,15 @@ void log(const QString&); void postLine(); +protected: + bool eventFilter(QObject*, QEvent*) override; + private: Ui::DebuggerConsole m_ui; + QStringList m_history; + int m_historyOffset; DebuggerConsoleController* m_consoleController; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DebuggerController.cpp mgba-0.7.0/src/platform/qt/DebuggerController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/DebuggerController.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DebuggerController.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,59 +5,80 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GDBController.h" -#include "GameController.h" +#include "CoreController.h" using namespace QGBA; -DebuggerController::DebuggerController(GameController* controller, mDebugger* debugger, QObject* parent) +DebuggerController::DebuggerController(mDebugger* debugger, QObject* parent) : QObject(parent) , m_debugger(debugger) - , m_gameController(controller) { } bool DebuggerController::isAttached() { + if (!m_gameController) { + return false; + } return m_gameController->debugger() == m_debugger; } +void DebuggerController::setController(std::shared_ptr controller) { + if (m_gameController && controller != m_gameController) { + m_gameController->disconnect(this); + detach(); + } + m_gameController = controller; + if (controller) { + connect(m_gameController.get(), &CoreController::stopping, [this]() { + setController(nullptr); + }); + if (m_autoattach) { + m_autoattach = false; + attach(); + } + } +} + void DebuggerController::attach() { if (isAttached()) { return; } - if (m_gameController->isLoaded()) { + if (m_gameController) { attachInternal(); m_gameController->setDebugger(m_debugger); mDebuggerEnter(m_debugger, DEBUGGER_ENTER_ATTACHED, 0); } else { - QObject::disconnect(m_autoattach); - m_autoattach = connect(m_gameController, &GameController::gameStarted, this, &DebuggerController::attach); + m_autoattach = true; } } void DebuggerController::detach() { - QObject::disconnect(m_autoattach); if (!isAttached()) { return; } - GameController::Interrupter interrupter(m_gameController); - shutdownInternal(); - m_gameController->setDebugger(nullptr); + if (m_gameController) { + CoreController::Interrupter interrupter(m_gameController); + shutdownInternal(); + m_gameController->setDebugger(nullptr); + } else { + m_autoattach = false; + } } void DebuggerController::breakInto() { if (!isAttached()) { return; } - GameController::Interrupter interrupter(m_gameController); + CoreController::Interrupter interrupter(m_gameController); mDebuggerEnter(m_debugger, DEBUGGER_ENTER_MANUAL, 0); } void DebuggerController::shutdown() { - QObject::disconnect(m_autoattach); + m_autoattach = false; if (!isAttached()) { return; } - GameController::Interrupter interrupter(m_gameController); + CoreController::Interrupter interrupter(m_gameController); shutdownInternal(); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DebuggerController.h mgba-0.7.0/src/platform/qt/DebuggerController.h --- mgba-0.6.3+dfsg1/src/platform/qt/DebuggerController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DebuggerController.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,25 +3,27 @@ * 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_DEBUGGER_CONTROLLER -#define QGBA_DEBUGGER_CONTROLLER +#pragma once #include +#include + struct mDebugger; namespace QGBA { -class GameController; +class CoreController; class DebuggerController : public QObject { Q_OBJECT public: - DebuggerController(GameController* controller, mDebugger* debugger, QObject* parent = nullptr); + DebuggerController(mDebugger* debugger, QObject* parent = nullptr); public: bool isAttached(); + void setController(std::shared_ptr); public slots: virtual void attach(); @@ -34,12 +36,10 @@ virtual void shutdownInternal(); mDebugger* const m_debugger; - GameController* const m_gameController; + std::shared_ptr m_gameController; private: - QMetaObject::Connection m_autoattach; + bool m_autoattach = false; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/Display.cpp mgba-0.7.0/src/platform/qt/Display.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/Display.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/Display.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -8,12 +8,6 @@ #include "DisplayGL.h" #include "DisplayQt.h" -#ifdef M_CORE_GB -#include -#elif defined(M_CORE_GBA) -#include -#endif - using namespace QGBA; #if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) @@ -55,11 +49,6 @@ : QWidget(parent) { setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); -#ifdef M_CORE_GB - setMinimumSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); -#elif defined(M_CORE_GBA) - setMinimumSize(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); -#endif connect(&m_mouseTimer, &QTimer::timeout, this, &Display::hideCursor); m_mouseTimer.setSingleShot(true); m_mouseTimer.setInterval(MOUSE_DISAPPEAR_TIMER); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DisplayGL.cpp mgba-0.7.0/src/platform/qt/DisplayGL.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/DisplayGL.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DisplayGL.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -7,12 +7,14 @@ #if defined(BUILD_GL) || defined(BUILD_GLES2) +#include "CoreController.h" + #include #include #include #include -#include +#include #ifdef BUILD_GL #include "platform/opengl/gl.h" #endif @@ -27,14 +29,18 @@ DisplayGL::DisplayGL(const QGLFormat& format, QWidget* parent) : Display(parent) - , m_gl(new EmptyGLWidget(format, this)) + , m_gl(nullptr) { + // This can spontaneously re-enter into this->resizeEvent before creation is done, so we + // need to make sure it's initialized to nullptr before we assign the new object to it + m_gl = new EmptyGLWidget(format, this); m_painter = new PainterGL(format.majorVersion() < 2 ? 1 : m_gl->format().majorVersion(), m_gl); m_gl->setMouseTracking(true); m_gl->setAttribute(Qt::WA_TransparentForMouseEvents); // This doesn't seem to work? } DisplayGL::~DisplayGL() { + stopDrawing(); delete m_painter; } @@ -52,14 +58,14 @@ return shaders; } -void DisplayGL::startDrawing(mCoreThread* thread) { +void DisplayGL::startDrawing(std::shared_ptr controller) { if (m_drawThread) { return; } m_isDrawing = true; - m_painter->setContext(thread); + m_painter->setContext(controller); m_painter->setMessagePainter(messagePainter()); - m_context = thread; + m_context = controller; m_painter->resize(size()); m_gl->move(0, 0); m_drawThread = new QThread(this); @@ -69,7 +75,6 @@ m_painter->moveToThread(m_drawThread); connect(m_drawThread, &QThread::started, m_painter, &PainterGL::start); m_drawThread->start(); - mCoreSyncSetVideoSync(&m_context->sync, false); lockAspectRatio(isAspectRatioLocked()); lockIntegerScaling(isIntegerScalingLocked()); @@ -85,41 +90,27 @@ void DisplayGL::stopDrawing() { if (m_drawThread) { m_isDrawing = false; - if (mCoreThreadIsActive(m_context)) { - mCoreThreadInterrupt(m_context); - } + CoreController::Interrupter interrupter(m_context); QMetaObject::invokeMethod(m_painter, "stop", Qt::BlockingQueuedConnection); m_drawThread->exit(); m_drawThread = nullptr; - if (mCoreThreadIsActive(m_context)) { - mCoreThreadContinue(m_context); - } } + m_context.reset(); } void DisplayGL::pauseDrawing() { if (m_drawThread) { m_isDrawing = false; - if (mCoreThreadIsActive(m_context)) { - mCoreThreadInterrupt(m_context); - } + CoreController::Interrupter interrupter(m_context); QMetaObject::invokeMethod(m_painter, "pause", Qt::BlockingQueuedConnection); - if (mCoreThreadIsActive(m_context)) { - mCoreThreadContinue(m_context); - } } } void DisplayGL::unpauseDrawing() { if (m_drawThread) { m_isDrawing = true; - if (mCoreThreadIsActive(m_context)) { - mCoreThreadInterrupt(m_context); - } + CoreController::Interrupter interrupter(m_context); QMetaObject::invokeMethod(m_painter, "unpause", Qt::BlockingQueuedConnection); - if (mCoreThreadIsActive(m_context)) { - mCoreThreadContinue(m_context); - } } } @@ -150,9 +141,9 @@ } } -void DisplayGL::framePosted(const uint32_t* buffer) { - if (m_drawThread && buffer) { - m_painter->enqueue(buffer); +void DisplayGL::framePosted() { + if (m_drawThread) { + m_painter->enqueue(m_context->drawContext()); QMetaObject::invokeMethod(m_painter, "draw"); } } @@ -169,13 +160,24 @@ QMetaObject::invokeMethod(m_painter, "clearShaders"); } + +void DisplayGL::resizeContext() { + if (m_drawThread) { + m_isDrawing = false; + CoreController::Interrupter interrupter(m_context); + QMetaObject::invokeMethod(m_painter, "resizeContext", Qt::BlockingQueuedConnection); + } +} + void DisplayGL::resizeEvent(QResizeEvent* event) { Display::resizeEvent(event); resizePainter(); } void DisplayGL::resizePainter() { - m_gl->resize(size()); + if (m_gl) { + m_gl->resize(size()); + } if (m_drawThread) { QMetaObject::invokeMethod(m_painter, "resize", Qt::BlockingQueuedConnection, Q_ARG(QSize, size())); } @@ -183,12 +185,6 @@ PainterGL::PainterGL(int majorVersion, QGLWidget* parent) : m_gl(parent) - , m_active(false) - , m_started(false) - , m_context(nullptr) - , m_shader{} - , m_backend(nullptr) - , m_messagePainter(nullptr) { #ifdef BUILD_GL mGLContext* glBackend; @@ -197,9 +193,16 @@ mGLES2Context* gl2Backend; #endif + m_gl->makeCurrent(); +#if defined(_WIN32) && defined(USE_EPOXY) + epoxy_handle_external_wglMakeCurrent(); +#endif + + QStringList extensions = QString(reinterpret_cast(glGetString(GL_EXTENSIONS))).split(' '); + #if !defined(_WIN32) || defined(USE_EPOXY) - if (majorVersion >= 2) { - gl2Backend = new mGLES2Context; + if (extensions.contains("GL_ARB_framebuffer_object") && majorVersion >= 2) { + gl2Backend = static_cast(malloc(sizeof(mGLES2Context))); mGLES2ContextCreate(gl2Backend); m_backend = &gl2Backend->d; m_supportsShaders = true; @@ -208,7 +211,7 @@ #ifdef BUILD_GL if (!m_backend) { - glBackend = new mGLContext; + glBackend = static_cast(malloc(sizeof(mGLContext))); mGLContextCreate(glBackend); m_backend = &glBackend->d; m_supportsShaders = false; @@ -219,10 +222,6 @@ painter->m_gl->swapBuffers(); }; - m_gl->makeCurrent(); -#if defined(_WIN32) && defined(USE_EPOXY) - epoxy_handle_external_wglMakeCurrent(); -#endif m_backend->init(m_backend, reinterpret_cast(m_gl->winId())); #if !defined(_WIN32) || defined(USE_EPOXY) if (m_supportsShaders) { @@ -258,14 +257,17 @@ #endif m_backend->deinit(m_backend); m_gl->doneCurrent(); - delete m_backend; + free(m_backend); m_backend = nullptr; } -void PainterGL::setContext(mCoreThread* context) { +void PainterGL::setContext(std::shared_ptr context) { m_context = context; + resizeContext(); +} - if (!context) { +void PainterGL::resizeContext() { + if (!m_context) { return; } @@ -273,9 +275,8 @@ #if defined(_WIN32) && defined(USE_EPOXY) epoxy_handle_external_wglMakeCurrent(); #endif - unsigned width, height; - context->core->desiredVideoDimensions(context->core, &width, &height); - m_backend->setDimensions(m_backend, width, height); + QSize size = m_context->screenDimensions(); + m_backend->setDimensions(m_backend, size.width(), size.height()); m_gl->doneCurrent(); } @@ -329,13 +330,13 @@ } void PainterGL::draw() { - if (m_queue.isEmpty() || !mCoreThreadIsActive(m_context)) { + if (m_queue.isEmpty()) { return; } - if (mCoreSyncWaitFrameStart(&m_context->sync) || !m_queue.isEmpty()) { + if (mCoreSyncWaitFrameStart(&m_context->thread()->impl->sync) || !m_queue.isEmpty()) { dequeue(); - mCoreSyncWaitFrameEnd(&m_context->sync); + mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync); m_painter.begin(m_gl->context()->device()); performDraw(); m_painter.end(); @@ -349,7 +350,7 @@ m_delayTimer.restart(); } } else { - mCoreSyncWaitFrameEnd(&m_context->sync); + mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync); } if (!m_queue.isEmpty()) { QMetaObject::invokeMethod(this, "draw", Qt::QueuedConnection); @@ -375,6 +376,7 @@ m_backend->swap(m_backend); m_gl->doneCurrent(); m_gl->context()->moveToThread(m_gl->thread()); + m_context.reset(); moveToThread(m_gl->thread()); } @@ -409,9 +411,8 @@ } else { buffer = m_free.takeLast(); } - unsigned width, height; - m_context->core->desiredVideoDimensions(m_context->core, &width, &height); - memcpy(buffer, backing, width * height * BYTES_PER_PIXEL); + QSize size = m_context->screenDimensions(); + memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL); m_queue.enqueue(buffer); m_mutex.unlock(); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DisplayGL.h mgba-0.7.0/src/platform/qt/DisplayGL.h --- mgba-0.6.3+dfsg1/src/platform/qt/DisplayGL.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DisplayGL.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_DISPLAY_GL -#define QGBA_DISPLAY_GL +#pragma once #if defined(BUILD_GL) || defined(BUILD_GLES2) @@ -46,12 +45,12 @@ DisplayGL(const QGLFormat& format, QWidget* parent = nullptr); ~DisplayGL(); + void startDrawing(std::shared_ptr) override; bool isDrawing() const override { return m_isDrawing; } bool supportsShaders() const override; VideoShader* shaders() override; public slots: - void startDrawing(mCoreThread* context) override; void stopDrawing() override; void pauseDrawing() override; void unpauseDrawing() override; @@ -59,9 +58,10 @@ void lockAspectRatio(bool lock) override; void lockIntegerScaling(bool lock) override; void filter(bool filter) override; - void framePosted(const uint32_t*) override; + void framePosted() override; void setShaders(struct VDir*) override; void clearShaders() override; + void resizeContext() override; protected: virtual void paintEvent(QPaintEvent*) override {} @@ -74,7 +74,7 @@ QGLWidget* m_gl; PainterGL* m_painter; QThread* m_drawThread = nullptr; - mCoreThread* m_context = nullptr; + std::shared_ptr m_context; }; class PainterGL : public QObject { @@ -84,7 +84,7 @@ PainterGL(int majorVersion, QGLWidget* parent); ~PainterGL(); - void setContext(mCoreThread*); + void setContext(std::shared_ptr); void setMessagePainter(MessagePainter*); void enqueue(const uint32_t* backing); @@ -101,6 +101,7 @@ void lockAspectRatio(bool lock); void lockIntegerScaling(bool lock); void filter(bool filter); + void resizeContext(); void setShaders(struct VDir*); void clearShaders(); @@ -116,19 +117,17 @@ QPainter m_painter; QMutex m_mutex; QGLWidget* m_gl; - bool m_active; - bool m_started; - mCoreThread* m_context; + bool m_active = false; + bool m_started = false; + std::shared_ptr m_context = nullptr; bool m_supportsShaders; - VideoShader m_shader; - VideoBackend* m_backend; + VideoShader m_shader{}; + VideoBackend* m_backend = nullptr; QSize m_size; - MessagePainter* m_messagePainter; + MessagePainter* m_messagePainter = nullptr; QElapsedTimer m_delayTimer; }; } #endif - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/Display.h mgba-0.7.0/src/platform/qt/Display.h --- mgba-0.6.3+dfsg1/src/platform/qt/Display.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/Display.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,21 +3,23 @@ * 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_DISPLAY -#define QGBA_DISPLAY +#pragma once #include +#include + #include #include "MessagePainter.h" -struct mCoreThread; struct VDir; struct VideoShader; namespace QGBA { +class CoreController; + class Display : public QWidget { Q_OBJECT @@ -41,6 +43,7 @@ bool isIntegerScalingLocked() const { return m_lockIntegerScaling; } bool isFiltered() const { return m_filter; } + virtual void startDrawing(std::shared_ptr) = 0; virtual bool isDrawing() const = 0; virtual bool supportsShaders() const = 0; virtual VideoShader* shaders() = 0; @@ -50,7 +53,6 @@ void hideCursor(); public slots: - virtual void startDrawing(mCoreThread* context) = 0; virtual void stopDrawing() = 0; virtual void pauseDrawing() = 0; virtual void unpauseDrawing() = 0; @@ -58,9 +60,10 @@ virtual void lockAspectRatio(bool lock); virtual void lockIntegerScaling(bool lock); virtual void filter(bool filter); - virtual void framePosted(const uint32_t*) = 0; + virtual void framePosted() = 0; virtual void setShaders(struct VDir*) = 0; virtual void clearShaders() = 0; + virtual void resizeContext() = 0; void showMessage(const QString& message); @@ -82,5 +85,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DisplayQt.cpp mgba-0.7.0/src/platform/qt/DisplayQt.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/DisplayQt.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DisplayQt.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,10 +5,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "DisplayQt.h" +#include "CoreController.h" + #include #include #include +#include using namespace QGBA; @@ -17,10 +20,18 @@ { } -void DisplayQt::startDrawing(mCoreThread* context) { - context->core->desiredVideoDimensions(context->core, &m_width, &m_height); +void DisplayQt::startDrawing(std::shared_ptr controller) { + QSize size = controller->screenDimensions(); + m_width = size.width(); + m_height = size.height(); m_backing = std::move(QImage()); m_isDrawing = true; + m_context = controller; +} + +void DisplayQt::stopDrawing() { + m_isDrawing = false; + m_context.reset(); } void DisplayQt::lockAspectRatio(bool lock) { @@ -38,8 +49,9 @@ update(); } -void DisplayQt::framePosted(const uint32_t* buffer) { +void DisplayQt::framePosted() { update(); + const color_t* buffer = m_context->drawContext(); if (const_cast(m_backing).bits() == reinterpret_cast(buffer)) { return; } @@ -55,6 +67,18 @@ #endif } +void DisplayQt::resizeContext() { + if (!m_context) { + return; + } + QSize size = m_context->screenDimensions(); + if (m_width != size.width() || m_height != size.height()) { + m_width = size.width(); + m_height = size.height(); + m_backing = std::move(QImage()); + } +} + void DisplayQt::paintEvent(QPaintEvent*) { QPainter painter(this); painter.fillRect(QRect(QPoint(), size()), Qt::black); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/DisplayQt.h mgba-0.7.0/src/platform/qt/DisplayQt.h --- mgba-0.6.3+dfsg1/src/platform/qt/DisplayQt.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/DisplayQt.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_DISPLAY_QT -#define QGBA_DISPLAY_QT +#pragma once #include "Display.h" @@ -19,22 +18,23 @@ public: DisplayQt(QWidget* parent = nullptr); + void startDrawing(std::shared_ptr) override; bool isDrawing() const override { return m_isDrawing; } bool supportsShaders() const override { return false; } VideoShader* shaders() override { return nullptr; } public slots: - void startDrawing(mCoreThread* context) override; - void stopDrawing() override { m_isDrawing = false; } + void stopDrawing() override; void pauseDrawing() override { m_isDrawing = false; } void unpauseDrawing() override { m_isDrawing = true; } void forceDraw() override { update(); } void lockAspectRatio(bool lock) override; void lockIntegerScaling(bool lock) override; void filter(bool filter) override; - void framePosted(const uint32_t*) override; + void framePosted() override; void setShaders(struct VDir*) override {} void clearShaders() override {} + void resizeContext() override; protected: virtual void paintEvent(QPaintEvent*) override; @@ -44,8 +44,7 @@ unsigned m_width; unsigned m_height; QImage m_backing{nullptr}; + std::shared_ptr m_context = nullptr; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GameController.cpp mgba-0.7.0/src/platform/qt/GameController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/GameController.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GameController.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,1275 +0,0 @@ -/* Copyright (c) 2013-2014 Jeffrey Pfau - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "GameController.h" - -#include "AudioProcessor.h" -#include "InputController.h" -#include "LogController.h" -#include "MultiplayerController.h" -#include "Override.h" -#include "VFileDevice.h" - -#include -#include - -#include - -#include -#include -#include -#include -#ifdef M_CORE_GBA -#include -#include -#include -#include -#include -#endif -#ifdef M_CORE_GB -#include -#include -#endif -#include -#include - -using namespace QGBA; -using namespace std; - -GameController::GameController(QObject* parent) - : QObject(parent) - , m_audioProcessor(AudioProcessor::create()) - , m_saveStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS | SAVESTATE_RTC | SAVESTATE_METADATA) - , m_loadStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_RTC) -{ -#ifdef M_CORE_GBA - m_lux.p = this; - m_lux.sample = [](GBALuminanceSource* context) { - GameControllerLux* lux = static_cast(context); - lux->value = 0xFF - lux->p->m_luxValue; - }; - - m_lux.readLuminance = [](GBALuminanceSource* context) { - GameControllerLux* lux = static_cast(context); - return lux->value; - }; - setLuminanceLevel(0); -#endif - - m_threadContext.startCallback = [](mCoreThread* context) { - GameController* controller = static_cast(context->userData); - context->core->setPeripheral(context->core, mPERIPH_ROTATION, controller->m_inputController->rotationSource()); - context->core->setPeripheral(context->core, mPERIPH_RUMBLE, controller->m_inputController->rumble()); - - for (size_t i = 0; i < controller->m_audioChannels.size(); ++i) { - context->core->enableAudioChannel(context->core, i, controller->m_audioChannels[i]); - } - for (size_t i = 0; i < controller->m_videoLayers.size(); ++i) { - context->core->enableVideoLayer(context->core, i, controller->m_videoLayers[i]); - } - - switch (context->core->platform(context->core)) { -#ifdef M_CORE_GBA - case PLATFORM_GBA: - context->core->setPeripheral(context->core, mPERIPH_GBA_LUMINANCE, &controller->m_lux); - break; -#endif - default: - break; - } - controller->m_fpsTarget = context->sync.fpsTarget; - - if (controller->m_override) { - controller->m_override->identify(context->core); - controller->m_override->apply(context->core); - } - - if (mCoreLoadState(context->core, 0, controller->m_loadStateFlags)) { - mCoreDeleteState(context->core, 0); - } - - controller->m_gameOpen = true; - if (controller->m_multiplayer) { - controller->m_multiplayer->attachGame(controller); - } - - QString path = controller->m_fname; - if (!controller->m_fsub.isEmpty()) { - path += QDir::separator() + controller->m_fsub; - } - QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(mCoreThread*, context), Q_ARG(const QString&, path)); - QMetaObject::invokeMethod(controller, "startAudio"); - }; - - m_threadContext.resetCallback = [](mCoreThread* context) { - GameController* controller = static_cast(context->userData); - for (auto action : controller->m_resetActions) { - action(); - } - controller->m_resetActions.clear(); - - unsigned width, height; - controller->m_threadContext.core->desiredVideoDimensions(controller->m_threadContext.core, &width, &height); - memset(controller->m_frontBuffer, 0xFF, width * height * BYTES_PER_PIXEL); - QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer)); - if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) { - mCoreThreadPauseFromThread(context); - QMetaObject::invokeMethod(controller, "gamePaused", Q_ARG(mCoreThread*, context)); - } - }; - - m_threadContext.cleanCallback = [](mCoreThread* context) { - GameController* controller = static_cast(context->userData); - - if (controller->m_multiplayer) { - controller->m_multiplayer->detachGame(controller); - } - controller->clearOverride(); - controller->endVideoLog(); - - QMetaObject::invokeMethod(controller->m_audioProcessor, "pause"); - - QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(mCoreThread*, context)); - QMetaObject::invokeMethod(controller, "cleanGame"); - }; - - m_threadContext.frameCallback = [](mCoreThread* context) { - GameController* controller = static_cast(context->userData); - unsigned width, height; - controller->m_threadContext.core->desiredVideoDimensions(controller->m_threadContext.core, &width, &height); - memcpy(controller->m_frontBuffer, controller->m_drawContext, width * height * BYTES_PER_PIXEL); - QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer)); - - // If no one is using the tile cache, disable it - if (controller->m_tileCache && controller->m_tileCache.unique()) { - switch (controller->platform()) { -#ifdef M_CORE_GBA - case PLATFORM_GBA: { - GBA* gba = static_cast(context->core->board); - gba->video.renderer->cache = nullptr; - break; - } -#endif -#ifdef M_CORE_GB - case PLATFORM_GB: { - GB* gb = static_cast(context->core->board); - gb->video.renderer->cache = nullptr; - break; - } -#endif - default: - break; - } - mTileCacheDeinit(controller->m_tileCache.get()); - controller->m_tileCache.reset(); - } - - - if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) { - mCoreThreadPauseFromThread(context); - QMetaObject::invokeMethod(controller, "gamePaused", Q_ARG(mCoreThread*, context)); - } - }; - - m_threadContext.sleepCallback = [](mCoreThread* context) { - if (!context) { - return; - } - GameController* controller = static_cast(context->userData); - if (!mCoreSaveState(context->core, 0, controller->m_saveStateFlags)) { - return; - } - QMetaObject::invokeMethod(controller, "closeGame"); - }; - - m_threadContext.logger.d.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { - mThreadLogger* logContext = reinterpret_cast(logger); - mCoreThread* context = logContext->p; - - static const char* savestateMessage = "State %i loaded"; - static const char* savestateFailedMessage = "State %i failed to load"; - static int biosCat = -1; - static int statusCat = -1; - if (!context) { - return; - } - GameController* controller = static_cast(context->userData); - QString message; - if (biosCat < 0) { - biosCat = mLogCategoryById("gba.bios"); - } - if (statusCat < 0) { - statusCat = mLogCategoryById("core.status"); - } -#ifdef M_CORE_GBA - if (level == mLOG_STUB && category == biosCat) { - va_list argc; - va_copy(argc, args); - int immediate = va_arg(argc, int); - va_end(argc); - QMetaObject::invokeMethod(controller, "unimplementedBiosCall", Q_ARG(int, immediate)); - } else -#endif - if (category == statusCat) { - // Slot 0 is reserved for suspend points - if (strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) { - va_list argc; - va_copy(argc, args); - int slot = va_arg(argc, int); - va_end(argc); - if (slot == 0) { - format = "Loaded suspend state"; - } - } else if (strncmp(savestateFailedMessage, format, strlen(savestateFailedMessage)) == 0) { - va_list argc; - va_copy(argc, args); - int slot = va_arg(argc, int); - va_end(argc); - if (slot == 0) { - return; - } - } - message = QString().vsprintf(format, args); - QMetaObject::invokeMethod(controller, "statusPosted", Q_ARG(const QString&, message)); - } - if (level == mLOG_FATAL) { - mCoreThreadMarkCrashed(controller->thread()); - QMetaObject::invokeMethod(controller, "crashGame", Q_ARG(const QString&, QString().vsprintf(format, args))); - } else if (!(controller->m_logLevels & level)) { - return; - } - message = QString().vsprintf(format, args); - QMetaObject::invokeMethod(controller, "postLog", Q_ARG(int, level), Q_ARG(int, category), Q_ARG(const QString&, message)); - }; - - m_threadContext.userData = this; - - connect(this, &GameController::gamePaused, m_audioProcessor, &AudioProcessor::pause); - connect(this, &GameController::gameStarted, m_audioProcessor, &AudioProcessor::setInput); - connect(this, &GameController::frameAvailable, this, &GameController::pollEvents); - connect(this, &GameController::frameAvailable, this, &GameController::updateAutofire); -} - -GameController::~GameController() { - disconnect(); - closeGame(); - clearMultiplayerController(); - delete m_backupLoadState; -} - -void GameController::setMultiplayerController(MultiplayerController* controller) { - if (controller == m_multiplayer) { - return; - } - clearMultiplayerController(); - m_multiplayer = controller; - if (isLoaded()) { - mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* thread) { - GameController* controller = static_cast(thread->userData); - controller->m_multiplayer->attachGame(controller); - }); - } -} - -void GameController::clearMultiplayerController() { - if (!m_multiplayer) { - return; - } - m_multiplayer->detachGame(this); - m_multiplayer = nullptr; -} - -void GameController::setOverride(Override* override) { - m_override = override; - if (isLoaded()) { - Interrupter interrupter(this); - m_override->identify(m_threadContext.core); - } -} - -void GameController::clearOverride() { - delete m_override; - m_override = nullptr; -} - -void GameController::setConfig(const mCoreConfig* config) { - m_config = config; - if (isLoaded()) { - Interrupter interrupter(this); - mCoreLoadForeignConfig(m_threadContext.core, config); - m_audioSync = m_threadContext.sync.audioWait; - m_videoSync = m_threadContext.sync.videoFrameWait; - m_audioProcessor->setInput(&m_threadContext); - } -} - -#ifdef USE_DEBUGGERS -mDebugger* GameController::debugger() { - if (!isLoaded()) { - return nullptr; - } - return m_threadContext.core->debugger; -} - -void GameController::setDebugger(mDebugger* debugger) { - Interrupter interrupter(this); - if (debugger) { - mDebuggerAttach(debugger, m_threadContext.core); - } else { - m_threadContext.core->detachDebugger(m_threadContext.core); - } -} -#endif - -void GameController::loadGame(const QString& path) { - closeGame(); - QFileInfo info(path); - if (!info.isReadable()) { - QString fname = info.fileName(); - QString base = info.path(); - if (base.endsWith("/") || base.endsWith(QDir::separator())) { - base.chop(1); - } - VDir* dir = VDirOpenArchive(base.toUtf8().constData()); - if (dir) { - VFile* vf = dir->openFile(dir, fname.toUtf8().constData(), O_RDONLY); - if (vf) { - struct VFile* vfclone = VFileMemChunk(NULL, vf->size(vf)); - uint8_t buffer[2048]; - ssize_t read; - while ((read = vf->read(vf, buffer, sizeof(buffer))) > 0) { - vfclone->write(vfclone, buffer, read); - } - vf->close(vf); - vf = vfclone; - } - dir->close(dir); - loadGame(vf, fname, base); - } else { - LOG(QT, ERROR) << tr("Failed to open game file: %1").arg(path); - } - return; - } else { - m_fname = info.canonicalFilePath(); - m_fsub = QString(); - } - m_vf = nullptr; - openGame(); -} - -void GameController::loadGame(VFile* vf, const QString& path, const QString& base) { - closeGame(); - QFileInfo info(base); - if (info.isDir()) { - m_fname = QFileInfo(base + '/' + path).canonicalFilePath(); - m_fsub = QString(); - } else { - m_fname = info.canonicalFilePath(); - m_fsub = path; - } - m_vf = vf; - openGame(); -} - -void GameController::bootBIOS() { - closeGame(); - m_fname = QString(); - openGame(true); -} - -void GameController::openGame(bool biosOnly) { - if (m_fname.isEmpty()) { - biosOnly = true; - } - if (isLoaded()) { - // We need to delay if the game is still cleaning up - QTimer::singleShot(10, this, SLOT(openGame())); - return; - } else if(m_gameOpen) { - cleanGame(); - } - - m_threadContext.core = nullptr; - if (!biosOnly) { - if (m_vf) { - m_threadContext.core = mCoreFindVF(m_vf); - } else { - m_threadContext.core = mCoreFind(m_fname.toUtf8().constData()); - } -#ifdef M_CORE_GBA - } else { - m_threadContext.core = GBACoreCreate(); -#endif - } - - if (!m_threadContext.core) { - return; - } - - m_pauseAfterFrame = false; - - if (m_turbo) { - m_threadContext.sync.videoFrameWait = false; - m_threadContext.sync.audioWait = false; - } else { - m_threadContext.sync.videoFrameWait = m_videoSync; - m_threadContext.sync.audioWait = m_audioSync; - } - m_threadContext.core->init(m_threadContext.core); - mCoreInitConfig(m_threadContext.core, nullptr); - - unsigned width, height; - m_threadContext.core->desiredVideoDimensions(m_threadContext.core, &width, &height); - m_drawContext = new uint32_t[width * height]; - m_frontBuffer = new uint32_t[width * height]; - - if (m_config) { - mCoreLoadForeignConfig(m_threadContext.core, m_config); - } - - QByteArray bytes; - if (!biosOnly) { - bytes = m_fname.toUtf8(); - if (m_preload) { - if (m_vf) { - mCorePreloadVF(m_threadContext.core, m_vf); - } else { - mCorePreloadFile(m_threadContext.core, bytes.constData()); - mDirectorySetDetachBase(&m_threadContext.core->dirs); - } - } else { - if (m_vf) { - m_threadContext.core->loadROM(m_threadContext.core, m_vf); - } else { - mCoreLoadFile(m_threadContext.core, bytes.constData()); - mDirectorySetDetachBase(&m_threadContext.core->dirs); - } - } - } else { - bytes = m_bios.toUtf8(); - } - if (bytes.isNull()) { - return; - } - - char dirname[PATH_MAX]; - separatePath(bytes.constData(), dirname, m_threadContext.core->dirs.baseName, 0); - mDirectorySetAttachBase(&m_threadContext.core->dirs, VDirOpen(dirname)); - - m_threadContext.core->setVideoBuffer(m_threadContext.core, m_drawContext, width); - - m_inputController->recalibrateAxes(); - memset(m_drawContext, 0xF8, width * height * 4); - - m_threadContext.core->setAVStream(m_threadContext.core, m_stream); - - if (!biosOnly) { - mCoreAutoloadSave(m_threadContext.core); - if (!m_patch.isNull()) { - VFile* patch = VFileDevice::open(m_patch, O_RDONLY); - if (patch) { - m_threadContext.core->loadPatch(m_threadContext.core, patch); - } - patch->close(patch); - m_patch = QString(); - } else { - mCoreAutoloadPatch(m_threadContext.core); - } - } - m_vf = nullptr; - - if (!mCoreThreadStart(&m_threadContext)) { - emit gameFailed(); - } -} - -void GameController::loadBIOS(int platform, const QString& path) { - if (m_bios == path) { - return; - } - if (!m_bios.isNull() && m_gameOpen && this->platform() == platform) { - closeGame(); - m_bios = path; - openGame(); - } else if (!m_gameOpen || m_bios.isNull()) { - m_bios = path; - } -} - -void GameController::loadSave(const QString& path, bool temporary) { - if (!isLoaded()) { - return; - } - m_resetActions.append([this, path, temporary]() { - VFile* vf = VFileDevice::open(path, temporary ? O_RDONLY : O_RDWR); - if (!vf) { - LOG(QT, ERROR) << tr("Failed to open save file: %1").arg(path); - return; - } - - if (temporary) { - m_threadContext.core->loadTemporarySave(m_threadContext.core, vf); - } else { - m_threadContext.core->loadSave(m_threadContext.core, vf); - } - }); - reset(); -} - -void GameController::yankPak() { - if (!m_gameOpen) { - return; - } - Interrupter interrupter(this); - GBAYankROM(static_cast(m_threadContext.core->board)); -} - -void GameController::replaceGame(const QString& path) { - if (!m_gameOpen) { - return; - } - - QFileInfo info(path); - if (!info.isReadable()) { - LOG(QT, ERROR) << tr("Failed to open game file: %1").arg(path); - return; - } - m_fname = info.canonicalFilePath(); - Interrupter interrupter(this); - mDirectorySetDetachBase(&m_threadContext.core->dirs); - mCoreLoadFile(m_threadContext.core, m_fname.toLocal8Bit().constData()); -} - -void GameController::loadPatch(const QString& path) { - m_patch = path; - if (m_gameOpen) { - closeGame(); - openGame(); - } -} - -void GameController::importSharkport(const QString& path) { - if (!isLoaded()) { - return; - } -#ifdef M_CORE_GBA - if (platform() != PLATFORM_GBA) { - return; - } - VFile* vf = VFileDevice::open(path, O_RDONLY); - if (!vf) { - LOG(QT, ERROR) << tr("Failed to open snapshot file for reading: %1").arg(path); - return; - } - threadInterrupt(); - GBASavedataImportSharkPort(static_cast(m_threadContext.core->board), vf, false); - threadContinue(); - vf->close(vf); -#endif -} - -void GameController::exportSharkport(const QString& path) { - if (!isLoaded()) { - return; - } -#ifdef M_CORE_GBA - if (platform() != PLATFORM_GBA) { - return; - } - VFile* vf = VFileDevice::open(path, O_WRONLY | O_CREAT | O_TRUNC); - if (!vf) { - LOG(QT, ERROR) << tr("Failed to open snapshot file for writing: %1").arg(path); - return; - } - threadInterrupt(); - GBASavedataExportSharkPort(static_cast(m_threadContext.core->board), vf); - threadContinue(); - vf->close(vf); -#endif -} - -void GameController::closeGame() { - if (!m_gameOpen) { - return; - } -#ifdef USE_DEBUGGERS - setDebugger(nullptr); -#endif - if (mCoreThreadIsPaused(&m_threadContext)) { - mCoreThreadUnpause(&m_threadContext); - } - mCoreThreadEnd(&m_threadContext); -} - -void GameController::cleanGame() { - if (!m_gameOpen || mCoreThreadIsActive(&m_threadContext)) { - return; - } - - m_audioProcessor->pause(); - mCoreThreadJoin(&m_threadContext); - - if (m_tileCache) { - mTileCacheDeinit(m_tileCache.get()); - m_tileCache.reset(); - } - - delete[] m_drawContext; - delete[] m_frontBuffer; - - mCoreConfigDeinit(&m_threadContext.core->config); - m_threadContext.core->deinit(m_threadContext.core); - m_threadContext.core = nullptr; - m_gameOpen = false; -} - -void GameController::crashGame(const QString& crashMessage) { - closeGame(); - emit gameCrashed(crashMessage); -} - -bool GameController::isPaused() { - if (!m_gameOpen) { - return false; - } - return mCoreThreadIsPaused(&m_threadContext); -} - -mPlatform GameController::platform() const { - if (!m_gameOpen) { - return PLATFORM_NONE; - } - return m_threadContext.core->platform(m_threadContext.core); -} - -QSize GameController::screenDimensions() const { - if (!m_gameOpen) { - return QSize(); - } - unsigned width, height; - m_threadContext.core->desiredVideoDimensions(m_threadContext.core, &width, &height); - - return QSize(width, height); -} - -void GameController::setPaused(bool paused) { - if (!isLoaded() || paused == mCoreThreadIsPaused(&m_threadContext)) { - return; - } - m_wasPaused = paused; - if (paused) { - m_pauseAfterFrame.testAndSetRelaxed(false, true); - } else { - mCoreThreadUnpause(&m_threadContext); - startAudio(); - emit gameUnpaused(&m_threadContext); - } -} - -void GameController::reset() { - if (!m_gameOpen) { - return; - } - bool wasPaused = isPaused(); - setPaused(false); - Interrupter interrupter(this); - mCoreThreadReset(&m_threadContext); - if (wasPaused) { - setPaused(true); - } -} - -void GameController::threadInterrupt() { - if (m_gameOpen) { - mCoreThreadInterrupt(&m_threadContext); - } -} - -void GameController::threadContinue() { - if (m_gameOpen) { - mCoreThreadContinue(&m_threadContext); - } -} - -void GameController::frameAdvance() { - if (m_pauseAfterFrame.testAndSetRelaxed(false, true)) { - setPaused(false); - m_wasPaused = true; - } -} - -void GameController::setRewind(bool enable, int capacity, bool rewindSave) { - if (m_gameOpen) { - Interrupter interrupter(this); - if (m_threadContext.core->opts.rewindEnable && m_threadContext.core->opts.rewindBufferCapacity > 0) { - mCoreRewindContextDeinit(&m_threadContext.rewind); - } - m_threadContext.core->opts.rewindEnable = enable; - m_threadContext.core->opts.rewindBufferCapacity = capacity; - m_threadContext.core->opts.rewindSave = rewindSave; - if (enable && capacity > 0) { - mCoreRewindContextInit(&m_threadContext.rewind, capacity, true); - m_threadContext.rewind.stateFlags = rewindSave ? SAVESTATE_SAVEDATA : 0; - } - } -} - -void GameController::rewind(int states) { - threadInterrupt(); - if (!states) { - states = INT_MAX; - } - for (int i = 0; i < states; ++i) { - if (!mCoreRewindRestore(&m_threadContext.rewind, m_threadContext.core)) { - break; - } - } - threadContinue(); - emit frameAvailable(m_drawContext); - emit rewound(&m_threadContext); -} - -void GameController::startRewinding() { - if (!isLoaded()) { - return; - } - if (!m_threadContext.core->opts.rewindEnable) { - return; - } - if (m_multiplayer && m_multiplayer->attached() > 1) { - return; - } - if (m_wasPaused) { - setPaused(false); - m_wasPaused = true; - } - mCoreThreadSetRewinding(&m_threadContext, true); -} - -void GameController::stopRewinding() { - if (!isLoaded()) { - return; - } - mCoreThreadSetRewinding(&m_threadContext, false); - bool signalsBlocked = blockSignals(true); - setPaused(m_wasPaused); - blockSignals(signalsBlocked); -} - -void GameController::keyPressed(int key) { - int mappedKey = 1 << key; - m_activeKeys |= mappedKey; - if (!m_inputController->allowOpposing()) { - if ((m_activeKeys & 0x30) == 0x30) { - m_inactiveKeys |= mappedKey ^ 0x30; - m_activeKeys ^= mappedKey ^ 0x30; - } - if ((m_activeKeys & 0xC0) == 0xC0) { - m_inactiveKeys |= mappedKey ^ 0xC0; - m_activeKeys ^= mappedKey ^ 0xC0; - } - } - updateKeys(); -} - -void GameController::keyReleased(int key) { - int mappedKey = 1 << key; - m_activeKeys &= ~mappedKey; - if (!m_inputController->allowOpposing()) { - if (mappedKey & 0x30) { - m_activeKeys |= m_inactiveKeys & (0x30 ^ mappedKey); - m_inactiveKeys &= ~0x30; - } - if (mappedKey & 0xC0) { - m_activeKeys |= m_inactiveKeys & (0xC0 ^ mappedKey); - m_inactiveKeys &= ~0xC0; - } - } - updateKeys(); -} - -void GameController::clearKeys() { - m_activeKeys = 0; - m_inactiveKeys = 0; - updateKeys(); -} - -void GameController::setAutofire(int key, bool enable) { - if (key >= GBA_KEY_MAX || key < 0) { - return; - } - - if (!enable && m_autofireStatus[key]) { - keyReleased(key); - } - - m_autofire[key] = enable; - m_autofireStatus[key] = 0; -} - -void GameController::setAudioBufferSamples(int samples) { - if (m_audioProcessor) { - threadInterrupt(); - redoSamples(samples); - threadContinue(); - m_audioProcessor->setBufferSamples(samples); - } -} - -void GameController::setAudioSampleRate(unsigned rate) { - if (!rate) { - return; - } - if (m_audioProcessor) { - threadInterrupt(); - redoSamples(m_audioProcessor->getBufferSamples()); - threadContinue(); - m_audioProcessor->requestSampleRate(rate); - } -} - -void GameController::setAudioChannelEnabled(int channel, bool enable) { - if (channel > 5 || channel < 0) { - return; - } - m_audioChannels.reserve(channel + 1); - while (m_audioChannels.size() <= channel) { - m_audioChannels.append(true); - } - m_audioChannels[channel] = enable; - if (isLoaded()) { - m_threadContext.core->enableAudioChannel(m_threadContext.core, channel, enable); - } -} - -void GameController::startAudio() { - if (!m_audioProcessor->start()) { - LOG(QT, ERROR) << tr("Failed to start audio processor"); - // Don't freeze! - m_audioSync = false; - m_videoSync = true; - m_threadContext.sync.audioWait = false; - m_threadContext.sync.videoFrameWait = true; - } -} - -void GameController::setVideoLayerEnabled(int layer, bool enable) { - if (layer > 4 || layer < 0) { - return; - } - m_videoLayers.reserve(layer + 1); - while (m_videoLayers.size() <= layer) { - m_videoLayers.append(true); - } - m_videoLayers[layer] = enable; - if (isLoaded()) { - m_threadContext.core->enableVideoLayer(m_threadContext.core, layer, enable); - } -} - -void GameController::setFPSTarget(float fps) { - Interrupter interrupter(this); - m_fpsTarget = fps; - m_threadContext.sync.fpsTarget = fps; - if (m_turbo && m_turboSpeed > 0) { - m_threadContext.sync.fpsTarget *= m_turboSpeed; - } - if (m_audioProcessor) { - redoSamples(m_audioProcessor->getBufferSamples()); - } -} - -void GameController::setUseBIOS(bool use) { - if (use == m_useBios) { - return; - } - m_useBios = use; - if (m_gameOpen) { - closeGame(); - openGame(); - } -} - -void GameController::loadState(int slot) { - if (m_fname.isEmpty()) { - // We're in the BIOS - return; - } - if (slot > 0 && slot != m_stateSlot) { - m_stateSlot = slot; - m_backupSaveState.clear(); - } - mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { - GameController* controller = static_cast(context->userData); - if (!controller->m_backupLoadState) { - controller->m_backupLoadState = VFileMemChunk(nullptr, 0); - } - mCoreLoadStateNamed(context->core, controller->m_backupLoadState, controller->m_saveStateFlags); - if (mCoreLoadState(context->core, controller->m_stateSlot, controller->m_loadStateFlags)) { - emit controller->frameAvailable(controller->m_drawContext); - emit controller->stateLoaded(context); - } - }); -} - -void GameController::saveState(int slot) { - if (m_fname.isEmpty()) { - // We're in the BIOS - return; - } - if (slot > 0) { - m_stateSlot = slot; - } - mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { - GameController* controller = static_cast(context->userData); - VFile* vf = mCoreGetState(context->core, controller->m_stateSlot, false); - if (vf) { - controller->m_backupSaveState.resize(vf->size(vf)); - vf->read(vf, controller->m_backupSaveState.data(), controller->m_backupSaveState.size()); - vf->close(vf); - } - mCoreSaveState(context->core, controller->m_stateSlot, controller->m_saveStateFlags); - }); -} - -void GameController::loadBackupState() { - if (!m_backupLoadState) { - return; - } - - mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { - GameController* controller = static_cast(context->userData); - controller->m_backupLoadState->seek(controller->m_backupLoadState, 0, SEEK_SET); - if (mCoreLoadStateNamed(context->core, controller->m_backupLoadState, controller->m_loadStateFlags)) { - mLOG(STATUS, INFO, "Undid state load"); - controller->frameAvailable(controller->m_drawContext); - controller->stateLoaded(context); - } - controller->m_backupLoadState->close(controller->m_backupLoadState); - controller->m_backupLoadState = nullptr; - }); -} - -void GameController::saveBackupState() { - if (m_backupSaveState.isEmpty()) { - return; - } - - mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { - GameController* controller = static_cast(context->userData); - VFile* vf = mCoreGetState(context->core, controller->m_stateSlot, true); - if (vf) { - vf->write(vf, controller->m_backupSaveState.constData(), controller->m_backupSaveState.size()); - vf->close(vf); - mLOG(STATUS, INFO, "Undid state save"); - } - controller->m_backupSaveState.clear(); - }); -} - -void GameController::setTurbo(bool set, bool forced) { - if (m_turboForced && !forced) { - return; - } - if (m_turbo == set && m_turboForced == (set && forced)) { - // Don't interrupt the thread if we don't need to - return; - } - if (!m_sync) { - return; - } - m_turbo = set; - m_turboForced = set && forced; - enableTurbo(); -} - -void GameController::setTurboSpeed(float ratio) { - m_turboSpeed = ratio; - enableTurbo(); -} - -void GameController::enableTurbo() { - Interrupter interrupter(this); - bool shouldRedoSamples = false; - if (!m_turbo) { - shouldRedoSamples = m_threadContext.sync.fpsTarget != m_fpsTarget; - m_threadContext.sync.fpsTarget = m_fpsTarget; - m_threadContext.sync.audioWait = m_audioSync; - m_threadContext.sync.videoFrameWait = m_videoSync; - } else if (m_turboSpeed <= 0) { - shouldRedoSamples = m_threadContext.sync.fpsTarget != m_fpsTarget; - m_threadContext.sync.fpsTarget = m_fpsTarget; - m_threadContext.sync.audioWait = false; - m_threadContext.sync.videoFrameWait = false; - } else { - shouldRedoSamples = m_threadContext.sync.fpsTarget != m_fpsTarget * m_turboSpeed; - m_threadContext.sync.fpsTarget = m_fpsTarget * m_turboSpeed; - m_threadContext.sync.audioWait = true; - m_threadContext.sync.videoFrameWait = false; - } - if (m_audioProcessor && shouldRedoSamples) { - redoSamples(m_audioProcessor->getBufferSamples()); - } -} - -void GameController::setSync(bool enable) { - m_turbo = false; - m_turboForced = false; - if (!enable) { - m_threadContext.sync.audioWait = false; - m_threadContext.sync.videoFrameWait = false; - } else { - m_threadContext.sync.audioWait = m_audioSync; - m_threadContext.sync.videoFrameWait = m_videoSync; - } - m_sync = enable; -} - -void GameController::setAudioSync(bool enable) { - m_audioSync = enable; - m_threadContext.sync.audioWait = enable; -} - -void GameController::setVideoSync(bool enable) { - m_videoSync = enable; - m_threadContext.sync.videoFrameWait = enable; -} - -void GameController::setAVStream(mAVStream* stream) { - Interrupter interrupter(this); - m_stream = stream; - if (isLoaded()) { - m_threadContext.core->setAVStream(m_threadContext.core, stream); - } -} - -void GameController::clearAVStream() { - Interrupter interrupter(this); - m_stream = nullptr; - if (isLoaded()) { - m_threadContext.core->setAVStream(m_threadContext.core, nullptr); - } -} - -#ifdef USE_PNG -void GameController::screenshot() { - mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) { - mCoreTakeScreenshot(context->core); - }); -} -#endif - -void GameController::reloadAudioDriver() { - int samples = 0; - unsigned sampleRate = 0; - if (m_audioProcessor) { - m_audioProcessor->pause(); - samples = m_audioProcessor->getBufferSamples(); - sampleRate = m_audioProcessor->sampleRate(); - delete m_audioProcessor; - } - m_audioProcessor = AudioProcessor::create(); - if (samples) { - m_audioProcessor->setBufferSamples(samples); - } - if (sampleRate) { - m_audioProcessor->requestSampleRate(sampleRate); - } - connect(this, &GameController::gamePaused, m_audioProcessor, &AudioProcessor::pause); - connect(this, &GameController::gameStarted, m_audioProcessor, &AudioProcessor::setInput); - if (isLoaded()) { - m_audioProcessor->setInput(&m_threadContext); - startAudio(); - } -} - -void GameController::setSaveStateExtdata(int flags) { - m_saveStateFlags = flags; -} - -void GameController::setLoadStateExtdata(int flags) { - m_loadStateFlags = flags; -} - -void GameController::setPreload(bool preload) { - m_preload = preload; -} - -void GameController::setLuminanceValue(uint8_t value) { - m_luxValue = value; - value = std::max(value - 0x16, 0); - m_luxLevel = 10; - for (int i = 0; i < 10; ++i) { - if (value < GBA_LUX_LEVELS[i]) { - m_luxLevel = i; - break; - } - } - emit luminanceValueChanged(m_luxValue); -} - -void GameController::setLuminanceLevel(int level) { - int value = 0x16; - level = std::max(0, std::min(10, level)); - if (level > 0) { - value += GBA_LUX_LEVELS[level - 1]; - } - setLuminanceValue(value); -} - -void GameController::setRealTime() { - if (!isLoaded()) { - return; - } - m_threadContext.core->rtc.override = RTC_NO_OVERRIDE; -} - -void GameController::setFixedTime(const QDateTime& time) { - if (!isLoaded()) { - return; - } - m_threadContext.core->rtc.override = RTC_FIXED; - m_threadContext.core->rtc.value = time.toMSecsSinceEpoch(); -} - -void GameController::setFakeEpoch(const QDateTime& time) { - if (!isLoaded()) { - return; - } - m_threadContext.core->rtc.override = RTC_FAKE_EPOCH; - m_threadContext.core->rtc.value = time.toMSecsSinceEpoch(); -} - -void GameController::updateKeys() { - int activeKeys = m_activeKeys; - activeKeys |= m_activeButtons; - activeKeys &= ~m_inactiveKeys; - if (isLoaded()) { - m_threadContext.core->setKeys(m_threadContext.core, activeKeys); - } -} - -void GameController::redoSamples(int samples) { - if (m_gameOpen && m_threadContext.core) { - m_threadContext.core->setAudioBufferSize(m_threadContext.core, samples); - } - m_audioProcessor->inputParametersChanged(); -} - -void GameController::setLogLevel(int levels) { - Interrupter interrupter(this); - m_logLevels = levels; -} - -void GameController::enableLogLevel(int levels) { - Interrupter interrupter(this); - m_logLevels |= levels; -} - -void GameController::disableLogLevel(int levels) { - Interrupter interrupter(this); - m_logLevels &= ~levels; -} - -void GameController::startVideoLog(const QString& path) { - if (!isLoaded() || m_vl) { - return; - } - - Interrupter interrupter(this); - m_vl = mVideoLogContextCreate(m_threadContext.core); - m_vlVf = VFileDevice::open(path, O_WRONLY | O_CREAT | O_TRUNC); - mVideoLogContextSetOutput(m_vl, m_vlVf); - mVideoLogContextWriteHeader(m_vl, m_threadContext.core); -} - -void GameController::endVideoLog() { - if (!m_vl) { - return; - } - - Interrupter interrupter(this); - mVideoLogContextDestroy(m_threadContext.core, m_vl); - if (m_vlVf) { - m_vlVf->close(m_vlVf); - m_vlVf = nullptr; - } - m_vl = nullptr; -} - -void GameController::pollEvents() { - if (!m_inputController) { - return; - } - - m_activeButtons = m_inputController->pollEvents(); - updateKeys(); -} - -void GameController::updateAutofire() { - // TODO: Move all key events onto the CPU thread...somehow - for (int k = 0; k < GBA_KEY_MAX; ++k) { - if (!m_autofire[k]) { - continue; - } - m_autofireStatus[k] ^= 1; - if (m_autofireStatus[k]) { - keyPressed(k); - } else { - keyReleased(k); - } - } -} - -std::shared_ptr GameController::tileCache() { - if (m_tileCache) { - return m_tileCache; - } - Interrupter interrupter(this); - switch (platform()) { -#ifdef M_CORE_GBA - case PLATFORM_GBA: { - GBA* gba = static_cast(m_threadContext.core->board); - m_tileCache = std::make_shared(); - GBAVideoTileCacheInit(m_tileCache.get()); - GBAVideoTileCacheAssociate(m_tileCache.get(), &gba->video); - mTileCacheSetPalette(m_tileCache.get(), 0); - break; - } -#endif -#ifdef M_CORE_GB - case PLATFORM_GB: { - GB* gb = static_cast(m_threadContext.core->board); - m_tileCache = std::make_shared(); - GBVideoTileCacheInit(m_tileCache.get()); - GBVideoTileCacheAssociate(m_tileCache.get(), &gb->video); - mTileCacheSetPalette(m_tileCache.get(), 0); - break; - } -#endif - default: - return nullptr; - } - return m_tileCache; -} - -GameController::Interrupter::Interrupter(GameController* parent, bool fromThread) - : m_parent(parent) - , m_fromThread(fromThread) -{ - if (!m_fromThread) { - m_parent->threadInterrupt(); - } else { - mCoreThreadInterruptFromThread(m_parent->thread()); - } -} - -GameController::Interrupter::~Interrupter() { - if (!m_fromThread) { - m_parent->threadContinue(); - } else { - mCoreThreadContinue(m_parent->thread()); - } -} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GameController.h mgba-0.7.0/src/platform/qt/GameController.h --- mgba-0.6.3+dfsg1/src/platform/qt/GameController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GameController.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,262 +0,0 @@ -/* Copyright (c) 2013-2015 Jeffrey Pfau - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef QGBA_GAME_CONTROLLER -#define QGBA_GAME_CONTROLLER - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#ifdef BUILD_SDL -#include "platform/sdl/sdl-events.h" -#endif - -struct Configuration; -struct GBAAudio; -struct mCoreConfig; -struct mDebugger; -struct mTileCache; -struct mVideoLogContext; - -namespace QGBA { - -class AudioProcessor; -class InputController; -class MultiplayerController; -class Override; - -class GameController : public QObject { -Q_OBJECT - -public: - static const bool VIDEO_SYNC = false; - static const bool AUDIO_SYNC = true; - - class Interrupter { - public: - Interrupter(GameController*, bool fromThread = false); - ~Interrupter(); - - private: - GameController* m_parent; - bool m_fromThread; - }; - - GameController(QObject* parent = nullptr); - ~GameController(); - - const uint32_t* drawContext() const { return m_drawContext; } - mCoreThread* thread() { return &m_threadContext; } - mCheatDevice* cheatDevice() { return m_threadContext.core ? m_threadContext.core->cheatDevice(m_threadContext.core) : nullptr; } - - void threadInterrupt(); - void threadContinue(); - - bool isPaused(); - bool isLoaded() { return m_gameOpen && mCoreThreadIsActive(&m_threadContext); } - mPlatform platform() const; - - bool audioSync() const { return m_audioSync; } - bool videoSync() const { return m_videoSync; } - QSize screenDimensions() const; - - void setInputController(InputController* controller) { m_inputController = controller; } - - void setMultiplayerController(MultiplayerController* controller); - MultiplayerController* multiplayerController() { return m_multiplayer; } - void clearMultiplayerController(); - - void setOverride(Override* override); - Override* override() { return m_override; } - void clearOverride(); - - void setConfig(const mCoreConfig*); - - int stateSlot() const { return m_stateSlot; } - -#ifdef USE_DEBUGGERS - mDebugger* debugger(); - void setDebugger(mDebugger*); -#endif - - std::shared_ptr tileCache(); - -signals: - void frameAvailable(const uint32_t*); - void gameStarted(mCoreThread*, const QString& fname); - void gameStopped(mCoreThread*); - void gamePaused(mCoreThread*); - void gameUnpaused(mCoreThread*); - void gameCrashed(const QString& errorMessage); - void gameFailed(); - void stateLoaded(mCoreThread*); - void rewound(mCoreThread*); - void unimplementedBiosCall(int); - - void luminanceValueChanged(int); - - void statusPosted(const QString& message); - void postLog(int level, int category, const QString& log); - -public slots: - void loadGame(const QString& path); - void loadGame(VFile* vf, const QString& path, const QString& base); - void loadBIOS(int platform, const QString& path); - void loadSave(const QString& path, bool temporary = true); - void yankPak(); - void replaceGame(const QString& path); - void setUseBIOS(bool); - void loadPatch(const QString& path); - void importSharkport(const QString& path); - void exportSharkport(const QString& path); - void bootBIOS(); - void closeGame(); - void setPaused(bool paused); - void reset(); - void frameAdvance(); - void setRewind(bool enable, int capacity, bool rewindSave); - void rewind(int states = 0); - void startRewinding(); - void stopRewinding(); - void keyPressed(int key); - void keyReleased(int key); - void clearKeys(); - void setAutofire(int key, bool enable); - void setAudioBufferSamples(int samples); - void setAudioSampleRate(unsigned rate); - void setAudioChannelEnabled(int channel, bool enable = true); - void startAudio(); - void setVideoLayerEnabled(int layer, bool enable = true); - void setFPSTarget(float fps); - void loadState(int slot = 0); - void saveState(int slot = 0); - void loadBackupState(); - void saveBackupState(); - void setTurbo(bool, bool forced = true); - void setTurboSpeed(float ratio); - void setSync(bool); - void setAudioSync(bool); - void setVideoSync(bool); - void setAVStream(mAVStream*); - void clearAVStream(); - void reloadAudioDriver(); - void setSaveStateExtdata(int flags); - void setLoadStateExtdata(int flags); - void setPreload(bool); - -#ifdef USE_PNG - void screenshot(); -#endif - - void setLuminanceValue(uint8_t value); - uint8_t luminanceValue() const { return m_luxValue; } - void setLuminanceLevel(int level); - void increaseLuminanceLevel() { setLuminanceLevel(m_luxLevel + 1); } - void decreaseLuminanceLevel() { setLuminanceLevel(m_luxLevel - 1); } - - void setRealTime(); - void setFixedTime(const QDateTime& time); - void setFakeEpoch(const QDateTime& time); - - void setLogLevel(int); - void enableLogLevel(int); - void disableLogLevel(int); - - void startVideoLog(const QString& path); - void endVideoLog(); - -private slots: - void openGame(bool bios = false); - void crashGame(const QString& crashMessage); - void cleanGame(); - - void pollEvents(); - void updateAutofire(); - -private: - void updateKeys(); - void redoSamples(int samples); - void enableTurbo(); - - uint32_t* m_drawContext = nullptr; - uint32_t* m_frontBuffer = nullptr; - mCoreThread m_threadContext{}; - const mCoreConfig* m_config; - mCheatDevice* m_cheatDevice; - int m_activeKeys = 0; - int m_activeButtons = 0; - int m_inactiveKeys = 0; - int m_logLevels = 0; - - bool m_gameOpen = false; - - QString m_fname; - QString m_fsub; - VFile* m_vf = nullptr; - QString m_bios; - bool m_useBios = false; - QString m_patch; - Override* m_override = nullptr; - - AudioProcessor* m_audioProcessor; - - QAtomicInt m_pauseAfterFrame{false}; - QList> m_resetActions; - - bool m_sync = true; - bool m_videoSync = VIDEO_SYNC; - bool m_audioSync = AUDIO_SYNC; - float m_fpsTarget = -1; - bool m_turbo = false; - bool m_turboForced = false; - float m_turboSpeed = -1; - bool m_wasPaused = false; - - std::shared_ptr m_tileCache; - - QList m_audioChannels; - QList m_videoLayers; - - bool m_autofire[GBA_KEY_MAX] = {}; - int m_autofireStatus[GBA_KEY_MAX] = {}; - - int m_stateSlot = 1; - struct VFile* m_backupLoadState = nullptr; - QByteArray m_backupSaveState{nullptr}; - int m_saveStateFlags; - int m_loadStateFlags; - - bool m_preload = false; - - InputController* m_inputController = nullptr; - MultiplayerController* m_multiplayer = nullptr; - - mAVStream* m_stream = nullptr; - - mVideoLogContext* m_vl = nullptr; - VFile* m_vlVf = nullptr; - - struct GameControllerLux : GBALuminanceSource { - GameController* p; - uint8_t value; - } m_lux; - uint8_t m_luxValue; - int m_luxLevel; -}; - -} - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GamepadAxisEvent.h mgba-0.7.0/src/platform/qt/GamepadAxisEvent.h --- mgba-0.6.3+dfsg1/src/platform/qt/GamepadAxisEvent.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GamepadAxisEvent.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_GAMEPAD_AXIS_EVENT -#define QGBA_GAMEPAD_AXIS_EVENT +#pragma once #include @@ -42,5 +41,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GamepadButtonEvent.h mgba-0.7.0/src/platform/qt/GamepadButtonEvent.h --- mgba-0.6.3+dfsg1/src/platform/qt/GamepadButtonEvent.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GamepadButtonEvent.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_GAMEPAD_BUTTON_EVENT -#define QGBA_GAMEPAD_BUTTON_EVENT +#pragma once #include @@ -34,5 +33,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GamepadHatEvent.h mgba-0.7.0/src/platform/qt/GamepadHatEvent.h --- mgba-0.6.3+dfsg1/src/platform/qt/GamepadHatEvent.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GamepadHatEvent.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_GAMEPAD_HAT_EVENT -#define QGBA_GAMEPAD_HAT_EVENT +#pragma once #include @@ -44,5 +43,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GBAApp.cpp mgba-0.7.0/src/platform/qt/GBAApp.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/GBAApp.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GBAApp.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -6,9 +6,10 @@ #include "GBAApp.h" #include "AudioProcessor.h" +#include "CoreController.h" +#include "CoreManager.h" #include "ConfigController.h" #include "Display.h" -#include "GameController.h" #include "Window.h" #include "VFileDevice.h" @@ -57,21 +58,34 @@ reloadGameDB(); + m_manager.setConfig(m_configController->config()); + m_manager.setMultiplayerController(&m_multiplayer); + if (!m_configController->getQtOption("audioDriver").isNull()) { AudioProcessor::setDriver(static_cast(m_configController->getQtOption("audioDriver").toInt())); } + + connect(this, &GBAApp::aboutToQuit, this, &GBAApp::cleanup); } -GBAApp::~GBAApp() { +void GBAApp::cleanup() { + m_workerThreads.waitForDone(); + + while (!m_workerJobs.isEmpty()) { + finishJob(m_workerJobs.firstKey()); + } + #ifdef USE_SQLITE3 - m_parseThread.quit(); - m_parseThread.wait(); + if (m_db) { + NoIntroDBDestroy(m_db); + } #endif } bool GBAApp::event(QEvent* event) { if (event->type() == QEvent::FileOpen) { - m_windows[0]->controller()->loadGame(static_cast(event)->file()); + CoreController* core = m_manager.loadGame(static_cast(event)->file()); + m_windows[0]->setController(core, static_cast(event)->file()); return true; } return QApplication::event(event); @@ -81,7 +95,7 @@ if (m_windows.count() >= MAX_GBAS) { return nullptr; } - Window* w = new Window(m_configController, m_multiplayer.attached()); + Window* w = new Window(&m_manager, m_configController, m_multiplayer.attached()); int windowId = m_multiplayer.attached(); connect(w, &Window::destroyed, [this, w]() { m_windows.removeAll(w); @@ -93,7 +107,6 @@ w->setAttribute(Qt::WA_DeleteOnClose); w->loadConfig(); w->show(); - w->controller()->setMultiplayerController(&m_multiplayer); w->multiplayerChanged(); for (Window* w : m_windows) { w->updateMultiplayerStatus(m_windows.count() < MAX_GBAS); @@ -107,7 +120,7 @@ void GBAApp::pauseAll(QList* paused) { for (auto& window : m_windows) { - if (!window->controller()->isLoaded() || window->controller()->isPaused()) { + if (!window->controller() || window->controller()->isPaused()) { continue; } window->controller()->setPaused(true); @@ -117,7 +130,9 @@ void GBAApp::continueAll(const QList& paused) { for (auto& window : paused) { - window->controller()->setPaused(false); + if (window->controller()) { + window->controller()->setPaused(false); + } } } @@ -174,14 +189,8 @@ NoIntroDBDestroy(m_db); } if (db) { - if (m_parseThread.isRunning()) { - m_parseThread.quit(); - m_parseThread.wait(); - } - GameDBParser* parser = new GameDBParser(db); - m_parseThread.start(); - parser->moveToThread(&m_parseThread); - QMetaObject::invokeMethod(parser, "parseNoIntroDB"); + std::shared_ptr parser = std::make_shared(db); + submitWorkerJob(std::bind(&GameDBParser::parseNoIntroDB, parser)); m_db = db; return true; } @@ -193,6 +202,77 @@ } #endif +qint64 GBAApp::submitWorkerJob(std::function job, std::function callback) { + return submitWorkerJob(job, nullptr, callback); +} + +qint64 GBAApp::submitWorkerJob(std::function job, QObject* context, std::function callback) { + qint64 jobId = m_nextJob; + ++m_nextJob; + WorkerJob* jobRunnable = new WorkerJob(jobId, job, this); + m_workerJobs.insert(jobId, jobRunnable); + if (callback) { + waitOnJob(jobId, context, callback); + } + m_workerThreads.start(jobRunnable); + return jobId; +} + +bool GBAApp::removeWorkerJob(qint64 jobId) { + for (auto& job : m_workerJobCallbacks.values(jobId)) { + disconnect(job); + } + m_workerJobCallbacks.remove(jobId); + if (!m_workerJobs.contains(jobId)) { + return true; + } + bool success = false; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) + success = m_workerThreads.tryTake(m_workerJobs[jobId]); +#endif + if (success) { + m_workerJobs.remove(jobId); + } + return success; +} + + +bool GBAApp::waitOnJob(qint64 jobId, QObject* context, std::function callback) { + if (!m_workerJobs.contains(jobId)) { + return false; + } + if (!context) { + context = this; + } + QMetaObject::Connection connection = connect(this, &GBAApp::jobFinished, context, [jobId, callback](qint64 testedJobId) { + if (jobId != testedJobId) { + return; + } + callback(); + }); + m_workerJobCallbacks.insert(m_nextJob, connection); + return true; +} + +void GBAApp::finishJob(qint64 jobId) { + m_workerJobs.remove(jobId); + emit jobFinished(jobId); + m_workerJobCallbacks.remove(jobId); +} + +GBAApp::WorkerJob::WorkerJob(qint64 id, std::function job, GBAApp* owner) + : m_id(id) + , m_job(job) + , m_owner(owner) +{ + setAutoDelete(true); +} + +void GBAApp::WorkerJob::run() { + m_job(); + QMetaObject::invokeMethod(m_owner, "finishJob", Q_ARG(qint64, m_id)); +} + #ifdef USE_SQLITE3 GameDBParser::GameDBParser(NoIntroDB* db, QObject* parent) : QObject(parent) diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GBAApp.h mgba-0.7.0/src/platform/qt/GBAApp.h --- mgba-0.6.3+dfsg1/src/platform/qt/GBAApp.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GBAApp.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,13 +3,21 @@ * 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_APP_H -#define QGBA_APP_H +#pragma once #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CoreManager.h" #include "MultiplayerController.h" struct NoIntroDB; @@ -44,7 +52,6 @@ public: GBAApp(int& argc, char* argv[], ConfigController*); - ~GBAApp(); static GBAApp* app(); static QString dataDir(); @@ -58,10 +65,35 @@ const NoIntroDB* gameDB() const { return m_db; } bool reloadGameDB(); + qint64 submitWorkerJob(std::function job, std::function callback = {}); + qint64 submitWorkerJob(std::function job, QObject* context, std::function callback); + bool removeWorkerJob(qint64 jobId); + bool waitOnJob(qint64 jobId, QObject* context, std::function callback); + +signals: + void jobFinished(qint64 jobId); + protected: bool event(QEvent*); +private slots: + void finishJob(qint64 jobId); + void cleanup(); + private: + class WorkerJob : public QRunnable { + public: + WorkerJob(qint64 id, std::function job, GBAApp* owner); + + public: + void run() override; + + private: + qint64 m_id; + std::function m_job; + GBAApp* m_owner; + }; + Window* newWindowInternal(); void pauseAll(QList* paused); @@ -70,13 +102,14 @@ ConfigController* m_configController; QList m_windows; MultiplayerController m_multiplayer; + CoreManager m_manager; + + QMap m_workerJobs; + QMultiMap m_workerJobCallbacks; + QThreadPool m_workerThreads; + qint64 m_nextJob = 1; NoIntroDB* m_db = nullptr; -#ifdef USE_SQLITE3 - QThread m_parseThread; -#endif }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GBAKeyEditor.cpp mgba-0.7.0/src/platform/qt/GBAKeyEditor.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/GBAKeyEditor.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GBAKeyEditor.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -278,13 +278,13 @@ if (description->highDirection != GBA_KEY_NONE) { KeyEditor* key = self->keyById(static_cast(description->highDirection)); if (key) { - key->setValueAxis(axis, description->deadHigh); + key->setValueAxis(axis, GamepadAxisEvent::POSITIVE); } } if (description->lowDirection != GBA_KEY_NONE) { KeyEditor* key = self->keyById(static_cast(description->lowDirection)); if (key) { - key->setValueAxis(axis, description->deadLow); + key->setValueAxis(axis, GamepadAxisEvent::NEGATIVE); } } }, this); @@ -350,14 +350,6 @@ } #ifdef BUILD_SDL -void GBAKeyEditor::setAxisValue(int axis, int32_t value) { - if (!findFocus()) { - return; - } - KeyEditor* focused = *m_currentKey; - focused->setValueAxis(axis, value); -} - void GBAKeyEditor::selectGamepad(int index) { m_controller->setGamepad(m_type, index); m_profile = m_profileSelect->currentText(); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GBAKeyEditor.h mgba-0.7.0/src/platform/qt/GBAKeyEditor.h --- mgba-0.6.3+dfsg1/src/platform/qt/GBAKeyEditor.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GBAKeyEditor.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_GBA_KEY_EDITOR -#define QGBA_GBA_KEY_EDITOR +#pragma once #include #include @@ -43,7 +42,6 @@ void setNext(); void refresh(); #ifdef BUILD_SDL - void setAxisValue(int axis, int32_t value); void selectGamepad(int index); void updateJoysticks(); #endif @@ -92,5 +90,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GBAOverride.h mgba-0.7.0/src/platform/qt/GBAOverride.h --- mgba-0.6.3+dfsg1/src/platform/qt/GBAOverride.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GBAOverride.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_GBA_OVERRIDE -#define QGBA_GBA_OVERRIDE +#pragma once #include "Override.h" @@ -22,5 +21,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GBOverride.h mgba-0.7.0/src/platform/qt/GBOverride.h --- mgba-0.6.3+dfsg1/src/platform/qt/GBOverride.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GBOverride.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_GB_OVERRIDE -#define QGBA_GB_OVERRIDE +#pragma once #include "Override.h" @@ -22,5 +21,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GDBController.cpp mgba-0.7.0/src/platform/qt/GDBController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/GDBController.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GDBController.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,12 +5,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GDBController.h" -#include "GameController.h" +#include "CoreController.h" using namespace QGBA; -GDBController::GDBController(GameController* controller, QObject* parent) - : DebuggerController(controller, &m_gdbStub.d, parent) +GDBController::GDBController(QObject* parent) + : DebuggerController(&m_gdbStub.d, parent) , m_bindAddress({ IPV4, 0 }) { GDBStubCreate(&m_gdbStub); @@ -21,7 +21,7 @@ } bool GDBController::isAttached() { - return m_gameController->debugger() == &m_gdbStub.d; + return m_gameController && m_gameController->debugger() == &m_gdbStub.d; } void GDBController::setPort(ushort port) { @@ -34,7 +34,6 @@ } void GDBController::listen() { - GameController::Interrupter interrupter(m_gameController); if (!isAttached()) { attach(); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GDBController.h mgba-0.7.0/src/platform/qt/GDBController.h --- mgba-0.6.3+dfsg1/src/platform/qt/GDBController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GDBController.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_GDB_CONTROLLER -#define QGBA_GDB_CONTROLLER +#pragma once #include "DebuggerController.h" @@ -14,13 +13,13 @@ namespace QGBA { -class GameController; +class CoreController; class GDBController : public DebuggerController { Q_OBJECT public: - GDBController(GameController* controller, QObject* parent = nullptr); + GDBController(QObject* parent = nullptr); public: ushort port(); @@ -38,7 +37,7 @@ private: virtual void shutdownInternal() override; - GDBStub m_gdbStub; + GDBStub m_gdbStub{}; ushort m_port = 2345; Address m_bindAddress; @@ -47,5 +46,3 @@ } #endif - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GDBWindow.h mgba-0.7.0/src/platform/qt/GDBWindow.h --- mgba-0.6.3+dfsg1/src/platform/qt/GDBWindow.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GDBWindow.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_GDB_WINDOW -#define QGBA_GDB_WINDOW +#pragma once #include @@ -40,5 +39,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GIFView.cpp mgba-0.7.0/src/platform/qt/GIFView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/GIFView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GIFView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -7,6 +7,7 @@ #ifdef USE_MAGICK +#include "CoreController.h" #include "GBAApp.h" #include "LogController.h" @@ -39,6 +40,12 @@ stopRecording(); } +void GIFView::setController(std::shared_ptr controller) { + connect(controller.get(), &CoreController::stopping, this, &GIFView::stopRecording); + connect(this, &GIFView::recordingStarted, controller.get(), &CoreController::setAVStream); + connect(this, &GIFView::recordingStopped, controller.get(), &CoreController::clearAVStream, Qt::DirectConnection); +} + void GIFView::startRecording() { int delayMs = m_ui.delayAuto->isChecked() ? -1 : m_ui.delayMs->value(); ImageMagickGIFEncoderSetParams(&m_encoder, m_ui.frameskip->value(), delayMs); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/GIFView.h mgba-0.7.0/src/platform/qt/GIFView.h --- mgba-0.6.3+dfsg1/src/platform/qt/GIFView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/GIFView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,19 +3,22 @@ * 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_GIF_VIEW -#define QGBA_GIF_VIEW +#pragma once #ifdef USE_MAGICK #include +#include + #include "ui_GIFView.h" #include "feature/imagemagick/imagemagick-gif-encoder.h" namespace QGBA { +class CoreController; + class GIFView : public QWidget { Q_OBJECT @@ -26,6 +29,8 @@ mAVStream* getStream() { return &m_encoder.d; } public slots: + void setController(std::shared_ptr); + void startRecording(); void stopRecording(); @@ -49,5 +54,3 @@ } #endif - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/InputController.cpp mgba-0.7.0/src/platform/qt/InputController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/InputController.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/InputController.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -9,10 +9,15 @@ #include "GamepadAxisEvent.h" #include "GamepadButtonEvent.h" #include "InputProfile.h" +#include "LogController.h" #include #include #include +#ifdef BUILD_QT_MULTIMEDIA +#include +#include +#endif #include #include @@ -53,6 +58,10 @@ m_gamepadTimer.setInterval(50); m_gamepadTimer.start(); +#ifdef BUILD_QT_MULTIMEDIA + connect(&m_videoDumper, &VideoDumper::imageAvailable, this, &InputController::setCamImage); +#endif + mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_X, GBA_KEY_A); mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Z, GBA_KEY_B); mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_A, GBA_KEY_L); @@ -63,6 +72,67 @@ mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Down, GBA_KEY_DOWN); mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Left, GBA_KEY_LEFT); mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Right, GBA_KEY_RIGHT); + + +#ifdef M_CORE_GBA + m_lux.p = this; + m_lux.sample = [](GBALuminanceSource* context) { + InputControllerLux* lux = static_cast(context); + lux->value = 0xFF - lux->p->m_luxValue; + }; + + m_lux.readLuminance = [](GBALuminanceSource* context) { + InputControllerLux* lux = static_cast(context); + return lux->value; + }; + setLuminanceLevel(0); +#endif + + m_image.p = this; + m_image.startRequestImage = [](mImageSource* context, unsigned w, unsigned h, int) { + InputControllerImage* image = static_cast(context); + image->w = w; + image->h = h; + if (image->image.isNull()) { + image->image.load(":/res/no-cam.png"); + } +#ifdef BUILD_QT_MULTIMEDIA + if (image->p->m_config->getQtOption("cameraDriver").toInt() == static_cast(CameraDriver::QT_MULTIMEDIA)) { + QMetaObject::invokeMethod(image->p, "setupCam"); + } +#endif + }; + + m_image.stopRequestImage = [](mImageSource* context) { + InputControllerImage* image = static_cast(context); +#ifdef BUILD_QT_MULTIMEDIA + QMetaObject::invokeMethod(image->p, "teardownCam"); +#endif + }; + + m_image.requestImage = [](mImageSource* context, const void** buffer, size_t* stride, mColorFormat* format) { + InputControllerImage* image = static_cast(context); + QSize size; + { + QMutexLocker locker(&image->mutex); + if (image->outOfDate) { + image->resizedImage = image->image.scaled(image->w, image->h, Qt::KeepAspectRatioByExpanding); + image->resizedImage = image->resizedImage.convertToFormat(QImage::Format_RGB16); + image->outOfDate = false; + } + } + size = image->resizedImage.size(); + const uint16_t* bits = reinterpret_cast(image->resizedImage.constBits()); + if (size.width() > image->w) { + bits += (size.width() - image->w) / 2; + } + if (size.height() > image->h) { + bits += ((size.height() - image->h) / 2) * size.width(); + } + *buffer = bits; + *stride = image->resizedImage.bytesPerLine() / sizeof(*bits); + *format = mCOLOR_RGB565; + }; } InputController::~InputController() { @@ -82,7 +152,6 @@ void InputController::setConfiguration(ConfigController* config) { m_config = config; - setAllowOpposing(config->getOption("allowOpposingDirections").toInt()); loadConfiguration(KEYBOARD); #ifdef BUILD_SDL mSDLEventsLoadConfig(&s_sdlEvents, config->input()); @@ -607,3 +676,98 @@ m_focusParent = m_topLevel; } } + +void InputController::loadCamImage(const QString& path) { + setCamImage(QImage(path)); +} + +void InputController::setCamImage(const QImage& image) { + if (image.isNull()) { + return; + } + QMutexLocker locker(&m_image.mutex); + m_image.image = image; + m_image.resizedImage = QImage(); + m_image.outOfDate = true; +} + +void InputController::increaseLuminanceLevel() { + setLuminanceLevel(m_luxLevel + 1); +} + +void InputController::decreaseLuminanceLevel() { + setLuminanceLevel(m_luxLevel - 1); +} + +void InputController::setLuminanceLevel(int level) { + int value = 0x16; + level = std::max(0, std::min(10, level)); + if (level > 0) { + value += GBA_LUX_LEVELS[level - 1]; + } + setLuminanceValue(value); +} + +void InputController::setLuminanceValue(uint8_t value) { + m_luxValue = value; + value = std::max(value - 0x16, 0); + m_luxLevel = 10; + for (int i = 0; i < 10; ++i) { + if (value < GBA_LUX_LEVELS[i]) { + m_luxLevel = i; + break; + } + } + emit luminanceValueChanged(m_luxValue); +} + +void InputController::setupCam() { +#ifdef BUILD_QT_MULTIMEDIA + if (!m_camera) { + m_camera = std::make_unique(); + } + QVideoFrame::PixelFormat format(QVideoFrame::Format_RGB32); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) + m_camera->load(); + QCameraViewfinderSettings settings; + QSize size(1920, 1080); + auto cameraRes = m_camera->supportedViewfinderResolutions(settings); + for (auto& cameraSize : cameraRes) { + if (cameraSize.width() < m_image.w || cameraSize.height() < m_image.h) { + continue; + } + if (cameraSize.width() <= size.width() && cameraSize.height() <= size.height()) { + size = cameraSize; + } + } + settings.setResolution(size); + auto cameraFormats = m_camera->supportedViewfinderPixelFormats(settings); + auto goodFormats = m_videoDumper.supportedPixelFormats(); + bool goodFormatFound = false; + for (auto& goodFormat : goodFormats) { + if (cameraFormats.contains(goodFormat)) { + settings.setPixelFormat(goodFormat); + format = goodFormat; + goodFormatFound = true; + break; + } + } + if (!goodFormatFound) { + LOG(QT, WARN) << "Could not find a valid camera format!"; + } + m_camera->setViewfinderSettings(settings); +#endif + m_camera->setCaptureMode(QCamera::CaptureVideo); + m_camera->setViewfinder(&m_videoDumper); + m_camera->start(); +#endif +} + +void InputController::teardownCam() { +#ifdef BUILD_QT_MULTIMEDIA + if (m_camera) { + m_camera->stop(); + m_camera.reset(); + } +#endif +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/InputController.h mgba-0.7.0/src/platform/qt/InputController.h --- mgba-0.6.3+dfsg1/src/platform/qt/InputController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/InputController.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,26 +3,37 @@ * 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_INPUT_CONTROLLER_H -#define QGBA_INPUT_CONTROLLER_H +#pragma once #include "GamepadAxisEvent.h" #include "GamepadHatEvent.h" +#include +#include #include #include #include #include +#include + +#include #include #ifdef BUILD_SDL #include "platform/sdl/sdl-events.h" #endif + +#ifdef BUILD_QT_MULTIMEDIA +#include "VideoDumper.h" +#endif + struct mRotationSource; struct mRumble; +class QCamera; + namespace QGBA { class ConfigController; @@ -31,6 +42,13 @@ Q_OBJECT public: + enum class CameraDriver : int { + NONE = 0, +#ifdef BUILD_QT_MULTIMEDIA + QT_MULTIMEDIA = 1, +#endif + }; + static const uint32_t KEYBOARD = 0x51545F4B; InputController(int playerId = 0, QWidget* topLevel = nullptr, QObject* parent = nullptr); @@ -44,9 +62,6 @@ void saveProfile(uint32_t type, const QString& profile); const char* profileForType(uint32_t type); - bool allowOpposing() const { return m_allowOpposing; } - void setAllowOpposing(bool allowOpposing) { m_allowOpposing = allowOpposing; } - GBAKey mapKeyboard(int key) const; void bindKey(uint32_t type, int key, GBAKey); @@ -84,9 +99,12 @@ mRumble* rumble(); mRotationSource* rotationSource(); + mImageSource* imageSource() { return &m_image; } + GBALuminanceSource* luminance() { return &m_lux; } signals: void profileLoaded(const QString& profile); + void luminanceValueChanged(int value); public slots: void testGamepad(int type); @@ -97,16 +115,48 @@ void resumeScreensaver(); void setScreensaverSuspendable(bool); + void increaseLuminanceLevel(); + void decreaseLuminanceLevel(); + void setLuminanceLevel(int level); + void setLuminanceValue(uint8_t value); + + void loadCamImage(const QString& path); + void setCamImage(const QImage& image); + +private slots: + void setupCam(); + void teardownCam(); + private: void postPendingEvent(GBAKey); void clearPendingEvent(GBAKey); bool hasPendingEvent(GBAKey) const; void sendGamepadEvent(QEvent*); + struct InputControllerLux : GBALuminanceSource { + InputController* p; + uint8_t value; + } m_lux; + uint8_t m_luxValue; + int m_luxLevel; + + struct InputControllerImage : mImageSource { + InputController* p; + QImage image; + QImage resizedImage; + bool outOfDate; + QMutex mutex; + unsigned w, h; + } m_image; + +#ifdef BUILD_QT_MULTIMEDIA + std::unique_ptr m_camera; + VideoDumper m_videoDumper; +#endif + mInputMap m_inputMap; ConfigController* m_config = nullptr; int m_playerId; - bool m_allowOpposing = false; QWidget* m_topLevel; QWidget* m_focusParent; @@ -128,5 +178,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/InputProfile.h mgba-0.7.0/src/platform/qt/InputProfile.h --- mgba-0.6.3+dfsg1/src/platform/qt/InputProfile.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/InputProfile.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_INPUT_PROFILE -#define QGBA_INPUT_PROFILE +#pragma once #include "GamepadAxisEvent.h" @@ -94,5 +93,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/IOViewer.cpp mgba-0.7.0/src/platform/qt/IOViewer.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/IOViewer.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/IOViewer.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "IOViewer.h" -#include "GameController.h" +#include "CoreController.h" #include #include @@ -1023,7 +1023,7 @@ return s_registers; } -IOViewer::IOViewer(GameController* controller, QWidget* parent) +IOViewer::IOViewer(std::shared_ptr controller, QWidget* parent) : QDialog(parent) , m_controller(controller) { @@ -1067,16 +1067,17 @@ } selectRegister(0); + + connect(controller.get(), &CoreController::stopping, this, &QWidget::close); } void IOViewer::updateRegister() { m_value = 0; uint16_t value = 0; - m_controller->threadInterrupt(); - if (m_controller->isLoaded()) { + { + CoreController::Interrupter interrupter(m_controller); value = GBAView16(static_cast(m_controller->thread()->core->cpu), BASE_IO | m_register); } - m_controller->threadContinue(); for (int i = 0; i < 16; ++i) { m_b[i]->setChecked(value & (1 << i) ? Qt::Checked : Qt::Unchecked); @@ -1095,11 +1096,10 @@ } void IOViewer::writeback() { - m_controller->threadInterrupt(); - if (m_controller->isLoaded()) { + { + CoreController::Interrupter interrupter(m_controller); GBAIOWrite(static_cast(m_controller->thread()->core->board), m_register, m_value); } - m_controller->threadContinue(); updateRegister(); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/IOViewer.h mgba-0.7.0/src/platform/qt/IOViewer.h --- mgba-0.6.3+dfsg1/src/platform/qt/IOViewer.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/IOViewer.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,17 +3,18 @@ * 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_IOVIEWER -#define QGBA_IOVIEWER +#pragma once #include #include +#include + #include "ui_IOViewer.h" namespace QGBA { -class GameController; +class CoreController; class IOViewer : public QDialog { Q_OBJECT @@ -39,7 +40,7 @@ }; typedef QList RegisterDescription; - IOViewer(GameController* controller, QWidget* parent = nullptr); + IOViewer(std::shared_ptr controller, QWidget* parent = nullptr); static const QList& registerDescriptions(); @@ -65,9 +66,7 @@ QCheckBox* m_b[16]; - GameController* m_controller; + std::shared_ptr m_controller; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/KeyEditor.cpp mgba-0.7.0/src/platform/qt/KeyEditor.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/KeyEditor.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/KeyEditor.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -48,10 +48,10 @@ setValue(button); } -void KeyEditor::setValueAxis(int axis, int32_t value) { +void KeyEditor::setValueAxis(int axis, GamepadAxisEvent::Direction direction) { m_button = true; m_axis = axis; - m_direction = value < 0 ? GamepadAxisEvent::NEGATIVE : GamepadAxisEvent::POSITIVE; + m_direction = direction; updateButtonText(); emit axisChanged(axis, m_direction); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/KeyEditor.h mgba-0.7.0/src/platform/qt/KeyEditor.h --- mgba-0.6.3+dfsg1/src/platform/qt/KeyEditor.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/KeyEditor.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_KEY_EDITOR -#define QGBA_KEY_EDITOR +#pragma once #include "GamepadAxisEvent.h" #include "GamepadHatEvent.h" @@ -34,7 +33,7 @@ void setValue(int key); void setValueKey(int key); void setValueButton(int button); - void setValueAxis(int axis, int32_t value); + void setValueAxis(int axis, GamepadAxisEvent::Direction value); void setValueHat(int hat, GamepadHatEvent::Direction value); void clearButton(); void clearAxis(); @@ -64,5 +63,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryController.cpp mgba-0.7.0/src/platform/qt/library/LibraryController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryController.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/library/LibraryController.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -29,16 +29,6 @@ } } -LibraryLoaderThread::LibraryLoaderThread(QObject* parent) - : QThread(parent) -{ -} - -void LibraryLoaderThread::run() { - mLibraryLoadDirectory(m_library, m_directory.toUtf8().constData()); - m_directory = QString(); -} - LibraryController::LibraryController(QWidget* parent, const QString& path, ConfigController* config) : QStackedWidget(parent) , m_config(config) @@ -47,39 +37,26 @@ if (!path.isNull()) { // This can return NULL if the library is already open - m_library = mLibraryLoad(path.toUtf8().constData()); + m_library = std::shared_ptr(mLibraryLoad(path.toUtf8().constData()), mLibraryDestroy); } if (!m_library) { - m_library = mLibraryCreateEmpty(); + m_library = std::shared_ptr(mLibraryCreateEmpty(), mLibraryDestroy); } - mLibraryAttachGameDB(m_library, GBAApp::app()->gameDB()); + mLibraryAttachGameDB(m_library.get(), GBAApp::app()->gameDB()); - m_libraryTree = new LibraryTree(this); + m_libraryTree = std::make_unique(this); addWidget(m_libraryTree->widget()); - m_libraryGrid = new LibraryGrid(this); + m_libraryGrid = std::make_unique(this); addWidget(m_libraryGrid->widget()); - connect(&m_loaderThread, &QThread::finished, this, &LibraryController::refresh, Qt::QueuedConnection); - setViewStyle(LibraryStyle::STYLE_LIST); refresh(); } LibraryController::~LibraryController() { mLibraryListingDeinit(&m_listing); - - if (m_loaderThread.isRunning()) { - m_loaderThread.wait(); - } - if (!m_loaderThread.isRunning() && m_loaderThread.m_library) { - m_library = m_loaderThread.m_library; - m_loaderThread.m_library = nullptr; - } - if (m_library) { - mLibraryDestroy(m_library); - } } void LibraryController::setViewStyle(LibraryStyle newStyle) { @@ -90,9 +67,9 @@ AbstractGameList* newCurrentList = nullptr; if (newStyle == LibraryStyle::STYLE_LIST || newStyle == LibraryStyle::STYLE_TREE) { - newCurrentList = m_libraryTree; + newCurrentList = m_libraryTree.get(); } else { - newCurrentList = m_libraryGrid; + newCurrentList = m_libraryGrid.get(); } newCurrentList->selectEntry(selectedEntry()); newCurrentList->setViewStyle(newStyle); @@ -117,7 +94,7 @@ VFile* LibraryController::selectedVFile() { LibraryEntryRef entry = selectedEntry(); if (entry) { - return mLibraryOpenVFile(m_library, entry->entry); + return mLibraryOpenVFile(m_library.get(), entry->entry); } else { return nullptr; } @@ -129,35 +106,26 @@ } void LibraryController::addDirectory(const QString& dir) { - m_loaderThread.m_directory = dir; - m_loaderThread.m_library = m_library; - // The m_loaderThread temporarily owns the library - m_library = nullptr; - m_loaderThread.start(); + // The worker thread temporarily owns the library + std::shared_ptr library = m_library; + m_libraryJob = GBAApp::app()->submitWorkerJob(std::bind(&LibraryController::loadDirectory, this, dir), this, [this, library]() { + m_libraryJob = -1; + refresh(); + }); } void LibraryController::clear() { - if (!m_library) { - if (!m_loaderThread.isRunning() && m_loaderThread.m_library) { - m_library = m_loaderThread.m_library; - m_loaderThread.m_library = nullptr; - } else { - return; - } + if (m_libraryJob > 0) { + return; } - mLibraryClear(m_library); + mLibraryClear(m_library.get()); refresh(); } void LibraryController::refresh() { - if (!m_library) { - if (!m_loaderThread.isRunning() && m_loaderThread.m_library) { - m_library = m_loaderThread.m_library; - m_loaderThread.m_library = nullptr; - } else { - return; - } + if (m_libraryJob > 0) { + return; } setDisabled(true); @@ -166,7 +134,7 @@ QList newEntries; mLibraryListingClear(&m_listing); - mLibraryGetEntries(m_library, &m_listing, 0, 0, nullptr); + mLibraryGetEntries(m_library.get(), &m_listing, 0, 0, nullptr); for (size_t i = 0; i < mLibraryListingSize(&m_listing); i++) { mLibraryEntry* entry = mLibraryListingGetPointer(&m_listing, i); QString fullpath = QString("%1/%2").arg(entry->base, entry->filename); @@ -210,4 +178,10 @@ } } +void LibraryController::loadDirectory(const QString& dir) { + // This class can get delted during this function (sigh) so we need to hold onto this + std::shared_ptr library = m_library; + mLibraryLoadDirectory(library.get(), dir.toUtf8().constData()); +} + } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryController.h mgba-0.7.0/src/platform/qt/library/LibraryController.h --- mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/library/LibraryController.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,14 +3,12 @@ * 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_LIBRARY_CONTROLLER -#define QGBA_LIBRARY_CONTROLLER +#pragma once #include #include #include -#include #include #include @@ -67,19 +65,6 @@ virtual QWidget* widget() = 0; }; -class LibraryLoaderThread final : public QThread { -Q_OBJECT - -public: - LibraryLoaderThread(QObject* parent = nullptr); - - mLibrary* m_library = nullptr; - QString m_directory; - -protected: - virtual void run() override; -}; - class LibraryController final : public QStackedWidget { Q_OBJECT @@ -111,19 +96,19 @@ void refresh(); private: + void loadDirectory(const QString&); // Called on separate thread + ConfigController* m_config = nullptr; - LibraryLoaderThread m_loaderThread; - mLibrary* m_library = nullptr; + std::shared_ptr m_library; + qint64 m_libraryJob = -1; mLibraryListing m_listing; QMap m_entries; LibraryStyle m_currentStyle; AbstractGameList* m_currentList = nullptr; - LibraryGrid* m_libraryGrid = nullptr; - LibraryTree* m_libraryTree = nullptr; + std::unique_ptr m_libraryGrid; + std::unique_ptr m_libraryTree; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryGrid.h mgba-0.7.0/src/platform/qt/library/LibraryGrid.h --- mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryGrid.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/library/LibraryGrid.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_LIBRARY_GRID -#define QGBA_LIBRARY_GRID +#pragma once #include @@ -46,5 +45,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryTree.cpp mgba-0.7.0/src/platform/qt/library/LibraryTree.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryTree.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/library/LibraryTree.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -62,6 +62,12 @@ }); } +LibraryTree::~LibraryTree() { + for (QTreeWidgetItem* i : m_items.values()) { + delete i; + } +} + void LibraryTree::resizeAllCols() { for (int i = 0; i < m_widget->columnCount(); i++) { m_widget->resizeColumnToContents(i); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryTree.h mgba-0.7.0/src/platform/qt/library/LibraryTree.h --- mgba-0.6.3+dfsg1/src/platform/qt/library/LibraryTree.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/library/LibraryTree.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_LIBRARY_TREE -#define QGBA_LIBRARY_TREE +#pragma once #include @@ -53,5 +52,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/LoadSaveState.cpp mgba-0.7.0/src/platform/qt/LoadSaveState.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/LoadSaveState.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/LoadSaveState.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,11 +5,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "LoadSaveState.h" -#include "GameController.h" +#include "CoreController.h" #include "GamepadAxisEvent.h" #include "GamepadButtonEvent.h" #include "VFileDevice.h" +#include #include #include #include @@ -20,14 +21,15 @@ using namespace QGBA; -LoadSaveState::LoadSaveState(GameController* controller, QWidget* parent) +LoadSaveState::LoadSaveState(std::shared_ptr controller, QWidget* parent) : QWidget(parent) , m_controller(controller) , m_mode(LoadSave::LOAD) , m_currentFocus(controller->stateSlot() - 1) { - setAttribute(Qt::WA_TranslucentBackground); m_ui.setupUi(this); + m_ui.lsLabel->setFocusProxy(this); + setFocusPolicy(Qt::ClickFocus); m_slots[0] = m_ui.state1; m_slots[1] = m_ui.state2; @@ -55,12 +57,15 @@ if (m_currentFocus < 0) { m_currentFocus = 0; } + m_slots[m_currentFocus]->setFocus(); QAction* escape = new QAction(this); connect(escape, &QAction::triggered, this, &QWidget::close); escape->setShortcut(QKeySequence("Esc")); escape->setShortcutContext(Qt::WidgetWithChildrenShortcut); addAction(escape); + + connect(m_controller.get(), &CoreController::stopping, this, &QWidget::close); } void LoadSaveState::setMode(LoadSave mode) { @@ -239,6 +244,10 @@ QWidget::showEvent(event); } +void LoadSaveState::focusInEvent(QFocusEvent*) { + m_slots[m_currentFocus]->setFocus(); +} + void LoadSaveState::paintEvent(QPaintEvent*) { QPainter painter(this); QRect full(QPoint(), size()); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/LoadSaveState.h mgba-0.7.0/src/platform/qt/LoadSaveState.h --- mgba-0.6.3+dfsg1/src/platform/qt/LoadSaveState.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/LoadSaveState.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,16 +3,17 @@ * 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_LOAD_SAVE_STATE -#define QGBA_LOAD_SAVE_STATE +#pragma once #include +#include + #include "ui_LoadSaveState.h" namespace QGBA { -class GameController; +class CoreController; class InputController; class SavestateButton; @@ -27,7 +28,7 @@ public: const static int NUM_SLOTS = 9; - LoadSaveState(GameController* controller, QWidget* parent = nullptr); + LoadSaveState(std::shared_ptr controller, QWidget* parent = nullptr); void setInputController(InputController* controller); void setMode(LoadSave mode); @@ -40,13 +41,14 @@ virtual void closeEvent(QCloseEvent*) override; virtual void showEvent(QShowEvent*) override; virtual void paintEvent(QPaintEvent*) override; + virtual void focusInEvent(QFocusEvent*) override; private: void loadState(int slot); void triggerState(int slot); Ui::LoadSaveState m_ui; - GameController* m_controller; + std::shared_ptr m_controller; SavestateButton* m_slots[NUM_SLOTS]; LoadSave m_mode; @@ -55,5 +57,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/LogController.cpp mgba-0.7.0/src/platform/qt/LogController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/LogController.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/LogController.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -11,8 +11,12 @@ LogController::LogController(int levels, QObject* parent) : QObject(parent) - , m_logLevel(levels) { + mLogFilterInit(&m_filter); + mLogFilterSet(&m_filter, "gba.bios", mLOG_STUB | mLOG_FATAL); + mLogFilterSet(&m_filter, "core.status", mLOG_ALL & ~mLOG_DEBUG); + m_filter.defaultLevels = levels; + if (this != &s_global) { connect(&s_global, &LogController::logPosted, this, &LogController::postLog); connect(this, &LogController::levelsSet, &s_global, &LogController::setLevels); @@ -21,29 +25,33 @@ } } +LogController::~LogController() { + mLogFilterDeinit(&m_filter); +} + LogController::Stream LogController::operator()(int category, int level) { return Stream(this, category, level); } void LogController::postLog(int level, int category, const QString& string) { - if (!(m_logLevel & level)) { + if (!mLogFilterTest(&m_filter, category, static_cast(level))) { return; } emit logPosted(level, category, string); } void LogController::setLevels(int levels) { - m_logLevel = levels; + m_filter.defaultLevels = levels; emit levelsSet(levels); } void LogController::enableLevels(int levels) { - m_logLevel |= levels; + m_filter.defaultLevels |= levels; emit levelsEnabled(levels); } void LogController::disableLevels(int levels) { - m_logLevel &= ~levels; + m_filter.defaultLevels &= ~levels; emit levelsDisabled(levels); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/LogController.h mgba-0.7.0/src/platform/qt/LogController.h --- mgba-0.6.3+dfsg1/src/platform/qt/LogController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/LogController.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,11 +3,12 @@ * 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_LOG_CONTROLLER -#define QGBA_LOG_CONTROLLER +#pragma once #include "GBAApp.h" +#include + #include #include @@ -34,8 +35,10 @@ public: LogController(int levels, QObject* parent = nullptr); + ~LogController(); - int levels() const { return m_logLevel; } + int levels() const { return m_filter.defaultLevels; } + mLogFilter* filter() { return &m_filter; } Stream operator()(int category, int level); @@ -55,7 +58,7 @@ void disableLevels(int levels); private: - int m_logLevel; + mLogFilter m_filter; static LogController s_global; }; @@ -63,5 +66,3 @@ #define LOG(C, L) (*LogController::global())(mLOG_ ## L, _mLOG_CAT_ ## C ()) } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/LogView.h mgba-0.7.0/src/platform/qt/LogView.h --- mgba-0.6.3+dfsg1/src/platform/qt/LogView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/LogView.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_LOG_VIEW -#define QGBA_LOG_VIEW +#pragma once #include #include @@ -50,5 +49,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/main.cpp mgba-0.7.0/src/platform/qt/main.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/main.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/main.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -19,10 +19,17 @@ #ifdef QT_STATIC #include -#ifdef _WIN32 +#ifdef Q_OS_WIN Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); #ifdef BUILD_QT_MULTIMEDIA Q_IMPORT_PLUGIN(QWindowsAudioPlugin); +Q_IMPORT_PLUGIN(DSServicePlugin); +#endif +#elif defined(Q_OS_MAC) +Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin); +#ifdef BUILD_QT_MULTIMEDIA +Q_IMPORT_PLUGIN(CoreAudioPlugin); +Q_IMPORT_PLUGIN(AVFServicePlugin); #endif #endif #endif @@ -30,9 +37,11 @@ using namespace QGBA; int main(int argc, char* argv[]) { -#if defined(BUILD_SDL) && SDL_VERSION_ATLEAST(2, 0, 0) +#ifdef BUILD_SDL +#if SDL_VERSION_ATLEAST(2, 0, 0) // CPP does not shortcut function lookup SDL_SetMainReady(); #endif +#endif ConfigController configController; diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MapView.cpp mgba-0.7.0/src/platform/qt/MapView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/MapView.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MapView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,190 @@ +/* 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 "MapView.h" + +#include "CoreController.h" +#include "GBAApp.h" +#include "LogController.h" + +#include +#include +#ifdef M_CORE_GBA +#include +#endif +#ifdef M_CORE_GB +#include +#endif + +#include +#include +#include +#include +#include + +using namespace QGBA; + +MapView::MapView(std::shared_ptr controller, QWidget* parent) + : AssetView(controller, parent) + , m_controller(controller) +{ + m_ui.setupUi(this); + m_ui.tile->setController(controller); + + switch (m_controller->platform()) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: + m_boundary = 2048; + m_addressBase = BASE_VRAM; + m_addressWidth = 8; + break; +#endif +#ifdef M_CORE_GB + case PLATFORM_GB: + m_boundary = 1024; + m_addressBase = GB_BASE_VRAM; + m_addressWidth = 4; + break; +#endif + default: + return; + } + m_ui.tile->setBoundary(m_boundary, 0, 0); + + connect(m_ui.magnification, static_cast(&QSpinBox::valueChanged), [this]() { + updateTiles(true); + }); + + CoreController::Interrupter interrupter(m_controller); + const mCoreChannelInfo* videoLayers; + size_t nVideo = m_controller->thread()->core->listVideoLayers(m_controller->thread()->core, &videoLayers); + QButtonGroup* group = new QButtonGroup(this); + for (size_t i = 0; i < nVideo; ++i) { + if (strncmp(videoLayers[i].internalName, "bg", 2) != 0) { + continue; + } + QRadioButton* button = new QRadioButton(tr(videoLayers[i].visibleName)); + if (!i) { + button->setChecked(true); + } + m_ui.bgLayout->addWidget(button); + connect(button, &QAbstractButton::pressed, button, [this, i]() { + selectMap(i); + }); + group->addButton(button); + } +#ifdef USE_PNG + connect(m_ui.exportButton, &QAbstractButton::clicked, this, &MapView::exportMap); +#else + m_ui.exportButton->setVisible(false); +#endif + m_ui.map->installEventFilter(this); + m_ui.tile->addCustomProperty("mapAddr", tr("Map Addr.")); + m_ui.tile->addCustomProperty("flip", tr("Mirror")); + selectTile(0, 0); +} + +void MapView::selectMap(int map) { + if (map >= mMapCacheSetSize(&m_cacheSet->maps)) { + return; + } + if (map == m_map) { + return; + } + m_map = map; + updateTiles(true); +} + +void MapView::selectTile(int x, int y) { + CoreController::Interrupter interrupter(m_controller); + mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map); + size_t tileCache = mTileCacheSetIndex(&m_cacheSet->tiles, mapCache->tileCache); + m_ui.tile->setBoundary(m_boundary, tileCache, tileCache); + uint32_t location = mMapCacheTileId(mapCache, x, y); + mMapCacheEntry* entry = &m_mapStatus[location]; + m_ui.tile->selectIndex(entry->tileId + mapCache->tileStart); + m_ui.tile->setPalette(mMapCacheEntryFlagsGetPaletteId(entry->flags)); + m_ui.tile->setFlip(mMapCacheEntryFlagsGetHMirror(entry->flags), mMapCacheEntryFlagsGetVMirror(entry->flags)); + location <<= (mMapCacheSystemInfoGetMapAlign(mapCache->sysConfig)); + location += m_addressBase + mapCache->mapStart; + + QString flip(tr("None")); + if (mMapCacheEntryFlagsGetHMirror(entry->flags) && mMapCacheEntryFlagsGetVMirror(entry->flags)) { + flip = tr("Both"); + } else if (mMapCacheEntryFlagsGetHMirror(entry->flags)) { + flip = tr("Horizontal"); + } else if (mMapCacheEntryFlagsGetVMirror(entry->flags)) { + flip = tr("Vertical"); + } + m_ui.tile->setCustomProperty("flip", flip); + m_ui.tile->setCustomProperty("mapAddr", QString("%0%1") + .arg(m_addressWidth == 8 ? "0x" : "") + .arg(location, m_addressWidth, 16, QChar('0'))); +} + +bool MapView::eventFilter(QObject* obj, QEvent* event) { + if (event->type() != QEvent::MouseButtonPress) { + return false; + } + int x = static_cast(event)->x(); + int y = static_cast(event)->y(); + x /= 8 * m_ui.magnification->value(); + y /= 8 * m_ui.magnification->value(); + selectTile(x, y); + return true; +} + +void MapView::updateTilesGBA(bool force) { + { + CoreController::Interrupter interrupter(m_controller); + mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map); + int tilesW = 1 << mMapCacheSystemInfoGetTilesWide(mapCache->sysConfig); + int tilesH = 1 << mMapCacheSystemInfoGetTilesHigh(mapCache->sysConfig); + m_rawMap = QImage(QSize(tilesW * 8, tilesH * 8), QImage::Format_ARGB32); + uchar* bgBits = m_rawMap.bits(); + for (int j = 0; j < tilesH; ++j) { + for (int i = 0; i < tilesW; ++i) { + mMapCacheCleanTile(mapCache, m_mapStatus, i, j); + } + for (int i = 0; i < 8; ++i) { + memcpy(static_cast(&bgBits[tilesW * 32 * (i + j * 8)]), mMapCacheGetRow(mapCache, i + j * 8), tilesW * 32); + } + } + } + m_rawMap = m_rawMap.rgbSwapped(); + QPixmap map = QPixmap::fromImage(m_rawMap.convertToFormat(QImage::Format_RGB32)); + if (m_ui.magnification->value() > 1) { + map = map.scaled(map.size() * m_ui.magnification->value()); + } + m_ui.map->setPixmap(map); +} + +#ifdef M_CORE_GB +void MapView::updateTilesGB(bool force) { + updateTilesGBA(force); +} +#endif + +#ifdef USE_PNG +void MapView::exportMap() { + QString filename = GBAApp::app()->getSaveFileName(this, tr("Export map"), + tr("Portable Network Graphics (*.png)")); + VFile* vf = VFileDevice::open(filename, O_WRONLY | O_CREAT | O_TRUNC); + if (!vf) { + LOG(QT, ERROR) << tr("Failed to open output PNG file: %1").arg(filename); + return; + } + + CoreController::Interrupter interrupter(m_controller); + png_structp png = PNGWriteOpen(vf); + png_infop info = PNGWriteHeaderA(png, m_rawMap.width(), m_rawMap.height()); + + mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map); + QImage map = m_rawMap.rgbSwapped(); + PNGWritePixelsA(png, map.width(), map.height(), map.bytesPerLine() / 4, static_cast(map.constBits())); + PNGWriteClose(png, info); + vf->close(vf); +} +#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MapView.h mgba-0.7.0/src/platform/qt/MapView.h --- mgba-0.6.3+dfsg1/src/platform/qt/MapView.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MapView.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,55 @@ +/* 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/. */ +#pragma once + +#include "AssetView.h" + +#include "ui_MapView.h" + +#include + +namespace QGBA { + +class CoreController; + +class MapView : public AssetView { +Q_OBJECT + +public: + MapView(std::shared_ptr controller, QWidget* parent = nullptr); + +#ifdef USE_PNG +public slots: + void exportMap(); +#endif + +private slots: + void selectMap(int); + void selectTile(int x, int y); + +protected: + bool eventFilter(QObject*, QEvent*) override; + +private: +#ifdef M_CORE_GBA + void updateTilesGBA(bool force) override; +#endif +#ifdef M_CORE_GB + void updateTilesGB(bool force) override; +#endif + + Ui::MapView m_ui; + + std::shared_ptr m_controller; + mMapCacheEntry m_mapStatus[128 * 128] = {}; // TODO: Correct size + int m_map = 0; + QImage m_rawMap; + int m_boundary; + int m_addressBase; + int m_addressWidth; +}; + +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MapView.ui mgba-0.7.0/src/platform/qt/MapView.ui --- mgba-0.6.3+dfsg1/src/platform/qt/MapView.ui 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MapView.ui 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,139 @@ + + + MapView + + + + 0 + 0 + 641 + 489 + + + + Maps + + + + + + + + + true + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + 0 + 0 + 457 + 463 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + 0 + 0 + + + + × + + + 1 + + + 4 + + + + + + + Magnification + + + + + + + + + Export + + + + + + + + QGBA::AssetTile + QGroupBox +
AssetTile.h
+ 1 +
+
+ + +
diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MemoryModel.cpp mgba-0.7.0/src/platform/qt/MemoryModel.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/MemoryModel.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MemoryModel.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -6,7 +6,7 @@ #include "MemoryModel.h" #include "GBAApp.h" -#include "GameController.h" +#include "CoreController.h" #include "LogController.h" #include "VFileDevice.h" @@ -91,7 +91,7 @@ setRegion(0, 0x10000000, tr("All")); } -void MemoryModel::setController(GameController* controller) { +void MemoryModel::setController(std::shared_ptr controller) { m_core = controller->thread()->core; } @@ -149,12 +149,6 @@ } void MemoryModel::jumpToAddress(uint32_t address) { - if (address >= 0x10000000) { - return; - } - if (address < m_base || address >= m_base + m_size) { - setRegion(0, 0x10000000, tr("All")); - } m_top = (address - m_base) / 16; boundsCheck(); verticalScrollBar()->setValue(m_top); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MemoryModel.h mgba-0.7.0/src/platform/qt/MemoryModel.h --- mgba-0.6.3+dfsg1/src/platform/qt/MemoryModel.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MemoryModel.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,14 +3,14 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef QGBA_MEMORY_MODEL -#define QGBA_MEMORY_MODEL +#pragma once #include #include #include #include #include + #include #include @@ -19,7 +19,7 @@ namespace QGBA { -class GameController; +class CoreController; class MemoryModel : public QAbstractScrollArea { Q_OBJECT @@ -27,7 +27,7 @@ public: MemoryModel(QWidget* parent = nullptr); - void setController(GameController* controller); + void setController(std::shared_ptr controller); void setRegion(uint32_t base, uint32_t size, const QString& name = QString(), int segment = -1); void setSegment(int segment); @@ -98,5 +98,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MemorySearch.cpp mgba-0.7.0/src/platform/qt/MemorySearch.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/MemorySearch.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MemorySearch.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -8,12 +8,12 @@ #include -#include "GameController.h" +#include "CoreController.h" #include "MemoryView.h" using namespace QGBA; -MemorySearch::MemorySearch(GameController* controller, QWidget* parent) +MemorySearch::MemorySearch(std::shared_ptr controller, QWidget* parent) : QWidget(parent) , m_controller(controller) { @@ -26,6 +26,8 @@ connect(m_ui.numHex, &QPushButton::clicked, this, &MemorySearch::refresh); connect(m_ui.numDec, &QPushButton::clicked, this, &MemorySearch::refresh); connect(m_ui.viewMem, &QPushButton::clicked, this, &MemorySearch::openMemory); + + connect(controller.get(), &CoreController::stopping, this, &QWidget::close); } MemorySearch::~MemorySearch() { @@ -39,49 +41,60 @@ QByteArray string; bool ok = false; if (m_ui.typeNum->isChecked()) { + params->type = mCORE_MEMORY_SEARCH_INT; + if (m_ui.opDelta->isChecked()) { + params->op = mCORE_MEMORY_SEARCH_DELTA; + } else if (m_ui.opGreater->isChecked()) { + params->op = mCORE_MEMORY_SEARCH_GREATER; + } else if (m_ui.opLess->isChecked()) { + params->op = mCORE_MEMORY_SEARCH_LESS; + } else { + params->op = mCORE_MEMORY_SEARCH_EQUAL; + } + params->align = -1; if (m_ui.bits8->isChecked()) { - params->type = mCORE_MEMORY_SEARCH_8; + params->width = 1; } if (m_ui.bits16->isChecked()) { - params->type = mCORE_MEMORY_SEARCH_16; + params->width = 2; } if (m_ui.bits32->isChecked()) { - params->type = mCORE_MEMORY_SEARCH_32; + params->width = 4; + } + if (m_ui.bitsGuess->isChecked()) { + params->width = -1; } if (m_ui.numHex->isChecked()) { uint32_t v = m_ui.value->text().toUInt(&ok, 16); if (ok) { - switch (params->type) { - case mCORE_MEMORY_SEARCH_8: + params->valueInt = v; + switch (params->width) { + case 1: ok = v < 0x100; - params->value8 = v; break; - case mCORE_MEMORY_SEARCH_16: + case 2: ok = v < 0x10000; - params->value16 = v; break; - case mCORE_MEMORY_SEARCH_32: - params->value32 = v; + case 4: break; default: ok = false; + break; } } } if (m_ui.numDec->isChecked()) { uint32_t v = m_ui.value->text().toUInt(&ok, 10); if (ok) { - switch (params->type) { - case mCORE_MEMORY_SEARCH_8: + params->valueInt = v; + switch (params->width) { + case 1: ok = v < 0x100; - params->value8 = v; break; - case mCORE_MEMORY_SEARCH_16: + case 2: ok = v < 0x10000; - params->value16 = v; break; - case mCORE_MEMORY_SEARCH_32: - params->value32 = v; + case 4: break; default: ok = false; @@ -99,6 +112,7 @@ params->type = mCORE_MEMORY_SEARCH_STRING; m_string = m_ui.value->text().toLocal8Bit(); params->valueStr = m_string.constData(); + params->width = m_ui.value->text().size(); ok = true; } return ok; @@ -109,10 +123,7 @@ mCoreMemorySearchParams params; - GameController::Interrupter interrupter(m_controller); - if (!m_controller->isLoaded()) { - return; - } + CoreController::Interrupter interrupter(m_controller); mCore* core = m_controller->thread()->core; if (createParams(¶ms)) { @@ -125,10 +136,7 @@ void MemorySearch::searchWithin() { mCoreMemorySearchParams params; - GameController::Interrupter interrupter(m_controller); - if (!m_controller->isLoaded()) { - return; - } + CoreController::Interrupter interrupter(m_controller); mCore* core = m_controller->thread()->core; if (createParams(¶ms)) { @@ -139,74 +147,78 @@ } void MemorySearch::refresh() { - GameController::Interrupter interrupter(m_controller); - if (!m_controller->isLoaded()) { - return; - } + CoreController::Interrupter interrupter(m_controller); mCore* core = m_controller->thread()->core; m_ui.results->clearContents(); m_ui.results->setRowCount(mCoreMemorySearchResultsSize(&m_results)); + m_ui.opDelta->setEnabled(false); for (size_t i = 0; i < mCoreMemorySearchResultsSize(&m_results); ++i) { mCoreMemorySearchResult* result = mCoreMemorySearchResultsGetPointer(&m_results, i); QTableWidgetItem* item = new QTableWidgetItem(QString("%1").arg(result->address, 8, 16, QChar('0'))); m_ui.results->setItem(i, 0, item); QTableWidgetItem* type; - if (m_ui.numHex->isChecked()) { - switch (result->type) { - case mCORE_MEMORY_SEARCH_8: + QByteArray string; + if (result->type == mCORE_MEMORY_SEARCH_INT && m_ui.numHex->isChecked()) { + switch (result->width) { + case 1: item = new QTableWidgetItem(QString("%1").arg(core->rawRead8(core, result->address, result->segment), 2, 16, QChar('0'))); break; - case mCORE_MEMORY_SEARCH_16: + case 2: item = new QTableWidgetItem(QString("%1").arg(core->rawRead16(core, result->address, result->segment), 4, 16, QChar('0'))); break; - case mCORE_MEMORY_SEARCH_GUESS: - case mCORE_MEMORY_SEARCH_32: + case 4: item = new QTableWidgetItem(QString("%1").arg(core->rawRead32(core, result->address, result->segment), 8, 16, QChar('0'))); break; - case mCORE_MEMORY_SEARCH_STRING: - item = new QTableWidgetItem("?"); // TODO } } else { switch (result->type) { - case mCORE_MEMORY_SEARCH_8: - item = new QTableWidgetItem(QString::number(core->rawRead8(core, result->address, result->segment))); - break; - case mCORE_MEMORY_SEARCH_16: - item = new QTableWidgetItem(QString::number(core->rawRead16(core, result->address, result->segment))); - break; - case mCORE_MEMORY_SEARCH_GUESS: - case mCORE_MEMORY_SEARCH_32: - item = new QTableWidgetItem(QString::number(core->rawRead32(core, result->address, result->segment))); + case mCORE_MEMORY_SEARCH_INT: + switch (result->width) { + case 1: + item = new QTableWidgetItem(QString::number(core->rawRead8(core, result->address, result->segment))); + break; + case 2: + item = new QTableWidgetItem(QString::number(core->rawRead16(core, result->address, result->segment))); + break; + case 4: + item = new QTableWidgetItem(QString::number(core->rawRead32(core, result->address, result->segment))); + break; + } break; case mCORE_MEMORY_SEARCH_STRING: - item = new QTableWidgetItem("?"); // TODO + string.reserve(result->width); + for (int i = 0; i < result->width; ++i) { + string.append(core->rawRead8(core, result->address + i, result->segment)); + } + item = new QTableWidgetItem(QLatin1String(string)); // TODO } } QString divisor; if (result->guessDivisor > 1) { - divisor = tr(" (⅟%0×)").arg(result->guessDivisor); + if (result->guessMultiplier > 1) { + divisor = tr(" (%0/%1×)").arg(result->guessMultiplier).arg(result->guessMultiplier); + } else { + divisor = tr(" (⅟%0×)").arg(result->guessDivisor); + } + } else if (result->guessMultiplier > 1) { + divisor = tr(" (%0×)").arg(result->guessMultiplier); } switch (result->type) { - case mCORE_MEMORY_SEARCH_8: - type = new QTableWidgetItem(tr("1 byte%0").arg(divisor)); - break; - case mCORE_MEMORY_SEARCH_16: - type = new QTableWidgetItem(tr("2 bytes%0").arg(divisor)); - break; - case mCORE_MEMORY_SEARCH_GUESS: - case mCORE_MEMORY_SEARCH_32: - type = new QTableWidgetItem(tr("4 bytes%0").arg(divisor)); + case mCORE_MEMORY_SEARCH_INT: + type = new QTableWidgetItem(tr("%1 byte%2").arg(result->width).arg(divisor)); break; case mCORE_MEMORY_SEARCH_STRING: - item = new QTableWidgetItem("?"); // TODO + type = new QTableWidgetItem("string"); } m_ui.results->setItem(i, 1, item); m_ui.results->setItem(i, 2, type); + m_ui.opDelta->setEnabled(true); + } + if (m_ui.opDelta->isChecked() && !m_ui.opDelta->isEnabled()) { + m_ui.opEqual->setChecked(true); } m_ui.results->sortItems(0); - m_ui.results->resizeColumnsToContents(); - m_ui.results->resizeRowsToContents(); } void MemorySearch::openMemory() { @@ -220,7 +232,6 @@ MemoryView* memView = new MemoryView(m_controller); memView->jumpToAddress(address); - connect(m_controller, &GameController::gameStopped, memView, &QWidget::close); memView->setAttribute(Qt::WA_DeleteOnClose); memView->show(); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MemorySearch.h mgba-0.7.0/src/platform/qt/MemorySearch.h --- mgba-0.6.3+dfsg1/src/platform/qt/MemorySearch.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MemorySearch.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,8 +3,9 @@ * 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_MEMORY_SEARCH -#define QGBA_MEMORY_SEARCH +#pragma once + +#include #include "ui_MemorySearch.h" @@ -12,7 +13,7 @@ namespace QGBA { -class GameController; +class CoreController; class MemorySearch : public QWidget { Q_OBJECT @@ -20,7 +21,7 @@ public: static constexpr size_t LIMIT = 10000; - MemorySearch(GameController* controller, QWidget* parent = nullptr); + MemorySearch(std::shared_ptr controller, QWidget* parent = nullptr); ~MemorySearch(); public slots: @@ -36,12 +37,10 @@ Ui::MemorySearch m_ui; - GameController* m_controller; + std::shared_ptr m_controller; mCoreMemorySearchResults m_results; QByteArray m_string; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MemorySearch.ui mgba-0.7.0/src/platform/qt/MemorySearch.ui --- mgba-0.6.3+dfsg1/src/platform/qt/MemorySearch.ui 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MemorySearch.ui 2019-01-27 00:06:06.000000000 +0000 @@ -6,8 +6,8 @@ 0 0 - 631 - 378 + 540 + 491 @@ -99,14 +99,34 @@
- + + + + Qt::Horizontal + + + + Width - + + + + Guess + + + true + + + width + + + + 1 Byte (8-bit) @@ -116,7 +136,7 @@ - + 2 Bytes (16-bit) @@ -126,50 +146,117 @@ - + 4 Bytes (32-bit) - true + false width - + + + + Qt::Horizontal + + + + Number type - - + + - Hexadecimal + Guess true - + Decimal - - + + - Guess + Hexadecimal + + + + Qt::Horizontal + + + + + + + Compare + + + + + + + Equal + + + true + + + op + + + + + + + Greater + + + op + + + + + + + Less + + + op + + + + + + + false + + + Delta + + + op + + + @@ -235,5 +322,6 @@ +
diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MemoryView.cpp mgba-0.7.0/src/platform/qt/MemoryView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/MemoryView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MemoryView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -6,13 +6,13 @@ #include "MemoryView.h" -#include "GameController.h" +#include "CoreController.h" #include using namespace QGBA; -MemoryView::MemoryView(GameController* controller, QWidget* parent) +MemoryView::MemoryView(std::shared_ptr controller, QWidget* parent) : QWidget(parent) , m_controller(controller) { @@ -42,15 +42,15 @@ connect(m_ui.width16, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(2); }); connect(m_ui.width32, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(4); }); connect(m_ui.setAddress, static_cast(&QSpinBox::valueChanged), - m_ui.hexfield, static_cast(&MemoryModel::jumpToAddress)); + this, static_cast(&MemoryView::jumpToAddress)); connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection); - connect(controller, &GameController::gameStopped, this, &QWidget::close); + connect(controller.get(), &CoreController::stopping, this, &QWidget::close); - connect(controller, &GameController::frameAvailable, this, &MemoryView::update); - connect(controller, &GameController::gamePaused, this, &MemoryView::update); - connect(controller, &GameController::stateLoaded, this, &MemoryView::update); - connect(controller, &GameController::rewound, this, &MemoryView::update); + connect(controller.get(), &CoreController::frameAvailable, this, &MemoryView::update); + connect(controller.get(), &CoreController::paused, this, &MemoryView::update); + connect(controller.get(), &CoreController::stateLoaded, this, &MemoryView::update); + connect(controller.get(), &CoreController::rewound, this, &MemoryView::update); connect(m_ui.copy, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::copy); connect(m_ui.save, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::save); @@ -66,6 +66,7 @@ size_t nBlocks = core->listMemoryBlocks(core, &blocks); const mCoreMemoryBlock& info = blocks[index]; + m_region = qMakePair(info.start, info.end); m_ui.segments->setValue(-1); m_ui.segments->setVisible(info.maxSegment > 0); m_ui.segments->setMaximum(info.maxSegment); @@ -86,6 +87,17 @@ updateStatus(); } +void MemoryView::jumpToAddress(uint32_t address) { + if (address < m_region.first || address >= m_region.second) { + m_ui.regions->setCurrentIndex(0); + setIndex(0); + } + if (address < m_region.first || address >= m_region.second) { + return; + } + m_ui.hexfield->jumpToAddress(address); +} + void MemoryView::updateSelection(uint32_t start, uint32_t end) { m_selection.first = start; m_selection.second = end; @@ -94,9 +106,6 @@ void MemoryView::updateStatus() { int align = m_ui.hexfield->alignment(); - if (!m_controller->isLoaded()) { - return; - } mCore* core = m_controller->thread()->core; QByteArray selection(m_ui.hexfield->serialize()); QString text(m_ui.hexfield->decodeText(selection)); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MemoryView.h mgba-0.7.0/src/platform/qt/MemoryView.h --- mgba-0.6.3+dfsg1/src/platform/qt/MemoryView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MemoryView.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_MEMORY_VIEW -#define QGBA_MEMORY_VIEW +#pragma once #include "MemoryModel.h" @@ -12,17 +11,17 @@ namespace QGBA { -class GameController; +class CoreController; class MemoryView : public QWidget { Q_OBJECT public: - MemoryView(GameController* controller, QWidget* parent = nullptr); + MemoryView(std::shared_ptr controller, QWidget* parent = nullptr); public slots: void update(); - void jumpToAddress(uint32_t address) { m_ui.hexfield->jumpToAddress(address); } + void jumpToAddress(uint32_t address); private slots: void setIndex(int); @@ -33,10 +32,9 @@ private: Ui::MemoryView m_ui; - GameController* m_controller; + std::shared_ptr m_controller; + QPair m_region; QPair m_selection; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MemoryView.ui mgba-0.7.0/src/platform/qt/MemoryView.ui --- mgba-0.6.3+dfsg1/src/platform/qt/MemoryView.ui 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MemoryView.ui 2019-01-27 00:06:06.000000000 +0000 @@ -6,8 +6,8 @@ 0 0 - 565 - 658 + 822 + 886 @@ -98,7 +98,7 @@ - 1 Byte + &1 Byte true @@ -121,7 +121,7 @@ - 2 Bytes + &2 Bytes @@ -141,7 +141,7 @@ - 4 Bytes + &4 Bytes @@ -168,7 +168,6 @@ 0 - diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MessagePainter.h mgba-0.7.0/src/platform/qt/MessagePainter.h --- mgba-0.6.3+dfsg1/src/platform/qt/MessagePainter.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MessagePainter.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_MESSAGE_PAINTER -#define QGBA_MESSAGE_PAINTER +#pragma once #include #include @@ -43,5 +42,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MultiplayerController.cpp mgba-0.7.0/src/platform/qt/MultiplayerController.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/MultiplayerController.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MultiplayerController.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "MultiplayerController.h" -#include "GameController.h" +#include "CoreController.h" #ifdef M_CORE_GBA #include @@ -153,7 +153,7 @@ }; } -bool MultiplayerController::attachGame(GameController* controller) { +bool MultiplayerController::attachGame(CoreController* controller) { if (m_lockstep.attached == MAX_GBAS) { return false; } @@ -232,13 +232,18 @@ return false; } -void MultiplayerController::detachGame(GameController* controller) { +void MultiplayerController::detachGame(CoreController* controller) { + if (m_players.empty()) { + return; + } mCoreThread* thread = controller->thread(); if (!thread) { return; } + QList interrupters; + for (int i = 0; i < m_players.count(); ++i) { - m_players[i].controller->threadInterrupt(); + interrupters.append(m_players[i].controller); } switch (controller->platform()) { #ifdef M_CORE_GBA @@ -269,20 +274,16 @@ break; } - controller->threadContinue(); for (int i = 0; i < m_players.count(); ++i) { if (m_players[i].controller == controller) { m_players.removeAt(i); break; } } - for (int i = 0; i < m_players.count(); ++i) { - m_players[i].controller->threadContinue(); - } emit gameDetached(); } -int MultiplayerController::playerId(GameController* controller) { +int MultiplayerController::playerId(CoreController* controller) { for (int i = 0; i < m_players.count(); ++i) { if (m_players[i].controller == controller) { return i; diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/MultiplayerController.h mgba-0.7.0/src/platform/qt/MultiplayerController.h --- mgba-0.6.3+dfsg1/src/platform/qt/MultiplayerController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/MultiplayerController.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_MULTIPLAYER_CONTROLLER -#define QGBA_MULTIPLAYER_CONTROLLER +#pragma once #include #include @@ -23,7 +22,7 @@ namespace QGBA { -class GameController; +class CoreController; class MultiplayerController : public QObject { Q_OBJECT @@ -31,11 +30,11 @@ public: MultiplayerController(); - bool attachGame(GameController*); - void detachGame(GameController*); + bool attachGame(CoreController*); + void detachGame(CoreController*); int attached(); - int playerId(GameController*); + int playerId(CoreController*); signals: void gameAttached(); @@ -43,7 +42,7 @@ private: struct Player { - GameController* controller; + CoreController* controller; GBSIOLockstepNode* gbNode; GBASIOLockstepNode* gbaNode; int awake; @@ -64,4 +63,3 @@ }; } -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ObjView.cpp mgba-0.7.0/src/platform/qt/ObjView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/ObjView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ObjView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ObjView.h" +#include "CoreController.h" #include "GBAApp.h" #include @@ -21,10 +22,11 @@ #include #endif #include +#include using namespace QGBA; -ObjView::ObjView(GameController* controller, QWidget* parent) +ObjView::ObjView(std::shared_ptr controller, QWidget* parent) : AssetView(controller, parent) , m_controller(controller) { @@ -63,7 +65,7 @@ void ObjView::translateIndex(int index) { unsigned x = index % m_objInfo.width; unsigned y = index / m_objInfo.width; - m_ui.tile->selectIndex(x + y * m_objInfo.stride + m_tileOffset); + m_ui.tile->selectIndex(x + y * m_objInfo.stride + m_tileOffset + m_boundary); } #ifdef M_CORE_GBA @@ -86,19 +88,19 @@ unsigned bits; if (GBAObjAttributesAIs256Color(obj->a)) { m_ui.palette->setText("256-color"); - paletteSet = 1; + paletteSet = 3; + m_ui.tile->setBoundary(1024, 1, 3); m_ui.tile->setPalette(0); - m_ui.tile->setPaletteSet(1, 1024, 1536); - palette = 1; - tile = tile / 2 + 1024; + m_boundary = 1024; + palette = 0; + tile /= 2; bits = 8; } else { m_ui.palette->setText(QString::number(palette)); - paletteSet = 0; + paletteSet = 2; + m_ui.tile->setBoundary(2048, 0, 2); m_ui.tile->setPalette(palette); - m_ui.tile->setPaletteSet(0, 2048, 3072); - palette += 16; - tile += 2048; + m_boundary = 2048; bits = 4; } ObjInfo newInfo{ @@ -119,16 +121,16 @@ }; m_objInfo = newInfo; m_tileOffset = tile; - mTileCacheSetPalette(m_tileCache.get(), paletteSet); + mTileCache* tileCache = mTileCacheSetGetPointer(&m_cacheSet->tiles, paletteSet); int i = 0; for (int y = 0; y < height / 8; ++y) { for (int x = 0; x < width / 8; ++x, ++i, ++tile, ++tileBase) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * tileBase], tile, palette); + const color_t* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[16 * tileBase], tile, palette); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), tile, palette)); + m_ui.tiles->setTile(i, mTileCacheGetTile(tileCache, tile, palette)); } } tile += newInfo.stride - width / 8; @@ -177,6 +179,7 @@ const GB* gb = static_cast(m_controller->thread()->core->board); const GBObj* obj = &gb->video.oam.obj[m_objId]; + mTileCache* tileCache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0); unsigned width = 8; unsigned height = 8; GBRegisterLCDC lcdc = gb->memory.io[REG_LCDC]; @@ -185,6 +188,7 @@ } unsigned tile = obj->tile; m_ui.tiles->setTileCount(width * height / 64); + m_ui.tile->setBoundary(1024, 0, 0); m_ui.tiles->setMinimumSize(QSize(width, height) * m_ui.magnification->value()); m_ui.tiles->resize(QSize(width, height) * m_ui.magnification->value()); unsigned palette = 0; @@ -213,18 +217,17 @@ } m_objInfo = newInfo; m_tileOffset = tile; + m_boundary = 1024; int i = 0; - mTileCacheSetPalette(m_tileCache.get(), 0); m_ui.tile->setPalette(palette); - m_ui.tile->setPaletteSet(0, 512, 1024); for (int y = 0; y < height / 8; ++y, ++i) { unsigned t = tile + i; - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[16 * t], t, palette); + const color_t* data = mTileCacheGetTileIfDirty(tileCache, &m_tileStatus[8 * t], t, palette); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), t, palette)); + m_ui.tiles->setTile(i, mTileCacheGetTile(tileCache, t, palette)); } } @@ -255,22 +258,18 @@ return; } - GameController::Interrupter interrupter(m_controller); - mTileCacheSetPalette(m_tileCache.get(), m_objInfo.paletteSet); + CoreController::Interrupter interrupter(m_controller); png_structp png = PNGWriteOpen(vf); png_infop info = PNGWriteHeader8(png, m_objInfo.width * 8, m_objInfo.height * 8); - const uint16_t* rawPalette = mTileCacheGetPalette(m_tileCache.get(), m_objInfo.paletteId); + mTileCache* tileCache = mTileCacheSetGetPointer(&m_cacheSet->tiles, m_objInfo.paletteSet); + const color_t* rawPalette = mTileCacheGetPalette(tileCache, m_objInfo.paletteId); unsigned colors = 1 << m_objInfo.bits; uint32_t palette[256]; - for (unsigned c = 0; c < colors && c < 256; ++c) { - uint16_t color = rawPalette[c]; - palette[c] = M_R8(rawPalette[c]); - palette[c] |= M_G8(rawPalette[c]) << 8; - palette[c] |= M_B8(rawPalette[c]) << 16; - if (c) { - palette[c] |= 0xFF000000; - } + + palette[0] = rawPalette[0]; + for (unsigned c = 1; c < colors && c < 256; ++c) { + palette[c] = rawPalette[c] | 0xFF000000; } PNGWritePalette(png, info, palette, colors); @@ -278,13 +277,14 @@ unsigned t = m_objInfo.tile; for (int y = 0; y < m_objInfo.height; ++y) { for (int x = 0; x < m_objInfo.width; ++x, ++t) { - compositeTile(t, static_cast(buffer), m_objInfo.width * 8, x * 8, y * 8, m_objInfo.bits); + compositeTile(static_cast(mTileCacheGetVRAM(tileCache, t)), reinterpret_cast(buffer), m_objInfo.width * 8, x * 8, y * 8, m_objInfo.bits); } t += m_objInfo.stride - m_objInfo.width; } PNGWritePixels8(png, m_objInfo.width * 8, m_objInfo.height * 8, m_objInfo.width * 8, static_cast(buffer)); PNGWriteClose(png, info); delete[] buffer; + vf->close(vf); } #endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ObjView.h mgba-0.7.0/src/platform/qt/ObjView.h --- mgba-0.6.3+dfsg1/src/platform/qt/ObjView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ObjView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,11 +3,9 @@ * 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_OBJ_VIEW -#define QGBA_OBJ_VIEW +#pragma once #include "AssetView.h" -#include "GameController.h" #include "ui_ObjView.h" @@ -15,11 +13,13 @@ namespace QGBA { +class CoreController; + class ObjView : public AssetView { Q_OBJECT public: - ObjView(GameController* controller, QWidget* parent = nullptr); + ObjView(std::shared_ptr controller, QWidget* parent = nullptr); #ifdef USE_PNG public slots: @@ -40,7 +40,7 @@ Ui::ObjView m_ui; - GameController* m_controller; + std::shared_ptr m_controller; mTileCacheEntry m_tileStatus[1024 * 32] = {}; // TODO: Correct size int m_objId = 0; struct ObjInfo { @@ -56,8 +56,7 @@ } m_objInfo = {}; int m_tileOffset; + int m_boundary; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/Override.h mgba-0.7.0/src/platform/qt/Override.h --- mgba-0.6.3+dfsg1/src/platform/qt/Override.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/Override.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_OVERRIDE -#define QGBA_OVERRIDE +#pragma once struct Configuration; struct mCore; @@ -21,5 +20,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/OverrideView.cpp mgba-0.7.0/src/platform/qt/OverrideView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/OverrideView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/OverrideView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,11 +5,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "OverrideView.h" -#include #include #include "ConfigController.h" -#include "GameController.h" +#include "CoreController.h" #ifdef M_CORE_GBA #include "GBAOverride.h" @@ -28,9 +27,8 @@ QList OverrideView::s_mbcList; #endif -OverrideView::OverrideView(GameController* controller, ConfigController* config, QWidget* parent) +OverrideView::OverrideView(ConfigController* config, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) - , m_controller(controller) , m_config(config) { #ifdef M_CORE_GB @@ -45,21 +43,21 @@ s_mbcList.append(GB_MBC5); s_mbcList.append(GB_MBC5_RUMBLE); s_mbcList.append(GB_MBC7); + s_mbcList.append(GB_POCKETCAM); + s_mbcList.append(GB_TAMA5); s_mbcList.append(GB_HuC3); } if (s_gbModelList.isEmpty()) { // NB: Keep in sync with OverrideView.ui s_gbModelList.append(GB_MODEL_AUTODETECT); s_gbModelList.append(GB_MODEL_DMG); + s_gbModelList.append(GB_MODEL_SGB); s_gbModelList.append(GB_MODEL_CGB); s_gbModelList.append(GB_MODEL_AGB); } #endif m_ui.setupUi(this); - connect(controller, &GameController::gameStarted, this, &OverrideView::gameStarted); - connect(controller, &GameController::gameStopped, this, &OverrideView::gameStopped); - connect(m_ui.hwAutodetect, &QAbstractButton::toggled, [this] (bool enabled) { m_ui.hwRTC->setEnabled(!enabled); m_ui.hwGyro->setEnabled(!enabled); @@ -68,34 +66,24 @@ m_ui.hwRumble->setEnabled(!enabled); }); - connect(m_ui.savetype, &QComboBox::currentTextChanged, this, &OverrideView::updateOverrides); - connect(m_ui.hwAutodetect, &QAbstractButton::clicked, this, &OverrideView::updateOverrides); - connect(m_ui.hwRTC, &QAbstractButton::clicked, this, &OverrideView::updateOverrides); - connect(m_ui.hwGyro, &QAbstractButton::clicked, this, &OverrideView::updateOverrides); - connect(m_ui.hwLight, &QAbstractButton::clicked, this, &OverrideView::updateOverrides); - connect(m_ui.hwTilt, &QAbstractButton::clicked, this, &OverrideView::updateOverrides); - connect(m_ui.hwRumble, &QAbstractButton::clicked, this, &OverrideView::updateOverrides); - connect(m_ui.hwGBPlayer, &QAbstractButton::clicked, this, &OverrideView::updateOverrides); - - connect(m_ui.gbModel, &QComboBox::currentTextChanged, this, &OverrideView::updateOverrides); - connect(m_ui.mbc, &QComboBox::currentTextChanged, this, &OverrideView::updateOverrides); - - QPalette palette = m_ui.color0->palette(); - palette.setColor(backgroundRole(), QColor(0xF8, 0xF8, 0xF8)); - m_ui.color0->setPalette(palette); - palette.setColor(backgroundRole(), QColor(0xA8, 0xA8, 0xA8)); - m_ui.color1->setPalette(palette); - palette.setColor(backgroundRole(), QColor(0x50, 0x50, 0x50)); - m_ui.color2->setPalette(palette); - palette.setColor(backgroundRole(), QColor(0x00, 0x00, 0x00)); - m_ui.color3->setPalette(palette); - - m_ui.color0->installEventFilter(this); - m_ui.color1->installEventFilter(this); - m_ui.color2->installEventFilter(this); - m_ui.color3->installEventFilter(this); + m_colorPickers[0] = ColorPicker(m_ui.color0, QColor(0xF8, 0xF8, 0xF8)); + m_colorPickers[1] = ColorPicker(m_ui.color1, QColor(0xA8, 0xA8, 0xA8)); + m_colorPickers[2] = ColorPicker(m_ui.color2, QColor(0x50, 0x50, 0x50)); + m_colorPickers[3] = ColorPicker(m_ui.color3, QColor(0x00, 0x00, 0x00)); + m_colorPickers[4] = ColorPicker(m_ui.color4, QColor(0xF8, 0xF8, 0xF8)); + m_colorPickers[5] = ColorPicker(m_ui.color5, QColor(0xA8, 0xA8, 0xA8)); + m_colorPickers[6] = ColorPicker(m_ui.color6, QColor(0x50, 0x50, 0x50)); + m_colorPickers[7] = ColorPicker(m_ui.color7, QColor(0x00, 0x00, 0x00)); + m_colorPickers[8] = ColorPicker(m_ui.color8, QColor(0xF8, 0xF8, 0xF8)); + m_colorPickers[9] = ColorPicker(m_ui.color9, QColor(0xA8, 0xA8, 0xA8)); + m_colorPickers[10] = ColorPicker(m_ui.color10, QColor(0x50, 0x50, 0x50)); + m_colorPickers[11] = ColorPicker(m_ui.color11, QColor(0x00, 0x00, 0x00)); + for (int colorId = 0; colorId < 12; ++colorId) { + connect(&m_colorPickers[colorId], &ColorPicker::colorChanged, this, [this, colorId](const QColor& color) { + m_gbColors[colorId] = color.rgb() | 0xFF000000; + }); + } - connect(m_ui.tabWidget, &QTabWidget::currentChanged, this, &OverrideView::updateOverrides); #ifndef M_CORE_GBA m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.tabGBA)); #endif @@ -106,63 +94,48 @@ connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &OverrideView::saveOverride); connect(m_ui.buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close); - if (controller->isLoaded()) { - gameStarted(controller->thread()); - } + m_recheck.setInterval(200); + connect(&m_recheck, &QTimer::timeout, this, &OverrideView::recheck); } -bool OverrideView::eventFilter(QObject* obj, QEvent* event) { -#ifdef M_CORE_GB - if (event->type() != QEvent::MouseButtonRelease) { - return false; - } - int colorId; - if (obj == m_ui.color0) { - colorId = 0; - } else if (obj == m_ui.color1) { - colorId = 1; - } else if (obj == m_ui.color2) { - colorId = 2; - } else if (obj == m_ui.color3) { - colorId = 3; - } else { - return false; - } - - QWidget* swatch = static_cast(obj); - - QColorDialog* colorPicker = new QColorDialog; - colorPicker->setAttribute(Qt::WA_DeleteOnClose); - colorPicker->open(); - connect(colorPicker, &QColorDialog::colorSelected, [this, swatch, colorId](const QColor& color) { - QPalette palette = swatch->palette(); - palette.setColor(backgroundRole(), color); - swatch->setPalette(palette); - m_gbColors[colorId] = color.rgb(); - updateOverrides(); - }); - return true; -#else - return false; -#endif +void OverrideView::setController(std::shared_ptr controller) { + m_controller = controller; + connect(controller.get(), &CoreController::started, this, &OverrideView::gameStarted); + connect(controller.get(), &CoreController::stopping, this, &OverrideView::gameStopped); + recheck(); } void OverrideView::saveOverride() { + if (!m_controller) { + m_savePending = true; + return; + } + Override* override = m_controller->override(); if (!override) { return; } - if (m_controller->isLoaded()) { - m_config->saveOverride(*override); + m_config->saveOverride(*override); +} + +void OverrideView::recheck() { + if (!m_controller) { + return; + } + if (m_controller->hasStarted()) { + gameStarted(); } else { - m_savePending = true; + updateOverrides(); } } void OverrideView::updateOverrides() { + if (!m_controller) { + return; + } #ifdef M_CORE_GBA if (m_ui.tabWidget->currentWidget() == m_ui.tabGBA) { - GBAOverride* gba = new GBAOverride; + std::unique_ptr gba(new GBAOverride); memset(gba->override.id, 0, 4); gba->override.savetype = static_cast(m_ui.savetype->currentIndex() - 1); gba->override.hardware = HW_NO_OVERRIDE; @@ -199,41 +172,39 @@ if (gba->override.savetype != SAVEDATA_AUTODETECT || gba->override.hardware != HW_NO_OVERRIDE || gba->override.idleLoop != IDLE_LOOP_NONE) { - m_controller->setOverride(gba); + m_controller->setOverride(std::move(gba)); } else { m_controller->clearOverride(); - delete gba; } } #endif #ifdef M_CORE_GB if (m_ui.tabWidget->currentWidget() == m_ui.tabGB) { - GBOverride* gb = new GBOverride; + std::unique_ptr gb(new GBOverride); gb->override.mbc = s_mbcList[m_ui.mbc->currentIndex()]; gb->override.model = s_gbModelList[m_ui.gbModel->currentIndex()]; - gb->override.gbColors[0] = m_gbColors[0]; - gb->override.gbColors[1] = m_gbColors[1]; - gb->override.gbColors[2] = m_gbColors[2]; - gb->override.gbColors[3] = m_gbColors[3]; + bool hasColor = false; + for (int i = 0; i < 12; ++i) { + gb->override.gbColors[i] = m_gbColors[i]; + hasColor = hasColor || (m_gbColors[i] & 0xFF000000); + } bool hasOverride = gb->override.mbc != GB_MBC_AUTODETECT || gb->override.model != GB_MODEL_AUTODETECT; - hasOverride = hasOverride || (m_gbColors[0] | m_gbColors[1] | m_gbColors[2] | m_gbColors[3]); + hasOverride = hasOverride || hasColor; if (hasOverride) { - m_controller->setOverride(gb); + m_controller->setOverride(std::move(gb)); } else { m_controller->clearOverride(); - delete gb; } } #endif } -void OverrideView::gameStarted(mCoreThread* thread) { - if (!thread->core) { - gameStopped(); - return; - } +void OverrideView::gameStarted() { + CoreController::Interrupter interrupter(m_controller); + mCoreThread* thread = m_controller->thread(); m_ui.tabWidget->setEnabled(false); + m_recheck.start(); switch (thread->core->platform(thread->core)) { #ifdef M_CORE_GBA @@ -286,12 +257,12 @@ } void OverrideView::gameStopped() { + m_recheck.stop(); + m_controller.reset(); m_ui.tabWidget->setEnabled(true); m_ui.savetype->setCurrentIndex(0); m_ui.idleLoop->clear(); m_ui.mbc->setCurrentIndex(0); m_ui.gbModel->setCurrentIndex(0); - - updateOverrides(); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/OverrideView.h mgba-0.7.0/src/platform/qt/OverrideView.h --- mgba-0.6.3+dfsg1/src/platform/qt/OverrideView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/OverrideView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,15 +3,20 @@ * 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_OVERRIDE_VIEW -#define QGBA_OVERRIDE_VIEW +#pragma once #include +#include + +#include #ifdef M_CORE_GB #include #endif +#include "ColorPicker.h" +#include "Override.h" + #include "ui_OverrideView.h" struct mCoreThread; @@ -19,35 +24,37 @@ namespace QGBA { class ConfigController; -class GameController; +class CoreController; class Override; class OverrideView : public QDialog { Q_OBJECT public: - OverrideView(GameController* controller, ConfigController* config, QWidget* parent = nullptr); + OverrideView(ConfigController* config, QWidget* parent = nullptr); + + void setController(std::shared_ptr controller); public slots: void saveOverride(); + void recheck(); private slots: void updateOverrides(); - void gameStarted(mCoreThread*); + void gameStarted(); void gameStopped(); -protected: - bool eventFilter(QObject* obj, QEvent* event) override; - private: Ui::OverrideView m_ui; - GameController* m_controller; + std::shared_ptr m_controller; ConfigController* m_config; bool m_savePending = false; + QTimer m_recheck; #ifdef M_CORE_GB - uint32_t m_gbColors[4]{}; + uint32_t m_gbColors[12]{}; + ColorPicker m_colorPickers[12]; static QList s_gbModelList; static QList s_mbcList; @@ -55,5 +62,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/OverrideView.ui mgba-0.7.0/src/platform/qt/OverrideView.ui --- mgba-0.6.3+dfsg1/src/platform/qt/OverrideView.ui 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/OverrideView.ui 2019-01-27 00:06:06.000000000 +0000 @@ -255,6 +255,11 @@ + Super Game Boy (SGB) + + + + Game Boy Color (CGB) @@ -321,6 +326,16 @@ + Pocket Cam + + + + + TAMA5 + + + + HuC-3 @@ -329,7 +344,7 @@ - Colors + Background Colors @@ -397,6 +412,180 @@ 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + Sprite Colors 1 + + + + + + + Sprite Colors 2 + + + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 30 diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/PaletteView.cpp mgba-0.7.0/src/platform/qt/PaletteView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/PaletteView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/PaletteView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "PaletteView.h" +#include "CoreController.h" #include "GBAApp.h" #include "LogController.h" #include "VFileDevice.h" @@ -24,13 +25,13 @@ using namespace QGBA; -PaletteView::PaletteView(GameController* controller, QWidget* parent) +PaletteView::PaletteView(std::shared_ptr controller, QWidget* parent) : QWidget(parent) , m_controller(controller) { m_ui.setupUi(this); - connect(m_controller, &GameController::frameAvailable, this, &PaletteView::updatePalette); + connect(controller.get(), &CoreController::frameAvailable, this, &PaletteView::updatePalette); m_ui.bgGrid->setDimensions(QSize(16, 16)); m_ui.objGrid->setDimensions(QSize(16, 16)); int count = 256; @@ -61,7 +62,7 @@ connect(m_ui.exportBG, &QAbstractButton::clicked, [this, count] () { exportPalette(0, count); }); connect(m_ui.exportOBJ, &QAbstractButton::clicked, [this, count] () { exportPalette(count, count); }); - connect(controller, &GameController::gameStopped, this, &QWidget::close); + connect(controller.get(), &CoreController::stopping, this, &QWidget::close); } void PaletteView::updatePalette() { @@ -133,7 +134,7 @@ length = 512 - start; } - GameController::Interrupter interrupter(m_controller); + CoreController::Interrupter interrupter(m_controller); QString filename = GBAApp::app()->getSaveFileName(this, tr("Export palette"), tr("Windows PAL (*.pal);;Adobe Color Table (*.act)")); VFile* vf = VFileDevice::open(filename, O_WRONLY | O_CREAT | O_TRUNC); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/PaletteView.h mgba-0.7.0/src/platform/qt/PaletteView.h --- mgba-0.6.3+dfsg1/src/platform/qt/PaletteView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/PaletteView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,25 +3,26 @@ * 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_PALETTE_VIEW -#define QGBA_PALETTE_VIEW +#pragma once #include -#include "GameController.h" +#include + #include "Swatch.h" #include "ui_PaletteView.h" namespace QGBA { +class CoreController; class Swatch; class PaletteView : public QWidget { Q_OBJECT public: - PaletteView(GameController* controller, QWidget* parent = nullptr); + PaletteView(std::shared_ptr controller, QWidget* parent = nullptr); public slots: void updatePalette(); @@ -34,9 +35,7 @@ Ui::PaletteView m_ui; - GameController* m_controller; + std::shared_ptr m_controller; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/PlacementControl.cpp mgba-0.7.0/src/platform/qt/PlacementControl.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/PlacementControl.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/PlacementControl.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,76 @@ +/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "PlacementControl.h" + +#include "CoreController.h" + +#include + +#include + +using namespace QGBA; + +PlacementControl::PlacementControl(std::shared_ptr controller, QWidget* parent) + : QDialog(parent) + , m_controller(controller) +{ + m_ui.setupUi(this); + + connect(m_ui.offsetX, static_cast(&QSpinBox::valueChanged), [this](int x) { + adjustLayer(-1, x, m_ui.offsetY->value()); + }); + + connect(m_ui.offsetY, static_cast(&QSpinBox::valueChanged), [this](int y) { + adjustLayer(-1, m_ui.offsetX->value(), y); + }); + + QGridLayout* grid = static_cast(layout()); + CoreController::Interrupter interrupter(m_controller); + const mCoreChannelInfo* info; + size_t nVideo = m_controller->thread()->core->listVideoLayers(m_controller->thread()->core, &info); + for (size_t i = 0; i < nVideo; ++i) { + QSpinBox* offsetX = new QSpinBox; + QSpinBox* offsetY = new QSpinBox; + + offsetX->setWrapping(true); + offsetX->setMaximum(127); + offsetX->setMinimum(-128); + offsetX->setAccelerated(true); + + offsetY->setWrapping(true); + offsetY->setMaximum(127); + offsetY->setMinimum(-128); + offsetY->setAccelerated(true); + + m_layers.append(qMakePair(offsetX, offsetY)); + int row = grid->rowCount(); + grid->addWidget(new QLabel(QString(info[i].visibleName)), row, 0, Qt::AlignRight); + grid->addWidget(offsetX, row, 1); + grid->addWidget(offsetY, row, 2); + + connect(offsetX, static_cast(&QSpinBox::valueChanged), [this, i, offsetY](int x) { + adjustLayer(i, x, offsetY->value()); + }); + + connect(offsetY, static_cast(&QSpinBox::valueChanged), [this, i, offsetX](int y) { + adjustLayer(i, offsetX->value(), y); + }); + } +} + +void PlacementControl::adjustLayer(int layer, int32_t x, int32_t y) { + CoreController::Interrupter interrupter(m_controller); + mCore* core = m_controller->thread()->core; + size_t nVideo = core->listVideoLayers(core, nullptr); + + if (layer < 0) { + for (size_t i = 0; i < nVideo; ++i) { + core->adjustVideoLayer(core, i, x + m_layers[i].first->value(), y + m_layers[i].second->value()); + } + } else if ((size_t) layer < nVideo) { + core->adjustVideoLayer(core, layer, x + m_ui.offsetX->value(), y + m_ui.offsetY->value()); + } +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/PlacementControl.h mgba-0.7.0/src/platform/qt/PlacementControl.h --- mgba-0.6.3+dfsg1/src/platform/qt/PlacementControl.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/PlacementControl.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,34 @@ +/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + +#include +#include + +#include + +#include "ui_PlacementControl.h" + +namespace QGBA { + +class CoreController; + +class PlacementControl : public QDialog { +Q_OBJECT + +public: + PlacementControl(std::shared_ptr, QWidget* parent = nullptr); + +private: + void adjustLayer(int layer, int32_t x, int32_t y); + + std::shared_ptr m_controller; + QList> m_layers; + + Ui::PlacementControl m_ui; +}; + +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/PlacementControl.ui mgba-0.7.0/src/platform/qt/PlacementControl.ui --- mgba-0.6.3+dfsg1/src/platform/qt/PlacementControl.ui 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/PlacementControl.ui 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,87 @@ + + + PlacementControl + + + + 0 + 0 + 202 + 72 + + + + + 0 + 0 + + + + Adjust placement + + + + + + All + + + + + + + true + + + true + + + -128 + + + 127 + + + + + + + true + + + true + + + -128 + + + 127 + + + + + + + Offset + + + + + + + X + + + + + + + Y + + + + + + + + diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/PrinterView.cpp mgba-0.7.0/src/platform/qt/PrinterView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/PrinterView.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/PrinterView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -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/. */ +#include "PrinterView.h" + +#include "CoreController.h" +#include "GBAApp.h" + +#include + +using namespace QGBA; + +PrinterView::PrinterView(std::shared_ptr controller, QWidget* parent) + : QDialog(parent) + , m_controller(controller) +{ + m_ui.setupUi(this); + + connect(controller.get(), &CoreController::imagePrinted, this, &PrinterView::printImage); + connect(&m_timer, &QTimer::timeout, this, &PrinterView::printLine); + connect(m_ui.hurry, &QAbstractButton::clicked, this, &PrinterView::printAll); + connect(m_ui.tear, &QAbstractButton::clicked, this, &PrinterView::clear); + connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &PrinterView::save); + m_timer.setInterval(80); + clear(); +} + +PrinterView::~PrinterView() { + m_controller->detachPrinter(); +} + +void PrinterView::save() { + QString filename = GBAApp::app()->getSaveFileName(this, tr("Save Printout"), tr("Portable Network Graphics (*.png)")); + if (filename.isNull()) { + return; + } + m_image.save(filename); +} + +void PrinterView::clear() { + m_ui.image->setFixedHeight(0); + m_image = QPixmap(); + m_ui.image->clear(); + m_ui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(false); +} + +void PrinterView::printImage(const QImage& image) { + QPixmap pixmap(image.width(), image.height() + m_image.height()); + QPainter painter(&pixmap); + painter.drawPixmap(0, 0, m_image); + painter.drawImage(0, m_image.height(), image); + m_image = pixmap; + m_ui.image->setPixmap(m_image); + m_timer.start(); + m_ui.hurry->setEnabled(true); +} + +void PrinterView::printLine() { + m_ui.image->setFixedHeight(m_ui.image->height() + 1); + m_ui.scrollArea->ensureVisible(0, m_ui.image->height(), 0, 0); + if (m_ui.image->height() >= m_image.height()) { + printAll(); + } +} + +void PrinterView::printAll() { + m_timer.stop(); + m_ui.image->setFixedHeight(m_image.height()); + m_controller->endPrint(); + m_ui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(true); + m_ui.hurry->setEnabled(false); +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/PrinterView.h mgba-0.7.0/src/platform/qt/PrinterView.h --- mgba-0.6.3+dfsg1/src/platform/qt/PrinterView.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/PrinterView.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,47 @@ +/* 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/. */ +#pragma once + +#include +#include +#include + +#include + +#include "ui_PrinterView.h" + +namespace QGBA { + +class CoreController; + +class PrinterView : public QDialog { +Q_OBJECT + +public: + PrinterView(std::shared_ptr controller, QWidget* parent = nullptr); + ~PrinterView(); + +signals: + void donePrinting(); + +public slots: + void save(); + void clear(); + +private slots: + void printImage(const QImage&); + void printLine(); + void printAll(); + +private: + Ui::PrinterView m_ui; + QPixmap m_image; + QTimer m_timer; + + std::shared_ptr m_controller; +}; + +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/PrinterView.ui mgba-0.7.0/src/platform/qt/PrinterView.ui --- mgba-0.6.3+dfsg1/src/platform/qt/PrinterView.ui 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/PrinterView.ui 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,137 @@ + + + PrinterView + + + + 0 + 0 + 241 + 311 + + + + Game Boy Printer + + + + + + QFrame::NoFrame + + + true + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + + 160 + 1 + + + + + 160 + 16777215 + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + + QFrame::Plain + + + Qt::Horizontal + + + + + + + + + + + + + false + + + Hurry up! + + + + + + + Tear off + + + + + + + + + QDialogButtonBox::Close|QDialogButtonBox::Save + + + + + + + + + buttonBox + rejected() + PrinterView + close() + + + 112 + 226 + + + 112 + 123 + + + + + diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/RegisterView.cpp mgba-0.7.0/src/platform/qt/RegisterView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/RegisterView.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/RegisterView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,144 @@ +/* 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 "RegisterView.h" + +#include "CoreController.h" + +#ifdef M_CORE_GBA +#include +#endif +#ifdef M_CORE_GB +#include +#endif + +#include +#include +#include + +using namespace QGBA; + +RegisterView::RegisterView(std::shared_ptr controller, QWidget* parent) + : QWidget(parent) + , m_controller(controller) +{ + QFormLayout* layout = new QFormLayout; + setLayout(layout); + + switch (controller->platform()) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: + addRegisters({ + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", + "r12", + "sp", + "lr", + "pc", + "cpsr", + }); + break; +#endif +#ifdef M_CORE_GB + case PLATFORM_GB: + addRegisters({ + "a", + "f", + "b", + "c", + "d", + "e", + "h", + "l", + "sp", + "pc" + }); + break; +#endif + default: + break; + } +} + +void RegisterView::addRegisters(const QStringList& names) { + QFormLayout* form = static_cast(layout()); + const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont); + for (const auto& reg : names) { + QLabel* value = new QLabel; + value->setTextInteractionFlags(Qt::TextSelectableByMouse); + value->setFont(font); + form->addWidget(value); + m_registers[reg] = value; + form->addRow(reg, value); + } +} + +void RegisterView::updateRegisters() { + switch (m_controller->platform()) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: + updateRegistersARM(); + break; +#endif +#ifdef M_CORE_GB + case PLATFORM_GB: + updateRegistersLR35902(); + break; +#endif + default: + break; + } +} + +#ifdef M_CORE_GBA +void RegisterView::updateRegistersARM() { + CoreController::Interrupter interrupter(m_controller); + struct ARMCore* core = static_cast(m_controller->thread()->core->cpu); + m_registers["r0"]->setText(QString("%1").arg((uint32_t) core->gprs[0], 8, 16, QChar('0')).toUpper()); + m_registers["r1"]->setText(QString("%1").arg((uint32_t) core->gprs[1], 8, 16, QChar('0')).toUpper()); + m_registers["r2"]->setText(QString("%1").arg((uint32_t) core->gprs[2], 8, 16, QChar('0')).toUpper()); + m_registers["r3"]->setText(QString("%1").arg((uint32_t) core->gprs[3], 8, 16, QChar('0')).toUpper()); + m_registers["r4"]->setText(QString("%1").arg((uint32_t) core->gprs[4], 8, 16, QChar('0')).toUpper()); + m_registers["r5"]->setText(QString("%1").arg((uint32_t) core->gprs[5], 8, 16, QChar('0')).toUpper()); + m_registers["r6"]->setText(QString("%1").arg((uint32_t) core->gprs[6], 8, 16, QChar('0')).toUpper()); + m_registers["r7"]->setText(QString("%1").arg((uint32_t) core->gprs[7], 8, 16, QChar('0')).toUpper()); + m_registers["r8"]->setText(QString("%1").arg((uint32_t) core->gprs[8], 8, 16, QChar('0')).toUpper()); + m_registers["r9"]->setText(QString("%1").arg((uint32_t) core->gprs[9], 8, 16, QChar('0')).toUpper()); + m_registers["r10"]->setText(QString("%1").arg((uint32_t) core->gprs[10], 8, 16, QChar('0')).toUpper()); + m_registers["r11"]->setText(QString("%1").arg((uint32_t) core->gprs[11], 8, 16, QChar('0')).toUpper()); + m_registers["r12"]->setText(QString("%1").arg((uint32_t) core->gprs[12], 8, 16, QChar('0')).toUpper()); + m_registers["sp"]->setText(QString("%1").arg((uint32_t) core->gprs[ARM_SP], 8, 16, QChar('0')).toUpper()); + m_registers["lr"]->setText(QString("%1").arg((uint32_t) core->gprs[ARM_LR], 8, 16, QChar('0')).toUpper()); + m_registers["pc"]->setText(QString("%1").arg((uint32_t) core->gprs[ARM_PC], 8, 16, QChar('0')).toUpper()); + m_registers["cpsr"]->setText(QString("%1").arg((uint32_t) core->cpsr.packed, 8, 16, QChar('0')).toUpper()); +} +#endif + +#ifdef M_CORE_GB +void RegisterView::updateRegistersLR35902() { + CoreController::Interrupter interrupter(m_controller); + struct LR35902Core* core = static_cast(m_controller->thread()->core->cpu); + m_registers["a"]->setText(QString("%1").arg((uint8_t) core->a, 2, 16, QChar('0')).toUpper()); + m_registers["f"]->setText(QString("%1").arg((uint8_t) core->f.packed, 2, 16, QChar('0')).toUpper()); + m_registers["b"]->setText(QString("%1").arg((uint8_t) core->b, 2, 16, QChar('0')).toUpper()); + m_registers["c"]->setText(QString("%1").arg((uint8_t) core->c, 2, 16, QChar('0')).toUpper()); + m_registers["d"]->setText(QString("%1").arg((uint8_t) core->d, 2, 16, QChar('0')).toUpper()); + m_registers["e"]->setText(QString("%1").arg((uint8_t) core->e, 2, 16, QChar('0')).toUpper()); + m_registers["h"]->setText(QString("%1").arg((uint8_t) core->h, 2, 16, QChar('0')).toUpper()); + m_registers["l"]->setText(QString("%1").arg((uint8_t) core->l, 2, 16, QChar('0')).toUpper()); + m_registers["sp"]->setText(QString("%1").arg((uint8_t) core->sp, 4, 16, QChar('0')).toUpper()); + m_registers["pc"]->setText(QString("%1").arg((uint8_t) core->pc, 4, 16, QChar('0')).toUpper()); +} +#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/RegisterView.h mgba-0.7.0/src/platform/qt/RegisterView.h --- mgba-0.6.3+dfsg1/src/platform/qt/RegisterView.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/RegisterView.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,42 @@ +/* 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/. */ +#pragma once + +#include +#include + +#include + +class QLabel; + +namespace QGBA { + +class CoreController; + +class RegisterView : public QWidget { +Q_OBJECT + +public: + RegisterView(std::shared_ptr controller, QWidget* parent = nullptr); + +public slots: + void updateRegisters(); + +private: + void addRegisters(const QStringList& names); +#ifdef M_CORE_GBA + void updateRegistersARM(); +#endif +#ifdef M_CORE_GB + void updateRegistersLR35902(); +#endif + + QMap m_registers; + + std::shared_ptr m_controller; +}; + +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/resources.qrc mgba-0.7.0/src/platform/qt/resources.qrc --- mgba-0.6.3+dfsg1/src/platform/qt/resources.qrc 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/resources.qrc 2019-01-27 00:06:06.000000000 +0000 @@ -3,5 +3,6 @@ ../../../res/mgba-1024.png ../../../res/keymap.qpic ../../../res/patrons.txt + ../../../res/no-cam.png diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ROMInfo.cpp mgba-0.7.0/src/platform/qt/ROMInfo.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/ROMInfo.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ROMInfo.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -6,7 +6,7 @@ #include "ROMInfo.h" #include "GBAApp.h" -#include "GameController.h" +#include "CoreController.h" #include #ifdef M_CORE_GB @@ -21,21 +21,17 @@ using namespace QGBA; -ROMInfo::ROMInfo(GameController* controller, QWidget* parent) +ROMInfo::ROMInfo(std::shared_ptr controller, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) { m_ui.setupUi(this); - if (!controller->isLoaded()) { - return; - } - #ifdef USE_SQLITE3 const NoIntroDB* db = GBAApp::app()->gameDB(); #endif uint32_t crc32 = 0; - GameController::Interrupter interrupter(controller); + CoreController::Interrupter interrupter(controller); mCore* core = controller->thread()->core; char title[17] = {}; core->getGameTitle(core, title); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ROMInfo.h mgba-0.7.0/src/platform/qt/ROMInfo.h --- mgba-0.6.3+dfsg1/src/platform/qt/ROMInfo.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ROMInfo.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,27 +3,26 @@ * 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_ROM_INFO -#define QGBA_ROM_INFO +#pragma once #include +#include + #include "ui_ROMInfo.h" namespace QGBA { -class GameController; +class CoreController; class ROMInfo : public QDialog { Q_OBJECT public: - ROMInfo(GameController* controller, QWidget* parent = nullptr); + ROMInfo(std::shared_ptr controller, QWidget* parent = nullptr); private: Ui::ROMInfo m_ui; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/SavestateButton.h mgba-0.7.0/src/platform/qt/SavestateButton.h --- mgba-0.6.3+dfsg1/src/platform/qt/SavestateButton.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/SavestateButton.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_SAVESTATE_BUTTON -#define QGBA_SAVESTATE_BUTTON +#pragma once #include @@ -19,5 +18,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/SensorView.cpp mgba-0.7.0/src/platform/qt/SensorView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/SensorView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/SensorView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "SensorView.h" -#include "GameController.h" +#include "CoreController.h" #include "GamepadAxisEvent.h" #include "InputController.h" @@ -14,9 +14,8 @@ using namespace QGBA; -SensorView::SensorView(GameController* controller, InputController* input, QWidget* parent) +SensorView::SensorView(InputController* input, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) - , m_controller(controller) , m_input(input) , m_rotation(input->rotationSource()) { @@ -26,23 +25,14 @@ this, &SensorView::setLuminanceValue); connect(m_ui.lightSlide, &QAbstractSlider::valueChanged, this, &SensorView::setLuminanceValue); - connect(m_ui.timeNoOverride, &QAbstractButton::clicked, controller, &GameController::setRealTime); - connect(m_ui.timeFixed, &QRadioButton::clicked, [controller, this] () { - controller->setFixedTime(m_ui.time->dateTime().toUTC()); - }); - connect(m_ui.timeFakeEpoch, &QRadioButton::clicked, [controller, this] () { - controller->setFakeEpoch(m_ui.time->dateTime().toUTC()); - }); - connect(m_ui.time, &QDateTimeEdit::dateTimeChanged, [controller, this] (const QDateTime&) { + connect(m_ui.time, &QDateTimeEdit::dateTimeChanged, [this] (const QDateTime&) { m_ui.timeButtons->checkedButton()->clicked(); }); - connect(m_ui.timeNow, &QPushButton::clicked, [controller, this] () { + connect(m_ui.timeNow, &QPushButton::clicked, [this] () { m_ui.time->setDateTime(QDateTime::currentDateTime()); }); - connect(m_controller, &GameController::luminanceValueChanged, this, &SensorView::luminanceValueChanged); - - m_timer.setInterval(2); + m_timer.setInterval(15); connect(&m_timer, &QTimer::timeout, this, &SensorView::updateSensors); if (!m_rotation || !m_rotation->readTiltX || !m_rotation->readTiltY) { m_ui.tilt->hide(); @@ -66,6 +56,23 @@ m_input->setGyroSensitivity(value * 1e8f); }); m_input->stealFocus(this); + connect(m_input, &InputController::luminanceValueChanged, this, &SensorView::luminanceValueChanged); +} + +void SensorView::setController(std::shared_ptr controller) { + m_controller = controller; + connect(m_ui.timeNoOverride, &QAbstractButton::clicked, controller.get(), &CoreController::setRealTime); + connect(m_ui.timeFixed, &QRadioButton::clicked, [controller, this] () { + controller->setFixedTime(m_ui.time->dateTime().toUTC()); + }); + connect(m_ui.timeFakeEpoch, &QRadioButton::clicked, [controller, this] () { + controller->setFakeEpoch(m_ui.time->dateTime().toUTC()); + }); + m_ui.timeButtons->checkedButton()->clicked(); + + connect(controller.get(), &CoreController::stopping, [this]() { + m_controller.reset(); + }); } void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) { @@ -107,16 +114,7 @@ } void SensorView::updateSensors() { - GameController::Interrupter interrupter(m_controller); - if (m_rotation->sample && - (!m_controller->isLoaded() || !(static_cast(m_controller->thread()->core->board)->memory.hw.devices & (HW_GYRO | HW_TILT)))) { - m_rotation->sample(m_rotation); - m_rotation->sample(m_rotation); - m_rotation->sample(m_rotation); - m_rotation->sample(m_rotation); - m_rotation->sample(m_rotation); - m_rotation->sample(m_rotation); - m_rotation->sample(m_rotation); + if (m_rotation->sample && (!m_controller || m_controller->isPaused())) { m_rotation->sample(m_rotation); } if (m_rotation->readTiltX && m_rotation->readTiltY) { @@ -132,7 +130,9 @@ void SensorView::setLuminanceValue(int value) { value = std::max(0, std::min(value, 255)); - m_controller->setLuminanceValue(value); + if (m_input) { + m_input->setLuminanceValue(value); + } } void SensorView::luminanceValueChanged(int value) { diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/SensorView.h mgba-0.7.0/src/platform/qt/SensorView.h --- mgba-0.6.3+dfsg1/src/platform/qt/SensorView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/SensorView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,13 +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_SENSOR_VIEW -#define QGBA_SENSOR_VIEW +#pragma once #include #include #include +#include #include "ui_SensorView.h" @@ -18,7 +18,7 @@ namespace QGBA { class ConfigController; -class GameController; +class CoreController; class GamepadAxisEvent; class InputController; @@ -26,7 +26,9 @@ Q_OBJECT public: - SensorView(GameController* controller, InputController* input, QWidget* parent = nullptr); + SensorView(InputController* input, QWidget* parent = nullptr); + + void setController(std::shared_ptr); protected: bool eventFilter(QObject*, QEvent* event) override; @@ -41,7 +43,7 @@ Ui::SensorView m_ui; std::function m_jiggered; - GameController* m_controller; + std::shared_ptr m_controller; InputController* m_input; mRotationSource* m_rotation; QTimer m_timer; @@ -50,5 +52,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/SettingsView.cpp mgba-0.7.0/src/platform/qt/SettingsView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/SettingsView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/SettingsView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -20,14 +20,41 @@ using namespace QGBA; +#ifdef M_CORE_GB +QList SettingsView::s_gbModelList; +#endif + SettingsView::SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) , m_controller(controller) { m_ui.setupUi(this); +#ifdef M_CORE_GB + if (s_gbModelList.isEmpty()) { + // NB: Keep in sync with SettingsView.ui + s_gbModelList.append(GB_MODEL_AUTODETECT); + s_gbModelList.append(GB_MODEL_DMG); + s_gbModelList.append(GB_MODEL_SGB); + s_gbModelList.append(GB_MODEL_CGB); + s_gbModelList.append(GB_MODEL_AGB); + } +#endif + reloadConfig(); + connect(m_ui.volume, static_cast(&QSlider::valueChanged), [this](int v) { + if (v < m_ui.volumeFf->value()) { + m_ui.volumeFf->setValue(v); + } + }); + + connect(m_ui.mute, &QAbstractButton::toggled, [this](bool e) { + if (e) { + m_ui.muteFf->setChecked(e); + } + }); + if (m_ui.savegamePath->text().isEmpty()) { m_ui.savegameSameDir->setChecked(true); } @@ -91,6 +118,22 @@ m_ui.patchPath->setText(path); } }); + + if (m_ui.cheatsPath->text().isEmpty()) { + m_ui.cheatsSameDir->setChecked(true); + } + connect(m_ui.cheatsSameDir, &QAbstractButton::toggled, [this] (bool e) { + if (e) { + m_ui.cheatsPath->clear(); + } + }); + connect(m_ui.cheatsBrowse, &QAbstractButton::pressed, [this] () { + QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory"); + if (!path.isNull()) { + m_ui.cheatsSameDir->setChecked(false); + m_ui.cheatsPath->setText(path); + } + }); connect(m_ui.clearCache, &QAbstractButton::pressed, this, &SettingsView::libraryCleared); // TODO: Move to reloadConfig() @@ -130,15 +173,86 @@ } #endif + // TODO: Move to reloadConfig() + QVariant cameraDriver = m_controller->getQtOption("cameraDriver"); + m_ui.cameraDriver->addItem(tr("None (Still Image)"), static_cast(InputController::CameraDriver::NONE)); + if (cameraDriver.isNull() || cameraDriver.toInt() == static_cast(InputController::CameraDriver::NONE)) { + m_ui.cameraDriver->setCurrentIndex(m_ui.cameraDriver->count() - 1); + } + +#ifdef BUILD_QT_MULTIMEDIA + m_ui.cameraDriver->addItem(tr("Qt Multimedia"), static_cast(InputController::CameraDriver::QT_MULTIMEDIA)); + if (!cameraDriver.isNull() && cameraDriver.toInt() == static_cast(InputController::CameraDriver::QT_MULTIMEDIA)) { + m_ui.cameraDriver->setCurrentIndex(m_ui.cameraDriver->count() - 1); + } +#endif + +#ifdef M_CORE_GBA connect(m_ui.gbaBiosBrowse, &QPushButton::clicked, [this]() { selectBios(m_ui.gbaBios); }); +#else + m_ui.gbaBiosBrowse->hide(); +#endif + +#ifdef M_CORE_GB connect(m_ui.gbBiosBrowse, &QPushButton::clicked, [this]() { selectBios(m_ui.gbBios); }); connect(m_ui.gbcBiosBrowse, &QPushButton::clicked, [this]() { selectBios(m_ui.gbcBios); }); + connect(m_ui.sgbBiosBrowse, &QPushButton::clicked, [this]() { + selectBios(m_ui.sgbBios); + }); + + QList defaultColors; + defaultColors.append(QColor(0xF8, 0xF8, 0xF8)); + defaultColors.append(QColor(0xA8, 0xA8, 0xA8)); + defaultColors.append(QColor(0x50, 0x50, 0x50)); + defaultColors.append(QColor(0x00, 0x00, 0x00)); + defaultColors.append(QColor(0xF8, 0xF8, 0xF8)); + defaultColors.append(QColor(0xA8, 0xA8, 0xA8)); + defaultColors.append(QColor(0x50, 0x50, 0x50)); + defaultColors.append(QColor(0x00, 0x00, 0x00)); + defaultColors.append(QColor(0xF8, 0xF8, 0xF8)); + defaultColors.append(QColor(0xA8, 0xA8, 0xA8)); + defaultColors.append(QColor(0x50, 0x50, 0x50)); + defaultColors.append(QColor(0x00, 0x00, 0x00)); + QList colors{ + m_ui.color0, + m_ui.color1, + m_ui.color2, + m_ui.color3, + m_ui.color4, + m_ui.color5, + m_ui.color6, + m_ui.color7, + m_ui.color8, + m_ui.color9, + m_ui.color10, + m_ui.color11 + }; + for (int colorId = 0; colorId < 12; ++colorId) { + bool ok; + uint color = m_controller->getOption(QString("gb.pal[%0]").arg(colorId)).toUInt(&ok); + if (ok) { + defaultColors[colorId] = QColor::fromRgb(color); + m_gbColors[colorId] = color | 0xFF000000; + } else { + m_gbColors[colorId] = defaultColors[colorId].rgb() & ~0xFF000000; + } + m_colorPickers[colorId] = ColorPicker(colors[colorId], defaultColors[colorId]); + connect(&m_colorPickers[colorId], &ColorPicker::colorChanged, this, [this, colorId](const QColor& color) { + m_gbColors[colorId] = color.rgb(); + }); + } +#else + m_ui.gbBiosBrowse->hide(); + m_ui.gbcBiosBrowse->hide(); + m_ui.sgbBiosBrowse->hide(); + m_ui.gb->hide(); +#endif GBAKeyEditor* editor = new GBAKeyEditor(inputController, InputController::KEYBOARD, QString(), this); m_ui.stackedWidget->addWidget(editor); @@ -188,19 +302,26 @@ SettingsView::~SettingsView() { #if defined(BUILD_GL) || defined(BUILD_GLES2) - if (m_shader) { - m_ui.stackedWidget->removeWidget(m_shader); - m_shader->setParent(nullptr); - } + setShaderSelector(nullptr); #endif } void SettingsView::setShaderSelector(ShaderSelector* shaderSelector) { #if defined(BUILD_GL) || defined(BUILD_GLES2) + if (m_shader) { + auto items = m_ui.tabs->findItems(tr("Shaders"), Qt::MatchFixedString); + for (const auto& item : items) { + m_ui.tabs->removeItemWidget(item); + } + m_ui.stackedWidget->removeWidget(m_shader); + m_shader->setParent(nullptr); + } m_shader = shaderSelector; - m_ui.stackedWidget->addWidget(m_shader); - m_ui.tabs->addItem(tr("Shaders")); - connect(m_ui.buttonBox, &QDialogButtonBox::accepted, m_shader, &ShaderSelector::saved); + if (shaderSelector) { + m_ui.stackedWidget->addWidget(m_shader); + m_ui.tabs->addItem(tr("Shaders")); + connect(m_ui.buttonBox, &QDialogButtonBox::accepted, m_shader, &ShaderSelector::saved); + } #endif } @@ -215,6 +336,8 @@ saveSetting("gba.bios", m_ui.gbaBios); saveSetting("gb.bios", m_ui.gbBios); saveSetting("gbc.bios", m_ui.gbcBios); + saveSetting("sgb.bios", m_ui.sgbBios); + saveSetting("sgb.borders", m_ui.sgbBorders); saveSetting("useBios", m_ui.useBios); saveSetting("skipBios", m_ui.skipBios); saveSetting("audioBuffers", m_ui.audioBufferSize); @@ -223,13 +346,15 @@ saveSetting("audioSync", m_ui.audioSync); saveSetting("frameskip", m_ui.frameskip); saveSetting("fpsTarget", m_ui.fpsTarget); + saveSetting("autofireThreshold", m_ui.autofireThreshold); saveSetting("lockAspectRatio", m_ui.lockAspectRatio); saveSetting("lockIntegerScaling", m_ui.lockIntegerScaling); saveSetting("volume", m_ui.volume); saveSetting("mute", m_ui.mute); + saveSetting("fastForwardVolume", m_ui.volumeFf); + saveSetting("fastForwardMute", m_ui.muteFf); saveSetting("rewindEnable", m_ui.rewind); saveSetting("rewindBufferCapacity", m_ui.rewindCapacity); - saveSetting("rewindSave", m_ui.rewindSave); saveSetting("resampleVideo", m_ui.resampleVideo); saveSetting("allowOpposingDirections", m_ui.allowOpposingDirections); saveSetting("suspendScreensaver", m_ui.suspendScreensaver); @@ -238,9 +363,15 @@ saveSetting("savestatePath", m_ui.savestatePath); saveSetting("screenshotPath", m_ui.screenshotPath); saveSetting("patchPath", m_ui.patchPath); + saveSetting("cheatsPath", m_ui.cheatsPath); saveSetting("libraryStyle", m_ui.libraryStyle->currentIndex()); saveSetting("showLibrary", m_ui.showLibrary); saveSetting("preload", m_ui.preload); + saveSetting("showFps", m_ui.showFps); + saveSetting("cheatAutoload", m_ui.cheatAutoload); + saveSetting("cheatAutosave", m_ui.cheatAutosave); + saveSetting("autoload", m_ui.autoload); + saveSetting("autosave", m_ui.autosave); if (m_ui.fastForwardUnbounded->isChecked()) { saveSetting("fastForwardRatio", "-1"); @@ -283,15 +414,42 @@ if (displayDriver != m_controller->getQtOption("displayDriver")) { m_controller->setQtOption("displayDriver", displayDriver); Display::setDriver(static_cast(displayDriver.toInt())); + setShaderSelector(nullptr); emit displayDriverChanged(); } + QVariant cameraDriver = m_ui.cameraDriver->itemData(m_ui.cameraDriver->currentIndex()); + if (cameraDriver != m_controller->getQtOption("cameraDriver")) { + m_controller->setQtOption("cameraDriver", cameraDriver); + emit cameraDriverChanged(); + } + QLocale language = m_ui.languages->itemData(m_ui.languages->currentIndex()).toLocale(); if (language != m_controller->getQtOption("language").toLocale() && !(language.bcp47Name() == QLocale::system().bcp47Name() && m_controller->getQtOption("language").isNull())) { m_controller->setQtOption("language", language.bcp47Name()); emit languageChanged(); } +#ifdef M_CORE_GB + GBModel modelGB = s_gbModelList[m_ui.gbModel->currentIndex()]; + m_controller->setOption("gb.model", GBModelToName(modelGB)); + + GBModel modelSGB = s_gbModelList[m_ui.sgbModel->currentIndex()]; + m_controller->setOption("sgb.model", GBModelToName(modelSGB)); + + GBModel modelCGB = s_gbModelList[m_ui.cgbModel->currentIndex()]; + m_controller->setOption("cgb.model", GBModelToName(modelCGB)); + + for (int colorId = 0; colorId < 12; ++colorId) { + if (!(m_gbColors[colorId] & 0xFF000000)) { + continue; + } + QString color = QString("gb.pal[%0]").arg(colorId); + m_controller->setOption(color.toUtf8().constData(), m_gbColors[colorId] & ~0xFF000000); + + } +#endif + m_controller->write(); emit pathsChanged(); @@ -303,6 +461,8 @@ loadSetting("gba.bios", m_ui.gbaBios); loadSetting("gb.bios", m_ui.gbBios); loadSetting("gbc.bios", m_ui.gbcBios); + loadSetting("sgb.bios", m_ui.sgbBios); + loadSetting("sgb.borders", m_ui.sgbBorders, true); loadSetting("useBios", m_ui.useBios); loadSetting("skipBios", m_ui.skipBios); loadSetting("audioBuffers", m_ui.audioBufferSize); @@ -311,13 +471,15 @@ loadSetting("audioSync", m_ui.audioSync); loadSetting("frameskip", m_ui.frameskip); loadSetting("fpsTarget", m_ui.fpsTarget); + loadSetting("autofireThreshold", m_ui.autofireThreshold); loadSetting("lockAspectRatio", m_ui.lockAspectRatio); loadSetting("lockIntegerScaling", m_ui.lockIntegerScaling); - loadSetting("volume", m_ui.volume); - loadSetting("mute", m_ui.mute); + loadSetting("volume", m_ui.volume, 0x100); + loadSetting("mute", m_ui.mute, false); + loadSetting("fastForwardVolume", m_ui.volumeFf, m_ui.volume->value()); + loadSetting("fastForwardMute", m_ui.muteFf, m_ui.mute->isChecked()); loadSetting("rewindEnable", m_ui.rewind); loadSetting("rewindBufferCapacity", m_ui.rewindCapacity); - loadSetting("rewindSave", m_ui.rewindSave); loadSetting("resampleVideo", m_ui.resampleVideo); loadSetting("allowOpposingDirections", m_ui.allowOpposingDirections); loadSetting("suspendScreensaver", m_ui.suspendScreensaver); @@ -326,8 +488,14 @@ loadSetting("savestatePath", m_ui.savestatePath); loadSetting("screenshotPath", m_ui.screenshotPath); loadSetting("patchPath", m_ui.patchPath); + loadSetting("cheatsPath", m_ui.cheatsPath); loadSetting("showLibrary", m_ui.showLibrary); loadSetting("preload", m_ui.preload); + loadSetting("showFps", m_ui.showFps, true); + loadSetting("cheatAutoload", m_ui.cheatAutoload, true); + loadSetting("cheatAutosave", m_ui.cheatAutosave, true); + loadSetting("autoload", m_ui.autoload, true); + loadSetting("autosave", m_ui.autosave, false); m_ui.libraryStyle->setCurrentIndex(loadSetting("libraryStyle").toInt()); @@ -366,6 +534,29 @@ m_ui.saveStateScreenshot->setChecked(saveState & SAVESTATE_SCREENSHOT); m_ui.saveStateSave->setChecked(saveState & SAVESTATE_SAVEDATA); m_ui.saveStateCheats->setChecked(saveState & SAVESTATE_CHEATS); + +#ifdef M_CORE_GB + QString modelGB = m_controller->getOption("gb.model"); + if (!modelGB.isNull()) { + GBModel model = GBNameToModel(modelGB.toUtf8().constData()); + int index = s_gbModelList.indexOf(model); + m_ui.gbModel->setCurrentIndex(index >= 0 ? index : 0); + } + + QString modelSGB = m_controller->getOption("sgb.model"); + if (!modelSGB.isNull()) { + GBModel model = GBNameToModel(modelSGB.toUtf8().constData()); + int index = s_gbModelList.indexOf(model); + m_ui.sgbModel->setCurrentIndex(index >= 0 ? index : 0); + } + + QString modelCGB = m_controller->getOption("cgb.model"); + if (!modelCGB.isNull()) { + GBModel model = GBNameToModel(modelCGB.toUtf8().constData()); + int index = s_gbModelList.indexOf(model); + m_ui.cgbModel->setCurrentIndex(index >= 0 ? index : 0); + } +#endif } void SettingsView::saveSetting(const char* key, const QAbstractButton* field) { @@ -398,9 +589,9 @@ m_controller->updateOption(key); } -void SettingsView::loadSetting(const char* key, QAbstractButton* field) { +void SettingsView::loadSetting(const char* key, QAbstractButton* field, bool defaultVal) { QString option = loadSetting(key); - field->setChecked(!option.isNull() && option != "0"); + field->setChecked(option.isNull() ? defaultVal : option != "0"); } void SettingsView::loadSetting(const char* key, QComboBox* field) { @@ -417,9 +608,9 @@ field->setText(option); } -void SettingsView::loadSetting(const char* key, QSlider* field) { +void SettingsView::loadSetting(const char* key, QSlider* field, int defaultVal) { QString option = loadSetting(key); - field->setValue(option.toInt()); + field->setValue(option.isNull() ? defaultVal : option.toInt()); } void SettingsView::loadSetting(const char* key, QSpinBox* field) { diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/SettingsView.h mgba-0.7.0/src/platform/qt/SettingsView.h --- mgba-0.6.3+dfsg1/src/platform/qt/SettingsView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/SettingsView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,13 +3,18 @@ * 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_SETTINGS_VIEW -#define QGBA_SETTINGS_VIEW +#pragma once #include +#include "ColorPicker.h" + #include +#ifdef M_CORE_GB +#include +#endif + #include "ui_SettingsView.h" namespace QGBA { @@ -32,6 +37,7 @@ void biosLoaded(int platform, const QString&); void audioDriverChanged(); void displayDriverChanged(); + void cameraDriverChanged(); void pathsChanged(); void languageChanged(); void libraryCleared(); @@ -48,6 +54,12 @@ InputController* m_input; ShaderSelector* m_shader = nullptr; +#ifdef M_CORE_GB + uint32_t m_gbColors[12]{}; + ColorPicker m_colorPickers[12]; + static QList s_gbModelList; +#endif + void saveSetting(const char* key, const QAbstractButton*); void saveSetting(const char* key, const QComboBox*); void saveSetting(const char* key, const QDoubleSpinBox*); @@ -56,15 +68,13 @@ void saveSetting(const char* key, const QSpinBox*); void saveSetting(const char* key, const QVariant&); - void loadSetting(const char* key, QAbstractButton*); + void loadSetting(const char* key, QAbstractButton*, bool defaultVal = false); void loadSetting(const char* key, QComboBox*); void loadSetting(const char* key, QDoubleSpinBox*); void loadSetting(const char* key, QLineEdit*); - void loadSetting(const char* key, QSlider*); + void loadSetting(const char* key, QSlider*, int defaultVal = 0); void loadSetting(const char* key, QSpinBox*); QString loadSetting(const char* key); }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/SettingsView.ui mgba-0.7.0/src/platform/qt/SettingsView.ui --- mgba-0.6.3+dfsg1/src/platform/qt/SettingsView.ui 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/SettingsView.ui 2019-01-27 00:06:06.000000000 +0000 @@ -6,8 +6,8 @@ 0 0 - 650 - 454 + 588 + 488 @@ -65,6 +65,11 @@ Paths + + + Game Boy + + @@ -258,21 +263,61 @@ - + + + + Fast forward volume: + + + + + + + + + + 128 + 0 + + + + 256 + + + 16 + + + 256 + + + Qt::Horizontal + + + + + + + Mute + + + + + + Qt::Horizontal - + Display driver: - + @@ -282,14 +327,14 @@ - + Frameskip: - + @@ -310,17 +355,20 @@ - + FPS target: - + + + 4 + 0.010000000000000 @@ -341,21 +389,21 @@ - + Qt::Horizontal - + Sync: - + @@ -373,7 +421,7 @@ - + Lock aspect ratio @@ -381,16 +429,16 @@ - + - Bilinear filtering + Force integer scaling - - + + - Force integer scaling + Bilinear filtering @@ -414,6 +462,13 @@ + + + + Qt::Horizontal + + + @@ -483,13 +538,70 @@ - - + + + + Show FPS in title bar + + + true + + + + + + + Qt::Horizontal + + + + + Qt::Horizontal + + + + Automatically save cheats + + + true + + + + + + + Automatically load cheats + + + true + + + + + + + Automatically save state + + + true + + + + + + + Automatically load state + + + true + + + @@ -540,28 +652,45 @@ - + + + + Autofire interval: + + + + + + + 1 + + + 60 + + + + Qt::Horizontal - + Enable rewind - + Rewind history: - + @@ -612,6 +741,13 @@ + + + + Preload entire ROM into memory + + + @@ -656,6 +792,13 @@ + + + + Qt::Horizontal + + + @@ -687,30 +830,6 @@ - - - - Qt::Horizontal - - - - - - - Rewind affects save data - - - true - - - - - - - Preload entire ROM into memory - - - @@ -743,7 +862,7 @@ - + Use BIOS file if found @@ -753,14 +872,14 @@ - + Skip BIOS intro - + @@ -781,21 +900,21 @@ - + GBA BIOS file: - + GBC BIOS file: - + @@ -816,6 +935,34 @@ + + + + SGB BIOS file: + + + + + + + + + + 0 + 0 + + + + + + + + Browse + + + + + @@ -1008,11 +1155,470 @@ + + + + Qt::Horizontal + + + + + + + Cheats + + + + + + + + + + 0 + 0 + + + + + 170 + 0 + + + + + + + + Browse + + + + + + + + + Same directory as the ROM + + + - - - + + + + + + Game Boy model + + + + + + + + Autodetect + + + + + Game Boy (DMG) + + + + + Super Game Boy (SGB) + + + + + Game Boy Color (CGB) + + + + + Game Boy Advance (AGB) + + + + + + + + Super Game Boy model + + + + + + + + Autodetect + + + + + Game Boy (DMG) + + + + + Super Game Boy (SGB) + + + + + Game Boy Color (CGB) + + + + + Game Boy Advance (AGB) + + + + + + + + Game Boy Color model + + + + + + + + Autodetect + + + + + Game Boy (DMG) + + + + + Super Game Boy (SGB) + + + + + Game Boy Color (CGB) + + + + + Game Boy Advance (AGB) + + + + + + + + Qt::Horizontal + + + + + + + Default BG colors: + + + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + Super Game Boy borders + + + + + + + Qt::Horizontal + + + + + + + Camera driver: + + + + + + + + 0 + 0 + + + + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + 30 + 30 + + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + Default sprite colors 1: + + + + + + + Default sprite colors 2: + + + + + + + + @@ -1128,6 +1734,22 @@ + + cheatsSameDir + toggled(bool) + cheatsPath + setDisabled(bool) + + + 351 + 407 + + + 343 + 372 + + + fastForwardUnbounded toggled(bool) diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ShaderSelector.h mgba-0.7.0/src/platform/qt/ShaderSelector.h --- mgba-0.6.3+dfsg1/src/platform/qt/ShaderSelector.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ShaderSelector.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_SHADER_SELECTOR_H -#define QGBA_SHADER_SELECTOR_H +#pragma once #if defined(BUILD_GL) || defined(BUILD_GLES2) @@ -58,5 +57,3 @@ } #endif - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ShortcutController.h mgba-0.7.0/src/platform/qt/ShortcutController.h --- mgba-0.6.3+dfsg1/src/platform/qt/ShortcutController.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ShortcutController.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_SHORTCUT_MODEL -#define QGBA_SHORTCUT_MODEL +#pragma once #include "GamepadAxisEvent.h" @@ -144,5 +143,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ShortcutView.h mgba-0.7.0/src/platform/qt/ShortcutView.h --- mgba-0.6.3+dfsg1/src/platform/qt/ShortcutView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ShortcutView.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_SHORTCUT_VIEW -#define QGBA_SHORTCUT_VIEW +#pragma once #include "GamepadAxisEvent.h" @@ -45,5 +44,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/Swatch.cpp mgba-0.7.0/src/platform/qt/Swatch.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/Swatch.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/Swatch.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -42,6 +42,14 @@ updateFill(index); } +void Swatch::setColor(int index, uint32_t color) { + m_colors[index].setRgb( + (color >> 0) & 0xFF, + (color >> 8) & 0xFF, + (color >> 16) & 0xFF); + updateFill(index); +} + void Swatch::paintEvent(QPaintEvent* event) { QPainter painter(this); painter.drawPixmap(QPoint(), m_backing); diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/Swatch.h mgba-0.7.0/src/platform/qt/Swatch.h --- mgba-0.6.3+dfsg1/src/platform/qt/Swatch.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/Swatch.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_SWATCH -#define QGBA_SWATCH +#pragma once #include #include @@ -23,6 +22,7 @@ public slots: void setColor(int index, uint16_t); + void setColor(int index, uint32_t); signals: void indexPressed(int index); @@ -41,5 +41,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/TilePainter.cpp mgba-0.7.0/src/platform/qt/TilePainter.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/TilePainter.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/TilePainter.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -40,14 +40,15 @@ emit indexPressed(y * (width() / m_size) + x); } -void TilePainter::setTile(int index, const uint16_t* data) { +void TilePainter::setTile(int index, const color_t* data) { QPainter painter(&m_backing); int w = width() / m_size; int x = index % w; int y = index / w; QRect r(x * m_size, y * m_size, m_size, m_size); - QImage tile(reinterpret_cast(data), 8, 8, QImage::Format_RGB555); - painter.drawImage(r, tile.rgbSwapped()); + QImage tile(reinterpret_cast(data), 8, 8, QImage::Format_ARGB32); + tile = tile.convertToFormat(QImage::Format_RGB32).rgbSwapped(); + painter.drawImage(r, tile); update(r); } @@ -58,8 +59,12 @@ int w = width() / m_size; int h = (tiles + w - 1) * m_size / w; setMinimumSize(m_size, h - (h % m_size)); - resizeEvent(nullptr); + } else { + int w = minimumSize().width() / m_size; + int h = (tiles + w - 1) * m_size / w; + setMinimumSize(minimumSize().width(), h - (h % m_size)); } + resizeEvent(nullptr); } void TilePainter::setTileMagnification(int mag) { diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/TilePainter.h mgba-0.7.0/src/platform/qt/TilePainter.h --- mgba-0.6.3+dfsg1/src/platform/qt/TilePainter.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/TilePainter.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,13 +3,14 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef QGBA_TILE_PAINTER -#define QGBA_TILE_PAINTER +#pragma once #include #include #include +#include + namespace QGBA { class TilePainter : public QWidget { @@ -19,7 +20,7 @@ TilePainter(QWidget* parent = nullptr); public slots: - void setTile(int index, const uint16_t*); + void setTile(int index, const color_t*); void setTileCount(int tiles); void setTileMagnification(int mag); @@ -38,5 +39,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/TileView.cpp mgba-0.7.0/src/platform/qt/TileView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/TileView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/TileView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "TileView.h" +#include "CoreController.h" #include "GBAApp.h" #include @@ -16,7 +17,7 @@ using namespace QGBA; -TileView::TileView(GameController* controller, QWidget* parent) +TileView::TileView(std::shared_ptr controller, QWidget* parent) : AssetView(controller, parent) , m_controller(controller) { @@ -24,40 +25,32 @@ m_ui.tile->setController(controller); connect(m_ui.tiles, &TilePainter::indexPressed, m_ui.tile, &AssetTile::selectIndex); - connect(m_ui.paletteId, &QAbstractSlider::valueChanged, this, &TileView::updatePalette); + connect(m_ui.paletteId, static_cast(&QSpinBox::valueChanged), this, &TileView::updatePalette); - int max = 1024; - int boundary = 1024; switch (m_controller->platform()) { #ifdef M_CORE_GBA case PLATFORM_GBA: - max = 3072; - boundary = 2048; + m_ui.tile->setBoundary(2048, 0, 2); break; #endif #ifdef M_CORE_GB case PLATFORM_GB: - max = 1024; - boundary = 512; m_ui.palette256->setEnabled(false); + m_ui.tile->setBoundary(1024, 0, 0); break; #endif default: return; } - m_ui.tile->setPaletteSet(0, boundary, max); connect(m_ui.palette256, &QAbstractButton::toggled, [this](bool selected) { if (selected) { m_ui.paletteId->setValue(0); } - int max = 1024; - int boundary = 1024; switch (m_controller->platform()) { #ifdef M_CORE_GBA case PLATFORM_GBA: - max = 3072 >> selected; - boundary = 2048 >> selected; + m_ui.tile->setBoundary(2048 >> selected, selected, selected + 2); break; #endif #ifdef M_CORE_GB @@ -67,52 +60,68 @@ default: break; } - m_ui.tile->setPaletteSet(selected, boundary, max); updateTiles(true); }); connect(m_ui.magnification, static_cast(&QSpinBox::valueChanged), [this]() { updateTiles(true); }); + + connect(m_ui.tilesPerRow, static_cast(&QSpinBox::valueChanged), [this](int count) { + m_ui.tiles->setMinimumSize(m_ui.magnification->value() * 8 * count, m_ui.tiles->minimumSize().height()); + updateTiles(true); + }); + + connect(m_ui.tileFit, &QAbstractButton::toggled, [this](bool selected) { + if (!selected) { + m_ui.tiles->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + m_ui.tiles->setMinimumSize(m_ui.magnification->value() * 8 * m_ui.tilesPerRow->value(), m_ui.tiles->minimumSize().height()); + } else { + m_ui.tiles->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + } + updateTiles(true); + }); } #ifdef M_CORE_GBA void TileView::updateTilesGBA(bool force) { if (m_ui.palette256->isChecked()) { m_ui.tiles->setTileCount(1536); - mTileCacheSetPalette(m_tileCache.get(), 1); + mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 1); for (int i = 0; i < 1024; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * i], i, 0); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, 0); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, 0)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i, 0)); } } + cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 3); for (int i = 1024; i < 1536; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * i], i, 1); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 1024, 0); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, 1)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i - 1024, 0)); } } } else { + mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0); m_ui.tiles->setTileCount(3072); - mTileCacheSetPalette(m_tileCache.get(), 0); for (int i = 0; i < 2048; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * i], i, m_paletteId); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, m_paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, m_paletteId)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i, m_paletteId)); } } + cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 2); for (int i = 2048; i < 3072; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[32 * i], i, m_paletteId + 16); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 2048, m_paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, m_paletteId + 16)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i - 2048, m_paletteId)); } } } @@ -124,13 +133,13 @@ const GB* gb = static_cast(m_controller->thread()->core->board); int count = gb->model >= GB_MODEL_CGB ? 1024 : 512; m_ui.tiles->setTileCount(count); - mTileCacheSetPalette(m_tileCache.get(), 0); + mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0); for (int i = 0; i < count; ++i) { - const uint16_t* data = mTileCacheGetTileIfDirty(m_tileCache.get(), &m_tileStatus[16 * i], i, m_paletteId); + const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[8 * i], i, m_paletteId); if (data) { m_ui.tiles->setTile(i, data); } else if (force) { - m_ui.tiles->setTile(i, mTileCacheGetTile(m_tileCache.get(), i, m_paletteId)); + m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i, m_paletteId)); } } } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/TileView.h mgba-0.7.0/src/platform/qt/TileView.h --- mgba-0.6.3+dfsg1/src/platform/qt/TileView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/TileView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,11 +3,9 @@ * 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_TILE_VIEW -#define QGBA_TILE_VIEW +#pragma once #include "AssetView.h" -#include "GameController.h" #include "ui_TileView.h" @@ -15,11 +13,13 @@ namespace QGBA { +class CoreController; + class TileView : public AssetView { Q_OBJECT public: - TileView(GameController* controller, QWidget* parent = nullptr); + TileView(std::shared_ptr controller, QWidget* parent = nullptr); public slots: void updatePalette(int); @@ -34,11 +34,9 @@ Ui::TileView m_ui; - GameController* m_controller; + std::shared_ptr m_controller; mTileCacheEntry m_tileStatus[3072 * 32] = {}; // TODO: Correct size int m_paletteId = 0; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/TileView.ui mgba-0.7.0/src/platform/qt/TileView.ui --- mgba-0.6.3+dfsg1/src/platform/qt/TileView.ui 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/TileView.ui 2019-01-27 00:06:06.000000000 +0000 @@ -6,87 +6,15 @@ 0 0 - 498 - 335 + 693 + 467 Tiles - - - - - 256 colors - - - - - - - - 170 - 16777215 - - - - 15 - - - 1 - - - Qt::Horizontal - - - QSlider::TicksBelow - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - - - - × - - - 1 - - - 4 - - - - - - - Magnification - - - - - - + + @@ -105,7 +33,7 @@ 0 0 - 286 + 405 768 @@ -152,8 +80,98 @@ + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + 15 + + + + + + + 256 colors + + + + + + + + 0 + 0 + + + + × + + + 1 + + + 4 + + + + + + + Magnification + + + + + + + false + + + 1 + + + 64 + + + 32 + + + + + + + Tiles per row + + + + + + + Fit to window + + + true + + + + + @@ -176,18 +194,18 @@ - palette256 + tileFit toggled(bool) - paletteId + tilesPerRow setDisabled(bool) - 100 - 54 + 162 + 180 - 96 - 22 + 39 + 133 @@ -198,12 +216,28 @@ setTileMagnification(int) - 36 - 83 + 39 + 81 + + + 462 + 391 + + + + + palette256 + toggled(bool) + paletteId + setDisabled(bool) + + + 148 + 24 - 339 - 396 + 39 + 29 diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ts/mgba-de.ts mgba-0.7.0/src/platform/qt/ts/mgba-de.ts --- mgba-0.6.3+dfsg1/src/platform/qt/ts/mgba-de.ts 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ts/mgba-de.ts 2019-01-27 00:06:06.000000000 +0000 @@ -72,49 +72,55 @@ AssetTile - + AssetTile AssetTile - + Tile # Tile # - + + 0 0 - + + Palette # + Palette # + + + Address Adresse - + 0x06000000 0x06000000 - + Red Rot - + Green Grün - + Blue Blau - - - + + + 0x00 (00) 0x00 (00) @@ -455,6 +461,29 @@ + MapView + + + Maps + Maps + + + + × + × + + + + Magnification + Vergrößerung + + + + Export + Exportieren + + + MemorySearch @@ -493,62 +522,88 @@ Text - + Width Breite - + 1 Byte (8-bit) 1 Byte (8-bit) - + 2 Bytes (16-bit) 2 Bytes (16-bit) - + 4 Bytes (32-bit) 4 Bytes (32-bit) - + Number type Zahlensystem - + Hexadecimal Hexadezimal - + Decimal Dezimal - + + Guess automatisch - + + Compare + Vergleichen + + + + Equal + Gleichwertig + + + + Greater + Größer + + + + Less + Kleiner + + + + Delta + Differenz + + + Search Suchen - + Search Within Suchen innerhalb - + Open in Memory Viewer Im Speicher-Monitor öffnen - + Refresh Aktualisieren @@ -793,7 +848,7 @@ - + Autodetect Automatisch erkennen @@ -829,7 +884,7 @@ - + None keiner @@ -880,63 +935,88 @@ + Super Game Boy (SGB) + Super Game Boy (SGB) + + + Game Boy Color (CGB) Game Boy Color (CGB) - + Game Boy Advance (AGB) Game Boy Advance (AGB) - + Memory bank controller Speicherbank-Controller - + MBC1 MBC1 - + MBC2 MBC2 - + MBC3 MBC3 - + MBC3 + RTC MBC3 + RTC - + MBC5 MBC5 - + MBC5 + Rumble MBC5 + Rumble - + MBC7 MBC7 - + + Pocket Cam + Pocket Cam + + + + TAMA5 + TAMA5 + + + HuC-3 HuC-3 - - Colors - Farben + + Background Colors + Hintergrund-Farbpalette + + + + Sprite Colors 1 + Sprite-Farbpalette 1 + + + + Sprite Colors 2 + Sprite-Farbpalette 2 @@ -1025,16 +1105,62 @@ + PlacementControl + + + Adjust placement + Lage anpassen + + + + All + Alle + + + + Offset + Versatz + + + + X + X + + + + Y + Y + + + + PrinterView + + + Game Boy Printer + Game Boy Printer + + + + Hurry up! + Los geht's! + + + + Tear off + Abreißen + + + QGBA::AssetTile - + %0%1%2 %0%1%2 - - - + + + 0x%0 (%1) 0x%0 (%1) @@ -1047,7 +1173,7 @@ (unbenannt) - + Failed to open cheats file: %1 Fehler beim Öffnen der Cheat-Datei: %1 @@ -1083,6 +1209,37 @@ + QGBA::CoreController + + + Failed to open save file: %1 + Fehler beim Öffnen der Speicherdatei: %1 + + + + Failed to open game file: %1 + Fehler beim Öffnen der Spieldatei: %1 + + + + Failed to open snapshot file for reading: %1 + Konnte Snapshot-Datei %1 nicht zum Lesen öffnen + + + + Failed to open snapshot file for writing: %1 + Konnte Snapshot-Datei %1 nicht zum Schreiben öffnen + + + + QGBA::CoreManager + + + Failed to open game file: %1 + Fehler beim Öffnen der Spieldatei: %1 + + + QGBA::GBAKeyEditor @@ -1151,51 +1308,22 @@ QGBA::GIFView - + Failed to open output GIF file: %1 Fehler beim Öffnen der Ausgabe-GIF-Datei: %1 - + Select output file Ausgabedatei auswählen - + Graphics Interchange Format (*.gif) Graphics Interchange Format (*.gif) - QGBA::GameController - - - - Failed to open game file: %1 - Fehler beim Öffnen der Spieldatei: %1 - - - - Failed to open save file: %1 - Fehler beim Öffnen der Speicherdatei: %1 - - - - Failed to open snapshot file for reading: %1 - Konnte Snapshot-Datei %1 nicht zum Lesen öffnen - - - - Failed to open snapshot file for writing: %1 - Konnte Snapshot-Datei %1 nicht zum Schreiben öffnen - - - - Failed to start audio processor - Fehler beim Starten des Audio-Prozessors - - - QGBA::IOViewer @@ -2575,27 +2703,27 @@ QGBA::LoadSaveState - + Load State Savestate laden - + Save State Savestate speichern - + Empty Leer - + Corrupted Defekt - + Slot %1 Speicherplatz %1 @@ -2603,42 +2731,90 @@ QGBA::LogController - + DEBUG DEBUG - + STUB STUB - + INFO INFO - + WARN WARN - + ERROR ERROR - + FATAL FATAL - + GAME ERROR GAME ERROR + QGBA::MapView + + + Map Addr. + Map-Addr. + + + + Mirror + Spiegel + + + + None + Keiner + + + + Both + Beidseitig + + + + Horizontal + Horizontal + + + + Vertical + Vertikal + + + + Export map + Map exportieren + + + + Portable Network Graphics (*.png) + Portable Network Graphics (*.png) + + + + Failed to open output PNG file: %1 + Fehler beim Öffnen der Ausgabe-PNG-Datei: %1 + + + QGBA::MemoryModel @@ -2662,7 +2838,6 @@ - All Alle @@ -2672,32 +2847,32 @@ TBL laden - + Save selected memory Ausgewählten Speicher abspeichern - + Failed to open output file: %1 Fehler beim Öffnen der Ausgabedatei: %1 - + Load memory Lade Speicher - + Failed to open input file: %1 Fehler beim Laden der Eingabedatei: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -2705,77 +2880,77 @@ QGBA::MemorySearch - - (⅟%0×) - (⅟%0×) + + (%0/%1×) + (%0/%1×) - - 1 byte%0 - 1 Byte%0 + + (⅟%0×) + (⅟%0×) - - 2 bytes%0 - 2 Bytes%0 + + (%0×) + (%0×) - - 4 bytes%0 - 4 Bytes%0 + + %1 byte%2 + %1 byte%2 QGBA::ObjView - - + + 0x%0 0x%0 - + Off Aus - + Normal Normal - + Trans Trans - + OBJWIN OBJWIN - + Invalid Ungültig - - + + N/A N/A - + Export sprite Sprite exportieren - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + Failed to open output PNG file: %1 Fehler beim Öffnen der Ausgabe-PNG-Datei: %1 @@ -2783,62 +2958,75 @@ QGBA::PaletteView - + #%0 #%0 - + 0x%0 0x%0 - + %0 %0 - + 0x%0 (%1) 0x%0 (%1) - + Export palette Palette exportieren - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 Fehler beim Öffnen der Ausgabe-Palettendatei: %1 + QGBA::PrinterView + + + Save Printout + Ausdruck speichern + + + + Portable Network Graphics (*.png) + Portable Network Graphics (*.png) + + + QGBA::ROMInfo - - - - - + + + + + (unknown) (unbekannt) - - + + bytes Bytes - + (no database present) (keine Datenbank vorhanden) @@ -2846,47 +3034,59 @@ QGBA::SettingsView - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (erzwinge Version 1.x) - + + None (Still Image) + Keiner (Standbild) + + + Keyboard Tastatur - + Controllers Gamepads - + Shortcuts Tastenkürzel - + + + Shaders + Shader + + + Select BIOS BIOS auswählen @@ -2894,37 +3094,32 @@ QGBA::ShaderSelector - + No shader active Kein Shader aktiv - + Load shader Shader laden - - %1 Shader (%.shader) - %1 Shader (%.shader) - - - + No shader loaded Kein Shader geladen - + by %1 von %1 - + Preprocessing Vorbehandlung - + Pass %1 Durchlauf %1 @@ -2950,17 +3145,17 @@ QGBA::VideoView - + Failed to open output video file: %1 Fehler beim Öffnen der Ausgabe-Videodatei: %1 - + Native (%0x%1) Nativ (%0x%1) - + Select output file Ausgabedatei auswählen @@ -2968,82 +3163,103 @@ QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance-ROMs (%1) - + Game Boy ROMs (%1) Game Boy-ROMs (%1) - + All ROMs (%1) Alle ROMs (%1) - + %1 Video Logs (*.mvl) %1 Video-Logs (*.mvl) - + Archives (%1) Archive (%1) - - - + + + Select ROM ROM auswählen - + Game Boy Advance save files (%1) Game Boy Advance-Speicherdateien (%1) - - - + + + Select save Speicherdatei wählen - + + mGBA savestate files (%1) + mGBA Savestate-Dateien (%1) + + + + + Select savestate + Savestate auswählen + + + Select patch Patch wählen - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - - + + Select image + Bild auswählen + + + + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) + Bild-Datei (*.png *.gif *.jpg *.jpeg);;Alle Dateien (*) + + + + GameShark saves (*.sps *.xps) GameShark-Speicherdaten (*.sps *.xps) - + Select video log Video-Log auswählen - + Video logs (*.mvl) Video-Logs (*.mvl) - + Crash Absturz - + The game has crashed with the following error: %1 @@ -3052,628 +3268,628 @@ %1 - + Couldn't Load Konnte nicht geladen werden - + Could not load game. Are you sure it's in the correct format? Konnte das Spiel nicht laden. Sind Sie sicher, dass es im korrekten Format vorliegt? - + Unimplemented BIOS call Nicht implementierter BIOS-Aufruf - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Dieses Spiel verwendet einen BIOS-Aufruf, der nicht implementiert ist. Bitte verwenden Sie für die beste Spielerfahrung das offizielle BIOS. - + Really make portable? Portablen Modus wirklich aktivieren? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Diese Einstellung wird den Emulator so konfigurieren, dass er seine Konfiguration aus dem gleichen Verzeichnis wie die Programmdatei lädt. Möchten Sie fortfahren? - + Restart needed Neustart benötigt - + Some changes will not take effect until the emulator is restarted. Einige Änderungen werden erst übernommen, wenn der Emulator neu gestartet wurde. - + - Player %1 of %2 - Spieler %1 von %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 Bilder/Sekunde) - %4 - + &File &Datei - + Load &ROM... &ROM laden... - + Load ROM in archive... ROM aus Archiv laden... - + + Load alternate save... + Alternative Speicherdatei laden... + + + Load temporary save... Temporäre Speicherdatei laden... - + Load &patch... &Patch laden... - + Boot BIOS BIOS booten - + Replace ROM... ROM ersetzen... - + ROM &info... ROM-&Informationen... - + Recent Zuletzt verwendet - + Make portable Portablen Modus aktivieren - + &Load state - Savestate &laden + Savestate (aktueller Zustand) &laden - + F10 F10 - + + Load state file... + Ssavestate-Datei laden... + + + &Save state - Savestate &speichern + Savestate (aktueller Zustand) &speichern - + Shift+F10 Umschalt+F10 - + + Save state file... + Savestate-Datei speichern... + + + Quick load Schnell laden - + Quick save Schnell speichern - + Load recent Lade zuletzt gespeicherten Savestate - + Save recent - Speichere aktuellen Stand + Speichere aktuellen Zustand - + Undo load state Laden des Savestate rückgängig machen - + F11 F11 - + Undo save state Speichern des Savestate rückgängig machen - + Shift+F11 Umschalt+F11 - - + + State &%1 Savestate &%1 - + F%1 F%1 - + Shift+F%1 Umschalt+F%1 - + + Load camera image... + Lade Kamerabild... + + + Import GameShark Save Importiere GameShark-Speicherstand - + Export GameShark Save Exportiere GameShark-Speicherstand - + New multiplayer window Neues Multiplayer-Fenster - + About Über - + E&xit &Beenden - + &Emulation &Emulation - + &Reset Zu&rücksetzen - + Ctrl+R Strg+R - + Sh&utdown Schli&eßen - + Yank game pak Spielmodul herausziehen - + &Pause &Pause - + Ctrl+P Strg+P - + &Next frame &Nächstes Bild - + Ctrl+N Strg+N - + Fast forward (held) Schneller Vorlauf (gehalten) - + &Fast forward Schneller &Vorlauf - + Shift+Tab Umschalt+Tab - + Fast forward speed Vorlauf-Geschwindigkeit - + Unbounded Unbegrenzt - + %0x %0x - + Rewind (held) Zurückspulen (gehalten) - + Re&wind Zur&ückspulen - + ~ ~ - + Step backwards Schrittweiser Rücklauf - + Ctrl+B Strg+B - + Sync to &video Mit &Video synchronisieren - + Sync to &audio Mit &Audio synchronisieren - + Solar sensor Solar-Sensor - + Increase solar level Sonnen-Level erhöhen - + Decrease solar level Sonnen-Level verringern - + Brightest solar level Hellster Sonnen-Level - + Darkest solar level Dunkelster Sonnen-Level - + Brightness %1 Helligkeit %1 - + Audio/&Video Audio/&Video - + Frame size Bildgröße - + %1x %1x - + Toggle fullscreen Vollbildmodus umschalten - + Lock aspect ratio Seitenverhältnis korrigieren - + Force integer scaling Pixelgenaue Skalierung (Integer scaling) - + Frame&skip Frame&skip - - Shader options... - Shader-Optionen... - - - + Mute Stummschalten - + FPS target Bildwiederholrate - - 15 - 15 - - - - 30 - 30 - - - - 45 - 45 - - - - Native (59.7) - Nativ (59.7) - - - - 60 - 60 - - - - 90 - 90 - - - - 120 - 120 - - - - 240 - 240 - - - + Take &screenshot &Screenshot erstellen - + F12 F12 - + Record output... Ausgabe aufzeichen... - + Record GIF... GIF aufzeichen... - + Record video log... Video-Log aufzeichnen... - + Stop video log Video-Log beenden - + + Game Boy Printer... + Game Boy Printer... + + + Video layers Video-Ebenen - + Audio channels Audio-Kanäle - + + Adjust layer placement... + Lage der Bildebenen anpassen... + + + &Tools &Werkzeuge - + View &logs... &Logs ansehen... - + Game &overrides... Spiel-&Überschreibungen... - + Game &Pak sensors... Game &Pak-Sensoren... - + &Cheats... &Cheats... - + Open debugger console... - Debugger-Konsole äffnen... + Debugger-Konsole öffnen... - + Start &GDB server... &GDB-Server starten... - + Settings... Einstellungen... - + Select folder Ordner auswählen - + Add folder to library... Ordner zur Bibliothek hinzufügen... - + Bilinear filtering Bilineare Filterung - + + Native (59.7275) + Nativ (59.7275) + + + View &palette... &Palette betrachten... - + View &sprites... &Sprites betrachten... - + View &tiles... &Tiles betrachten... - + + View &map... + &Map betrachten... + + + View memory... Speicher betrachten... - + Search memory... Speicher durchsuchen... - + View &I/O registers... &I/O-Register betrachten... - + Exit fullscreen Vollbildmodus beenden - + + GameShark Button (held) + GameShark-Taste (gehalten) + + + Autofire Autofeuer - + Autofire A Autofeuer A - + Autofire B Autofeuer B - + Autofire L Autofeuer L - + Autofire R Autofeuer R - + Autofire Start Autofeuer Start - + Autofire Select Autofeuer Select - + Autofire Up Autofeuer nach oben - + Autofire Right Autofeuer rechts - + Autofire Down Autofeuer nach unten - + Autofire Left Autofeuer links @@ -3792,39 +4008,39 @@ dd/mm/yy hh:mm:ss - + Light sensor Lichtsensor - + Brightness Helligkeit - + Tilt sensor Neigungssensor - - + + Set Y Setze Y - - + + Set X Setze X - + Gyroscope Gyroskop - + Sensitivity Empfindlichkeit @@ -3857,240 +4073,352 @@ Verzeichnisse - + + Game Boy + Game Boy + + + Audio driver: Audio-Treiber: - + Audio buffer: Audio-Puffer: - - + + 1536 1536 - + 512 512 - + 768 768 - + 1024 1024 - + 2048 2048 - + 3072 3072 - + 4096 4096 - + samples Samples - + Sample rate: Abtastrate: - - + + 44100 44100 - + 22050 22050 - + 32000 32000 - + 48000 48000 - + Hz Hz - + Volume: Lautstärke: - + + Mute Stummschalten - + + Fast forward volume: + Vorspul-Lautstärke: + + + Display driver: Anzeige-Treiber: - + Frameskip: Frameskip: - + Skip every - Alle + Überspringe - - + + frames - Bilder + Bild(er) - + FPS target: Bildwiederholrate: - + frames per second Bilder pro Sekunde - + Sync: Synchronisierung: - + Video Video - + Audio Audio - + Lock aspect ratio Seitenverhältnis korrigieren - + Force integer scaling Erzwinge pixelgenaue Skalierung (Integer scaling) - + Language Sprache - + English Englisch - + List view Listenansicht - + Tree view Baumansicht - + + Show FPS in title bar + Bildwiederholrate in der Titelleiste anzeigen + + + + Automatically save cheats + Cheats automatisch speichern + + + + Automatically load cheats + Cheats automatisch laden + + + + Automatically save state + Zustand (Savestate) automatisch speichern + + + + Automatically load state + Zustand (Savestate) automatisch laden + + + + Cheats + Cheats + + + + Game Boy model + Game Boy-Modell + + + + + + Autodetect + Automatisch erkennen + + + + + + Game Boy (DMG) + Game Boy (DMG) + + + + + + Super Game Boy (SGB) + Super Game Boy (SGB) + + + + + + Game Boy Color (CGB) + Game Boy Color (CGB) + + + + + + Game Boy Advance (AGB) + Game Boy Advance (AGB) + + + + Super Game Boy model + Super Game Boy-Modell + + + + Game Boy Color model + Game Boy Color-Modell + + + + Default BG colors: + Standard-Hintergrundfarben: + + + + Default sprite colors 1: + Standard-Sprite-Farben 1: + + + + Default sprite colors 2: + Standard-Sprite-Farben 2: + + + + Super Game Boy borders + Super Game Boy-Rahmen + + + + Camera driver: + Kamera-Treiber: + + + Library: Bibliothek: - + Show when no game open Anzeigen, wenn kein Spiel geöffnet ist - + Clear cache Cache leeren - + Fast forward speed: Vorlauf-Geschwindigkeit: - - Rewind affects save data - Rücklauf beeinflusst -Speicherdaten - - - + Preload entire ROM into memory ROM-Datei vollständig in Arbeitsspeicher vorladen - - - - - - - + + + + + + + + + Browse Durchsuchen - + Use BIOS file if found BIOS-Datei verwenden, wenn vorhanden - + Skip BIOS intro BIOS-Intro überspringen - + × × - + Unbounded unbegrenzt - + Suspend screensaver Bildschirmschoner deaktivieren @@ -4100,118 +4428,129 @@ BIOS - + Pause when inactive Pause, wenn inaktiv - + Run all Alle ausführen - + Remove known Bekannte entfernen - + Detect and remove Erkennen und entfernen - + Allow opposing input directions Gegensätzliche Eingaberichtungen erlauben - - + + Screenshot Screenshot - - + + Save data Speicherdaten - - + + Cheat codes Cheat-Codes - + Enable rewind Rücklauf aktivieren - + Bilinear filtering Bilineare Filterung - + Rewind history: Rücklauf-Verlauf: - + Idle loops: Leerlaufprozesse: - + Savestate extra data: Zusätzliche Savestate-Daten: - + Load extra data: Lade zusätzliche Daten: - + + Autofire interval: + Autofeuer-Intervall: + + + GB BIOS file: Datei mit GB-BIOS: - + GBA BIOS file: Datei mit GBA-BIOS: - + GBC BIOS file: Datei mit GBC-BIOS: - + + SGB BIOS file: + Datei mit SGB-BIOS: + + + Save games Spielstände - - - - + + + + + Same directory as the ROM Verzeichnis der ROM-Datei - + Save states Savestates - + Screenshots Screenshots - + Patches Patches @@ -4285,17 +4624,17 @@ Tiles - + 256 colors 256 Farben - + × × - + Magnification Vergrößerung @@ -4328,47 +4667,12 @@ Vorgaben - - High Quality - Hohe Qualität - - - - YouTube - YouTube - - WebM WebM - - Lossless - Verlustfrei - - - - 1080p - 1080p - - - - 720p - 720p - - - - 480p - 480p - - - - Native - Nativ - - Format Format @@ -4389,31 +4693,66 @@ MP4 - - PNG - PNG + + High &Quality + Hohe &Qualität - + + &YouTube + &YouTube + + + + &Lossless + Ver&lustfrei + + + + &1080p + &1080p + + + + &720p + &720p + + + + &480p + &480p + + + + &Native + &Nativ + + + h.264 h.264 - + h.264 (NVENC) h.264 (NVENC) - + HEVC HEVC - + VP8 VP8 + + VP9 + VP9 + + FFV1 FFV1 @@ -4459,32 +4798,32 @@ VBR - + ABR ABR - + Dimensions Abmessungen - + : : - + × × - + Lock aspect ratio Seitenverhältnis sperren - + Show advanced Erweiterte Optionen anzeigen diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ts/mgba-es.ts mgba-0.7.0/src/platform/qt/ts/mgba-es.ts --- mgba-0.6.3+dfsg1/src/platform/qt/ts/mgba-es.ts 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ts/mgba-es.ts 2019-01-27 00:06:06.000000000 +0000 @@ -72,49 +72,55 @@ AssetTile - + AssetTile AssetTile - + Tile # Tile Nº - + + 0 0 - + + Palette # + Paleta Nº + + + Address Dirección - + 0x06000000 0x06000000 - + Red Rojo - + Green Verde - + Blue Azul - - - + + + 0x00 (00) 0x00 (00) @@ -162,7 +168,7 @@ Enter command (try `help` for more info) - Ingresa un comando (intenta `help` para más información) + Ingresa un comando (prueba con `help` para más información) @@ -455,6 +461,29 @@ + MapView + + + Maps + Mapas + + + + × + x + + + + Magnification + Ampliación + + + + Export + Exportar + + + MemorySearch @@ -493,62 +522,88 @@ Texto - + Width Ancho - + 1 Byte (8-bit) 1 byte (8 bits) - + 2 Bytes (16-bit) 2 bytes (16 bits) - + 4 Bytes (32-bit) 4 bytes (32 bits) - + Number type Tipo de número - + Hexadecimal Hexadecimal - + Decimal Decimal - + + Guess Adivinar - + + Compare + Comparar + + + + Equal + Igual a + + + + Greater + Mayor que + + + + Less + Menor que + + + + Delta + Diferencia + + + Search Buscar - + Search Within Buscar dentro - + Open in Memory Viewer Abrir en el Visor de memoria - + Refresh Actualizar @@ -793,7 +848,7 @@ - + Autodetect Detección automática @@ -829,7 +884,7 @@ - + None Ninguno @@ -880,63 +935,92 @@ + Super Game Boy (SGB) + + + + Game Boy Color (CGB) Game Boy Color (CGB) - + Game Boy Advance (AGB) Game Boy Advance (AGB) - + Memory bank controller Controlador de bancos de memoria - + MBC1 MBC1 - + MBC2 MBC2 - + MBC3 MBC3 - + MBC3 + RTC MBC3 + RTC - + MBC5 MBC5 - + MBC5 + Rumble MBC5 + Rumble - + MBC7 MBC7 - + + Pocket Cam + + + + + TAMA5 + + + + HuC-3 HuC-3 - + + Background Colors + Colores de fondo + + + + Sprite Colors 1 + Colores de sprite 1 + + + + Sprite Colors 2 + Colores de sprite 2 + + Colors - Colores + Colores @@ -1025,16 +1109,62 @@ + PlacementControl + + + Adjust placement + Ajustar ubicación + + + + All + Todo + + + + Offset + Compensación + + + + X + + + + + Y + + + + + PrinterView + + + Game Boy Printer + Game Boy Printer + + + + Hurry up! + ¡Apúrate! + + + + Tear off + Arrancar papel + + + QGBA::AssetTile - + %0%1%2 %0%1%2 - - - + + + 0x%0 (%1) 0x%0 (%1) @@ -1060,7 +1190,7 @@ QGBA::AudioProcessorQt - + Can't start an audio processor without input No se puede iniciar un procesador de audio sin entrada @@ -1068,7 +1198,7 @@ QGBA::AudioProcessorSDL - + Can't start an audio processor without input No se puede iniciar un procesador de audio sin entrada @@ -1081,7 +1211,7 @@ (sin título) - + Failed to open cheats file: %1 Error al abrir el archivo de trucos: %1 @@ -1117,6 +1247,37 @@ + QGBA::CoreController + + + Failed to open save file: %1 + Error al abrir el archivo de guardado: %1 + + + + Failed to open game file: %1 + Error al abrir el archivo del juego: %1 + + + + Failed to open snapshot file for reading: %1 + Error al leer del archivo de captura: %1 + + + + Failed to open snapshot file for writing: %1 + Error al escribir al archivo de captura: %1 + + + + QGBA::CoreManager + + + Failed to open game file: %1 + Error al abrir el archivo del juego: %1 + + + QGBA::GBAKeyEditor @@ -1185,17 +1346,17 @@ QGBA::GIFView - + Failed to open output GIF file: %1 Error al abrir el archivo GIF de salida: %1 - + Select output file Seleccionar archivo de salida - + Graphics Interchange Format (*.gif) Graphics Interchange Format (*.gif) @@ -1203,30 +1364,24 @@ QGBA::GameController - - Failed to open game file: %1 - Error al abrir el archivo del juego: %1 + Error al abrir el archivo del juego: %1 - Failed to open save file: %1 - Error al abrir el archivo de guardado: %1 + Error al abrir el archivo de guardado: %1 - Failed to open snapshot file for reading: %1 - Error al leer del archivo de captura: %1 + Error al leer del archivo de captura: %1 - Failed to open snapshot file for writing: %1 - Error al escribir al archivo de captura: %1 + Error al escribir al archivo de captura: %1 - Failed to start audio processor - Error al iniciar el procesador de audio + Error al iniciar el procesador de audio @@ -2609,27 +2764,27 @@ QGBA::LoadSaveState - + Load State Cargar estado - + Save State Guardar estado - + Empty Vacío - + Corrupted Dañado - + Slot %1 Espacio %1 @@ -2637,42 +2792,90 @@ QGBA::LogController - + DEBUG DEPURACIÓN - + STUB STUB - + INFO INFORMACIÓN - + WARN ADVERTENCIA - + ERROR ERROR - + FATAL FATAL - + GAME ERROR ERROR DE JUEGO + QGBA::MapView + + + Map Addr. + Dir de mapa + + + + Mirror + Espejar + + + + None + Ninguno + + + + Both + Ambos + + + + Horizontal + Horizontal + + + + Vertical + Vertical + + + + Export map + Exportar mapa + + + + Portable Network Graphics (*.png) + Gráficos de red portátiles (*.png) + + + + Failed to open output PNG file: %1 + Error al abrir el archivo PNG de salida: %1 + + + QGBA::MemoryModel @@ -2696,7 +2899,6 @@ - All Todo @@ -2706,32 +2908,32 @@ Cargar TBL - + Save selected memory Guardar memoria seleccionada - + Failed to open output file: %1 Error al abrir el archivo de salida: %1 - + Load memory Cargar memoria - + Failed to open input file: %1 Error al abrir el archivo de entrada: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -2739,77 +2941,89 @@ QGBA::MemorySearch - + + (%0/%1×) + (%0/%1×) + + + (⅟%0×) (⅟%0×) - + + (%0×) + (%0×) + + + + %1 byte%2 + %1 byte%2 + + 1 byte%0 - 1 byte%0 + 1 byte%0 - 2 bytes%0 - 2 bytes%0 + 2 bytes%0 - 4 bytes%0 - 4 bytes%0 + 4 bytes%0 QGBA::ObjView - - + + 0x%0 0x%0 - + Off No - + Normal Normal - + Trans Trans - + OBJWIN OBJWIN - + Invalid Inválido - - + + N/A n/d - + Export sprite Exportar sprite - + Portable Network Graphics (*.png) Portable Network Graphics (*.png) - + Failed to open output PNG file: %1 Error al abrir el archivo PNG de salida: %1 @@ -2817,62 +3031,75 @@ QGBA::PaletteView - + #%0 #%0 - + 0x%0 0x%0 - + %0 %0 - + 0x%0 (%1) 0x%0 (%1) - + Export palette Exportar paleta - + Windows PAL (*.pal);;Adobe Color Table (*.act) Windows PAL (*.pal);;Adobe Color Table (*.act) - + Failed to open output palette file: %1 Error al abrir el archivo de paleta de salida: %1 + QGBA::PrinterView + + + Save Printout + Guardar impresión + + + + Portable Network Graphics (*.png) + Gráficos de red portátiles (*.png) + + + QGBA::ROMInfo - - - - - + + + + + (unknown) (desconocido) - - + + bytes bytes - + (no database present) (no hay base de datos) @@ -2880,52 +3107,59 @@ QGBA::SettingsView - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forzar versión 1.x) - + + None (Still Image) + Nada (imagen estática) + + + Keyboard Teclado - + Controllers Controladores - + Shortcuts Atajos de teclado - + + Shaders Shaders - + Select BIOS Seleccionar BIOS @@ -2984,17 +3218,17 @@ QGBA::VideoView - + Failed to open output video file: %1 Error al abrir el archivo de video de salida: %1 - + Native (%0x%1) Native (%0x%1) - + Select output file Seleccionar archivo de salida @@ -3002,87 +3236,108 @@ QGBA::Window - + Game Boy Advance ROMs (%1) ROMs de Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs de Game Boy (%1) - + All ROMs (%1) Todas las ROMs (%1) - + %1 Video Logs (*.mvl) Video-registros de %1 (*.mvl) - + Archives (%1) Contenedores (%1) - - - + + + Select ROM Seleccionar ROM - + Select folder Seleccionar carpeta - + Game Boy Advance save files (%1) Archivos de guardado de Game Boy Advance (%1) - - - + + + Select save Seleccionar guardado - + + mGBA savestate files (%1) + Archivos de estado de guardado de mGBA (%1) + + + + + Select savestate + Elegir estado de guardado + + + Select patch Seleccionar parche - + Patches (*.ips *.ups *.bps) Parches (*.ips *.ups *.bps) - - + + Select image + Seleccionar imagen + + + + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) + Archivo de imagen (*.png *.gif *.jpg *.jpeg);;Todos los archivos (*) + + + + GameShark saves (*.sps *.xps) Guardados de GameShark (*.sps *.xps) - + Select video log Seleccionar video-registro - + Video logs (*.mvl) Video-registros (*.mvl) - + Crash Error fatal - + The game has crashed with the following error: %1 @@ -3091,618 +3346,655 @@ %1 - + Couldn't Load No se pudo cargar - + Could not load game. Are you sure it's in the correct format? No se pudo cargar el juego. ¿Estás seguro de que está en el formato correcto? - + Unimplemented BIOS call Llamada a BIOS no implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este juego utiliza una llamada al BIOS que no se ha implementado. Utiliza el BIOS oficial para obtener la mejor experiencia. - + Really make portable? ¿Hacer "portable"? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Esto hará que el emulador cargue su configuración desde el mismo directorio que el ejecutable. ¿Quieres continuar? - + Restart needed Reinicio necesario - + Some changes will not take effect until the emulator is restarted. Algunos cambios no surtirán efecto hasta que se reinicie el emulador. - + - Player %1 of %2 - Jugador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Archivo - + Load &ROM... Cargar &ROM... - + Load ROM in archive... Cargar ROM desde contenedor... - + Add folder to library... Agregar carpeta a la biblioteca... - + + Load alternate save... + Cargar guardado alternativo... + + + Load temporary save... Cargar guardado temporal... - + Load &patch... Cargar &parche... - + Boot BIOS Arrancar BIOS - + Replace ROM... Reemplazar ROM... - + ROM &info... &Información de la ROM... - + Recent Recientes - + Make portable Hacer "portable" - + &Load state Ca&rgar estado - + F10 F10 - + + Load state file... + Cargar archivo de estado... + + + &Save state Guardar e&stado - + Shift+F10 Shift+F10 - + + Save state file... + Guardar archivo de estado... + + + Quick load Cargado rápido - + Quick save Guardado rápido - + Load recent Cargar reciente - + Save recent Guardar reciente - + Undo load state Deshacer cargar estado - + F11 F11 - + Undo save state Deshacer guardar estado - + Shift+F11 Shift+F11 - - + + State &%1 Estado &%1 - + F%1 F%1 - + Shift+F%1 Shift+F%1 - + + Load camera image... + Cargar imagen para la cámara... + + + Import GameShark Save Importar guardado de GameShark - + Export GameShark Save Exportar guardado de GameShark - + New multiplayer window Nueva ventana multijugador - + About Acerca de - + E&xit Salir (&X) - + &Emulation &Emulación - + &Reset &Reinicializar - + Ctrl+R Ctrl+R - + Sh&utdown Apagar (&U) - + Yank game pak Tirar del cartucho - + &Pause &Pausar - + Ctrl+P Ctrl+P - + &Next frame Cuadro siguie&nte - + Ctrl+N Ctrl+N - + Fast forward (held) Avance rápido (mantener) - + &Fast forward &Avance rápido - + Shift+Tab Shift+Tab - + Fast forward speed Velocidad de avance rápido - + Unbounded Sin límite - + %0x %0x - + Rewind (held) Rebobinar (mantener) - + Re&wind Re&bobinar - + ~ ~ - + Step backwards Paso hacia atrás - + Ctrl+B Ctrl+B - + Sync to &video Sincronizar a &video - + Sync to &audio Sincronizar a au&dio - + Solar sensor Sensor solar - + Increase solar level Subir nivel - + Decrease solar level Bajar nivel - + Brightest solar level Más claro - + Darkest solar level Más oscuro - + Brightness %1 Brillo %1 - + Audio/&Video Audio/&video - + Frame size Tamaño del cuadro - + %1x %1x - + Toggle fullscreen Pantalla completa - + Lock aspect ratio Bloquear proporción de aspecto - + Force integer scaling Forzar escala a enteros - + Bilinear filtering Filtro bilineal - + Frame&skip &Salto de cuadros - + Mute Silenciar - + FPS target Objetivo de FPS - + + Native (59.7275) + Nativo (59,7275) + + 15 - 15 + 15 - 30 - 30 + 30 - 45 - 45 + 45 - Native (59.7) - Nativo (59.7) + Nativo (59.7) - 60 - 60 + 60 - 90 - 90 + 90 - 120 - Bilineal120 + Bilineal120 - 240 - 240 + 240 - + Take &screenshot Tomar pan&tallazo - + F12 F12 - + Record output... Grabar salida... - + Record GIF... Grabar GIF... - + Record video log... Grabar video-registro... - + Stop video log Detener video-registro - + + Game Boy Printer... + Game Boy Printer... + + + Video layers Capas de video - + Audio channels Canales de audio - + + Adjust layer placement... + Ajustar ubicación de capas... + + + &Tools Herramien&tas - + View &logs... Ver re&gistros... - + Game &overrides... Ajustes específic&os por juego... - + Game &Pak sensors... Sensores del Game &Pak... - + &Cheats... Tru&cos... - + Settings... Ajustes... - + Open debugger console... Abrir consola de depuración... - + Start &GDB server... Iniciar servidor &GDB... - + View &palette... Ver &paleta... - + View &sprites... Ver &sprites... - + View &tiles... Ver &tiles... - + + View &map... + Ver &mapa... + + + View memory... Ver memoria... - + Search memory... Buscar memoria... - + View &I/O registers... Ver registros &I/O... - + Exit fullscreen Salir de pantalla completa - + + GameShark Button (held) + Botón GameShark (mantener) + + + Autofire Disparo automático - + Autofire A Disparo automático A - + Autofire B Disparo automático B - + Autofire L Disparo automático L - + Autofire R Disparo automático R - + Autofire Start Disparo automático Start - + Autofire Select Disparo automático Select - + Autofire Up Disparo automático Arriba - + Autofire Right Disparo automático Derecha - + Autofire Down Disparo automático Abajo - + Autofire Left Disparo automático Izquierda @@ -3821,39 +4113,39 @@ dd/MM/yy HH:mm:ss - + Light sensor Sensor de luz - + Brightness Brillo - + Tilt sensor Sensor de inclinación - - + + Set Y Ajustar Y - - + + Set X Ajustar X - + Gyroscope Giroscopio - + Sensitivity Sensibilidad @@ -3891,355 +4183,483 @@ Rutas - + + Game Boy + Game Boy + + + Audio driver: Sistema de audio: - + Audio buffer: Búfer de audio: - - + + 1536 1536 - + 512 512 - + 768 768 - + 1024 1024 - + 2048 2048 - + 3072 3072 - + 4096 4096 - + samples muestras - + Sample rate: Tasa de muestreo: - - + + 44100 44100 - + 22050 22050 - + 32000 32000 - + 48000 48000 - + Hz Hz - + Volume: Volumen: - + + Mute Silenciar - + + Fast forward volume: + Vol. durante av. rápido: + + + Display driver: Sistema de video: - + Frameskip: Salto de cuadros: - + Skip every Saltar cada - - + + frames cuadros - + FPS target: Objetivo de FPS: - + frames per second cuadros por segundo - + Sync: Sincronizar con: - + Video Video - + Audio Audio - + Lock aspect ratio Bloquear proporción de aspecto - + Bilinear filtering Filtro bilineal - + Force integer scaling - Forzar escala a enteros + Forzar escalado de enteros - + Language Idioma - + English English - + Library: Biblioteca: - + List view Lista - + Tree view Árbol - + Show when no game open Mostrar cuando no haya un juego abierto - + Clear cache Limpiar caché - + Allow opposing input directions Permitir direcciones opuestas al mismo tiempo - + Suspend screensaver Suspender protector de pantalla - + Pause when inactive Pausar al no estar activo - + + Show FPS in title bar + Mostrar FPS en la barra de título + + + + Automatically save cheats + Guardar trucos automáticamente + + + + Automatically load cheats + Cargar trucos automáticamente + + + + Automatically save state + Guardar estado automáticamente + + + + Automatically load state + Cargar estado automáticamente + + + Fast forward speed: Velocidad de avance rápido: - + × × - + Unbounded Sin límite - + Enable rewind Habilitar el rebobinar - + Rewind history: Historial de rebobinado: - + Idle loops: Bucles inactivos: - + Run all Ejecutarlos todos - + Remove known Eliminar los conocidos - + Detect and remove Detectar y eliminar - + Savestate extra data: Guardar datos extra con el estado: - - + + Screenshot Pantallazo - - + + Save data Datos de guardado - - + + Cheat codes Trucos - + Load extra data: Cargar datos extra con el estado: - Rewind affects save data - El rebobinar afecta los datos de guardado + El rebobinar afecta los datos de guardado - + Preload entire ROM into memory Cargar ROM completa a la memoria - + + Autofire interval: + Intervalo de disparo automático: + + + GB BIOS file: Archivo BIOS GB: - - - - - - - + + + + + + + + + Browse Examinar - + Use BIOS file if found Usar archivo BIOS si fue encontrado - + Skip BIOS intro Saltar animación de entrada del BIOS - + GBA BIOS file: Archivo BIOS GBA: - + GBC BIOS file: Archivo BIOS GBC: - + + SGB BIOS file: + SGB BIOS file: + + + Save games Datos de guardado - - - - + + + + + Same directory as the ROM Al mismo directorio que la ROM - + Save states Estados de guardado - + Screenshots Pantallazos - + Patches Parches + + + Cheats + Trucos + + + + Game Boy model + Modelo de Game Boy + + + + + + Autodetect + Detección automática + + + + + + Game Boy (DMG) + Game Boy (DMG) + + + + + + Super Game Boy (SGB) + + + + + + + Game Boy Color (CGB) + Game Boy Color (CGB) + + + + + + Game Boy Advance (AGB) + Game Boy Advance (AGB) + + + + Super Game Boy model + Modelo de Super Game Boy + + + + Game Boy Color model + Modelo de Game Boy Color + + + + Default BG colors: + Colores de fondo por defecto: + + + + Super Game Boy borders + Bordes de Super Game Boy + + + + Camera driver: + Controlador de cámara: + + + + Default sprite colors 1: + Colores de sprite 1 por defecto: + + + + Default sprite colors 2: + Colores de sprite 2 por defecto: + ShaderSelector @@ -4310,17 +4730,17 @@ Tiles - + 256 colors 256 colores - + × × - + Magnification Ampliación @@ -4353,14 +4773,12 @@ Ajustes predefinidos - High Quality - Alta calidad + Alta calidad - YouTube - YouTube + YouTube @@ -4369,29 +4787,24 @@ WebM - Lossless - Sin pérdidas + Sin pérdidas - 1080p - 1080p + 1080p - 720p - 720p + 720p - 480p - 480p + 480p - Native - Nativa + Nativa @@ -4414,31 +4827,70 @@ MP4 - PNG - PNG + PNG - + + High &Quality + Alta &calidad + + + + &YouTube + &YouTube + + + + &Lossless + Sin pér&didas + + + + &1080p + &1080p + + + + &720p + &720p + + + + &480p + &480p + + + + &Native + &NAtivo + + + h.264 h.264 - + h.264 (NVENC) h.264 (NVENC) - + HEVC HEVC - + VP8 VP8 + + VP9 + VP9 + + FFV1 FFV1 @@ -4484,32 +4936,32 @@ VBR - + ABR ABR - + Dimensions Dimensiones - + : : - + × × - + Lock aspect ratio Bloquear proporción de aspecto - + Show advanced Mostrar ajustes avanzados diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ts/mgba-fr.ts mgba-0.7.0/src/platform/qt/ts/mgba-fr.ts --- mgba-0.6.3+dfsg1/src/platform/qt/ts/mgba-fr.ts 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ts/mgba-fr.ts 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,4871 @@ + + + + + AboutScreen + + + About + A Propos De + + + + <a href="http://mgba.io/">Website</a> • <a href="https://forums.mgba.io/">Forums / Support</a> • <a href="https://patreon.com/mgba">Donate</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Source</a> + + + + + Branch: <tt>{gitBranch}</tt><br/>Revision: <tt>{gitCommit}</tt> + + + + + {projectName} + + + + + {projectName} would like to thank the following patrons from Patreon: + {projectName} aimerait remercier les donateurs suivant venant de Patreon : + + + + © 2013 – 2018 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 +Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + © 2013 – 2018 Jeffrey Pfau, est autorisé sous la license Publique de Mozilla, version 2.0 +Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. + + + + {projectVersion} + + + + + {logo} + + + + + {projectName} is an open-source Game Boy Advance emulator + {projectName} est un émulateur open-source Game Boy Advance + + + + {patrons} + + + + + ArchiveInspector + + + Open in archive... + Ouvrir dans l'archive... + + + + Loading... + Chargement... + + + + AssetTile + + + AssetTile + + + + + Tile # + + + + + + 0 + + + + + Palette # + + + + + Address + Adresse + + + + 0x06000000 + + + + + Red + Rouge + + + + Green + Vert + + + + Blue + Bleu + + + + + + 0x00 (00) + + + + + CheatsView + + + Cheats + Triches + + + + Remove + Enlever + + + + Save + Sauvegarder + + + + Load + Charger + + + + Add New Set + Ajouter un Nouveau Set + + + + Add + Ajouter + + + + DebuggerConsole + + + Debugger + Débugeur + + + + Enter command (try `help` for more info) + Entrer une commande (essayer `help` pour plus d'information) + + + + Break + Arrêter + + + + GIFView + + + Record GIF + Enregistrer un GIF + + + + Start + Démarrer + + + + Stop + Arrêter + + + + Select File + Chsoiir un fichier + + + + Frameskip + Saut d'image + + + + Frame delay (ms) + Retard Image + + + + Automatic + Automatique + + + + IOViewer + + + I/O Viewer + Visualiseur E/S + + + + 0x0000 + + + + + 2 + + + + + 5 + + + + + 4 + + + + + 7 + + + + + 0 + + + + + 9 + + + + + 1 + + + + + 3 + + + + + 8 + + + + + C + + + + + E + + + + + 6 + + + + + D + + + + + F + + + + + A + + + + + B + + + + + LibraryTree + + + Name + Nom + + + + Location + Localisation + + + + Platform + Plateforme + + + + Size + Taille + + + + CRC32 + + + + + LoadSaveState + + + + %1 State + %1 Etat + + + + + + + + + + + + No Save + Pas de Sauve + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + 9 + + + + + LogView + + + Logs + Enregistrements + + + + Enabled Levels + Niveaux Activés + + + + Debug + Débug + + + + Stub + + + + + Info + + + + + Warning + Avertissement + + + + Error + Erreur + + + + Fatal + + + + + Game Error + Erreur de Jeu + + + + Clear + Vider + + + + Max Lines + Lignes Max + + + + MapView + + + Maps + Définitions + + + + × + + + + + Magnification + + + + + Export + Exporter + + + + MemorySearch + + + Memory Search + Fouiller dans la Mémoire + + + + Address + Adresse + + + + Current Value + Valeur en cours + + + + + Type + + + + + Value + Valeur + + + + Numeric + Numérique + + + + Text + Texte + + + + Width + Longueur + + + + + Guess + Défaut + + + + 1 Byte (8-bit) + + + + + 2 Bytes (16-bit) + + + + + 4 Bytes (32-bit) + + + + + Number type + Nombre Type + + + + Decimal + Décimal + + + + Hexadecimal + Héxadécimal + + + + Compare + Comparer + + + + Equal + Egal + + + + Greater + Plus grand que + + + + Less + Moins + + + + Delta + + + + + Search + Rechercher + + + + Search Within + Rechercher dans + + + + Open in Memory Viewer + Ouvrir dans le Visualiseur + + + + Refresh + Rafraîchir + + + + MemoryView + + + Memory + Mémoire + + + + Inspect Address: + Examiner l'adresse : + + + + 0x + + + + + Set Alignment: + Choisir les alignements : + + + + 1 Byte + + + + + 2 Bytes + + + + + 4 Bytes + + + + + Unsigned Integer: + Entier non signé : + + + + Signed Integer: + Entier signé : + + + + String: + Chaîne : + + + + Load TBL + Charger TBL + + + + Copy Selection + Copier la Sélection + + + + Paste + Coller + + + + Save Selection + Sauvegarder la sélection + + + + Load + Charger + + + + ObjView + + + Sprites + + + + + + × + + + + + Magnification + + + + + Export + Exporter + + + + Attributes + Attributs + + + + Transform + Transformer + + + + Off + + + + + Palette + + + + + + + + 0 + + + + + Double Size + Taille Double + + + + + + + Return, Ctrl+R + + + + + Flipped + Inversé + + + + H + + + + + V + + + + + Mode + + + + + Normal + + + + + Mosaic + Mosaïque + + + + Enabled + Activé + + + + Priority + Priorité + + + + Tile + + + + + Geometry + Géomètrie + + + + Position + + + + + , + + + + + Dimensions + + + + + + 8 + + + + + Address + Adresse + + + + 0x07000000 + + + + + OverrideView + + + Game Overrides + Passer outre le jeu + + + + Game Boy Advance + + + + + + + + Autodetect + Détection Auto + + + + Realtime clock + Horloge en temps réel + + + + Gyroscope + + + + + Tilt + + + + + Light sensor + Détection de lumière + + + + Rumble + Vibration + + + + Save type + Type de Sauv + + + + + None + Aucune + + + + SRAM + + + + + Flash 512kb + + + + + Flash 1Mb + + + + + EEPROM + + + + + Idle loop + + + + + Game Boy Player features + Fonction Joueur Game Boy + + + + Game Boy + + + + + Game Boy model + Modèle de Game Boy + + + + Game Boy (DMG) + + + + + Super Game Boy (SGB) + + + + + Game Boy Color (CGB) + + + + + Game Boy Advance (AGB) + + + + + Memory bank controller + Contrôleur Banque Mémoire + + + + MBC1 + + + + + MBC2 + + + + + MBC3 + + + + + MBC3 + RTC + + + + + MBC5 + + + + + MBC5 + Rumble + MBC5 + Vibration + + + + MBC7 + + + + + Pocket Cam + + + + + TAMA5 + + + + + HuC-3 + + + + + Background Colors + Couleurs en arrière plan + + + + Sprite Colors 1 + Couleurs du Sprite 1 + + + + Sprite Colors 2 + Couleurs du Sprite 2 + + + + PaletteView + + + Palette + + + + + Background + Arrière plan + + + + Objects + Objets + + + + Selection + Sélection + + + + Red + Rouge + + + + Green + Vert + + + + Blue + Bleu + + + + + + 0x00 (00) + + + + + 16-bit value + Valeur 16-bit + + + + Hex code + Code Héxa + + + + Palette index + Index Palette + + + + 0x0000 + + + + + #000000 + + + + + 000 + + + + + Export BG + Exporter le BG + + + + Export OBJ + Exporter l'OBJ + + + + PlacementControl + + + Adjust placement + + + + + All + Tout + + + + Offset + + + + + X + + + + + Y + + + + + PrinterView + + + Game Boy Printer + Imprimante Game Boy + + + + Hurry up! + Vite ! + + + + Tear off + + + + + QGBA::AssetTile + + + %0%1%2 + + + + + + + 0x%0 (%1) + + + + + QGBA::AudioDevice + + + Can't set format of context-less audio device + + + + + Audio device is missing its core + + + + + Writing data to read-only audio device + + + + + QGBA::AudioProcessorQt + + + Can't start an audio processor without input + + + + + QGBA::AudioProcessorSDL + + + Can't start an audio processor without input + + + + + QGBA::CheatsModel + + + (untitled) + (sans titre) + + + + Failed to open cheats file: %1 + Echec de l'ouverture du fichier de triche : %1 + + + + QGBA::CheatsView + + + + Add GameShark + Ajouter GameShark + + + + Add Pro Action Replay + Ajouter Pro Action Replay + + + + Add CodeBreaker + Ajouter CodeBreaker + + + + Add GameGenie + Ajouter Game Génie + + + + + Select cheats file + Choisir un fichier de triches + + + + QGBA::CoreController + + + Failed to open save file: %1 + Echec de l'ouverture du fichier de sauvegarde : %1 + + + + Failed to open game file: %1 + Echec de l'ouverture du fichier jeu : %1 + + + + Failed to open snapshot file for reading: %1 + Echec de l'ouverture fichier de capture d'écran à lire : %1 + + + + Failed to open snapshot file for writing: %1 + Echec de l'ouverture du fichier de capture d'écran à écrire : %1 + + + + QGBA::CoreManager + + + Failed to open game file: %1 + Echec de l'ouverture du fichier de capture d'écran à lire : %1 + + + + QGBA::GBAKeyEditor + + + Clear Button + Bouton Vider + + + + Clear Analog + Vider Analog + + + + Refresh + Rafraîchir + + + + Set all + Tout sélectionner + + + + QGBA::GDBWindow + + + Server settings + + + + + Local port + + + + + Bind address + + + + + Break + Arrêter + + + + Stop + Arrêter + + + + Start + Démarrer + + + + Crash + Plantage + + + + Could not start GDB server + + + + + QGBA::GIFView + + + Failed to open output GIF file: %1 + Echec de l'ouverture du fichier de sortie GIF : %1 + + + + Select output file + Choisir le fichier de sortie + + + + Graphics Interchange Format (*.gif) + + + + + QGBA::IOViewer + + + Background mode + Mode en arrière plan + + + + Mode 0: 4 tile layers + Mode 0: 4 couches tile + + + + Mode 1: 2 tile layers + 1 rotated/scaled tile layer + Mode 1 : 2 couches tile + 1 couche tile en rotation/à l'échelle + + + + Mode 2: 2 rotated/scaled tile layers + Mode 2 : 2 couches tile en roation/à l'échelle + + + + Mode 3: Full 15-bit bitmap + Mode 3 : Bitmap complet 15-bit + + + + Mode 4: Full 8-bit bitmap + Mode 4 : Bitmap complet 8 bit + + + + Mode 5: Small 15-bit bitmap + Mode 5 : Bitmap réduit 15-bit + + + + CGB Mode + Mode CGB + + + + Frame select + Choisir l'image + + + + Unlocked HBlank + HBlank Débloqué + + + + Linear OBJ tile mapping + Définir le tile OBJ linèaire + + + + Force blank screen + Forcer l'écran vide + + + + Enable background 0 + Activer l'arrière plan 0 + + + + Enable background 1 + Activer l'arrière plan 1 + + + + Enable background 2 + Activer l'arrière plan 2 + + + + Enable background 3 + Activer l'arrière plan 3 + + + + Enable OBJ + Activer l'OBJ + + + + Enable Window 0 + Activer la fenêtre 0 + + + + Enable Window 1 + Actvier la fenêtre 1 + + + + Enable OBJ Window + Activer la fenêtre OBJ + + + + Currently in VBlank + Actuellement en VBlank + + + + Currently in HBlank + Actuellement en HBlank + + + + Currently in VCounter + Actuellement en VCounter + + + + Enable VBlank IRQ generation + Activer la génération de l'IRQ du VBlank + + + + Enable HBlank IRQ generation + Activer la génération de l'IRQ du HBlank + + + + Enable VCounter IRQ generation + Activer la génération de l'IRQ du VCounter + + + + VCounter scanline + Scanline du VCounter + + + + Current scanline + Scanline en cours + + + + + + + Priority + Priorité + + + + + + + Tile data base (* 16kB) + Base de donnée Tile (* 16kB) + + + + + + + Enable mosaic + Activer la mosaïque + + + + + + + Enable 256-color + Activer les 256 couleurs + + + + + + + Tile map base (* 2kB) + Base définie Tile (*x2kB) + + + + + + + Background dimensions + Dimensions de l'arrière plan + + + + + Overflow wraps + + + + + + + + Horizontal offset + + + + + + + + Vertical offset + + + + + + + + + + + + + + + + Fractional part + + + + + + + + + + + + Integer part + + + + + + + + Integer part (bottom) + + + + + + + + Integer part (top) + + + + + + End x + Fin x + + + + + Start x + Début x + + + + + End y + Fin y + + + + + Start y + Début y + + + + Window 0 enable BG 0 + La fenêtre 0 active BG 0 + + + + Window 0 enable BG 1 + La fenêtre 0 active BG 1 + + + + Window 0 enable BG 2 + La fenêtre 0 active BG 2 + + + + Window 0 enable BG 3 + La fenêtre 0 active BG 3 + + + + Window 0 enable OBJ + La fenêtre 0 active OBJ + + + + Window 0 enable blend + La fenêtre 0 active le blend + + + + Window 1 enable BG 0 + La fenêtre 1 active BG 0 + + + + Window 1 enable BG 1 + Fenêtre 1 active BG 1 + + + + Window 1 enable BG 2 + La fenêtre 1 active BG 2 + + + + Window 1 enable BG 3 + La fenêtre 1 active BG 3 + + + + Window 1 enable OBJ + La fenêtre 1 active OBJ + + + + Window 1 enable blend + La fenêtre 1 active le blend + + + + Outside window enable BG 0 + La fenêtre de sortie active le BG 0 + + + + Outside window enable BG 1 + La fenêtre de sortie active le BG 1 + + + + Outside window enable BG 2 + La fenêtre de sortie active le BG 2 + + + + Outside window enable BG 3 + La fenêtre de sortie active le BG 3 + + + + Outside window enable OBJ + La fenêtre de sortie active l'OBJ + + + + Outside window enable blend + La fenêtre de sortie active le blend + + + + OBJ window enable BG 0 + La fenêtre OBJ active le BG 0 + + + + OBJ window enable BG 1 + La fenêtre OBJ active le BG 1 + + + + OBJ window enable BG 2 + La fenêtre OBJ active le BG 2 + + + + OBJ window enable BG 3 + La fenêtre OBJ active le BG 3 + + + + OBJ window enable OBJ + La fenêtre OBJ active l'OBJ + + + + OBJ window enable blend + La fenêtre OBJ active le blend + + + + Background mosaic size vertical + Taille vertical de la mosaïque en arrière plan + + + + Background mosaic size horizontal + Taille horizontal de la mosaïque en arrière plan + + + + Object mosaic size vertical + Taille vertical de la mosaïque de l'objet + + + + Object mosaic size horizontal + Taille horizontal de la mosaïque de l'objet + + + + BG 0 target 1 + Cible 1 du BG 0 + + + + BG 1 target 1 + Cible 1 du BG 1 + + + + BG 2 target 1 + Cible 1 du BG 2 + + + + BG 3 target 1 + Cible 1 du BG 3 + + + + OBJ target 1 + Cible 1 de l'OBJ + + + + Backdrop target 1 + Cible 1 du backdrop + + + + Blend mode + Mode blend (mélange) + + + + Disabled + Désactivé + + + + Additive blending + Mélange additif + + + + Brighten + Eclairé + + + + Darken + Assombrie + + + + BG 0 target 2 + Cible 2 du BG 0 + + + + BG 1 target 2 + Cible 2 du BG 1 + + + + BG 2 target 2 + Cible 2 du BG 2 + + + + BG 3 target 2 + Cible 2 du BG 3 + + + + OBJ target 2 + Cible 2 de l'OBJ + + + + Backdrop target 2 + Cible 2 du Backdrop + + + + Blend A (target 1) + Blend A (cible 1) + + + + Blend B (target 2) + Blend A (cible 2) + + + + Blend Y + + + + + Sweep shifts + + + + + Sweep subtract + + + + + Sweep time (in 1/128s) + + + + + + + + Sound length + Longueur du son + + + + + Duty cycle + Cycle de la tâche + + + + + + Envelope step time + + + + + + + Envelope increase + Augmenter l'enveloppe + + + + + + Initial volume + Volume initiale + + + + + + Sound frequency + Fréquence du son + + + + + + + Timed + Compté + + + + + + + Reset + Redémarrer + + + + Double-size wave table + Taille double de la table wave + + + + Active wave table + Activer la table wave + + + + Enable channel 3 + Activer le canal 3 + + + + Volume + + + + + 0% + + + + + + 100% + + + + + + 50% + + + + + + 25% + + + + + + + + 75% + + + + + Clock divider + Divison de l'horloge + + + + Register stages + + + + + 15 + + + + + 7 + + + + + Shifter frequency + + + + + PSG volume right + Volume droit PSG + + + + PSG volume left + Volume gauche PSG + + + + Enable channel 1 right + Activer le canal 1 à droite + + + + Enable channel 2 right + Activer le canal 2 à droite + + + + Enable channel 3 right + Activer le canal 3 à droite + + + + Enable channel 4 right + Activer le canal 4 à droite + + + + Enable channel 1 left + Activer le canal 1 à gauche + + + + Enable channel 2 left + Activer le canal 2 à gauche + + + + Enable channel 3 left + Activer le canal 3 à gauche + + + + Enable channel 4 left + Activer le canal 4 à gauche + + + + PSG master volume + Volume maître PSG + + + + Loud channel A + Canal fort A + + + + Loud channel B + Canal fort B + + + + Enable channel A right + Activer le canal A de droite + + + + Enable channel A left + Activer le canal A de gauche + + + + Channel A timer + Compteur du canal A + + + + + 0 + + + + + + + + + + + + + 1 + + + + + Channel A reset + Redémarrer la canal A + + + + Enable channel B right + Activer le canal B de droite + + + + Enable channel B left + Activer le canal B de gauche + + + + Channel B timer + Compteur du canal B + + + + Channel B reset + Redémarrer la canal B + + + + Active channel 1 + Activer le canal 1 + + + + Active channel 2 + Activer le canal 2 + + + + Active channel 3 + Activer le canal 3 + + + + Active channel 4 + Activer le canal 4 + + + + Enable audio + Activer l'audio + + + + Bias + + + + + Resolution + Résolution + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sample + Echantillon + + + + + + + + + + + Address (bottom) + Adresse (en bas) + + + + + + + + + + + Address (top) + Adresse (en haut) + + + + + + + Word count + Compteur de Word + + + + + + + Destination offset + + + + + + + + + + + + Increment + Incrémenter + + + + + + + + + + + Decrement + Decrémenter + + + + + + + + + + + Fixed + Corrigé + + + + + + + Increment and reload + Incrémenter et recharger + + + + + + + Source offset + + + + + + + + Repeat + Répèter + + + + + + + 32-bit + + + + + + + + Start timing + Commencer le timing + + + + + + + Immediate + Immédiat + + + + + + + + + VBlank + + + + + + + + + + HBlank + + + + + + + + + + + + + IRQ + + + + + + + + + + + + Enable + Activer + + + + + + Audio FIFO + + + + + Video Capture + Capture Vidéo + + + + DRQ + + + + + + + + Value + Valeur + + + + + + + Scale + Echelle + + + + + + + 1/64 + + + + + + + + 1/256 + + + + + + + + 1/1024 + + + + + + + Cascade + + + + + + A + + + + + + B + + + + + + Select + + + + + + Start + Démarrer + + + + + Right + Droite + + + + + Left + Gauche + + + + + Up + Haut + + + + + Down + Bas + + + + + R + + + + + + L + + + + + Condition + + + + + SC + + + + + SD + + + + + SI + + + + + SO + + + + + + VCounter + + + + + + Timer 0 + + + + + + Timer 1 + + + + + + Timer 2 + + + + + + Timer 3 + + + + + + SIO + + + + + + DMA 0 + + + + + + DMA 1 + + + + + + DMA 2 + + + + + + DMA 3 + + + + + + Keypad + + + + + + Gamepak + + + + + SRAM wait + + + + + + + + + 4 + + + + + + + + 3 + + + + + + + + + 2 + + + + + + + + + 8 + + + + + Cart 0 non-sequential + Cart 0 non-séquentiel + + + + Cart 0 sequential + Cart 0 séquentiel + + + + Cart 1 non-sequential + Cart 1 non-séquentiel + + + + Cart 1 sequential + Cart 1 séquentiel + + + + Cart 2 non-sequential + Cart 2 non-séquentiel + + + + Cart 2 sequential + Cart 2 séquentiel + + + + PHI terminal + + + + + Disable + Désactiver + + + + 4.19MHz + + + + + 8.38MHz + + + + + 16.78MHz + + + + + Gamepak prefetch + + + + + Enable IRQs + Activer les IRQs + + + + QGBA::KeyEditor + + + + --- + + + + + QGBA::LoadSaveState + + + Load State + Charger un Etat + + + + Save State + Sauvegarder un Etat + + + + Empty + Vide + + + + Corrupted + Corrompue + + + + Slot %1 + Emplacement %1 + + + + QGBA::LogController + + + DEBUG + + + + + STUB + + + + + INFO + + + + + WARN + AVERT + + + + ERROR + ERREUR + + + + FATAL + + + + + GAME ERROR + ERREUR JEU + + + + QGBA::MapView + + + Map Addr. + Définir l'Adre. + + + + Mirror + Symétrie + + + + None + Aucune + + + + Both + Les deux + + + + Horizontal + + + + + Vertical + + + + + Export map + Définir l'export + + + + Portable Network Graphics (*.png) + + + + + Failed to open output PNG file: %1 + Echec de l'ouverture du fichier de sortie PNG : %1 + + + + QGBA::MemoryModel + + + Copy selection + Copier la sélection + + + + Save selection + Sauvegarder la sélection + + + + Paste + Coller + + + + Load + Charger + + + + + All + Tout + + + + Load TBL + Charger le TBL + + + + Save selected memory + Sauvegarder la mémoire sélectionné + + + + Failed to open output file: %1 + Echec de l'ouverture du fichier de sortie : %1 + + + + Load memory + Charger la mémoire + + + + Failed to open input file: %1 + Echec de l'ouverture du fichier d'entrée : %1 + + + + TBL + + + + + ISO-8859-1 + + + + + QGBA::MemorySearch + + + (%0/%1×) + + + + + (⅟%0×) + + + + + (%0×) + + + + + %1 byte%2 + + + + + QGBA::ObjView + + + + 0x%0 + + + + + Off + + + + + Normal + + + + + Trans + + + + + OBJWIN + + + + + Invalid + Invalide + + + + + N/A + + + + + Export sprite + Exporter le Sprite + + + + Portable Network Graphics (*.png) + + + + + Failed to open output PNG file: %1 + Echec de l'ouverture du fichier d'entrée : %1 + + + + QGBA::PaletteView + + + #%0 + + + + + 0x%0 + + + + + %0 + + + + + + + 0x%0 (%1) + + + + + Export palette + Exporter la palette + + + + Windows PAL (*.pal);;Adobe Color Table (*.act) + + + + + Failed to open output palette file: %1 + Echec de l'ouberture du fichier de sortie de la palette : %1 + + + + QGBA::PrinterView + + + Save Printout + Sauvegarder l'impression + + + + Portable Network Graphics (*.png) + + + + + QGBA::ROMInfo + + + + + + + (unknown) + (inconnu) + + + + + bytes + + + + + (no database present) + (aucune base de donnée présente) + + + + QGBA::SettingsView + + + + Qt Multimedia + + + + + SDL + + + + + Software (Qt) + + + + + OpenGL + + + + + OpenGL (force version 1.x) + + + + + None (Still Image) + Aucune (encore l'image) + + + + Keyboard + Clavier + + + + Controllers + Contrôleurs + + + + Shortcuts + Raccourcis + + + + + Shaders + + + + + Select BIOS + Choisir le BIOS + + + + QGBA::ShaderSelector + + + No shader active + Aucun shader actif + + + + Load shader + Charger un shader + + + + No shader loaded + Aucun shader chargé + + + + by %1 + de %1 + + + + Preprocessing + Pré-traitement + + + + Pass %1 + Passe %1 + + + + QGBA::ShortcutController + + + Action + + + + + Keyboard + Clavier + + + + Gamepad + Manette de jeu + + + + QGBA::VideoView + + + Failed to open output video file: %1 + Echec de l'ouverture du fichier de sortie vidéo : %1 + + + + Native (%0x%1) + + + + + Select output file + Choisir le fichier de sortie + + + + QGBA::Window + + + Game Boy Advance ROMs (%1) + ROMs Game Boy Advance (%1) + + + + Game Boy ROMs (%1) + ROMs Game Boy (%1) + + + + All ROMs (%1) + Toutes les ROMs (%1) + + + + %1 Video Logs (*.mvl) + %1 enregistrements vidéo (*.mvl) + + + + Archives (%1) + + + + + + + Select ROM + Choisir une ROM + + + + Select folder + Choisir un dossier + + + + Game Boy Advance save files (%1) + Fichiers de sauvegarde Game Boy Advance (%1) + + + + + + Select save + Choisir une sauvegarde + + + + Select patch + Choisir un patch + + + + Patches (*.ips *.ups *.bps) + + + + + Select image + Choisir une image + + + + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) + fichier Image (*.png *.gif *.jpg *.jpeg);;Tous les fichiers (*) + + + + + GameShark saves (*.sps *.xps) + Sauvegardes GameShark (*.sps *.xps) + + + + Select video log + Choisir l'enregistrement vidéo + + + + Video logs (*.mvl) + Enregistrements Vidéo (*.mvl) + + + + Crash + Plantage + + + + The game has crashed with the following error: + +%1 + Le jeu a planté avec l'erreur suivante : + +%1 + + + + Couldn't Load + Ne peut pas charger + + + + Could not load game. Are you sure it's in the correct format? + Ne peut pas charger le jeu. Etes vous sûr que le format est correcte ? + + + + Unimplemented BIOS call + L'appel du bios n'est pas implémenté + + + + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. + Ce jeu utilises un appel du BIOS qui n'est pas implémenté. Veuillez utiliser un BIOS officeil pour une meilleure expèrience. + + + + Really make portable? + Le rendre vraiment portable ? + + + + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? + Ceci permettra à l'émulateur de charger la configuration depuis le même repértoire que le fichier exécutable. Souhaitez vous continuer ? + + + + Restart needed + Un redémarrage est nécessaire + + + + Some changes will not take effect until the emulator is restarted. + Certains changements ne prendront effet qu'après le redémarrage de l'émulateur. + + + + - Player %1 of %2 + - Joueur %1 of %2 + + + + %1 - %2 + + + + + %1 - %2 - %3 + + + + + %1 - %2 (%3 fps) - %4 + + + + + &File + &Fichier + + + + Load &ROM... + Charger une &ROM... + + + + Load ROM in archive... + Charger la ROM dans l'archive... + + + + Add folder to library... + Ajouter un dossier à la bibliothèque... + + + + Load alternate save... + + + + + Load temporary save... + Charger une sauvegarde temporaire... + + + + Load &patch... + Charger un &patch... + + + + Boot BIOS + Démarrer le BIOS + + + + Replace ROM... + Remplacer la ROM... + + + + ROM &info... + &Info sur la ROM... + + + + Recent + Récent + + + + Make portable + Rendre portable + + + + &Load state + &Charger un Etat + + + + F10 + + + + + &Save state + &Sauvegarder un Etat + + + + Shift+F10 + + + + + Quick load + Chargement rapide + + + + Quick save + Sauvegarde rapide + + + + Load recent + Charger un fichier récent + + + + Save recent + Sauvegarder un fichier récent + + + + Undo load state + Undo le chargement d'état + + + + F11 + + + + + Undo save state + Undo la sauvegarde d'état + + + + Shift+F11 + + + + + + State &%1 + Etat &%1 + + + + F%1 + + + + + Shift+F%1 + + + + + Load camera image... + Charger l'image de la caméra... + + + + Import GameShark Save + Importer une sauvegarde GameShark + + + + Export GameShark Save + Exporter une sauvegarde GameShark + + + + New multiplayer window + Nouvelle fenêtre multi joueur + + + + About + A propos de + + + + E&xit + Quitter + + + + &Emulation + + + + + &Reset + &Redémarrer + + + + Ctrl+R + + + + + Sh&utdown + Extin&ction + + + + Yank game pak + + + + + &Pause + + + + + Ctrl+P + + + + + &Next frame + &Image suivante + + + + Ctrl+N + + + + + Fast forward (held) + Avancée Rapide (maintenir) + + + + &Fast forward + A&vancée rapide + + + + Shift+Tab + + + + + Fast forward speed + Vitesse de l'avancée rapide + + + + Unbounded + Non lié + + + + %0x + + + + + Rewind (held) + Rembobiner (maintenir) + + + + Re&wind + Rem&bobiner + + + + ~ + + + + + Step backwards + + + + + Ctrl+B + + + + + Sync to &video + Synchro &vidéo + + + + Sync to &audio + Synchro &audio + + + + Solar sensor + Détection solaire + + + + Increase solar level + Augmenter le niveau solaire + + + + Decrease solar level + Diminuer le niveau solaire + + + + Brightest solar level + Eclaircier le niveau solaire + + + + Darkest solar level + Assombrir le niveau solaire + + + + Brightness %1 + Luminosité %1 + + + + Audio/&Video + Audio/&Vidéo + + + + Frame size + Taille de l'image + + + + %1x + + + + + Toggle fullscreen + Basculer en plein écran + + + + Lock aspect ratio + Bloquer les proportions + + + + Force integer scaling + Forcer la mise à l'échelle entier + + + + Bilinear filtering + Filtrage bilinèaire + + + + Frame&skip + &Saut d'image + + + + Mute + Muet + + + + FPS target + FPS cible + + + + 15 + + + + + 30 + + + + + 45 + + + + + Native (59.7) + + + + + 60 + + + + + 90 + + + + + 120 + + + + + 240 + + + + + Take &screenshot + Prendre une ca&pture d'écran + + + + F12 + + + + + Record output... + Enregistrer la sortie... + + + + Record GIF... + Enregistrer le GIF... + + + + Record video log... + Enregistrer l'enregsitrement vidéo... + + + + Stop video log + Arrêter l'enregistrement vidéo + + + + Game Boy Printer... + Imprimante GameBoy... + + + + Video layers + Couches vidéo + + + + Audio channels + Canaux audio + + + + Adjust layer placement... + + + + + &Tools + Ou&tils + + + + View &logs... + Voir les en&registrements... + + + + Game &overrides... + Passer &outre le jeu... + + + + Game &Pak sensors... + Détecteur Game &Pak... + + + + &Cheats... + Tri&ches... + + + + Settings... + Paramètres... + + + + Open debugger console... + Ouvrir la console de débug... + + + + Start &GDB server... + Démarrer le serveur &GDB... + + + + View &palette... + Voir la &palette... + + + + View &sprites... + Voir les &sprites... + + + + View &tiles... + Voir les &tiles... + + + + View &map... + Voir la &map... + + + + View memory... + Voir la mémoire... + + + + Search memory... + Fouiller la mémoire... + + + + View &I/O registers... + Voir les registres &E/S... + + + + Exit fullscreen + Quitter le plein écran + + + + GameShark Button (held) + Bouton GameShark (maintenir) + + + + Autofire + Tir Auto + + + + Autofire A + Tir Auto A + + + + Autofire B + Tir Auto B + + + + Autofire L + Autofire LL + + + + Autofire R + Tir Auto R + + + + Autofire Start + Tir Auto Start + + + + Autofire Select + Tir Auto Select + + + + Autofire Up + Tir Auto Haut + + + + Autofire Right + Tir Auto Droite + + + + Autofire Down + Tir Auto Bas + + + + Autofire Left + Tir Auto Gauche + + + + QObject + + + GBA + + + + + GB + + + + + ? + + + + + ROMInfo + + + ROM Info + Info ROM + + + + Game name: + Nom du Jeu : + + + + {NAME} + + + + + Internal name: + Nom Interne : + + + + {TITLE} + + + + + Game ID: + ID du jeu : + + + + {ID} + + + + + File size: + Taille du Fichier : + + + + {SIZE} + + + + + CRC32: + CRC32 : + + + + {CRC} + + + + + SensorView + + + Sensors + Détecteurs + + + + Realtime clock + Horloge en Temps Réel + + + + Fixed time + Correction de l'heure + + + + System time + Heure Système + + + + Start time at + Démarrer l'heure à + + + + Now + Maintenant + + + + MM/dd/yy hh:mm:ss AP + + + + + Light sensor + Détecteur de lumière + + + + Brightness + Luminosité + + + + Tilt sensor + Détecteur de Tilt + + + + + Set Y + Sélection Y + + + + + Set X + Sélection X + + + + Gyroscope + + + + + Sensitivity + Sensibilité + + + + SettingsView + + + Settings + Paramètres + + + + Audio/Video + Audio/Vidéo + + + + Interface + + + + + Emulation + + + + + BIOS + + + + + Paths + Chemins + + + + Game Boy + + + + + Audio driver: + Pilote Audio : + + + + Audio buffer: + Tampon Audio + + + + + 1536 + + + + + 512 + + + + + 768 + + + + + 1024 + + + + + 2048 + + + + + 3072 + + + + + 4096 + + + + + samples + Echantillons + + + + Sample rate: + Taux d'échantillonages + + + + + 44100 + + + + + 22050 + + + + + 32000 + + + + + 48000 + + + + + Hz + + + + + Volume: + Volume : + + + + Mute + Muet + + + + Display driver: + Pilote d'affichage : + + + + Frameskip: + Saut d'image : + + + + Skip every + Passer toutes les + + + + + frames + images + + + + FPS target: + FPS cible : + + + + frames per second + imaes par secondes + + + + Sync: + Synchro : + + + + Video + Vidéo + + + + Audio + + + + + Lock aspect ratio + Bloquer les proportions + + + + Bilinear filtering + Filtrage bilinèaire + + + + Force integer scaling + Forcer la mise à l'échelle en entier + + + + Language + Langue + + + + English + Anglais + + + + Library: + Bibliothèque : + + + + List view + Voir la liste + + + + Tree view + Voir l'arbre + + + + Show when no game open + Afficher quand aucun jeu est ouvert + + + + Clear cache + Vider le cache + + + + Allow opposing input directions + Autoriser les directions opposées + + + + Suspend screensaver + Suspendre l'écran de veille + + + + Pause when inactive + Mettre en pause si inactif + + + + Show FPS in title bar + Afficher les FPS dans la barre de titre + + + + Automatically save cheats + Sauvegarder automatiquement les triches + + + + Automatically load cheats + Charger automatiquement les triches + + + + Automatically save state + Sauvegarder automatiquement l'état + + + + Automatically load state + Charger automatiquement l'état + + + + Fast forward speed: + Vitesse de l'Avance rapide : + + + + × + + + + + Unbounded + Non lié + + + + Enable rewind + Activer le rembobinage + + + + Rewind history: + Historique du rembobinage : + + + + Idle loops: + Boucles en veille : + + + + Run all + Tout lancer + + + + Remove known + Enlever le connu + + + + Detect and remove + Détecter et enlever + + + + Savestate extra data: + Donnée supplèm. Sauve. Etat : + + + + + Screenshot + Capture d'écran + + + + + Save data + Sauvegarder les données + + + + + Cheat codes + Codes de triches + + + + Load extra data: + Charger les données supplèm. : + + + + Rewind affects save data + Rembobiner données sauveg. + + + + Preload entire ROM into memory + Précharger la mémoire complète dans la ROM + + + + Autofire interval: + Intervalle du Tir Auto : + + + + GB BIOS file: + Fichier BIOS GB : + + + + + + + + + + + + Browse + Parcourir + + + + Use BIOS file if found + Utiliser le fichier BIOS si trouvé + + + + Skip BIOS intro + Passer l'intro du BIOS + + + + GBA BIOS file: + Fichier BIOS GBA : + + + + GBC BIOS file: + Fichier BIOS GBC : + + + + SGB BIOS file: + Fichier BIOS SGB : + + + + Save games + Jeu Sauvega. + + + + + + + + Same directory as the ROM + Même répertoire que la ROM + + + + Save states + Sauve. Etat + + + + Screenshots + Capture Ecran + + + + Patches + + + + + Cheats + Triches + + + + Game Boy model + Modèle de GameBoy + + + + + + Autodetect + Détection Automatique + + + + + + Game Boy (DMG) + + + + + + + Super Game Boy (SGB) + + + + + + + Game Boy Color (CGB) + + + + + + + Game Boy Advance (AGB) + + + + + Super Game Boy model + + + + + Game Boy Color model + + + + + Default BG colors: + Couleurs BG par défaut : + + + + Super Game Boy borders + Bordures Super Game Boy + + + + Camera driver: + Pilote de la Camèra : + + + + Default sprite colors 1: + Couleurs Sprites 1 : + + + + Default sprite colors 2: + Couleurs Sprites 2 : + + + + ShaderSelector + + + Shaders + + + + + Active Shader: + Sahder actif : + + + + Name + Nom + + + + Author + Auteur + + + + Description + + + + + Unload Shader + Décharger le Shader + + + + Load New Shader + Charger nouveau shader + + + + ShortcutView + + + Edit Shortcuts + Editer le raccourci + + + + Keyboard + Clavier + + + + Gamepad + Manette de jeu + + + + Clear + Vider + + + + TileView + + + Tiles + + + + + 256 colors + 256 couleurs + + + + × + + + + + Magnification + + + + + VideoView + + + Record Video + Enregistrer la vidéo + + + + Start + Démarrer + + + + Stop + Arrêter + + + + Select File + Choix Fichier + + + + Presets + Préréglages + + + + High Quality + Haute qualité + + + + YouTube + + + + + + WebM + + + + + Lossless + + + + + 1080p + + + + + 720p + + + + + 480p + + + + + Native + Natif + + + + Format + + + + + MKV + + + + + AVI + + + + + MP4 + + + + + h.264 + + + + + h.264 (NVENC) + + + + + HEVC + + + + + VP8 + + + + + FFV1 + + + + + FLAC + + + + + Opus + + + + + Vorbis + + + + + MP3 + + + + + AAC + + + + + Uncompressed + Non compressé + + + + Bitrate (kbps) + + + + + VBR + + + + + ABR + + + + + Dimensions + + + + + : + + + + + × + + + + + Lock aspect ratio + Bloquer les proportions + + + + Show advanced + Affichage avancées + + + diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/ts/mgba-it.ts mgba-0.7.0/src/platform/qt/ts/mgba-it.ts --- mgba-0.6.3+dfsg1/src/platform/qt/ts/mgba-it.ts 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/ts/mgba-it.ts 2019-01-27 00:06:06.000000000 +0000 @@ -24,10 +24,9 @@ {projectName} desidera ringraziare i seguenti sponsor di Patreon: - © 2013 – 2016 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - © 2013 - 2016 Jeffrey Pfau, sotto licenza Mozilla Public License, versione 2.0 + © 2013 - 2016 Jeffrey Pfau, sotto licenza Mozilla Public License, versione 2.0 Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. @@ -41,6 +40,14 @@ {projectVersion} + + © 2013 – 2018 Jeffrey Pfau, licensed under the Mozilla Public License, version 2.0 +Game Boy Advance is a registered trademark of Nintendo Co., Ltd. + © 2013 - 2016 Jeffrey Pfau, sotto licenza Mozilla Public License, versione 2.0 +Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. {2013 ?} {2018 ?} {2.0 +?} + + {logo} {logo} @@ -72,49 +79,55 @@ AssetTile - + AssetTile AssetTile - + Tile # Tile Nº - + + 0 0 - + + Palette # + + + + Address Indirizzo - + 0x06000000 0x06000000 - + Red Rosso - + Green Verde - + Blue Blue - - - + + + 0x00 (00) 0x00 (00) @@ -302,11 +315,38 @@ + LibraryTree + + + Name + Nome + + + + Location + Posizione + + + + Platform + Piattaforma + + + + Size + Dimensione + + + + CRC32 + CRC32 + + + LibraryView - Library - Biblioteca + Biblioteca @@ -435,6 +475,154 @@ + MapView + + + Maps + + + + + × + × + + + + Magnification + Magnification + + + + Export + + + + + MemorySearch + + + Memory Search + + + + + Address + Indirizzo + + + + Current Value + + + + + + Type + + + + + Value + Valore + + + + Numeric + + + + + Text + + + + + Width + + + + + + Guess + + + + + 1 Byte (8-bit) + + + + + 2 Bytes (16-bit) + + + + + 4 Bytes (32-bit) + + + + + Number type + + + + + Decimal + + + + + Hexadecimal + + + + + Compare + + + + + Equal + + + + + Greater + + + + + Less + + + + + Delta + + + + + Search + + + + + Search Within + + + + + Open in Memory Viewer + + + + + Refresh + Aggiornare + + + MemoryView @@ -521,7 +709,7 @@ - + × × @@ -531,124 +719,129 @@ Magnification - + + Export + + + + Attributes Attributi - + Transform Transformazione - + Off No - + Palette Palette - - - - + + + + 0 0 - + Double Size Doppia Dimensione - - - - + + + + Return, Ctrl+R Return, Ctrl+R - + Flipped Flippato - + H H - + V V - + Mode Modalità - + Normal Normale - + Mosaic Mosaico - + Enabled Abilitato - + Priority Priorità - + Tile Tile - + Geometry Geometria - + Position Posizione - + , , - + Dimensions Dimensione - - + + 8 8 - + Address Indirizzo - + 0x07000000 0x07000000 @@ -669,7 +862,7 @@ - + Autodetect Rilevamento automatico @@ -705,7 +898,7 @@ - + None Nessuno @@ -756,59 +949,89 @@ + Super Game Boy (SGB) + + + + Game Boy Color (CGB) Game Boy Color (CGB) - + Game Boy Advance (AGB) Game Boy Advance (AGB) - + Memory bank controller Controller del banco di memoria - + MBC1 MBC1 - + MBC2 MBC2 - + MBC3 MBC3 - + MBC3 + RTC MBC3 + Reloj - + MBC5 MBC5 - + MBC5 + Rumble MBC5 + Vibrazione - + MBC7 MBC7 - + + Pocket Cam + + + + + TAMA5 + + + + HuC-3 HuC-3 + + + Background Colors + + + + + Sprite Colors 1 + + + + + Sprite Colors 2 + + PaletteView @@ -896,21 +1119,101 @@ + PlacementControl + + + Adjust placement + + + + + All + Tutto + + + + Offset + + + + + X + + + + + Y + + + + + PrinterView + + + Game Boy Printer + + + + + Hurry up! + + + + + Tear off + + + + QGBA::AssetTile - + %0%1%2 %0%1%2 - - - + + + 0x%0 (%1) 0x%0 (%1) + QGBA::AudioDevice + + + Can't set format of context-less audio device + + + + + Audio device is missing its core + + + + + Writing data to read-only audio device + + + + + QGBA::AudioProcessorQt + + + Can't start an audio processor without input + + + + + QGBA::AudioProcessorSDL + + + Can't start an audio processor without input + + + + QGBA::CheatsModel @@ -918,7 +1221,7 @@ (senza titolo) - + Failed to open cheats file: %1 Impossibile aprire il file cheats: %1 @@ -954,6 +1257,37 @@ + QGBA::CoreController + + + Failed to open save file: %1 + Impossibile aprire il file di salvataggio: %1 + + + + Failed to open game file: %1 + Impossibile aprire il file di gioco: %1 + + + + Failed to open snapshot file for reading: %1 + Impossibile aprire il file snapshot per la lettura: %1 + + + + Failed to open snapshot file for writing: %1 + Impossibile aprire il file snapshot per la scrittura: %1 + + + + QGBA::CoreManager + + + Failed to open game file: %1 + Impossibile aprire il file di gioco: %1 + + + QGBA::GBAKeyEditor @@ -1022,17 +1356,17 @@ QGBA::GIFView - + Failed to open output GIF file: %1 Impossibile aprire il file GIF di output: %1 - + Select output file Seleziona file di output - + Graphics Interchange Format (*.gif) Formato di interconnessione grafica (*.gif) @@ -1040,30 +1374,24 @@ QGBA::GameController - - Failed to open game file: %1 - Impossibile aprire il file di gioco: %1 + Impossibile aprire il file di gioco: %1 - Failed to open save file: %1 - Impossibile aprire il file di salvataggio: %1 + Impossibile aprire il file di salvataggio: %1 - Failed to open snapshot file for reading: %1 - Impossibile aprire il file snapshot per la lettura: %1 + Impossibile aprire il file snapshot per la lettura: %1 - Failed to open snapshot file for writing: %1 - Impossibile aprire il file snapshot per la scrittura: %1 + Impossibile aprire il file snapshot per la scrittura: %1 - Failed to start audio processor - Impossibile avviare il processore audio + Impossibile avviare il processore audio @@ -1529,7 +1857,7 @@ Additive blending - Miscelazione dell'additivo + Miscelazione dell'additivo @@ -1713,7 +2041,7 @@ Clock divider - Divisore dell'orologio + Divisore dell'orologio @@ -2437,8 +2765,8 @@ QGBA::KeyEditor - - + + --- --- @@ -2446,75 +2774,66 @@ QGBA::LibraryModel - Name - Nome + Nome - Filename - Nome del file + Nome del file - Size - Dimensione + Dimensione - Platform - Piattaforma + Piattaforma - GBA - GBA + GBA - GB - GB + GB - ? - ? + ? - Location - Posizione + Posizione - CRC32 - CRC32 + CRC32 QGBA::LoadSaveState - + Load State Carica stato - + Save State Salva stato - + Empty Vuoto - + Corrupted Corrotto - + Slot %1 Slot %1 @@ -2522,204 +2841,303 @@ QGBA::LogController - + DEBUG DEBUG - + STUB STUB - + INFO INFORMAZIONI - + WARN AVVERTENZA - + ERROR ERRORE - + FATAL FATALE - + GAME ERROR ERRORE NEL GIOCO + QGBA::MapView + + + Map Addr. + + + + + Mirror + + + + + None + Nessuno + + + + Both + + + + + Horizontal + + + + + Vertical + + + + + Export map + + + + + Portable Network Graphics (*.png) + + + + + Failed to open output PNG file: %1 + + + + QGBA::MemoryModel - + Copy selection Copia selezionato - + Save selection Salva selezionato - + Paste Incolla - + Load Carica - - + + All Tutto - + Load TBL Carica TBL - + Save selected memory Salva la memoria selezionate - + Failed to open output file: %1 Impossibile aprire il file di output: %1 - + Load memory Carica memoria - + Failed to open input file: %1 Impossibile aprire il file di input: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 + QGBA::MemorySearch + + + (%0/%1×) + + + + + (⅟%0×) + + + + + (%0×) + + + + + %1 byte%2 + + + + QGBA::ObjView - - + + 0x%0 0x%0 - + Off No - + Normal Normale - + Trans Trans - + OBJWIN OBJWIN - + Invalid Invalido - - + + N/A n/d + + + Export sprite + + + + + Portable Network Graphics (*.png) + + + + + Failed to open output PNG file: %1 + + QGBA::PaletteView - + #%0 #%0 - + 0x%0 0x%0 - + %0 %0 - + 0x%0 (%1) 0x%0 (%1) - + Export palette Esporta palette - + Windows PAL (*.pal);;Adobe Color Table (*.act) WIndows PAL (*.pal);;Tabella dei colori Adobe (*.act) - + Failed to open output palette file: %1 - Errore nell'aprire il file palette di output : %1 + Errore nell'aprire il file palette di output : %1 + + + + QGBA::PrinterView + + + Save Printout + + + + + Portable Network Graphics (*.png) + QGBA::ROMInfo - - - - - + + + + + (unknown) (sconosciuto) - - + + bytes bytes - + (no database present) (nessun database presente) @@ -2727,47 +3145,59 @@ QGBA::SettingsView - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forza la versione 1.x) - + + None (Still Image) + + + + Keyboard Tastiera - + Controllers Controllers - + Shortcuts Tasti di scelta rapida - + + + Shaders + Shaders + + + Select BIOS Seleziona BIOS @@ -2775,37 +3205,36 @@ QGBA::ShaderSelector - + No shader active Nessun shader attivo - + Load shader Carica shader - %1 Shader (%.shader) - %1 Shader (%.shader) + %1 Shader (%.shader) - + No shader loaded Nessun shader caricato - + by %1 por %1 - + Preprocessing Preprocesso - + Pass %1 Pass %1 @@ -2813,17 +3242,17 @@ QGBA::ShortcutController - + Action Azione - + Keyboard Tastiera - + Gamepad Gamepad @@ -2831,17 +3260,17 @@ QGBA::VideoView - + Failed to open output video file: %1 - Errore durante l'archiviazione del video: %1 + Errore durante l'archiviazione del video: %1 - + Native (%0x%1) Nativo (%0x%1) - + Select output file Seleziona file di output @@ -2849,61 +3278,86 @@ QGBA::Window - + Game Boy Advance ROMs (%1) ROM di Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs del Game Boy (%1) - + All ROMs (%1) Tutte le ROM (%1) - + + %1 Video Logs (*.mvl) + + + + Archives (%1) Archivio (%1) - - - + + + Select ROM Seleziona ROM - + Game Boy Advance save files (%1) Game Boy Advance file di salvataggio (%1) - - - + + + Select save Seleziona salvataggio - + Select patch Seleziona patch - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - - + + Select image + + + + + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) + + + + + GameShark saves (*.sps *.xps) Salvataggi GameShark (*.sps *.xps) + + Select video log + + + + + Video logs (*.mvl) + + + Crash Errore fatale @@ -2918,642 +3372,708 @@ %1 - + Couldn't Load Non è possibile caricare - + Could not load game. Are you sure it's in the correct format? Impossibile caricare il gioco. Sei sicuro che sia nel formato corretto? - + Unimplemented BIOS call BIOS non implementato - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Questo gioco utilizza una chiamata BIOS non implementata. Utilizza il BIOS ufficiale per una migliore esperienza - + Really make portable? Davvero rendere portatile? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - In questo modo l'emulatore carica la propria configurazione dalla stessa directory dell'eseguibile. Vuoi continuare? + In questo modo l'emulatore carica la propria configurazione dalla stessa directory dell'eseguibile. Vuoi continuare? - + Restart needed È necessario riavviare - + Some changes will not take effect until the emulator is restarted. - Alcune modifiche non avranno effetto finché l'emulatore non viene riavviato. + Alcune modifiche non avranno effetto finché l'emulatore non viene riavviato. - + - Player %1 of %2 - Giocatore %1 di %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &File - + Load &ROM... Carica &ROM... - + Load ROM in archive... Carica la ROM in archivio... - + + Load alternate save... + + + + Load temporary save... Carica il salvataggio temporaneo.. - + Load &patch... Carica &patch... - + Boot BIOS Boot BIOS - + Replace ROM... Sostituire la ROM... - + ROM &info... ROM &info... - + Recent Recente - + Make portable Rendi portatile - + &Load state &Carica stato - + F10 F10 - + &Save state &Salva stato - + Shift+F10 DO NOT TRANSLATE Shift+F10 - + Quick load Caricamento rapido - + Quick save Salvataggio rapido - + Load recent Carica recente - + Save recent Salva recente - + Undo load state Annulla il caricamento dello stato - + F11 DO NOT TRANSLATE F11 - + Undo save state Annulla salva stato - + Shift+F11 DO NOT TRANSLATE Shift+F11 - - + + State &%1 Stato &%1 - + F%1 F%1 - + Shift+F%1 DO NOT TRANSLATE Shift+F%1 - + + Load camera image... + + + + Import GameShark Save Importa il salvataggio del GameShark - + Export GameShark Save Esporta salvataggio dal GameShark - + New multiplayer window Nuova finestra multigiocatore - + About About - + E&xit Uscire (&X) - + &Emulation &Emulazione - + &Reset &Reset - + Ctrl+R Ctrl+R - + Sh&utdown Spegni (&U) - + Yank game pak Yank game pak - + &Pause &Pausa - + Ctrl+P Ctrl+P - + &Next frame Salta il prossimo frame (&N) - + Ctrl+N Ctrl+N - + Fast forward (held) Avanzamento rapido (sostenuto) - + &Fast forward Avanzamento rapido (&F) - + Shift+Tab Shift+Tab - + Fast forward speed Velocità di avanzamento rapido - + Unbounded Illimitato - + %0x %0x - + Rewind (held) Riavvolgi (sostenuto) - + Re&wind Riavvolgi (&W) - + ~ ~ - + Step backwards Torna indietro - + Ctrl+B Ctrl+B - + Sync to &video Sincronizzare su &video - + Sync to &audio Sincronizzare su &audio - + Solar sensor Sensore solare - + Increase solar level Aumenta il livello solare - + Decrease solar level Riduce il livello solare - + Brightest solar level Livello solare brillante - + Darkest solar level Livello solare più scuro - + Brightness %1 Luminosità %1 - + Audio/&Video Audio/&Video - + Frame size Dimensione Frame - + %1x %1x - + Toggle fullscreen Abilita schermo intero - + Lock aspect ratio Blocca aspect ratio - Resample video - Rimostra video + Rimostra video - + Frame&skip Frame&skip - Shader options... - Opzioni shader... + Opzioni shader... - + Mute Muto - + FPS target FPS mirato - + 15 15 - + 30 30 - + 45 45 - + Native (59.7) Nativo (59.7) - + 60 60 - + 90 90 - + 120 120 - + 240 240 - + Take &screenshot Effettua &screenshot - + F12 F12 - + Record output... Registra salida... - + Record GIF... Registra GIF... - + Video layers Layers video - Background %0 - Sfondo %0 + Sfondo %0 - OBJ (sprites) - OBJ (sprites) + OBJ (sprites) - + Audio channels Canali audio - Channel %0 - Canale %0 + Canale %0 - Channel A - Canale A + Canale A - Channel B - Canale B + Canale B - + &Tools &Strumenti - + View &logs... Visualizza registri... (&L) - + Game &overrides... Val&specifico per il gioco... - + Game &Pak sensors... Sensori di gioco &Pak... - + &Cheats... &Trucchi... - + Open debugger console... Apri debugger console... - + Start &GDB server... Avvia server &GDB... - + Settings... Impostazioni... - + Select folder Seleziona cartella - + Add folder to library... Aggiungi cartella alla libreria... - + + Force integer scaling + + + + + Bilinear filtering + + + + + Record video log... + + + + + Stop video log + + + + + Game Boy Printer... + + + + + Adjust layer placement... + + + + View &palette... Ver &palette... - + View &sprites... Ver &sprites... - + View &tiles... Ver &tiles... - + + View &map... + + + + View memory... Ver memoria... - + + Search memory... + + + + View &I/O registers... Ver reg&registri I/O... - + Exit fullscreen Esci da schermo intero - + + GameShark Button (held) + + + + Autofire Pulsanti Auto fuoco - + Autofire A Auto fuoco A - + Autofire B Auto fuoco B - + Autofire L Auto fuoco L - + Autofire R Auto fuoco R - + Autofire Start Avvia Auto fuoco - + Autofire Select Seleziona Auto fuoco - + Autofire Up Auto fuoco sù - + Autofire Right Auto fuoco destro - + Autofire Down Auto fuoco giù - + Autofire Left Auto fuoco sinistro + QObject + + + GBA + GBA + + + + GB + GB + + + + ? + ? + + + ROMInfo @@ -3649,39 +4169,39 @@ dd/MM/yy HH:mm:ss - + Light sensor Sensore di luce - + Brightness Luminosità - + Tilt sensor Sensore di inclinazione - - + + Set Y Config. Y - - + + Set X Config. X - + Gyroscope Giroscopio - + Sensitivity Sensibilità @@ -3714,206 +4234,292 @@ Paths - + + Game Boy + Game Boy + + + Audio driver: Audio driver: - + Audio buffer: Buffer audio: - - + + 1536 1536 - + 512 512 - + 768 768 - + 1024 1024 - + 2048 2048 - + 3072 3072 - + 4096 4096 - + samples samples - + Sample rate: Sample rate: - - + + 44100 44100 - + 22050 22050 - + 32000 32000 - + 48000 48000 - + Hz Hz - + Volume: Volume: - + Mute Muto - + Display driver: Visualizza driver: - + Frameskip: Frameskip: - + Skip every Salta ognuno - - + + frames frames - + FPS target: FPS mirato: - + frames per second frame per secondo - + Sync: Sincronizzare: - + Video Video - + Audio Audio - + Lock aspect ratio Blocca aspect ratio - + + Cheats + Trucchi + + + + Game Boy model + Modello del Game Boy + + + + + + Autodetect + Rilevamento automatico + + + + + + Game Boy (DMG) + Game Boy (DMG) + + + + + + Super Game Boy (SGB) + + + + + + + Game Boy Color (CGB) + Game Boy Color (CGB) + + + + + + Game Boy Advance (AGB) + Game Boy Advance (AGB) + + + + Super Game Boy model + + + + + Game Boy Color model + + + + + Default BG colors: + + + + + Super Game Boy borders + + + + + Camera driver: + + + + + Default sprite colors 1: + + + + + Default sprite colors 2: + + + Resample video - Rimostrare video + Rimostrare video - + Library: Biblioteca: - + Show when no game open Mostra quando nessun gioco è aperto - + Clear cache Cancella cache - + Fast forward speed: Velocità di avanzamento rapido: - - - - - - - + + + + + + + + + Browse Sfoglia - + Use BIOS file if found Utilizzare il file del BIOS se è stato trovato - + Skip BIOS intro Salta BIOS intro - + × × - + Unbounded Illimitato - + Suspend screensaver Sospendi screensaver @@ -3923,113 +4529,189 @@ BIOS - + Pause when inactive Pausa se inattivo - + Run all Avviare tutto - + Remove known Rimuovi conosciuto - + Detect and remove Rileva e rimuovi - + Allow opposing input directions Consenti direzioni opposte - - + + Screenshot Screenshot - - + + Save data Salva dati - - + + Cheat codes Trucchi - + Enable rewind Abilita riavvolgi - + + Bilinear filtering + + + + + Force integer scaling + + + + + Language + + + + + English + + + + + List view + + + + + Tree view + + + + + Show FPS in title bar + + + + + Automatically save cheats + + + + + Automatically load cheats + + + + + Automatically save state + + + + + Automatically load state + + + + Rewind history: Riavvolgi storia: - + Idle loops: Idle loops: - + Savestate extra data: Salva dati extra: - + Load extra data: Carica dati extra: - + + Rewind affects save data + + + + + Preload entire ROM into memory + + + + + Autofire interval: + + + + GB BIOS file: File GB BIOS: - + GBA BIOS file: File GBA BIOS: - + GBC BIOS file: File GBC BIOS: - + + SGB BIOS file: + + + + Save games Salva il gioco - - - - + + + + + Same directory as the ROM Stessa directory della ROM - + Save states Salva Stato - + Screenshots Screenshots - + Patches Patches @@ -4103,17 +4785,17 @@ Tiles - + 256 colors 256 colori - + × × - + Magnification Magnification @@ -4207,24 +4889,32 @@ MP4 - PNG - PNG + PNG - + h.264 h.264 + + h.264 (NVENC) + + + + HEVC + + + + VP8 - Xvid - Xvid + Xvid @@ -4272,32 +4962,32 @@ VBR - + ABR ABR - + Dimensions Dimensioni - + : : - + × × - + Lock aspect ratio Blocca aspect ratio - + Show advanced Mostra avanzato diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/utils.h mgba-0.7.0/src/platform/qt/utils.h --- mgba-0.6.3+dfsg1/src/platform/qt/utils.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/utils.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_UTILS_H -#define QGBA_UTILS_H +#pragma once #include @@ -16,5 +15,3 @@ QString nicePlatformFormat(mPlatform platform); } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/VFileDevice.cpp mgba-0.7.0/src/platform/qt/VFileDevice.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/VFileDevice.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/VFileDevice.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -13,7 +13,36 @@ : QIODevice(parent) , m_vf(vf) { - // Nothing to do + // TODO: Correct mode + if (vf) { + setOpenMode(QIODevice::ReadWrite); + } +} + +void VFileDevice::close() { + if (!m_vf) { + return; + } + QIODevice::close(); + m_vf->close(m_vf); + m_vf = nullptr; +} + +bool VFileDevice::resize(qint64 sz) { + m_vf->truncate(m_vf, sz); + return true; +} + +bool VFileDevice::seek(qint64 pos) { + QIODevice::seek(pos); + return m_vf->seek(m_vf, pos, SEEK_SET) == pos; +} + +VFileDevice& VFileDevice::operator=(VFile* vf) { + close(); + m_vf = vf; + setOpenMode(QIODevice::ReadWrite); + return *this; } qint64 VFileDevice::readData(char* data, qint64 maxSize) { diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/VFileDevice.h mgba-0.7.0/src/platform/qt/VFileDevice.h --- mgba-0.6.3+dfsg1/src/platform/qt/VFileDevice.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/VFileDevice.h 2019-01-27 00:06:06.000000000 +0000 @@ -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_VFILE_DEVICE -#define QGBA_VFILE_DEVICE +#pragma once #include @@ -17,7 +16,16 @@ Q_OBJECT public: - VFileDevice(VFile* vf, QObject* parent = nullptr); + VFileDevice(VFile* vf = nullptr, QObject* parent = nullptr); + + virtual void close() override; + virtual bool seek(qint64 pos) override; + virtual qint64 size() const override; + + bool resize(qint64 sz); + + VFileDevice& operator=(VFile*); + operator VFile*() { return m_vf; } static VFile* open(const QString& path, int mode); static VDir* openDir(const QString& path); @@ -26,12 +34,9 @@ protected: virtual qint64 readData(char* data, qint64 maxSize) override; virtual qint64 writeData(const char* data, qint64 maxSize) override; - virtual qint64 size() const override; private: VFile* m_vf; }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/VideoDumper.cpp mgba-0.7.0/src/platform/qt/VideoDumper.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/VideoDumper.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/VideoDumper.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,67 @@ +/* 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 "VideoDumper.h" + +#include + +using namespace QGBA; + +VideoDumper::VideoDumper(QObject* parent) + : QAbstractVideoSurface(parent) +{ +} + +bool VideoDumper::present(const QVideoFrame& frame) { + QVideoFrame mappedFrame(frame); + if (!mappedFrame.map(QAbstractVideoBuffer::ReadOnly)) { + return false; + } + QVideoFrame::PixelFormat vFormat = mappedFrame.pixelFormat(); + QImage::Format format = QVideoFrame::imageFormatFromPixelFormat(vFormat); + bool swap = false; + if (format == QImage::Format_Invalid) { + vFormat = static_cast(vFormat - QVideoFrame::Format_BGRA32 + QVideoFrame::Format_ARGB32); + format = QVideoFrame::imageFormatFromPixelFormat(vFormat); + if (format == QImage::Format_ARGB32) { + format = QImage::Format_RGBA8888; + } else if (format == QImage::Format_ARGB32_Premultiplied) { + format = QImage::Format_RGBA8888_Premultiplied; + } + swap = true; + } + uchar* bits = mappedFrame.bits(); + QImage image(bits, mappedFrame.width(), mappedFrame.height(), mappedFrame.bytesPerLine(), format); + if (swap) { + image = image.rgbSwapped(); + } else { +#ifdef Q_OS_WIN + // Qt's DirectShow plug-in is pretty dang buggy + image = image.mirrored(); +#else + image = image.copy(); // Create a deep copy of the bits +#endif + } + mappedFrame.unmap(); + emit imageAvailable(image); + return true; +} + +QList VideoDumper::supportedPixelFormats(QAbstractVideoBuffer::HandleType) const { + QList list; + list.append(QVideoFrame::Format_RGB32); + list.append(QVideoFrame::Format_ARGB32); + list.append(QVideoFrame::Format_RGB24); + list.append(QVideoFrame::Format_ARGB32_Premultiplied); + list.append(QVideoFrame::Format_RGB565); + list.append(QVideoFrame::Format_RGB555); + list.append(QVideoFrame::Format_BGR32); + list.append(QVideoFrame::Format_BGRA32); + list.append(QVideoFrame::Format_BGR24); + list.append(QVideoFrame::Format_BGRA32_Premultiplied); + list.append(QVideoFrame::Format_BGR565); + list.append(QVideoFrame::Format_BGR555); + return list; +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/VideoDumper.h mgba-0.7.0/src/platform/qt/VideoDumper.h --- mgba-0.6.3+dfsg1/src/platform/qt/VideoDumper.h 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/VideoDumper.h 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,25 @@ +/* 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/. */ +#pragma once + +#include + +namespace QGBA { + +class VideoDumper : public QAbstractVideoSurface { +Q_OBJECT + +public: + VideoDumper(QObject* parent = nullptr); + + bool present(const QVideoFrame& frame) override; + QList supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override; + +signals: + void imageAvailable(const QImage& image); +}; + +} diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/VideoView.cpp mgba-0.7.0/src/platform/qt/VideoView.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/VideoView.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/VideoView.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -51,6 +51,7 @@ if (s_acodecMap.empty()) { s_acodecMap["mp3"] = "libmp3lame"; s_acodecMap["opus"] = "libopus"; + s_acodecMap["vorbis"] = "libvorbis"; s_acodecMap["uncompressed"] = "pcm_s16le"; } if (s_vcodecMap.empty()) { @@ -99,9 +100,9 @@ setPreset({ .container = "MKV", - .vcodec = "PNG", + .vcodec = "h.264", .acodec = "FLAC", - .vbr = 0, + .vbr = -1, .abr = 0, .dims = QSize(), }); @@ -170,8 +171,8 @@ addPreset(m_ui.presetWebM, { .container = "WebM", - .vcodec = "VP8", - .acodec = "Vorbis", + .vcodec = "VP9", + .acodec = "Opus", .vbr = 800, .abr = 128 }); @@ -179,9 +180,9 @@ if (m_nativeWidth && m_nativeHeight) { addPreset(m_ui.presetLossless, { .container = "MKV", - .vcodec = "PNG", + .vcodec = "h.264", .acodec = "FLAC", - .vbr = 0, + .vbr = -1, .abr = 0, .dims = QSize(m_nativeWidth, m_nativeHeight) }); @@ -195,6 +196,14 @@ free(m_containerCstr); } +void VideoView::setController(std::shared_ptr controller) { + connect(controller.get(), &CoreController::stopping, this, &VideoView::stopRecording); + connect(this, &VideoView::recordingStarted, controller.get(), &CoreController::setAVStream); + connect(this, &VideoView::recordingStopped, controller.get(), &CoreController::clearAVStream, Qt::DirectConnection); + + setNativeResolution(controller->screenDimensions()); +} + void VideoView::startRecording() { if (!validateSettings()) { return; @@ -303,7 +312,7 @@ } void VideoView::setVideoBitrate(int br, bool manual) { - m_vbr = br * 1000; + m_vbr = br >= 0 ? br * 1000 : 0; FFmpegEncoderSetVideo(&m_encoder, m_videoCodecCstr, m_vbr); validateSettings(); if (manual) { diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/VideoView.h mgba-0.7.0/src/platform/qt/VideoView.h --- mgba-0.6.3+dfsg1/src/platform/qt/VideoView.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/VideoView.h 2019-01-27 00:06:06.000000000 +0000 @@ -3,19 +3,24 @@ * 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_VIDEO_VIEW -#define QGBA_VIDEO_VIEW +#pragma once #ifdef USE_FFMPEG #include +#include + +#include "CoreController.h" + #include "ui_VideoView.h" #include "feature/ffmpeg/ffmpeg-encoder.h" namespace QGBA { +class CoreController; + class VideoView : public QWidget { Q_OBJECT @@ -26,6 +31,8 @@ mAVStream* getStream() { return &m_encoder.d; } public slots: + void setController(std::shared_ptr); + void startRecording(); void stopRecording(); void setNativeResolution(const QSize&); @@ -109,5 +116,3 @@ } #endif - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/VideoView.ui mgba-0.7.0/src/platform/qt/VideoView.ui --- mgba-0.6.3+dfsg1/src/platform/qt/VideoView.ui 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/VideoView.ui 2019-01-27 00:06:06.000000000 +0000 @@ -106,7 +106,7 @@ - High Quality + High &Quality presets @@ -116,7 +116,7 @@ - YouTube + &YouTube presets @@ -136,7 +136,7 @@ - Lossless + &Lossless true @@ -153,7 +153,7 @@ - 1080p + &1080p resolutions @@ -163,7 +163,7 @@ - 720p + &720p resolutions @@ -173,7 +173,7 @@ - 480p + &480p resolutions @@ -186,7 +186,7 @@ false - Native + &Native true @@ -256,11 +256,6 @@ - PNG - - - - h.264 @@ -281,6 +276,11 @@ + VP9 + + + + FFV1 @@ -353,9 +353,6 @@ - - 200 - 10000 @@ -523,7 +520,7 @@ - + diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/Window.cpp mgba-0.7.0/src/platform/qt/Window.cpp --- mgba-0.6.3+dfsg1/src/platform/qt/Window.cpp 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/Window.cpp 2019-01-27 00:06:06.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016 Jeffrey Pfau +/* 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 @@ -20,12 +20,14 @@ #endif #include "AboutScreen.h" +#include "AudioProcessor.h" #include "CheatsView.h" #include "ConfigController.h" +#include "CoreController.h" #include "DebuggerConsole.h" #include "DebuggerConsoleController.h" #include "Display.h" -#include "GameController.h" +#include "CoreController.h" #include "GBAApp.h" #include "GDBController.h" #include "GDBWindow.h" @@ -33,12 +35,15 @@ #include "IOViewer.h" #include "LoadSaveState.h" #include "LogView.h" -#include "MultiplayerController.h" +#include "MapView.h" #include "MemorySearch.h" #include "MemoryView.h" +#include "MultiplayerController.h" #include "OverrideView.h" #include "ObjView.h" #include "PaletteView.h" +#include "PlacementControl.h" +#include "PrinterView.h" #include "ROMInfo.h" #include "SensorView.h" #include "SettingsView.h" @@ -48,6 +53,7 @@ #include "VideoView.h" #include +#include #ifdef M_CORE_GB #include #include @@ -62,8 +68,9 @@ using namespace QGBA; -Window::Window(ConfigController* config, int playerId, QWidget* parent) +Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWidget* parent) : QMainWindow(parent) + , m_manager(manager) , m_logView(new LogView(&m_log)) , m_screenWidget(new WindowBackground()) , m_config(config) @@ -73,20 +80,11 @@ setFocusPolicy(Qt::StrongFocus); setAcceptDrops(true); setAttribute(Qt::WA_DeleteOnClose); - m_controller = new GameController(this); - m_controller->setInputController(&m_inputController); updateTitle(); - m_display = Display::create(this); -#if defined(BUILD_GL) || defined(BUILD_GLES2) - m_shaderView = new ShaderSelector(m_display, m_config); -#endif - m_logo.setDevicePixelRatio(m_screenWidget->devicePixelRatio()); m_logo = m_logo; // Free memory left over in old pixmap - m_screenWidget->setMinimumSize(m_display->minimumSize()); - m_screenWidget->setSizePolicy(m_display->sizePolicy()); #if defined(M_CORE_GBA) float i = 2; #elif defined(M_CORE_GB) @@ -102,7 +100,7 @@ ConfigOption* showLibrary = m_config->addOption("showLibrary"); showLibrary->connect([this](const QVariant& value) { if (value.toBool()) { - if (m_controller->isLoaded()) { + if (m_controller) { m_screenWidget->layout()->addWidget(m_libraryView); } else { attachWidget(m_libraryView); @@ -122,7 +120,7 @@ VFile* output = m_libraryView->selectedVFile(); if (output) { QPair path = m_libraryView->selectedPath(); - m_controller->loadGame(output, path.second, path.first); + setController(m_manager->loadGame(output, path.second, path.first), path.first + "/" + path.second); } }); #endif @@ -137,61 +135,9 @@ m_screenWidget->setLockAspectRatio(true); setCentralWidget(m_screenWidget); - connect(m_controller, &GameController::gameStarted, this, &Window::gameStarted); - connect(m_controller, &GameController::gameStarted, &m_inputController, &InputController::suspendScreensaver); - connect(m_controller, &GameController::gameStopped, m_display, &Display::stopDrawing); - connect(m_controller, &GameController::gameStopped, this, &Window::gameStopped); - connect(m_controller, &GameController::gameStopped, &m_inputController, &InputController::resumeScreensaver); - connect(m_controller, &GameController::stateLoaded, m_display, &Display::forceDraw); - connect(m_controller, &GameController::rewound, m_display, &Display::forceDraw); - connect(m_controller, &GameController::gamePaused, [this](mCoreThread* context) { - unsigned width, height; - context->core->desiredVideoDimensions(context->core, &width, &height); - QImage currentImage(reinterpret_cast(m_controller->drawContext()), width, height, - width * BYTES_PER_PIXEL, QImage::Format_RGBX8888); - QPixmap pixmap; - pixmap.convertFromImage(currentImage); - m_screenWidget->setPixmap(pixmap); - }); - connect(m_controller, &GameController::gamePaused, m_display, &Display::pauseDrawing); -#ifndef Q_OS_MAC - connect(m_controller, &GameController::gamePaused, menuBar(), &QWidget::show); - connect(m_controller, &GameController::gameUnpaused, [this]() { - if(isFullScreen()) { - menuBar()->hide(); - } - }); -#endif - connect(m_controller, &GameController::gamePaused, &m_inputController, &InputController::resumeScreensaver); - connect(m_controller, &GameController::gameUnpaused, m_display, &Display::unpauseDrawing); - connect(m_controller, &GameController::gameUnpaused, &m_inputController, &InputController::suspendScreensaver); - connect(m_controller, &GameController::postLog, &m_log, &LogController::postLog); - connect(m_controller, &GameController::frameAvailable, this, &Window::recordFrame); - connect(m_controller, &GameController::frameAvailable, m_display, &Display::framePosted); - connect(m_controller, &GameController::gameCrashed, this, &Window::gameCrashed); - connect(m_controller, &GameController::gameFailed, this, &Window::gameFailed); - connect(m_controller, &GameController::unimplementedBiosCall, this, &Window::unimplementedBiosCall); - connect(m_controller, &GameController::statusPosted, m_display, &Display::showMessage); - connect(&m_log, &LogController::levelsSet, m_controller, &GameController::setLogLevel); - connect(&m_log, &LogController::levelsEnabled, m_controller, &GameController::enableLogLevel); - connect(&m_log, &LogController::levelsDisabled, m_controller, &GameController::disableLogLevel); - connect(this, &Window::startDrawing, m_display, &Display::startDrawing, Qt::QueuedConnection); - connect(this, &Window::shutdown, m_display, &Display::stopDrawing); - connect(this, &Window::shutdown, m_controller, &GameController::closeGame); connect(this, &Window::shutdown, m_logView, &QWidget::hide); - connect(this, &Window::audioBufferSamplesChanged, m_controller, &GameController::setAudioBufferSamples); - connect(this, &Window::sampleRateChanged, m_controller, &GameController::setAudioSampleRate); - connect(this, &Window::fpsTargetChanged, m_controller, &GameController::setFPSTarget); connect(&m_fpsTimer, &QTimer::timeout, this, &Window::showFPS); connect(&m_focusCheck, &QTimer::timeout, this, &Window::focusCheck); - connect(m_display, &Display::hideCursor, [this]() { - if (static_cast(m_screenWidget->layout())->currentWidget() == m_display) { - m_screenWidget->setCursor(Qt::BlankCursor); - } - }); - connect(m_display, &Display::showCursor, [this]() { - m_screenWidget->unsetCursor(); - }); connect(&m_inputController, &InputController::profileLoaded, m_shortcutController, &ShortcutController::loadProfile); m_log.setLevels(mLOG_WARN | mLOG_ERROR | mLOG_FATAL); @@ -222,17 +168,24 @@ loadConfig(); if (args->patch) { - m_controller->loadPatch(args->patch); + m_pendingPatch = args->patch; + } + + if (args->savestate) { + m_pendingState = args->savestate; } if (args->fname) { - m_controller->loadGame(args->fname); + setController(m_manager->loadGame(args->fname), args->fname); } #ifdef USE_GDB_STUB if (args->debuggerType == DEBUGGER_GDB) { if (!m_gdbController) { - m_gdbController = new GDBController(m_controller, this); + m_gdbController = new GDBController(this); + if (m_controller) { + m_gdbController->setController(m_controller); + } m_gdbController->listen(); } } @@ -257,19 +210,6 @@ const mCoreOptions* opts = m_config->options(); reloadConfig(); - // TODO: Move these to ConfigController - if (opts->fpsTarget) { - emit fpsTargetChanged(opts->fpsTarget); - } - - if (opts->audioBuffers) { - emit audioBufferSamplesChanged(opts->audioBuffers); - } - - if (opts->sampleRate) { - emit sampleRateChanged(opts->sampleRate); - } - if (opts->width && opts->height) { resizeFrame(QSize(opts->width, opts->height)); } @@ -278,22 +218,10 @@ enterFullScreen(); } -#if defined(BUILD_GL) || defined(BUILD_GLES2) - if (opts->shader) { - struct VDir* shader = VDirOpen(opts->shader); - if (shader) { - m_display->setShaders(shader); - m_shaderView->refreshShaders(); - shader->close(shader); - } - } -#endif - m_mruFiles = m_config->getMRU(); updateMRU(); m_inputController.setConfiguration(m_config); - m_controller->setUseBIOS(opts->useBios); } void Window::reloadConfig() { @@ -301,9 +229,18 @@ m_log.setLevels(opts->logLevel); - m_controller->setConfig(m_config->config()); - m_display->lockAspectRatio(opts->lockAspectRatio); - m_display->filter(opts->resampleVideo); + if (m_controller) { + m_controller->loadConfig(m_config); + if (m_audioProcessor) { + m_audioProcessor->setBufferSamples(opts->audioBuffers); + m_audioProcessor->requestSampleRate(opts->sampleRate); + } + m_display->resizeContext(); + } + if (m_display) { + m_display->lockAspectRatio(opts->lockAspectRatio); + m_display->filter(opts->resampleVideo); + } m_inputController.setScreensaverSuspendable(opts->suspendScreensaver); } @@ -326,6 +263,9 @@ #ifdef USE_LZMA "*.7z", #endif +#ifdef USE_ELF + "*.elf", +#endif "*.agb", "*.mb", "*.rom", @@ -338,6 +278,7 @@ QStringList gbFormats{ "*.gb", "*.gbc", + "*.sgb", #if defined(USE_LIBZIP) || defined(USE_ZLIB) "*.zip", #endif @@ -374,7 +315,7 @@ void Window::selectROM() { QString filename = GBAApp::app()->getOpenFileName(this, tr("Select ROM"), getFilters()); if (!filename.isEmpty()) { - m_controller->loadGame(filename); + setController(m_manager->loadGame(filename), filename); } } @@ -389,7 +330,7 @@ VFile* output = archiveInspector->selectedVFile(); QPair path = archiveInspector->selectedPath(); if (output) { - m_controller->loadGame(output, path.second, path.first); + setController(m_manager->loadGame(output, path.second, path.first), path.first + "/" + path.second); } archiveInspector->close(); }); @@ -422,33 +363,60 @@ } } +void Window::selectState(bool load) { + QStringList formats{"*.ss0", "*.ss1", "*.ss2", "*.ss3", "*.ss4", "*.ss5", "*.ss6", "*.ss7", "*.ss8", "*.ss9"}; + QString filter = tr("mGBA savestate files (%1)").arg(formats.join(QChar(' '))); + if (load) { + QString filename = GBAApp::app()->getOpenFileName(this, tr("Select savestate"), filter); + if (!filename.isEmpty()) { + m_controller->loadState(filename); + } + } else { + QString filename = GBAApp::app()->getSaveFileName(this, tr("Select savestate"), filter); + if (!filename.isEmpty()) { + m_controller->saveState(filename); + } + } +} + void Window::multiplayerChanged() { + if (!m_controller) { + return; + } int attached = 1; MultiplayerController* multiplayer = m_controller->multiplayerController(); if (multiplayer) { attached = multiplayer->attached(); } - if (m_controller->isLoaded()) { - for (QAction* action : m_nonMpActions) { - action->setDisabled(attached > 1); - } + for (QAction* action : m_nonMpActions) { + action->setDisabled(attached > 1); } } void Window::selectPatch() { QString filename = GBAApp::app()->getOpenFileName(this, tr("Select patch"), tr("Patches (*.ips *.ups *.bps)")); if (!filename.isEmpty()) { - m_controller->loadPatch(filename); + if (m_controller) { + m_controller->loadPatch(filename); + } else { + m_pendingPatch = filename; + } } } void Window::openView(QWidget* widget) { connect(this, &Window::shutdown, widget, &QWidget::close); - connect(m_controller, &GameController::gameStopped, widget, &QWidget::close); widget->setAttribute(Qt::WA_DeleteOnClose); widget->show(); } +void Window::loadCamImage() { + QString filename = GBAApp::app()->getOpenFileName(this, tr("Select image"), tr("Image file (*.png *.gif *.jpg *.jpeg);;All files (*)")); + if (!filename.isEmpty()) { + m_inputController.loadCamImage(filename); + } +} + void Window::importSharkport() { QString filename = GBAApp::app()->getOpenFileName(this, tr("Select save"), tr("GameShark saves (*.sps *.xps)")); if (!filename.isEmpty()) { @@ -467,23 +435,20 @@ SettingsView* settingsWindow = new SettingsView(m_config, &m_inputController, m_shortcutController); #if defined(BUILD_GL) || defined(BUILD_GLES2) if (m_display->supportsShaders()) { - settingsWindow->setShaderSelector(m_shaderView); + settingsWindow->setShaderSelector(m_shaderView.get()); } #endif - connect(settingsWindow, &SettingsView::biosLoaded, m_controller, &GameController::loadBIOS); - connect(settingsWindow, &SettingsView::audioDriverChanged, m_controller, &GameController::reloadAudioDriver); - connect(settingsWindow, &SettingsView::displayDriverChanged, this, &Window::mustRestart); + connect(settingsWindow, &SettingsView::displayDriverChanged, this, &Window::reloadDisplayDriver); + connect(settingsWindow, &SettingsView::audioDriverChanged, this, &Window::reloadAudioDriver); + connect(settingsWindow, &SettingsView::cameraDriverChanged, this, &Window::mustRestart); connect(settingsWindow, &SettingsView::languageChanged, this, &Window::mustRestart); connect(settingsWindow, &SettingsView::pathsChanged, this, &Window::reloadConfig); +#ifdef USE_SQLITE3 connect(settingsWindow, &SettingsView::libraryCleared, m_libraryView, &LibraryController::clear); +#endif openView(settingsWindow); } -void Window::openAboutScreen() { - AboutScreen* about = new AboutScreen(); - openView(about); -} - void Window::startVideoLog() { QString filename = GBAApp::app()->getSaveFileName(this, tr("Select video log"), tr("Video logs (*.mvl)")); if (!filename.isEmpty()) { @@ -491,18 +456,19 @@ } } -template -std::function Window::openTView(A arg) { +template +std::function Window::openTView(A... arg) { return [=]() { - T* view = new T(m_controller, arg); + T* view = new T(arg...); openView(view); }; } -template -std::function Window::openTView() { + +template +std::function Window::openControllerTView(A... arg) { return [=]() { - T* view = new T(m_controller); + T* view = new T(m_controller, arg...); openView(view); }; } @@ -511,15 +477,8 @@ void Window::openVideoWindow() { if (!m_videoView) { m_videoView = new VideoView(); - connect(m_videoView, &VideoView::recordingStarted, m_controller, &GameController::setAVStream); - connect(m_videoView, &VideoView::recordingStopped, m_controller, &GameController::clearAVStream, Qt::DirectConnection); - connect(m_controller, &GameController::gameStopped, m_videoView, &VideoView::stopRecording); - connect(m_controller, &GameController::gameStopped, m_videoView, &QWidget::close); - connect(m_controller, &GameController::gameStarted, [this]() { - m_videoView->setNativeResolution(m_controller->screenDimensions()); - }); - if (m_controller->isLoaded()) { - m_videoView->setNativeResolution(m_controller->screenDimensions()); + if (m_controller) { + m_videoView->setController(m_controller); } connect(this, &Window::shutdown, m_videoView, &QWidget::close); } @@ -531,10 +490,9 @@ void Window::openGIFWindow() { if (!m_gifView) { m_gifView = new GIFView(); - connect(m_gifView, &GIFView::recordingStarted, m_controller, &GameController::setAVStream); - connect(m_gifView, &GIFView::recordingStopped, m_controller, &GameController::clearAVStream, Qt::DirectConnection); - connect(m_controller, &GameController::gameStopped, m_gifView, &GIFView::stopRecording); - connect(m_controller, &GameController::gameStopped, m_gifView, &QWidget::close); + if (m_controller) { + m_gifView->setController(m_controller); + } connect(this, &Window::shutdown, m_gifView, &QWidget::close); } m_gifView->show(); @@ -544,9 +502,11 @@ #ifdef USE_GDB_STUB void Window::gdbOpen() { if (!m_gdbController) { - m_gdbController = new GDBController(m_controller, this); + m_gdbController = new GDBController(this); } GDBWindow* window = new GDBWindow(m_gdbController); + m_gdbController->setController(m_controller); + connect(m_controller.get(), &CoreController::stopping, window, &QWidget::close); openView(window); } #endif @@ -554,9 +514,12 @@ #ifdef USE_DEBUGGERS void Window::consoleOpen() { if (!m_console) { - m_console = new DebuggerConsoleController(m_controller, this); + m_console = new DebuggerConsoleController(this); } DebuggerConsole* window = new DebuggerConsole(m_console); + if (m_controller) { + m_console->setController(m_controller); + } openView(window); } #endif @@ -571,7 +534,9 @@ QWidget::keyPressEvent(event); return; } - m_controller->keyPressed(key); + if (m_controller) { + m_controller->addKey(key); + } event->accept(); } @@ -585,7 +550,9 @@ QWidget::keyPressEvent(event); return; } - m_controller->keyReleased(key); + if (m_controller) { + m_controller->clearKey(key); + } event->accept(); } @@ -597,7 +564,7 @@ int factor = 0; QSize size(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); - if (m_controller->isLoaded()) { + if (m_controller) { size = m_controller->screenDimensions(); } if (m_screenWidget->width() % size.width() == 0 && m_screenWidget->height() % size.height() == 0 && @@ -622,17 +589,19 @@ m_wasOpened = true; resizeFrame(m_screenWidget->sizeHint()); QVariant windowPos = m_config->getQtOption("windowPos"); - if (!windowPos.isNull()) { + QRect geom = QApplication::desktop()->availableGeometry(this); + if (!windowPos.isNull() && geom.contains(windowPos.toPoint())) { move(windowPos.toPoint()); } else { QRect rect = frameGeometry(); - rect.moveCenter(QApplication::desktop()->availableGeometry().center()); + rect.moveCenter(geom.center()); move(rect.topLeft()); } if (m_fullscreenOnStart) { enterFullScreen(); m_fullscreenOnStart = false; } + reloadDisplayDriver(); } void Window::closeEvent(QCloseEvent* event) { @@ -644,6 +613,7 @@ m_config->setOption("width", VIDEO_HORIZONTAL_PIXELS * m_savedScale); } saveConfig(); + m_display.reset(); QMainWindow::closeEvent(event); } @@ -652,9 +622,6 @@ } void Window::focusOutEvent(QFocusEvent*) { - m_controller->setTurbo(false, false); - m_controller->stopRewinding(); - m_controller->clearKeys(); } void Window::dragEnterEvent(QDragEnterEvent* event) { @@ -676,7 +643,7 @@ return; } event->accept(); - m_controller->loadGame(url.toLocalFile()); + setController(m_manager->loadGame(url.toLocalFile()), url.toLocalFile()); } void Window::mouseDoubleClickEvent(QMouseEvent* event) { @@ -696,7 +663,7 @@ } showFullScreen(); #ifndef Q_OS_MAC - if (m_controller->isLoaded() && !m_controller->isPaused()) { + if (m_controller && !m_controller->isPaused()) { menuBar()->hide(); } #endif @@ -719,89 +686,85 @@ } } -void Window::gameStarted(mCoreThread* context, const QString& fname) { - MutexLock(&context->stateMutex); - if (context->state < THREAD_EXITING) { - emit startDrawing(context); - } else { - MutexUnlock(&context->stateMutex); - return; - } - MutexUnlock(&context->stateMutex); +void Window::gameStarted() { for (QAction* action : m_gameActions) { action->setDisabled(false); } #ifdef M_CORE_GBA for (QAction* action : m_gbaActions) { - action->setDisabled(context->core->platform(context->core) != PLATFORM_GBA); + action->setDisabled(m_controller->platform() != PLATFORM_GBA); } #endif - multiplayerChanged(); - if (!fname.isEmpty()) { - setWindowFilePath(fname); - appendMRU(fname); - } - updateTitle(); - unsigned width, height; - context->core->desiredVideoDimensions(context->core, &width, &height); - m_display->setMinimumSize(width, height); - m_screenWidget->setMinimumSize(m_display->minimumSize()); - m_screenWidget->setDimensions(width, height); + QSize size = m_controller->screenDimensions(); + m_screenWidget->setDimensions(size.width(), size.height()); m_config->updateOption("lockIntegerScaling"); m_config->updateOption("lockAspectRatio"); if (m_savedScale > 0) { - resizeFrame(QSize(width, height) * m_savedScale); + resizeFrame(size * m_savedScale); } - attachWidget(m_display); + if (!m_display) { + reloadDisplayDriver(); + } + attachWidget(m_display.get()); + m_display->setMinimumSize(size); + setFocus(); #ifndef Q_OS_MAC if (isFullScreen()) { menuBar()->hide(); } #endif + m_display->startDrawing(m_controller); + + reloadAudioDriver(); + multiplayerChanged(); + updateTitle(); m_hitUnimplementedBiosCall = false; - m_fpsTimer.start(); + if (m_config->getOption("showFps", "1").toInt()) { + m_fpsTimer.start(); + m_frameTimer.start(); + } m_focusCheck.start(); if (m_display->underMouse()) { m_screenWidget->setCursor(Qt::BlankCursor); } - m_controller->threadInterrupt(); - if (m_controller->isLoaded()) { - mCore* core = m_controller->thread()->core; - const mCoreChannelInfo* videoLayers; - const mCoreChannelInfo* audioChannels; - size_t nVideo = core->listVideoLayers(core, &videoLayers); - size_t nAudio = core->listAudioChannels(core, &audioChannels); - - if (nVideo) { - for (size_t i = 0; i < nVideo; ++i) { - QAction* action = new QAction(videoLayers[i].visibleName, m_videoLayers); - action->setCheckable(true); - action->setChecked(true); - connect(action, &QAction::triggered, [this, videoLayers, i](bool enable) { - m_controller->setVideoLayerEnabled(videoLayers[i].id, enable); - }); - m_videoLayers->addAction(action); - } + CoreController::Interrupter interrupter(m_controller, true); + mCore* core = m_controller->thread()->core; + m_videoLayers->clear(); + m_audioChannels->clear(); + const mCoreChannelInfo* videoLayers; + const mCoreChannelInfo* audioChannels; + size_t nVideo = core->listVideoLayers(core, &videoLayers); + size_t nAudio = core->listAudioChannels(core, &audioChannels); + + if (nVideo) { + for (size_t i = 0; i < nVideo; ++i) { + QAction* action = new QAction(videoLayers[i].visibleName, m_videoLayers); + action->setCheckable(true); + action->setChecked(true); + connect(action, &QAction::triggered, [this, videoLayers, i](bool enable) { + m_controller->thread()->core->enableVideoLayer(m_controller->thread()->core, videoLayers[i].id, enable); + }); + m_videoLayers->addAction(action); } - if (nAudio) { - for (size_t i = 0; i < nAudio; ++i) { - QAction* action = new QAction(audioChannels[i].visibleName, m_audioChannels); - action->setCheckable(true); - action->setChecked(true); - connect(action, &QAction::triggered, [this, audioChannels, i](bool enable) { - m_controller->setAudioChannelEnabled(audioChannels[i].id, enable); - }); - m_audioChannels->addAction(action); - } + } + if (nAudio) { + for (size_t i = 0; i < nAudio; ++i) { + QAction* action = new QAction(audioChannels[i].visibleName, m_audioChannels); + action->setCheckable(true); + action->setChecked(true); + connect(action, &QAction::triggered, [this, audioChannels, i](bool enable) { + m_controller->thread()->core->enableAudioChannel(m_controller->thread()->core, audioChannels[i].id, enable); + }); + m_audioChannels->addAction(action); } } - m_controller->threadContinue(); } void Window::gameStopped() { + m_controller.reset(); #ifdef M_CORE_GBA for (QAction* action : m_gbaActions) { action->setDisabled(false); @@ -812,24 +775,27 @@ } setWindowFilePath(QString()); updateTitle(); - detachWidget(m_display); + detachWidget(m_display.get()); m_screenWidget->setDimensions(m_logo.width(), m_logo.height()); m_screenWidget->setLockIntegerScaling(false); m_screenWidget->setLockAspectRatio(true); m_screenWidget->setPixmap(m_logo); m_screenWidget->unsetCursor(); + if (m_display) { #ifdef M_CORE_GB - m_display->setMinimumSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); + m_display->setMinimumSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); #elif defined(M_CORE_GBA) - m_display->setMinimumSize(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); + m_display->setMinimumSize(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); #endif - m_screenWidget->setMinimumSize(m_display->minimumSize()); + } m_videoLayers->clear(); m_audioChannels->clear(); m_fpsTimer.stop(); m_focusCheck.stop(); + + emit paused(false); } void Window::gameCrashed(const QString& errorMessage) { @@ -838,7 +804,7 @@ QMessageBox::Ok, this, Qt::Sheet); crash->setAttribute(Qt::WA_DeleteOnClose); crash->show(); - connect(m_controller, &GameController::gameStarted, crash, &QWidget::close); + m_controller->stop(); } void Window::gameFailed() { @@ -847,7 +813,6 @@ QMessageBox::Ok, this, Qt::Sheet); fail->setAttribute(Qt::WA_DeleteOnClose); fail->show(); - connect(m_controller, &GameController::gameStarted, fail, &QWidget::close); } void Window::unimplementedBiosCall(int call) { @@ -864,6 +829,81 @@ fail->show(); } +void Window::reloadDisplayDriver() { + if (m_controller) { + m_display->stopDrawing(); + detachWidget(m_display.get()); + } + m_display = std::move(std::unique_ptr(Display::create(this))); +#if defined(BUILD_GL) || defined(BUILD_GLES2) + m_shaderView.reset(); + m_shaderView = std::make_unique(m_display.get(), m_config); +#endif + + connect(this, &Window::shutdown, m_display.get(), &Display::stopDrawing); + connect(m_display.get(), &Display::hideCursor, [this]() { + if (static_cast(m_screenWidget->layout())->currentWidget() == m_display.get()) { + m_screenWidget->setCursor(Qt::BlankCursor); + } + }); + connect(m_display.get(), &Display::showCursor, [this]() { + m_screenWidget->unsetCursor(); + }); + + const mCoreOptions* opts = m_config->options(); + m_display->lockAspectRatio(opts->lockAspectRatio); + m_display->filter(opts->resampleVideo); +#if defined(BUILD_GL) || defined(BUILD_GLES2) + if (opts->shader) { + struct VDir* shader = VDirOpen(opts->shader); + if (shader && m_display->supportsShaders()) { + m_display->setShaders(shader); + m_shaderView->refreshShaders(); + shader->close(shader); + } + } +#endif + + if (m_controller) { + m_display->setMinimumSize(m_controller->screenDimensions()); + connect(m_controller.get(), &CoreController::stopping, m_display.get(), &Display::stopDrawing); + connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::resizeContext); + connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::forceDraw); + connect(m_controller.get(), &CoreController::rewound, m_display.get(), &Display::forceDraw); + connect(m_controller.get(), &CoreController::paused, m_display.get(), &Display::pauseDrawing); + connect(m_controller.get(), &CoreController::unpaused, m_display.get(), &Display::unpauseDrawing); + connect(m_controller.get(), &CoreController::frameAvailable, m_display.get(), &Display::framePosted); + connect(m_controller.get(), &CoreController::statusPosted, m_display.get(), &Display::showMessage); + + attachWidget(m_display.get()); + m_display->startDrawing(m_controller); + } else { +#ifdef M_CORE_GB + m_display->setMinimumSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); +#elif defined(M_CORE_GBA) + m_display->setMinimumSize(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); +#endif + } +} + +void Window::reloadAudioDriver() { + if (!m_controller) { + return; + } + if (m_audioProcessor) { + m_audioProcessor->stop(); + m_audioProcessor.reset(); + } + + const mCoreOptions* opts = m_config->options(); + m_audioProcessor = std::move(std::unique_ptr(AudioProcessor::create())); + m_audioProcessor->setInput(m_controller); + m_audioProcessor->setBufferSamples(opts->audioBuffers); + m_audioProcessor->requestSampleRate(opts->sampleRate); + m_audioProcessor->start(); + connect(m_controller.get(), &CoreController::stopping, m_audioProcessor.get(), &AudioProcessor::stop); +} + void Window::tryMakePortable() { QMessageBox* confirm = new QMessageBox(QMessageBox::Question, tr("Really make portable?"), tr("This will make the emulator load its configuration from the same directory as the executable. Do you want to continue?"), @@ -882,10 +922,8 @@ } void Window::recordFrame() { - m_frameList.append(QDateTime::currentDateTime()); - while (m_frameList.count() > FRAME_LIST_SIZE) { - m_frameList.removeFirst(); - } + m_frameList.append(m_frameTimer.nsecsElapsed()); + m_frameTimer.restart(); } void Window::showFPS() { @@ -893,8 +931,12 @@ updateTitle(); return; } - qint64 interval = m_frameList.first().msecsTo(m_frameList.last()); - float fps = (m_frameList.count() - 1) * 10000.f / interval; + qint64 total = 0; + for (qint64 t : m_frameList) { + total += t; + } + double fps = (m_frameList.size() * 1e10) / total; + m_frameList.clear(); fps = round(fps) / 10.f; updateTitle(fps); } @@ -902,8 +944,8 @@ void Window::updateTitle(float fps) { QString title; - m_controller->threadInterrupt(); - if (m_controller->isLoaded()) { + if (m_controller) { + CoreController::Interrupter interrupter(m_controller); const NoIntroDB* db = GBAApp::app()->gameDB(); NoIntroGame game{}; uint32_t crc32 = 0; @@ -919,19 +961,18 @@ title = QLatin1String(game.name); } #endif - } - MultiplayerController* multiplayer = m_controller->multiplayerController(); - if (multiplayer && multiplayer->attached() > 1) { - title += tr(" - Player %1 of %2").arg(multiplayer->playerId(m_controller) + 1).arg(multiplayer->attached()); - for (QAction* action : m_nonMpActions) { - action->setDisabled(true); - } - } else if (m_controller->isLoaded()) { - for (QAction* action : m_nonMpActions) { - action->setDisabled(false); + MultiplayerController* multiplayer = m_controller->multiplayerController(); + if (multiplayer && multiplayer->attached() > 1) { + title += tr(" - Player %1 of %2").arg(multiplayer->playerId(m_controller.get()) + 1).arg(multiplayer->attached()); + for (QAction* action : m_nonMpActions) { + action->setDisabled(true); + } + } else { + for (QAction* action : m_nonMpActions) { + action->setDisabled(false); + } } } - m_controller->threadContinue(); if (title.isNull()) { setWindowTitle(tr("%1 - %2").arg(projectName).arg(projectVersion)); } else if (fps < 0) { @@ -952,7 +993,6 @@ bool wasPaused = m_controller->isPaused(); m_stateWindow = new LoadSaveState(m_controller); connect(this, &Window::shutdown, m_stateWindow, &QWidget::close); - connect(m_controller, &GameController::gameStopped, m_stateWindow, &QWidget::close); connect(m_stateWindow, &LoadSaveState::closed, [this]() { detachWidget(m_stateWindow); m_stateWindow = nullptr; @@ -960,10 +1000,15 @@ }); if (!wasPaused) { m_controller->setPaused(true); - connect(m_stateWindow, &LoadSaveState::closed, [this]() { m_controller->setPaused(false); }); + connect(m_stateWindow, &LoadSaveState::closed, [this]() { + if (m_controller) { + m_controller->setPaused(false); + } + }); } m_stateWindow->setAttribute(Qt::WA_DeleteOnClose); m_stateWindow->setMode(ls); + updateFrame(); attachWidget(m_stateWindow); } @@ -981,6 +1026,11 @@ "addDirToLibrary"); #endif + QAction* loadAlternateSave = new QAction(tr("Load alternate save..."), fileMenu); + connect(loadAlternateSave, &QAction::triggered, [this]() { this->selectSave(false); }); + m_gameActions.append(loadAlternateSave); + addControlledAction(fileMenu, loadAlternateSave, "loadAlternateSave"); + QAction* loadTemporarySave = new QAction(tr("Load temporary save..."), fileMenu); connect(loadTemporarySave, &QAction::triggered, [this]() { this->selectSave(true); }); m_gameActions.append(loadTemporarySave); @@ -988,17 +1038,18 @@ addControlledAction(fileMenu, fileMenu->addAction(tr("Load &patch..."), this, SLOT(selectPatch())), "loadPatch"); +#ifdef M_CORE_GBA QAction* bootBIOS = new QAction(tr("Boot BIOS"), fileMenu); connect(bootBIOS, &QAction::triggered, [this]() { - m_controller->loadBIOS(PLATFORM_GBA, m_config->getOption("gba.bios")); - m_controller->bootBIOS(); + setController(m_manager->loadBIOS(PLATFORM_GBA, m_config->getOption("gba.bios")), QString()); }); addControlledAction(fileMenu, bootBIOS, "bootBIOS"); +#endif addControlledAction(fileMenu, fileMenu->addAction(tr("Replace ROM..."), this, SLOT(replaceROM())), "replaceROM"); QAction* romInfo = new QAction(tr("ROM &info..."), fileMenu); - connect(romInfo, &QAction::triggered, openTView()); + connect(romInfo, &QAction::triggered, openControllerTView()); m_gameActions.append(romInfo); addControlledAction(fileMenu, romInfo, "romInfo"); @@ -1017,6 +1068,12 @@ m_nonMpActions.append(loadState); addControlledAction(fileMenu, loadState, "loadState"); + QAction* loadStateFile = new QAction(tr("Load state file..."), fileMenu); + connect(loadStateFile, &QAction::triggered, [this]() { this->selectState(true); }); + m_gameActions.append(loadStateFile); + m_nonMpActions.append(loadStateFile); + addControlledAction(fileMenu, loadStateFile, "loadStateFile"); + QAction* saveState = new QAction(tr("&Save state"), fileMenu); saveState->setShortcut(tr("Shift+F10")); connect(saveState, &QAction::triggered, [this]() { this->openStateWindow(LoadSave::SAVE); }); @@ -1024,19 +1081,29 @@ m_nonMpActions.append(saveState); addControlledAction(fileMenu, saveState, "saveState"); + QAction* saveStateFile = new QAction(tr("Save state file..."), fileMenu); + connect(saveStateFile, &QAction::triggered, [this]() { this->selectState(false); }); + m_gameActions.append(saveStateFile); + m_nonMpActions.append(saveStateFile); + addControlledAction(fileMenu, saveStateFile, "saveStateFile"); + QMenu* quickLoadMenu = fileMenu->addMenu(tr("Quick load")); QMenu* quickSaveMenu = fileMenu->addMenu(tr("Quick save")); m_shortcutController->addMenu(quickLoadMenu); m_shortcutController->addMenu(quickSaveMenu); QAction* quickLoad = new QAction(tr("Load recent"), quickLoadMenu); - connect(quickLoad, &QAction::triggered, m_controller, &GameController::loadState); + connect(quickLoad, &QAction::triggered, [this] { + m_controller->loadState(); + }); m_gameActions.append(quickLoad); m_nonMpActions.append(quickLoad); addControlledAction(quickLoadMenu, quickLoad, "quickLoad"); QAction* quickSave = new QAction(tr("Save recent"), quickSaveMenu); - connect(quickSave, &QAction::triggered, m_controller, &GameController::saveState); + connect(quickLoad, &QAction::triggered, [this] { + m_controller->saveState(); + }); m_gameActions.append(quickSave); m_nonMpActions.append(quickSave); addControlledAction(quickSaveMenu, quickSave, "quickSave"); @@ -1046,14 +1113,18 @@ QAction* undoLoadState = new QAction(tr("Undo load state"), quickLoadMenu); undoLoadState->setShortcut(tr("F11")); - connect(undoLoadState, &QAction::triggered, m_controller, &GameController::loadBackupState); + connect(undoLoadState, &QAction::triggered, [this]() { + m_controller->loadBackupState(); + }); m_gameActions.append(undoLoadState); m_nonMpActions.append(undoLoadState); addControlledAction(quickLoadMenu, undoLoadState, "undoLoadState"); QAction* undoSaveState = new QAction(tr("Undo save state"), quickSaveMenu); undoSaveState->setShortcut(tr("Shift+F11")); - connect(undoSaveState, &QAction::triggered, m_controller, &GameController::saveBackupState); + connect(undoSaveState, &QAction::triggered, [this]() { + m_controller->saveBackupState(); + }); m_gameActions.append(undoSaveState); m_nonMpActions.append(undoSaveState); addControlledAction(quickSaveMenu, undoSaveState, "undoSaveState"); @@ -1065,19 +1136,28 @@ for (i = 1; i < 10; ++i) { quickLoad = new QAction(tr("State &%1").arg(i), quickLoadMenu); quickLoad->setShortcut(tr("F%1").arg(i)); - connect(quickLoad, &QAction::triggered, [this, i]() { m_controller->loadState(i); }); + connect(quickLoad, &QAction::triggered, [this, i]() { + m_controller->loadState(i); + }); m_gameActions.append(quickLoad); m_nonMpActions.append(quickLoad); addControlledAction(quickLoadMenu, quickLoad, QString("quickLoad.%1").arg(i)); quickSave = new QAction(tr("State &%1").arg(i), quickSaveMenu); quickSave->setShortcut(tr("Shift+F%1").arg(i)); - connect(quickSave, &QAction::triggered, [this, i]() { m_controller->saveState(i); }); + connect(quickSave, &QAction::triggered, [this, i]() { + m_controller->saveState(i); + }); m_gameActions.append(quickSave); m_nonMpActions.append(quickSave); addControlledAction(quickSaveMenu, quickSave, QString("quickSave.%1").arg(i)); } + fileMenu->addSeparator(); + QAction* camImage = new QAction(tr("Load camera image..."), fileMenu); + connect(camImage, &QAction::triggered, this, &Window::loadCamImage); + addControlledAction(fileMenu, camImage, "loadCamImage"); + #ifdef M_CORE_GBA fileMenu->addSeparator(); QAction* importShark = new QAction(tr("Import GameShark Save"), fileMenu); @@ -1105,7 +1185,7 @@ #endif QAction* about = new QAction(tr("About"), fileMenu); - connect(about, &QAction::triggered, this, &Window::openAboutScreen); + connect(about, &QAction::triggered, openTView()); fileMenu->addAction(about); #ifndef Q_OS_MAC @@ -1116,18 +1196,24 @@ m_shortcutController->addMenu(emulationMenu); QAction* reset = new QAction(tr("&Reset"), emulationMenu); reset->setShortcut(tr("Ctrl+R")); - connect(reset, &QAction::triggered, m_controller, &GameController::reset); + connect(reset, &QAction::triggered, [this]() { + m_controller->reset(); + }); m_gameActions.append(reset); addControlledAction(emulationMenu, reset, "reset"); QAction* shutdown = new QAction(tr("Sh&utdown"), emulationMenu); - connect(shutdown, &QAction::triggered, m_controller, &GameController::closeGame); + connect(shutdown, &QAction::triggered, [this]() { + m_controller->stop(); + }); m_gameActions.append(shutdown); addControlledAction(emulationMenu, shutdown, "shutdown"); #ifdef M_CORE_GBA QAction* yank = new QAction(tr("Yank game pak"), emulationMenu); - connect(yank, &QAction::triggered, m_controller, &GameController::yankPak); + connect(yank, &QAction::triggered, [this]() { + m_controller->yankPak(); + }); m_gameActions.append(yank); m_gbaActions.append(yank); addControlledAction(emulationMenu, yank, "yank"); @@ -1138,39 +1224,52 @@ pause->setChecked(false); pause->setCheckable(true); pause->setShortcut(tr("Ctrl+P")); - connect(pause, &QAction::triggered, m_controller, &GameController::setPaused); - connect(m_controller, &GameController::gamePaused, [this, pause]() { - pause->setChecked(true); + connect(pause, &QAction::triggered, [this](bool paused) { + if (m_controller) { + m_controller->setPaused(paused); + } else { + m_pendingPause = paused; + } + }); + connect(this, &Window::paused, [pause](bool paused) { + pause->setChecked(paused); }); - connect(m_controller, &GameController::gameUnpaused, [pause]() { pause->setChecked(false); }); - m_gameActions.append(pause); addControlledAction(emulationMenu, pause, "pause"); QAction* frameAdvance = new QAction(tr("&Next frame"), emulationMenu); frameAdvance->setShortcut(tr("Ctrl+N")); - connect(frameAdvance, &QAction::triggered, m_controller, &GameController::frameAdvance); + connect(frameAdvance, &QAction::triggered, [this]() { + m_controller->frameAdvance(); + }); m_gameActions.append(frameAdvance); addControlledAction(emulationMenu, frameAdvance, "frameAdvance"); emulationMenu->addSeparator(); m_shortcutController->addFunctions(emulationMenu, [this]() { - m_controller->setTurbo(true, false); + if (m_controller) { + m_controller->setFastForward(true); + } }, [this]() { - m_controller->setTurbo(false, false); + if (m_controller) { + m_controller->setFastForward(false); + } }, QKeySequence(Qt::Key_Tab), tr("Fast forward (held)"), "holdFastForward"); QAction* turbo = new QAction(tr("&Fast forward"), emulationMenu); turbo->setCheckable(true); turbo->setChecked(false); turbo->setShortcut(tr("Shift+Tab")); - connect(turbo, SIGNAL(triggered(bool)), m_controller, SLOT(setTurbo(bool))); + connect(turbo, &QAction::triggered, [this](bool value) { + m_controller->forceFastForward(value); + }); addControlledAction(emulationMenu, turbo, "fastForward"); + m_gameActions.append(turbo); QMenu* ffspeedMenu = emulationMenu->addMenu(tr("Fast forward speed")); ConfigOption* ffspeed = m_config->addOption("fastForwardRatio"); ffspeed->connect([this](const QVariant& value) { - m_controller->setTurboSpeed(value.toFloat()); + reloadConfig(); }, this); ffspeed->addValue(tr("Unbounded"), -1.0f, ffspeedMenu); ffspeed->setValue(QVariant(-1.0f)); @@ -1181,14 +1280,20 @@ m_config->updateOption("fastForwardRatio"); m_shortcutController->addFunctions(emulationMenu, [this]() { - m_controller->startRewinding(); + if (m_controller) { + m_controller->setRewinding(true); + } }, [this]() { - m_controller->stopRewinding(); + if (m_controller) { + m_controller->setRewinding(false); + } }, QKeySequence("`"), tr("Rewind (held)"), "holdRewind"); QAction* rewind = new QAction(tr("Re&wind"), emulationMenu); rewind->setShortcut(tr("~")); - connect(rewind, &QAction::triggered, m_controller, &GameController::rewind); + connect(rewind, &QAction::triggered, [this]() { + m_controller->rewind(); + }); m_gameActions.append(rewind); m_nonMpActions.append(rewind); addControlledAction(emulationMenu, rewind, "rewind"); @@ -1205,14 +1310,14 @@ ConfigOption* videoSync = m_config->addOption("videoSync"); videoSync->addBoolean(tr("Sync to &video"), emulationMenu); videoSync->connect([this](const QVariant& value) { - m_controller->setVideoSync(value.toBool()); + reloadConfig(); }, this); m_config->updateOption("videoSync"); ConfigOption* audioSync = m_config->addOption("audioSync"); audioSync->addBoolean(tr("Sync to &audio"), emulationMenu); audioSync->connect([this](const QVariant& value) { - m_controller->setAudioSync(value.toBool()); + reloadConfig(); }, this); m_config->updateOption("audioSync"); @@ -1221,26 +1326,26 @@ QMenu* solarMenu = emulationMenu->addMenu(tr("Solar sensor")); m_shortcutController->addMenu(solarMenu); QAction* solarIncrease = new QAction(tr("Increase solar level"), solarMenu); - connect(solarIncrease, &QAction::triggered, m_controller, &GameController::increaseLuminanceLevel); + connect(solarIncrease, &QAction::triggered, &m_inputController, &InputController::increaseLuminanceLevel); addControlledAction(solarMenu, solarIncrease, "increaseLuminanceLevel"); QAction* solarDecrease = new QAction(tr("Decrease solar level"), solarMenu); - connect(solarDecrease, &QAction::triggered, m_controller, &GameController::decreaseLuminanceLevel); + connect(solarDecrease, &QAction::triggered, &m_inputController, &InputController::decreaseLuminanceLevel); addControlledAction(solarMenu, solarDecrease, "decreaseLuminanceLevel"); QAction* maxSolar = new QAction(tr("Brightest solar level"), solarMenu); - connect(maxSolar, &QAction::triggered, [this]() { m_controller->setLuminanceLevel(10); }); + connect(maxSolar, &QAction::triggered, [this]() { m_inputController.setLuminanceLevel(10); }); addControlledAction(solarMenu, maxSolar, "maxLuminanceLevel"); QAction* minSolar = new QAction(tr("Darkest solar level"), solarMenu); - connect(minSolar, &QAction::triggered, [this]() { m_controller->setLuminanceLevel(0); }); + connect(minSolar, &QAction::triggered, [this]() { m_inputController.setLuminanceLevel(0); }); addControlledAction(solarMenu, minSolar, "minLuminanceLevel"); solarMenu->addSeparator(); for (int i = 0; i <= 10; ++i) { QAction* setSolar = new QAction(tr("Brightness %1").arg(QString::number(i)), solarMenu); connect(setSolar, &QAction::triggered, [this, i]() { - m_controller->setLuminanceLevel(i); + m_inputController.setLuminanceLevel(i); }); addControlledAction(solarMenu, setSolar, QString("luminanceLevel.%1").arg(QString::number(i))); } @@ -1258,7 +1363,7 @@ connect(setSize, &QAction::triggered, [this, i, setSize]() { showNormal(); QSize size(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); - if (m_controller->isLoaded()) { + if (m_controller) { size = m_controller->screenDimensions(); } size *= i; @@ -1283,8 +1388,10 @@ ConfigOption* lockAspectRatio = m_config->addOption("lockAspectRatio"); lockAspectRatio->addBoolean(tr("Lock aspect ratio"), avMenu); lockAspectRatio->connect([this](const QVariant& value) { - m_display->lockAspectRatio(value.toBool()); - if (m_controller->isLoaded()) { + if (m_display) { + m_display->lockAspectRatio(value.toBool()); + } + if (m_controller) { m_screenWidget->setLockAspectRatio(value.toBool()); } }, this); @@ -1293,8 +1400,10 @@ ConfigOption* lockIntegerScaling = m_config->addOption("lockIntegerScaling"); lockIntegerScaling->addBoolean(tr("Force integer scaling"), avMenu); lockIntegerScaling->connect([this](const QVariant& value) { - m_display->lockIntegerScaling(value.toBool()); - if (m_controller->isLoaded()) { + if (m_display) { + m_display->lockIntegerScaling(value.toBool()); + } + if (m_controller) { m_screenWidget->setLockIntegerScaling(value.toBool()); } }, this); @@ -1303,7 +1412,9 @@ ConfigOption* resampleVideo = m_config->addOption("resampleVideo"); resampleVideo->addBoolean(tr("Bilinear filtering"), avMenu); resampleVideo->connect([this](const QVariant& value) { - m_display->filter(value.toBool()); + if (m_display) { + m_display->filter(value.toBool()); + } }, this); m_config->updateOption("resampleVideo"); @@ -1329,27 +1440,32 @@ QMenu* target = avMenu->addMenu(tr("FPS target")); ConfigOption* fpsTargetOption = m_config->addOption("fpsTarget"); - fpsTargetOption->connect([this](const QVariant& value) { - emit fpsTargetChanged(value.toFloat()); + QMap fpsTargets; + for (int fps : {15, 30, 45, 60, 90, 120, 240}) { + fpsTargets[fps] = fpsTargetOption->addValue(QString::number(fps), fps, target); + } + target->addSeparator(); + double nativeGB = double(GBA_ARM7TDMI_FREQUENCY) / double(VIDEO_TOTAL_LENGTH); + fpsTargets[nativeGB] = fpsTargetOption->addValue(tr("Native (59.7275)"), nativeGB, target); + + fpsTargetOption->connect([this, fpsTargets](const QVariant& value) { + reloadConfig(); + for (auto iter = fpsTargets.begin(); iter != fpsTargets.end(); ++iter) { + bool enableSignals = iter.value()->blockSignals(true); + iter.value()->setChecked(abs(iter.key() - value.toDouble()) < 0.001); + iter.value()->blockSignals(enableSignals); + } }, this); - fpsTargetOption->addValue(tr("15"), 15, target); - fpsTargetOption->addValue(tr("30"), 30, target); - fpsTargetOption->addValue(tr("45"), 45, target); - fpsTargetOption->addValue(tr("Native (59.7)"), float(GBA_ARM7TDMI_FREQUENCY) / float(VIDEO_TOTAL_LENGTH), target); - fpsTargetOption->addValue(tr("60"), 60, target); - fpsTargetOption->addValue(tr("90"), 90, target); - fpsTargetOption->addValue(tr("120"), 120, target); - fpsTargetOption->addValue(tr("240"), 240, target); m_config->updateOption("fpsTarget"); -#if defined(USE_PNG) || defined(USE_FFMPEG) || defined(USE_MAGICK) avMenu->addSeparator(); -#endif #ifdef USE_PNG QAction* screenshot = new QAction(tr("Take &screenshot"), avMenu); screenshot->setShortcut(tr("F12")); - connect(screenshot, &QAction::triggered, m_controller, &GameController::screenshot); + connect(screenshot, &QAction::triggered, [this]() { + m_controller->screenshot(); + }); m_gameActions.append(screenshot); addControlledAction(avMenu, screenshot, "screenshot"); #endif @@ -1373,10 +1489,24 @@ m_gameActions.append(recordVL); QAction* stopVL = new QAction(tr("Stop video log"), avMenu); - connect(stopVL, &QAction::triggered, m_controller, &GameController::endVideoLog); + connect(stopVL, &QAction::triggered, [this]() { + m_controller->endVideoLog(); + }); addControlledAction(avMenu, stopVL, "stopVL"); m_gameActions.append(stopVL); +#ifdef M_CORE_GB + QAction* gbPrint = new QAction(tr("Game Boy Printer..."), avMenu); + connect(gbPrint, &QAction::triggered, [this]() { + PrinterView* view = new PrinterView(m_controller); + openView(view); + m_controller->attachPrinter(); + + }); + addControlledAction(avMenu, gbPrint, "gbPrint"); + m_gameActions.append(gbPrint); +#endif + avMenu->addSeparator(); m_videoLayers = avMenu->addMenu(tr("Video layers")); m_shortcutController->addMenu(m_videoLayers, avMenu); @@ -1384,6 +1514,11 @@ m_audioChannels = avMenu->addMenu(tr("Audio channels")); m_shortcutController->addMenu(m_audioChannels, avMenu); + QAction* placementControl = new QAction(tr("Adjust layer placement..."), avMenu); + connect(placementControl, &QAction::triggered, openControllerTView()); + m_gameActions.append(placementControl); + addControlledAction(avMenu, placementControl, "placementControl"); + QMenu* toolsMenu = menubar->addMenu(tr("&Tools")); m_shortcutController->addMenu(toolsMenu); QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu); @@ -1391,15 +1526,34 @@ addControlledAction(toolsMenu, viewLogs, "viewLogs"); QAction* overrides = new QAction(tr("Game &overrides..."), toolsMenu); - connect(overrides, &QAction::triggered, openTView(m_config)); + connect(overrides, &QAction::triggered, [this]() { + if (!m_overrideView) { + m_overrideView = std::move(std::make_unique(m_config)); + if (m_controller) { + m_overrideView->setController(m_controller); + } + connect(this, &Window::shutdown, m_overrideView.get(), &QWidget::close); + } + m_overrideView->show(); + m_overrideView->recheck(); + }); addControlledAction(toolsMenu, overrides, "overrideWindow"); QAction* sensors = new QAction(tr("Game &Pak sensors..."), toolsMenu); - connect(sensors, &QAction::triggered, openTView(&m_inputController)); + connect(sensors, &QAction::triggered, [this]() { + if (!m_sensorView) { + m_sensorView = std::move(std::make_unique(&m_inputController)); + if (m_controller) { + m_sensorView->setController(m_controller); + } + connect(this, &Window::shutdown, m_sensorView.get(), &QWidget::close); + } + m_sensorView->show(); + }); addControlledAction(toolsMenu, sensors, "sensorWindow"); QAction* cheats = new QAction(tr("&Cheats..."), toolsMenu); - connect(cheats, &QAction::triggered, openTView()); + connect(cheats, &QAction::triggered, openControllerTView()); m_gameActions.append(cheats); addControlledAction(toolsMenu, cheats, "cheatsWindow"); @@ -1419,38 +1573,44 @@ QAction* gdbWindow = new QAction(tr("Start &GDB server..."), toolsMenu); connect(gdbWindow, &QAction::triggered, this, &Window::gdbOpen); m_gbaActions.append(gdbWindow); + m_gameActions.append(gdbWindow); addControlledAction(toolsMenu, gdbWindow, "gdbWindow"); #endif toolsMenu->addSeparator(); QAction* paletteView = new QAction(tr("View &palette..."), toolsMenu); - connect(paletteView, &QAction::triggered, openTView()); + connect(paletteView, &QAction::triggered, openControllerTView()); m_gameActions.append(paletteView); addControlledAction(toolsMenu, paletteView, "paletteWindow"); QAction* objView = new QAction(tr("View &sprites..."), toolsMenu); - connect(objView, &QAction::triggered, openTView()); + connect(objView, &QAction::triggered, openControllerTView()); m_gameActions.append(objView); addControlledAction(toolsMenu, objView, "spriteWindow"); QAction* tileView = new QAction(tr("View &tiles..."), toolsMenu); - connect(tileView, &QAction::triggered, openTView()); + connect(tileView, &QAction::triggered, openControllerTView()); m_gameActions.append(tileView); addControlledAction(toolsMenu, tileView, "tileWindow"); + QAction* mapView = new QAction(tr("View &map..."), toolsMenu); + connect(mapView, &QAction::triggered, openControllerTView()); + m_gameActions.append(mapView); + addControlledAction(toolsMenu, mapView, "mapWindow"); + QAction* memoryView = new QAction(tr("View memory..."), toolsMenu); - connect(memoryView, &QAction::triggered, openTView()); + connect(memoryView, &QAction::triggered, openControllerTView()); m_gameActions.append(memoryView); addControlledAction(toolsMenu, memoryView, "memoryView"); QAction* memorySearch = new QAction(tr("Search memory..."), toolsMenu); - connect(memorySearch, &QAction::triggered, openTView()); + connect(memorySearch, &QAction::triggered, openControllerTView()); m_gameActions.append(memorySearch); addControlledAction(toolsMenu, memorySearch, "memorySearch"); #ifdef M_CORE_GBA QAction* ioViewer = new QAction(tr("View &I/O registers..."), toolsMenu); - connect(ioViewer, &QAction::triggered, openTView()); + connect(ioViewer, &QAction::triggered, openControllerTView()); m_gameActions.append(ioViewer); m_gbaActions.append(ioViewer); addControlledAction(toolsMenu, ioViewer, "ioViewer"); @@ -1463,17 +1623,17 @@ ConfigOption* useBios = m_config->addOption("useBios"); useBios->connect([this](const QVariant& value) { - m_controller->setUseBIOS(value.toBool()); + reloadConfig(); }, this); ConfigOption* buffers = m_config->addOption("audioBuffers"); buffers->connect([this](const QVariant& value) { - emit audioBufferSamplesChanged(value.toInt()); + reloadConfig(); }, this); ConfigOption* sampleRate = m_config->addOption("sampleRate"); sampleRate->connect([this](const QVariant& value) { - emit sampleRateChanged(value.toUInt()); + reloadConfig(); }, this); ConfigOption* volume = m_config->addOption("volume"); @@ -1481,49 +1641,73 @@ reloadConfig(); }, this); + ConfigOption* volumeFf = m_config->addOption("fastForwardVolume"); + volumeFf->connect([this](const QVariant& value) { + reloadConfig(); + }, this); + + ConfigOption* muteFf = m_config->addOption("fastForwardMute"); + muteFf->connect([this](const QVariant& value) { + reloadConfig(); + }, this); + ConfigOption* rewindEnable = m_config->addOption("rewindEnable"); rewindEnable->connect([this](const QVariant& value) { - m_controller->setRewind(value.toBool(), m_config->getOption("rewindBufferCapacity").toInt(), m_config->getOption("rewindSave").toInt()); + reloadConfig(); }, this); ConfigOption* rewindBufferCapacity = m_config->addOption("rewindBufferCapacity"); rewindBufferCapacity->connect([this](const QVariant& value) { - m_controller->setRewind(m_config->getOption("rewindEnable").toInt(), value.toInt(), m_config->getOption("rewindSave").toInt()); - }, this); - - ConfigOption* rewindSave = m_config->addOption("rewindSave"); - rewindBufferCapacity->connect([this](const QVariant& value) { - m_controller->setRewind(m_config->getOption("rewindEnable").toInt(), m_config->getOption("rewindBufferCapacity").toInt(), value.toBool()); + reloadConfig(); }, this); ConfigOption* allowOpposingDirections = m_config->addOption("allowOpposingDirections"); allowOpposingDirections->connect([this](const QVariant& value) { - m_inputController.setAllowOpposing(value.toBool()); + reloadConfig(); }, this); ConfigOption* saveStateExtdata = m_config->addOption("saveStateExtdata"); saveStateExtdata->connect([this](const QVariant& value) { - m_controller->setSaveStateExtdata(value.toInt()); + reloadConfig(); }, this); - m_config->updateOption("saveStateExtdata"); ConfigOption* loadStateExtdata = m_config->addOption("loadStateExtdata"); loadStateExtdata->connect([this](const QVariant& value) { - m_controller->setLoadStateExtdata(value.toInt()); + reloadConfig(); }, this); - m_config->updateOption("loadStateExtdata"); ConfigOption* preload = m_config->addOption("preload"); preload->connect([this](const QVariant& value) { - m_controller->setPreload(value.toBool()); + m_manager->setPreload(value.toBool()); }, this); m_config->updateOption("preload"); + ConfigOption* showFps = m_config->addOption("showFps"); + showFps->connect([this](const QVariant& value) { + if (!value.toInt()) { + m_fpsTimer.stop(); + updateTitle(); + } else if (m_controller) { + m_fpsTimer.start(); + m_frameTimer.start(); + } + }, this); + QAction* exitFullScreen = new QAction(tr("Exit fullscreen"), frameMenu); connect(exitFullScreen, &QAction::triggered, this, &Window::exitFullScreen); exitFullScreen->setShortcut(QKeySequence("Esc")); addHiddenAction(frameMenu, exitFullScreen, "exitFullScreen"); + m_shortcutController->addFunctions(toolsMenu, [this]() { + if (m_controller) { + mCheatPressButton(m_controller->cheatDevice(), true); + } + }, [this]() { + if (m_controller) { + mCheatPressButton(m_controller->cheatDevice(), false); + } + }, QKeySequence(Qt::Key_Apostrophe), tr("GameShark Button (held)"), "holdGSButton"); + QMenu* autofireMenu = new QMenu(tr("Autofire"), this); m_shortcutController->addMenu(autofireMenu); @@ -1626,7 +1810,9 @@ for (const QString& file : m_mruFiles) { QAction* item = new QAction(QDir::toNativeSeparators(file).replace("&", "&&"), m_mruMenu); item->setShortcut(QString("Ctrl+%1").arg(i)); - connect(item, &QAction::triggered, [this, file]() { m_controller->loadGame(file); }); + connect(item, &QAction::triggered, [this, file]() { + setController(m_manager->loadGame(file), file); + }); m_mruMenu->addAction(item); ++i; } @@ -1649,7 +1835,7 @@ } void Window::focusCheck() { - if (!m_config->getOption("pauseOnFocusLost").toInt()) { + if (!m_config->getOption("pauseOnFocusLost").toInt() || !m_controller) { return; } if (QGuiApplication::focusWindow() && m_autoresume) { @@ -1661,12 +1847,146 @@ } } +void Window::updateFrame() { + QSize size = m_controller->screenDimensions(); + QImage currentImage(reinterpret_cast(m_controller->drawContext()), size.width(), size.height(), + size.width() * BYTES_PER_PIXEL, QImage::Format_RGBX8888); + QPixmap pixmap; + pixmap.convertFromImage(currentImage); + m_screenWidget->setPixmap(pixmap); + emit paused(true); +} + +void Window::setController(CoreController* controller, const QString& fname) { + if (!controller) { + return; + } + + if (m_controller) { + m_controller->stop(); + QTimer::singleShot(0, this, [this, controller, fname]() { + setController(controller, fname); + }); + return; + } + if (!fname.isEmpty()) { + setWindowFilePath(fname); + appendMRU(fname); + } + + m_controller = std::shared_ptr(controller); + m_inputController.recalibrateAxes(); + m_controller->setInputController(&m_inputController); + m_controller->setLogger(&m_log); + + connect(this, &Window::shutdown, [this]() { + if (!m_controller) { + return; + } + m_controller->stop(); + }); + + connect(m_controller.get(), &CoreController::started, this, &Window::gameStarted); + connect(m_controller.get(), &CoreController::started, &m_inputController, &InputController::suspendScreensaver); + connect(m_controller.get(), &CoreController::stopping, this, &Window::gameStopped); + { + connect(m_controller.get(), &CoreController::stopping, [this]() { + m_controller.reset(); + }); + } + connect(m_controller.get(), &CoreController::stopping, &m_inputController, &InputController::resumeScreensaver); + connect(m_controller.get(), &CoreController::paused, this, &Window::updateFrame); + +#ifndef Q_OS_MAC + connect(m_controller.get(), &CoreController::paused, menuBar(), &QWidget::show); + connect(m_controller.get(), &CoreController::unpaused, [this]() { + if(isFullScreen()) { + menuBar()->hide(); + } + }); +#endif + + connect(m_controller.get(), &CoreController::paused, &m_inputController, &InputController::resumeScreensaver); + connect(m_controller.get(), &CoreController::unpaused, [this]() { + emit paused(false); + }); + + connect(m_controller.get(), &CoreController::stopping, m_display.get(), &Display::stopDrawing); + connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::resizeContext); + connect(m_controller.get(), &CoreController::stateLoaded, m_display.get(), &Display::forceDraw); + connect(m_controller.get(), &CoreController::rewound, m_display.get(), &Display::forceDraw); + connect(m_controller.get(), &CoreController::paused, m_display.get(), &Display::pauseDrawing); + connect(m_controller.get(), &CoreController::unpaused, m_display.get(), &Display::unpauseDrawing); + connect(m_controller.get(), &CoreController::frameAvailable, m_display.get(), &Display::framePosted); + connect(m_controller.get(), &CoreController::statusPosted, m_display.get(), &Display::showMessage); + + connect(m_controller.get(), &CoreController::unpaused, &m_inputController, &InputController::suspendScreensaver); + connect(m_controller.get(), &CoreController::frameAvailable, this, &Window::recordFrame); + connect(m_controller.get(), &CoreController::crashed, this, &Window::gameCrashed); + connect(m_controller.get(), &CoreController::failed, this, &Window::gameFailed); + connect(m_controller.get(), &CoreController::unimplementedBiosCall, this, &Window::unimplementedBiosCall); + +#ifdef USE_GDB_STUB + if (m_gdbController) { + m_gdbController->setController(m_controller); + } +#endif + +#ifdef USE_DEBUGGERS + if (m_console) { + m_console->setController(m_controller); + } +#endif + +#ifdef USE_MAGICK + if (m_gifView) { + m_gifView->setController(m_controller); + } +#endif + +#ifdef USE_FFMPEG + if (m_videoView) { + m_videoView->setController(m_controller); + } +#endif + + if (m_sensorView) { + m_sensorView->setController(m_controller); + } + + if (m_overrideView) { + m_overrideView->setController(m_controller); + } + + if (!m_pendingPatch.isEmpty()) { + m_controller->loadPatch(m_pendingPatch); + m_pendingPatch = QString(); + } + + m_controller->loadConfig(m_config); + m_controller->start(); + + if (!m_pendingState.isEmpty()) { + m_controller->loadState(m_pendingState); + m_pendingState = QString(); + } + + if (m_pendingPause) { + m_controller->setPaused(true); + m_pendingPause = false; + } +} + WindowBackground::WindowBackground(QWidget* parent) - : QLabel(parent) + : QWidget(parent) { setLayout(new QStackedLayout()); layout()->setContentsMargins(0, 0, 0, 0); - setAlignment(Qt::AlignCenter); +} + +void WindowBackground::setPixmap(const QPixmap& pmap) { + m_pixmap = pmap; + update(); } void WindowBackground::setSizeHint(const QSize& hint) { @@ -1690,11 +2010,9 @@ m_lockAspectRatio = lock; } -void WindowBackground::paintEvent(QPaintEvent*) { - const QPixmap* logo = pixmap(); - if (!logo) { - return; - } +void WindowBackground::paintEvent(QPaintEvent* event) { + QWidget::paintEvent(event); + const QPixmap& logo = pixmap(); QPainter painter(this); painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.fillRect(QRect(QPoint(), size()), Qt::black); @@ -1713,5 +2031,5 @@ } QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); QRect full(origin, ds); - painter.drawPixmap(full, *logo); + painter.drawPixmap(full, logo); } diff -Nru mgba-0.6.3+dfsg1/src/platform/qt/Window.h mgba-0.7.0/src/platform/qt/Window.h --- mgba-0.6.3+dfsg1/src/platform/qt/Window.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/qt/Window.h 2019-01-27 00:06:06.000000000 +0000 @@ -1,17 +1,19 @@ -/* Copyright (c) 2013-2016 Jeffrey Pfau +/* 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 QGBA_WINDOW -#define QGBA_WINDOW +#pragma once +#include #include +#include #include #include #include #include +#include #include @@ -22,14 +24,18 @@ namespace QGBA { +class AudioProcessor; class ConfigController; +class CoreController; +class CoreManager; class DebuggerConsoleController; class Display; -class GameController; class GDBController; class GIFView; class LibraryController; class LogView; +class OverrideView; +class SensorView; class ShaderSelector; class ShortcutController; class VideoView; @@ -39,10 +45,10 @@ Q_OBJECT public: - Window(ConfigController* config, int playerId = 0, QWidget* parent = nullptr); + Window(CoreManager* manager, ConfigController* config, int playerId = 0, QWidget* parent = nullptr); virtual ~Window(); - GameController* controller() { return m_controller; } + std::shared_ptr controller() { return m_controller; } void setConfig(ConfigController*); void argumentsPassed(mArguments*); @@ -52,19 +58,19 @@ void updateMultiplayerStatus(bool canOpenAnother) { m_multiWindow->setEnabled(canOpenAnother); } signals: - void startDrawing(mCoreThread*); + void startDrawing(); void shutdown(); - void audioBufferSamplesChanged(int samples); - void sampleRateChanged(unsigned samples); - void fpsTargetChanged(float target); + void paused(bool); public slots: + void setController(CoreController* controller, const QString& fname); void selectROM(); #ifdef USE_SQLITE3 void selectROMInArchive(); void addDirToLibrary(); #endif void selectSave(bool temporary); + void selectState(bool load); void selectPatch(); void enterFullScreen(); void exitFullScreen(); @@ -73,6 +79,8 @@ void reloadConfig(); void saveConfig(); + void loadCamImage(); + void replaceROM(); void multiplayerChanged(); @@ -81,7 +89,6 @@ void exportSharkport(); void openSettingsWindow(); - void openAboutScreen(); void startVideoLog(); @@ -114,12 +121,15 @@ virtual void mouseDoubleClickEvent(QMouseEvent*) override; private slots: - void gameStarted(mCoreThread*, const QString&); + void gameStarted(); void gameStopped(); void gameCrashed(const QString&); void gameFailed(); void unimplementedBiosCall(int); + void reloadAudioDriver(); + void reloadDisplayDriver(); + void tryMakePortable(); void mustRestart(); @@ -127,9 +137,10 @@ void showFPS(); void focusCheck(); + void updateFrame(); + private: static const int FPS_TIMER_INTERVAL = 2000; - static const int FRAME_LIST_SIZE = 120; void setupMenu(QMenuBar*); void openStateWindow(LoadSave); @@ -142,8 +153,8 @@ void openView(QWidget* widget); - template std::function openTView(A arg); - template std::function openTView(); + template std::function openTView(A... arg); + template std::function openControllerTView(A... arg); QAction* addControlledAction(QMenu* menu, QAction* action, const QString& name); QAction* addHiddenAction(QMenu* menu, QAction* action, const QString& name); @@ -153,8 +164,11 @@ QString getFilters() const; QString getFiltersArchive() const; - GameController* m_controller; - Display* m_display; + CoreManager* m_manager; + std::shared_ptr m_controller; + std::unique_ptr m_audioProcessor; + + std::unique_ptr m_display; int m_savedScale; // TODO: Move these to a new class QList m_gameActions; @@ -174,21 +188,30 @@ QPixmap m_logo{":/res/mgba-1024.png"}; ConfigController* m_config; InputController m_inputController; - QList m_frameList; + QList m_frameList; + QElapsedTimer m_frameTimer; QTimer m_fpsTimer; QList m_mruFiles; QMenu* m_mruMenu = nullptr; QMenu* m_videoLayers; QMenu* m_audioChannels; ShortcutController* m_shortcutController; - ShaderSelector* m_shaderView; +#if defined(BUILD_GL) || defined(BUILD_GLES2) + std::unique_ptr m_shaderView; +#endif bool m_fullscreenOnStart = false; QTimer m_focusCheck; bool m_autoresume = false; bool m_wasOpened = false; + QString m_pendingPatch; + QString m_pendingState; + bool m_pendingPause = false; bool m_hitUnimplementedBiosCall; + std::unique_ptr m_overrideView; + std::unique_ptr m_sensorView; + #ifdef USE_FFMPEG VideoView* m_videoView = nullptr; #endif @@ -206,22 +229,26 @@ #endif }; -class WindowBackground : public QLabel { +class WindowBackground : public QWidget { Q_OBJECT public: WindowBackground(QWidget* parent = 0); + void setPixmap(const QPixmap& pixmap); void setSizeHint(const QSize& size); virtual QSize sizeHint() const override; void setDimensions(int width, int height); void setLockIntegerScaling(bool lock); void setLockAspectRatio(bool lock); + const QPixmap& pixmap() const { return m_pixmap; } + protected: virtual void paintEvent(QPaintEvent*) override; private: + QPixmap m_pixmap; QSize m_sizeHint; int m_aspectWidth; int m_aspectHeight; @@ -230,5 +257,3 @@ }; } - -#endif diff -Nru mgba-0.6.3+dfsg1/src/platform/sdl/CMakeLists.txt mgba-0.7.0/src/platform/sdl/CMakeLists.txt --- mgba-0.6.3+dfsg1/src/platform/sdl/CMakeLists.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/sdl/CMakeLists.txt 2019-01-27 00:06:06.000000000 +0000 @@ -8,21 +8,25 @@ set(SDL_LIBRARY ${SDL2_LIBRARIES}) link_directories(${SDL2_LIBDIR}) set(SDL_VERSION_DEBIAN "2-2.0-0") + set(SDL_FOUND ON PARENT_SCOPE) endif() endif() if(SDL_VERSION EQUAL "1.2" OR NOT SDL2_FOUND) find_package(SDL 1.2) - set(SDL_VERSION "1.2" PARENT_SCOPE) - set(SDL_VERSION_DEBIAN "1.2debian") - set(USE_PIXMAN ON) + if(SDL_FOUND) + set(SDL_VERSION "1.2") + set(SDL_VERSION_DEBIAN "1.2debian") + set(USE_PIXMAN ON) + endif() endif() if (NOT SDL2_FOUND AND NOT SDL_FOUND) - set(BUILD_SDL OFF PARENT_SCOPE) + set(SDL_FOUND OFF PARENT_SCOPE) return() endif() +set(SDL_VERSION "${SDL_VERSION}" PARENT_SCOPE) add_definitions(-DBUILD_SDL) find_feature(USE_PIXMAN "pixman-1") @@ -64,8 +68,8 @@ add_executable(${BINARY_NAME}-rpi ${PLATFORM_SRC} ${MAIN_SRC}) set_target_properties(${BINARY_NAME}-rpi PROPERTIES COMPILE_DEFINITIONS "${FEATURE_DEFINES};${FUNCTION_DEFINES}") target_link_libraries(${BINARY_NAME}-rpi ${BINARY_NAME} ${PLATFORM_LIBRARY} ${OPENGLES2_LIBRARY}) - install(TARGETS ${BINARY_NAME}-rpi DESTINATION bin COMPONENT ${BINARY_NAME}-rpi) - unset(OPENGLES2_INCLUDE_DIR} CACHE) # Clear NOTFOUND + install(TARGETS ${BINARY_NAME}-rpi DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-rpi) + unset(OPENGLES2_INCLUDE_DIR CACHE) # Clear NOTFOUND endif() if(BUILD_PANDORA) @@ -86,6 +90,12 @@ endif() endif() +if(ENABLE_SCRIPTING) + if(BUILD_PYTHON) + list(APPEND PLATFORM_LIBRARY ${BINARY_NAME}-pylib) + endif() +endif() + add_executable(${BINARY_NAME}-sdl WIN32 ${PLATFORM_SRC} ${MAIN_SRC}) set_target_properties(${BINARY_NAME}-sdl PROPERTIES COMPILE_DEFINITIONS "${FEATURE_DEFINES};${FUNCTION_DEFINES}") target_link_libraries(${BINARY_NAME}-sdl ${BINARY_NAME} ${PLATFORM_LIBRARY} ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) @@ -96,3 +106,11 @@ if(UNIX) install(FILES ${CMAKE_SOURCE_DIR}/doc/mgba.6 DESTINATION ${MANDIR}/man6 COMPONENT ${BINARY_NAME}-sdl) endif() + +if(DISTBUILD AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + if(NOT APPLE) + add_custom_command(TARGET ${BINARY_NAME}-sdl POST_BUILD COMMAND "${OBJCOPY}" --only-keep-debug "$" "$.dSYM") + add_custom_command(TARGET ${BINARY_NAME}-sdl POST_BUILD COMMAND "${STRIP}" -S "$") + install(FILES "$.dSYM" DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-sdl-dbg) + endif() +endif() diff -Nru mgba-0.6.3+dfsg1/src/platform/sdl/gles2-sdl.c mgba-0.7.0/src/platform/sdl/gles2-sdl.c --- mgba-0.6.3+dfsg1/src/platform/sdl/gles2-sdl.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/sdl/gles2-sdl.c 2019-01-27 00:06:06.000000000 +0000 @@ -98,12 +98,13 @@ mSDLGLCommonInit(renderer); #endif + size_t size = renderer->width * renderer->height * BYTES_PER_PIXEL; #ifndef __APPLE__ - renderer->outputBuffer = memalign(16, renderer->width * renderer->height * BYTES_PER_PIXEL); + renderer->outputBuffer = memalign(16, size); #else - posix_memalign((void**) &renderer->outputBuffer, 16, renderer->width * renderer->height * BYTES_PER_PIXEL); + posix_memalign((void**) &renderer->outputBuffer, 16, size); #endif - memset(renderer->outputBuffer, 0, renderer->width * renderer->height * BYTES_PER_PIXEL); + memset(renderer->outputBuffer, 0, size); renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, renderer->width); mGLES2ContextCreate(&renderer->gl2); @@ -124,7 +125,7 @@ SDL_Event event; struct VideoBackend* v = &renderer->gl2.d; - while (context->state < THREAD_EXITING) { + while (mCoreThreadIsActive(context)) { while (SDL_PollEvent(&event)) { mSDLHandleEvent(context, &renderer->player, &event); #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -137,10 +138,10 @@ #endif } - if (mCoreSyncWaitFrameStart(&context->sync)) { + if (mCoreSyncWaitFrameStart(&context->impl->sync)) { v->postFrame(v, renderer->outputBuffer); } - mCoreSyncWaitFrameEnd(&context->sync); + mCoreSyncWaitFrameEnd(&context->impl->sync); v->drawFrame(v); #ifdef BUILD_RASPI eglSwapBuffers(renderer->display, renderer->surface); diff -Nru mgba-0.6.3+dfsg1/src/platform/sdl/gl-sdl.c mgba-0.7.0/src/platform/sdl/gl-sdl.c --- mgba-0.6.3+dfsg1/src/platform/sdl/gl-sdl.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/sdl/gl-sdl.c 2019-01-27 00:06:06.000000000 +0000 @@ -9,6 +9,8 @@ #include #include +#include + #include "platform/opengl/gl.h" static bool mSDLGLInit(struct mSDLRenderer* renderer); @@ -24,8 +26,9 @@ bool mSDLGLInit(struct mSDLRenderer* renderer) { mSDLGLCommonInit(renderer); - renderer->outputBuffer = malloc(renderer->width * renderer->height * BYTES_PER_PIXEL); - memset(renderer->outputBuffer, 0, renderer->width * renderer->height * BYTES_PER_PIXEL); + size_t size = renderer->width * renderer->height * BYTES_PER_PIXEL; + renderer->outputBuffer = malloc(size); + memset(renderer->outputBuffer, 0, size); renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, renderer->width); mGLContextCreate(&renderer->gl); @@ -46,7 +49,7 @@ SDL_Event event; struct VideoBackend* v = &renderer->gl.d; - while (context->state < THREAD_EXITING) { + while (mCoreThreadIsActive(context)) { while (SDL_PollEvent(&event)) { mSDLHandleEvent(context, &renderer->player, &event); #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -58,11 +61,16 @@ } #endif } + renderer->core->desiredVideoDimensions(renderer->core, &renderer->width, &renderer->height); + if (renderer->width != v->width || renderer->height != v->height) { + renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, renderer->width); + v->setDimensions(v, renderer->width, renderer->height); + } - if (mCoreSyncWaitFrameStart(&context->sync)) { + if (mCoreSyncWaitFrameStart(&context->impl->sync)) { v->postFrame(v, renderer->outputBuffer); } - mCoreSyncWaitFrameEnd(&context->sync); + mCoreSyncWaitFrameEnd(&context->impl->sync); v->drawFrame(v); v->swap(v); } diff -Nru mgba-0.6.3+dfsg1/src/platform/sdl/main.c mgba-0.7.0/src/platform/sdl/main.c --- mgba-0.6.3+dfsg1/src/platform/sdl/main.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/sdl/main.c 2019-01-27 00:06:06.000000000 +0000 @@ -13,11 +13,19 @@ #ifdef USE_EDITLINE #include "feature/editline/cli-el-backend.h" #endif +#ifdef ENABLE_SCRIPTING +#include + +#ifdef ENABLE_PYTHON +#include "platform/python/engine.h" +#endif +#endif #include #include #include #include +#include #include #include @@ -36,6 +44,12 @@ static int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args); +static struct VFile* _state = NULL; + +static void _loadState(struct mCoreThread* thread) { + mCoreLoadStateNamed(thread->core, _state, SAVESTATE_RTC); +} + int main(int argc, char** argv) { struct mSDLRenderer renderer = {0}; @@ -43,7 +57,6 @@ .useBios = true, .rewindEnable = true, .rewindBufferCapacity = 600, - .rewindSave = true, .audioBuffers = 1024, .videoSync = false, .audioSync = true, @@ -174,6 +187,14 @@ return 1; } mCoreAutoloadSave(renderer->core); + mCoreAutoloadCheats(renderer->core); +#ifdef ENABLE_SCRIPTING + struct mScriptBridge* bridge = mScriptBridgeCreate(); +#ifdef ENABLE_PYTHON + mPythonSetup(bridge); +#endif +#endif + #ifdef USE_DEBUGGERS struct mDebugger* debugger = mDebuggerCreate(args->debuggerType, renderer->core); if (debugger) { @@ -185,6 +206,9 @@ #endif mDebuggerAttach(debugger, renderer->core); mDebuggerEnter(debugger, DEBUGGER_ENTER_MANUAL, NULL); + #ifdef ENABLE_SCRIPTING + mScriptBridgeSetDebugger(bridge, debugger); +#endif } #endif @@ -203,10 +227,26 @@ bool didFail = !mCoreThreadStart(&thread); if (!didFail) { #if SDL_VERSION_ATLEAST(2, 0, 0) + renderer->core->desiredVideoDimensions(renderer->core, &renderer->width, &renderer->height); + unsigned width = renderer->width * renderer->ratio; + unsigned height = renderer->height * renderer->ratio; + if (width != (unsigned) renderer->viewportWidth && height != (unsigned) renderer->viewportHeight) { + SDL_SetWindowSize(renderer->window, width, height); + renderer->player.windowUpdated = 1; + } mSDLSetScreensaverSuspendable(&renderer->events, renderer->core->opts.suspendScreensaver); mSDLSuspendScreensaver(&renderer->events); #endif if (mSDLInitAudio(&renderer->audio, &thread)) { + if (args->savestate) { + struct VFile* state = VFileOpen(args->savestate, O_RDONLY); + if (state) { + _state = state; + mCoreThreadRunFunction(&thread, _loadState); + _state = NULL; + state->close(state); + } + } renderer->runloop(renderer, &thread); mSDLPauseAudio(&renderer->audio); if (mCoreThreadHasCrashed(&thread)) { @@ -227,6 +267,11 @@ printf("Could not run game. Are you sure the file exists and is a compatible game?\n"); } renderer->core->unloadROM(renderer->core); + +#ifdef ENABLE_SCRIPTING + mScriptBridgeDestroy(bridge); +#endif + return didFail; } diff -Nru mgba-0.6.3+dfsg1/src/platform/sdl/sdl-audio.c mgba-0.7.0/src/platform/sdl/sdl-audio.c --- mgba-0.6.3+dfsg1/src/platform/sdl/sdl-audio.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/sdl/sdl-audio.c 2019-01-27 00:06:06.000000000 +0000 @@ -44,7 +44,7 @@ if (threadContext) { context->core = threadContext->core; - context->sync = &threadContext->sync; + context->sync = &threadContext->impl->sync; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_PauseAudioDevice(context->deviceId, 0); diff -Nru mgba-0.6.3+dfsg1/src/platform/sdl/sdl-events.c mgba-0.7.0/src/platform/sdl/sdl-events.c --- mgba-0.6.3+dfsg1/src/platform/sdl/sdl-events.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/sdl/sdl-events.c 2019-01-27 00:06:06.000000000 +0000 @@ -64,8 +64,12 @@ if (!SDL_JoystickListSize(&context->joysticks)) { int i; for (i = 0; i < nJoysticks; ++i) { + SDL_Joystick* sdlJoystick = SDL_JoystickOpen(i); + if (!sdlJoystick) { + continue; + } struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&context->joysticks); - joystick->joystick = SDL_JoystickOpen(i); + joystick->joystick = sdlJoystick; joystick->index = SDL_JoystickListSize(&context->joysticks) - 1; #if SDL_VERSION_ATLEAST(2, 0, 0) joystick->id = SDL_JoystickInstanceID(joystick->joystick); @@ -203,6 +207,9 @@ #else joystickName = SDL_JoystickName(SDL_JoystickIndex(SDL_JoystickListGetPointer(&events->joysticks, i)->joystick)); #endif + if (!joystickName) { + continue; + } if (events->preferredJoysticks[player->playerId] && strcmp(events->preferredJoysticks[player->playerId], joystickName) == 0) { index = i; break; @@ -253,6 +260,9 @@ #else const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick->joystick)); #endif + if (!name) { + return; + } mInputProfileLoad(context->bindings, SDL_BINDING_BUTTON, config, name); const char* value; @@ -304,7 +314,10 @@ #else const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick->joystick)); #endif - char value[12]; + if (!name) { + return; + } + char value[16]; snprintf(value, sizeof(value), "%i", context->rotation.axisX); mInputSetCustomValue(config, "gba", SDL_BINDING_BUTTON, "tiltAxisX", value, name); snprintf(value, sizeof(value), "%i", context->rotation.axisY); @@ -332,8 +345,12 @@ SDL_Event event; while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED) > 0) { if (event.type == SDL_JOYDEVICEADDED) { + SDL_Joystick* sdlJoystick = SDL_JoystickOpen(event.jdevice.which); + if (!sdlJoystick) { + continue; + } struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&events->joysticks); - joystick->joystick = SDL_JoystickOpen(event.jdevice.which); + joystick->joystick = sdlJoystick; joystick->id = SDL_JoystickInstanceID(joystick->joystick); joystick->index = SDL_JoystickListSize(&events->joysticks) - 1; #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -347,16 +364,18 @@ joystickName = SDL_JoystickName(SDL_JoystickIndex(joystick->joystick)); #endif size_t i; - for (i = 0; (int) i < events->playersAttached; ++i) { - if (events->players[i]->joystick) { - continue; - } - if (events->preferredJoysticks[i] && strcmp(events->preferredJoysticks[i], joystickName) == 0) { - events->players[i]->joystick = joystick; - if (config) { - mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName); + if (joystickName) { + for (i = 0; (int) i < events->playersAttached; ++i) { + if (events->players[i]->joystick) { + continue; + } + if (events->preferredJoysticks[i] && strcmp(events->preferredJoysticks[i], joystickName) == 0) { + events->players[i]->joystick = joystick; + if (config) { + mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName); + } + return; } - return; } } for (i = 0; (int) i < events->playersAttached; ++i) { @@ -364,7 +383,7 @@ continue; } events->players[i]->joystick = joystick; - if (config) { + if (config && joystickName) { mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName); } break; @@ -407,7 +426,7 @@ static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer* sdlContext, const struct SDL_KeyboardEvent* event) { int key = -1; - if (!event->keysym.mod) { + if (!(event->keysym.mod & ~(KMOD_NUM | KMOD_CAPS))) { key = mInputMapKey(sdlContext->bindings, SDL_BINDING_KEY, event->keysym.sym); } if (key != -1) { @@ -421,7 +440,7 @@ return; } if (event->keysym.sym == SDLK_TAB) { - context->sync.audioWait = event->type != SDL_KEYDOWN; + context->impl->sync.audioWait = event->type != SDL_KEYDOWN; return; } if (event->keysym.sym == SDLK_BACKQUOTE) { @@ -488,7 +507,7 @@ case SDLK_F8: case SDLK_F9: mCoreThreadInterrupt(context); - mCoreSaveState(context->core, event->keysym.sym - SDLK_F1 + 1, SAVESTATE_SAVEDATA | SAVESTATE_SCREENSHOT); + mCoreSaveState(context->core, event->keysym.sym - SDLK_F1 + 1, SAVESTATE_SAVEDATA | SAVESTATE_SCREENSHOT | SAVESTATE_RTC); mCoreThreadContinue(context); break; default: @@ -506,7 +525,7 @@ case SDLK_F8: case SDLK_F9: mCoreThreadInterrupt(context); - mCoreLoadState(context->core, event->keysym.sym - SDLK_F1 + 1, SAVESTATE_SCREENSHOT); + mCoreLoadState(context->core, event->keysym.sym - SDLK_F1 + 1, SAVESTATE_SCREENSHOT | SAVESTATE_RTC); mCoreThreadContinue(context); break; default: diff -Nru mgba-0.6.3+dfsg1/src/platform/sdl/sw-sdl.c mgba-0.7.0/src/platform/sdl/sw-sdl.c --- mgba-0.6.3+dfsg1/src/platform/sdl/sw-sdl.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/sdl/sw-sdl.c 2019-01-27 00:06:06.000000000 +0000 @@ -23,9 +23,9 @@ bool mSDLSWInit(struct mSDLRenderer* renderer) { #if !SDL_VERSION_ATLEAST(2, 0, 0) #ifdef COLOR_16_BIT - SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE); + SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE | (SDL_FULLSCREEN * renderer->fullscreen)); #else - SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE); + SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | (SDL_FULLSCREEN * renderer->fullscreen)); #endif #endif @@ -93,12 +93,12 @@ SDL_Surface* surface = SDL_GetVideoSurface(); #endif - while (context->state < THREAD_EXITING) { + while (mCoreThreadIsActive(context)) { while (SDL_PollEvent(&event)) { mSDLHandleEvent(context, &renderer->player, &event); } - if (mCoreSyncWaitFrameStart(&context->sync)) { + if (mCoreSyncWaitFrameStart(&context->impl->sync)) { #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_UnlockTexture(renderer->sdlTex); SDL_RenderCopy(renderer->sdlRenderer, renderer->sdlTex, 0, 0); @@ -134,7 +134,7 @@ SDL_LockSurface(surface); #endif } - mCoreSyncWaitFrameEnd(&context->sync); + mCoreSyncWaitFrameEnd(&context->impl->sync); } } diff -Nru mgba-0.6.3+dfsg1/src/platform/switch/CMakeLists.txt mgba-0.7.0/src/platform/switch/CMakeLists.txt --- mgba-0.6.3+dfsg1/src/platform/switch/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/switch/CMakeLists.txt 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,54 @@ +find_program(ELF2NRO elf2nro) +find_program(NACPTOOL nacptool) +find_program(BUILD_ROMFS build_romfs) +find_library(GLAPI_LIBRARY glapi REQUIRED) +find_library(EGL_LIBRARY EGL REQUIRED) + +set(OS_DEFINES USE_VFS_FILE IOAPI_NO_64) +list(APPEND CORE_VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c) +list(APPEND GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c) + +include_directories(AFTER ${OPENGLES3_INCLUDE_DIR} ${OPENGL_EGL_INCLUDE_DIR}) + +file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/wii/wii-*.c) +if(${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo) + find_library(NOUVEAU_LIBRARY drm_nouveaud REQUIRED) + list(APPEND OS_LIB nxd) +else() + find_library(NOUVEAU_LIBRARY drm_nouveau REQUIRED) + list(APPEND OS_LIB nx) +endif() +set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE) +set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE) +set(OS_SRC ${OS_SRC} PARENT_SCOPE) +set(OS_LIB ${OS_LIB} PARENT_SCOPE) + +if(BUILD_PERF) + add_custom_target(${BINARY_NAME}-perf.nro ALL + ${ELF2NRO} ../${BINARY_NAME}-perf ${BINARY_NAME}-perf.nro + DEPENDS ${BINARY_NAME}-perf) + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}-perf.nro + DESTINATION . COMPONENT ${BINARY_NAME}-perf) +endif() + +add_executable(${BINARY_NAME}.elf ${GUI_SRC} ${PLATFORM_SRC} main.c) +set_target_properties(${BINARY_NAME}.elf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") +target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} ${M_LIBRARY} ${EGL_LIBRARY} ${OPENGLES3_LIBRARY} ${GLAPI_LIBRARY} ${NOUVEAU_LIBRARY} stdc++ ${OS_LIB}) + +add_custom_command(OUTPUT control.nacp + COMMAND ${NACPTOOL} --create "${PROJECT_NAME}" "endrift" "${VERSION_STRING}" control.nacp) + +add_custom_command(OUTPUT romfs.bin + COMMAND ${CMAKE_COMMAND} -E make_directory romfs + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/res/font-new.png" romfs/ + COMMAND ${BUILD_ROMFS} romfs romfs.bin + COMMAND ${CMAKE_COMMAND} -E remove_directory romfs + DEPENDS "${CMAKE_SOURCE_DIR}/res/font-new.png") + +add_custom_target(${BINARY_NAME}.nro ALL + ${ELF2NRO} ${BINARY_NAME}.elf ${BINARY_NAME}.nro --romfs=romfs.bin --nacp=control.nacp --icon="${CMAKE_CURRENT_SOURCE_DIR}/icon.jpg" + DEPENDS ${BINARY_NAME}.elf control.nacp ${CMAKE_CURRENT_SOURCE_DIR}/icon.jpg romfs.bin) + +install(TARGETS ${BINARY_NAME}.elf DESTINATION . COMPONENT ${BINARY_NAME}-dbg) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.nro DESTINATION . COMPONENT ${BINARY_NAME}-switch) diff -Nru mgba-0.6.3+dfsg1/src/platform/switch/CMakeToolchain.txt mgba-0.7.0/src/platform/switch/CMakeToolchain.txt --- mgba-0.6.3+dfsg1/src/platform/switch/CMakeToolchain.txt 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/switch/CMakeToolchain.txt 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,56 @@ +if(DEFINED ENV{DEVKITPRO}) + set(DEVKITPRO $ENV{DEVKITPRO}) +else() + message(FATAL_ERROR "Could not find DEVKITPRO in environment") +endif() + +if(DEFINED ENV{DEVKITA64}) + set(DEVKITA64 $ENV{DEVKITA64}) +else() + set(DEVKITA64 ${DEVKITPRO}/devkitA64) +endif() + +if(DEFINED ENV{LIBNX}) + set(LIBNX $ENV{LIBNX}) +else() + set(LIBNX ${DEVKITPRO}/libnx) +endif() + +set(extension) +if (CMAKE_HOST_WIN32) + set(extension .exe) +endif() + +set(CMAKE_PROGRAM_PATH ${DEVKITA64}/bin) +set(cross_prefix aarch64-none-elf-) +set(arch_flags "-mtune=cortex-a57 -ffunction-sections -march=armv8-a -mtp=soft -fPIC -ftls-model=local-exec") +set(inc_flags "-I${LIBNX}/include ${arch_flags}") +set(link_flags "-L${LIBNX}/lib -lnx -specs=${LIBNX}/switch.specs ${arch_flags}") + +set(CMAKE_SYSTEM_NAME Generic CACHE INTERNAL "system name") +set(CMAKE_SYSTEM_PROCESSOR aarch64 CACHE INTERNAL "processor") +set(CMAKE_LIBRARY_ARCHITECTURE aarch64-none-elf CACHE INTERNAL "abi") + +find_program(CMAKE_AR ${cross_prefix}gcc-ar${extension}) +find_program(CMAKE_RANLIB ${cross_prefix}gcc-ranlib${extension}) +find_program(CMAKE_C_COMPILER ${cross_prefix}gcc${extension}) +find_program(CMAKE_CXX_COMPILER ${cross_prefix}g++${extension}) +find_program(CMAKE_ASM_COMPILER ${cross_prefix}gcc${extension}) +find_program(CMAKE_LINKER ${cross_prefix}ld${extension}) +set(CMAKE_C_FLAGS ${inc_flags} CACHE INTERNAL "c compiler flags") +set(CMAKE_ASM_FLAGS ${inc_flags} CACHE INTERNAL "assembler flags") +set(CMAKE_CXX_FLAGS ${inc_flags} CACHE INTERNAL "cxx compiler flags") +SET(CMAKE_ASM_COMPILE_OBJECT " -o -c ") + +set(CMAKE_EXE_LINKER_FLAGS ${link_flags} CACHE INTERNAL "exe link flags") +set(CMAKE_MODULE_LINKER_FLAGS ${link_flags} CACHE INTERNAL "module link flags") +set(CMAKE_SHARED_LINKER_FLAGS ${link_flags} CACHE INTERNAL "shared link flags") + +set(CMAKE_FIND_ROOT_PATH ${DEVKITARM}/aarch64-none-elf ${DEVKITPRO}/portlibs/switch) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE INTERNAL "") +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY CACHE INTERNAL "") +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY CACHE INTERNAL "") +set(PKG_CONFIG_EXECUTABLE "/dev/null" CACHE INTERNAL "" FORCE) + +set(SWITCH ON) +add_definitions(-D__SWITCH__) diff -Nru mgba-0.6.3+dfsg1/src/platform/switch/gui-font.c mgba-0.7.0/src/platform/switch/gui-font.c --- mgba-0.6.3+dfsg1/src/platform/switch/gui-font.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/switch/gui-font.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,357 @@ +/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include +#include +#include +#include + +#include + +#define GLYPH_HEIGHT 24 +#define CELL_HEIGHT 32 +#define CELL_WIDTH 32 + +static const GLfloat _offsets[] = { + 0.f, 0.f, + 1.f, 0.f, + 1.f, 1.f, + 0.f, 1.f, +}; + +static const GLchar* const _gles2Header = + "#version 100\n" + "precision mediump float;\n"; + +static const char* const _vertexShader = + "attribute vec2 offset;\n" + "uniform vec3 origin;\n" + "uniform vec2 glyph;\n" + "uniform vec2 dims;\n" + "uniform mat2 transform;\n" + "varying vec2 texCoord;\n" + + "void main() {\n" + " texCoord = (glyph + offset * dims) / 512.0;\n" + " vec2 scaledOffset = (transform * (offset * 2.0 - vec2(1.0)) + vec2(1.0)) / 2.0 * dims;\n" + " gl_Position = vec4((origin.x + scaledOffset.x) / 640.0 - 1.0, -(origin.y + scaledOffset.y) / 360.0 + 1.0, origin.z, 1.0);\n" + "}"; + +static const char* const _fragmentShader = + "varying vec2 texCoord;\n" + "uniform sampler2D tex;\n" + "uniform vec4 color;\n" + "uniform float cutoff;\n" + + "void main() {\n" + " vec4 texColor = texture2D(tex, texCoord);\n" + " texColor.a = clamp((texColor.a - cutoff) / (1.0 - cutoff), 0.0, 1.0);\n" + " texColor.rgb = color.rgb;\n" + " texColor.a *= color.a;\n" + " gl_FragColor = texColor;\n" + "}"; + +struct GUIFont { + GLuint font; + GLuint program; + GLuint vbo; + GLuint vao; + GLuint texLocation; + GLuint dimsLocation; + GLuint transformLocation; + GLuint colorLocation; + GLuint originLocation; + GLuint glyphLocation; + GLuint cutoffLocation; +}; + +static bool _loadTexture(const char* path) { + struct VFile* vf = VFileOpen(path, O_RDONLY); + if (!vf) { + return false; + } + png_structp png = PNGReadOpen(vf, 0); + png_infop info = png_create_info_struct(png); + png_infop end = png_create_info_struct(png); + bool success = false; + if (png && info && end) { + success = PNGReadHeader(png, info); + } + void* pixels = NULL; + if (success) { + unsigned height = png_get_image_height(png, info); + unsigned width = png_get_image_width(png, info); + pixels = malloc(width * height); + if (pixels) { + success = PNGReadPixels8(png, info, pixels, width, height, width); + success = success && PNGReadFooter(png, end); + } else { + success = false; + } + if (success) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); + } + } + PNGReadClose(png, info, end); + if (pixels) { + free(pixels); + } + vf->close(vf); + return success; +} + +struct GUIFont* GUIFontCreate(void) { + struct GUIFont* font = malloc(sizeof(struct GUIFont)); + if (!font) { + return NULL; + } + glGenTextures(1, &font->font); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, font->font); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (!_loadTexture("romfs:/font-new.png")) { + GUIFontDestroy(font); + return NULL; + } + + font->program = glCreateProgram(); + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + const GLchar* shaderBuffer[2]; + + shaderBuffer[0] = _gles2Header; + + shaderBuffer[1] = _vertexShader; + glShaderSource(vertexShader, 2, shaderBuffer, NULL); + + shaderBuffer[1] = _fragmentShader; + glShaderSource(fragmentShader, 2, shaderBuffer, NULL); + + glAttachShader(font->program, vertexShader); + glAttachShader(font->program, fragmentShader); + + glCompileShader(fragmentShader); + + GLint success; + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); + if (!success) { + GLchar msg[512]; + glGetShaderInfoLog(fragmentShader, sizeof(msg), NULL, msg); + puts(msg); + } + + glCompileShader(vertexShader); + + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + if (!success) { + GLchar msg[512]; + glGetShaderInfoLog(vertexShader, sizeof(msg), NULL, msg); + puts(msg); + } + glLinkProgram(font->program); + + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + + font->texLocation = glGetUniformLocation(font->program, "tex"); + font->colorLocation = glGetUniformLocation(font->program, "color"); + font->dimsLocation = glGetUniformLocation(font->program, "dims"); + font->transformLocation = glGetUniformLocation(font->program, "transform"); + font->originLocation = glGetUniformLocation(font->program, "origin"); + font->glyphLocation = glGetUniformLocation(font->program, "glyph"); + font->cutoffLocation = glGetUniformLocation(font->program, "cutoff"); + GLuint offsetLocation = glGetAttribLocation(font->program, "offset"); + + glGenBuffers(1, &font->vbo); + glGenVertexArrays(1, &font->vao); + glBindVertexArray(font->vao); + glBindBuffer(GL_ARRAY_BUFFER, font->vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(_offsets), _offsets, GL_STATIC_DRAW); + glVertexAttribPointer(offsetLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(offsetLocation); + glBindVertexArray(0); + + return font; +} + +void GUIFontDestroy(struct GUIFont* font) { + glDeleteBuffers(1, &font->vbo); + glDeleteProgram(font->program); + glDeleteTextures(1, &font->font); + glDeleteVertexArrays(1, &font->vao); + free(font); +} + +unsigned GUIFontHeight(const struct GUIFont* font) { + UNUSED(font); + return GLYPH_HEIGHT; +} + +unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) { + UNUSED(font); + if (glyph > 0x7F) { + glyph = '?'; + } + return defaultFontMetrics[glyph].width * 2; +} + +void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) { + UNUSED(font); + if (icon >= GUI_ICON_MAX) { + if (w) { + *w = 0; + } + if (h) { + *h = 0; + } + } else { + if (w) { + *w = defaultIconMetrics[icon].width * 2; + } + if (h) { + *h = defaultIconMetrics[icon].height * 2; + } + } +} + +void GUIFontDrawGlyph(const struct GUIFont* font, int x, int y, uint32_t color, uint32_t glyph) { + if (glyph > 0x7F) { + glyph = '?'; + } + struct GUIFontGlyphMetric metric = defaultFontMetrics[glyph]; + + glUseProgram(font->program); + glBindVertexArray(font->vao); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, font->font); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glUniform1i(font->texLocation, 0); + glUniform2f(font->glyphLocation, (glyph & 15) * CELL_WIDTH + metric.padding.left * 2, (glyph >> 4) * CELL_HEIGHT + metric.padding.top * 2); + glUniform2f(font->dimsLocation, CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2, CELL_HEIGHT - (metric.padding.top + metric.padding.bottom) * 2); + glUniform3f(font->originLocation, x, y - GLYPH_HEIGHT + metric.padding.top * 2, 0); + glUniformMatrix2fv(font->transformLocation, 1, GL_FALSE, (float[4]) {1.0, 0.0, 0.0, 1.0}); + + glUniform1f(font->cutoffLocation, 0.1f); + glUniform4f(font->colorLocation, 0.0, 0.0, 0.0, ((color >> 24) & 0xFF) / 128.0f); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glUniform1f(font->cutoffLocation, 0.7f); + glUniform4f(font->colorLocation, (color & 0xFF) / 255.0f, ((color >> 8) & 0xFF) / 255.0f, ((color >> 16) & 0xFF) / 255.0f, ((color >> 24) & 0xFF) / 255.0f); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); +} + +void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) { + if (icon >= GUI_ICON_MAX) { + return; + } + struct GUIIconMetric metric = defaultIconMetrics[icon]; + + float hFlip = 1.0f; + float vFlip = 1.0f; + switch (align & GUI_ALIGN_HCENTER) { + case GUI_ALIGN_HCENTER: + x -= metric.width; + break; + case GUI_ALIGN_RIGHT: + x -= metric.width * 2; + break; + } + switch (align & GUI_ALIGN_VCENTER) { + case GUI_ALIGN_VCENTER: + y -= metric.height; + break; + case GUI_ALIGN_BOTTOM: + y -= metric.height * 2; + break; + } + + glUseProgram(font->program); + switch (orient) { + case GUI_ORIENT_HMIRROR: + hFlip = -1.0; + break; + case GUI_ORIENT_VMIRROR: + vFlip = -1.0; + break; + case GUI_ORIENT_0: + default: + // TODO: Rotate + break; + } + + glUseProgram(font->program); + glBindVertexArray(font->vao); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, font->font); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glUniform1i(font->texLocation, 0); + glUniform2f(font->glyphLocation, metric.x * 2, metric.y * 2 + 256); + glUniform2f(font->dimsLocation, metric.width * 2, metric.height * 2); + glUniform3f(font->originLocation, x, y, 0); + glUniformMatrix2fv(font->transformLocation, 1, GL_FALSE, (float[4]) {hFlip, 0.0, 0.0, vFlip}); + + glUniform1f(font->cutoffLocation, 0.1f); + glUniform4f(font->colorLocation, 0.0, 0.0, 0.0, ((color >> 24) & 0xFF) / 128.0f); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glUniform1f(font->cutoffLocation, 0.7f); + glUniform4f(font->colorLocation, (color & 0xFF) / 255.0f, ((color >> 8) & 0xFF) / 255.0f, ((color >> 16) & 0xFF) / 255.0f, ((color >> 24) & 0xFF) / 255.0f); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); +} + +void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) { + if (icon >= GUI_ICON_MAX) { + return; + } + struct GUIIconMetric metric = defaultIconMetrics[icon]; + + if (!w) { + w = metric.width * 2; + } + if (!h) { + h = metric.height * 2; + } + + glUseProgram(font->program); + glBindVertexArray(font->vao); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, font->font); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glUniform1i(font->texLocation, 0); + glUniform2f(font->glyphLocation, metric.x * 2, metric.y * 2 + 256); + glUniform2f(font->dimsLocation, metric.width * 2, metric.height * 2); + glUniform3f(font->originLocation, x + w / 2 - metric.width, y + h / 2 - metric.height, 0); + glUniformMatrix2fv(font->transformLocation, 1, GL_FALSE, (float[4]) {w * 0.5f / metric.width, 0.0, 0.0, h * 0.5f / metric.height}); + + glUniform1f(font->cutoffLocation, 0.1f); + glUniform4f(font->colorLocation, 0.0, 0.0, 0.0, ((color >> 24) & 0xFF) / 128.0f); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glUniform1f(font->cutoffLocation, 0.7f); + glUniform4f(font->colorLocation, ((color >> 16) & 0xFF) / 255.0f, ((color >> 8) & 0xFF) / 255.0f, (color & 0xFF) / 255.0f, ((color >> 24) & 0xFF) / 255.0f); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); +} Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/src/platform/switch/icon.jpg and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/src/platform/switch/icon.jpg differ diff -Nru mgba-0.6.3+dfsg1/src/platform/switch/main.c mgba-0.7.0/src/platform/switch/main.c --- mgba-0.6.3+dfsg1/src/platform/switch/main.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/switch/main.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,748 @@ +/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "feature/gui/gui-runner.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define AUTO_INPUT 0x4E585031 +#define SAMPLES 0x400 +#define BUFFER_SIZE 0x1000 +#define N_BUFFERS 4 +#define ANALOG_DEADZONE 0x4000 + +TimeType __nx_time_type = TimeType_UserSystemClock; + +static EGLDisplay s_display; +static EGLContext s_context; +static EGLSurface s_surface; + +static const GLfloat _offsets[] = { + 0.f, 0.f, + 1.f, 0.f, + 1.f, 1.f, + 0.f, 1.f, +}; + +static const GLchar* const _gles2Header = + "#version 100\n" + "precision mediump float;\n"; + +static const char* const _vertexShader = + "attribute vec2 offset;\n" + "uniform vec2 dims;\n" + "uniform vec2 insize;\n" + "varying vec2 texCoord;\n" + + "void main() {\n" + " vec2 ratio = insize / 256.0;\n" + " vec2 scaledOffset = offset * dims;\n" + " gl_Position = vec4(scaledOffset.x * 2.0 - dims.x, scaledOffset.y * -2.0 + dims.y, 0.0, 1.0);\n" + " texCoord = offset * ratio;\n" + "}"; + +static const char* const _fragmentShader = + "varying vec2 texCoord;\n" + "uniform sampler2D tex;\n" + "uniform vec4 color;\n" + + "void main() {\n" + " vec4 texColor = vec4(texture2D(tex, texCoord).rgb, 1.0);\n" + " texColor *= color;\n" + " gl_FragColor = texColor;\n" + "}"; + +static GLuint program; +static GLuint vbo; +static GLuint vao; +static GLuint pbo; +static GLuint texLocation; +static GLuint dimsLocation; +static GLuint insizeLocation; +static GLuint colorLocation; +static GLuint tex; + +static color_t* frameBuffer; +static struct mAVStream stream; +static struct mSwitchRumble { + struct mRumble d; + int up; + int down; + HidVibrationValue value; +} rumble; +static struct mRotationSource rotation = {0}; +static int audioBufferActive; +static struct GBAStereoSample audioBuffer[N_BUFFERS][SAMPLES] __attribute__((__aligned__(0x1000))); +static AudioOutBuffer audoutBuffer[N_BUFFERS]; +static int enqueuedBuffers; +static bool frameLimiter = true; +static unsigned framecount = 0; +static unsigned framecap = 10; +static u32 vibrationDeviceHandles[4]; +static HidVibrationValue vibrationStop = { .freq_low = 160.f, .freq_high = 320.f }; + +static enum ScreenMode { + SM_PA, + SM_AF, + SM_SF, + SM_MAX +} screenMode = SM_PA; + +static bool initEgl() { + s_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (!s_display) { + goto _fail0; + } + + eglInitialize(s_display, NULL, NULL); + + EGLConfig config; + EGLint numConfigs; + static const EGLint attributeList[] = { + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_NONE + }; + eglChooseConfig(s_display, attributeList, &config, 1, &numConfigs); + if (!numConfigs) { + goto _fail1; + } + + s_surface = eglCreateWindowSurface(s_display, config, nwindowGetDefault(), NULL); + if (!s_surface) { + goto _fail1; + } + + EGLint contextAttributeList[] = { + EGL_CONTEXT_CLIENT_VERSION, 3, + EGL_NONE + }; + s_context = eglCreateContext(s_display, config, EGL_NO_CONTEXT, contextAttributeList); + if (!s_context) { + goto _fail2; + } + + eglMakeCurrent(s_display, s_surface, s_surface, s_context); + return true; + +_fail2: + eglDestroySurface(s_display, s_surface); + s_surface = NULL; +_fail1: + eglTerminate(s_display); + s_display = NULL; +_fail0: + return false; +} + +static void deinitEgl() { + if (s_display) { + if (s_context) { + eglDestroyContext(s_display, s_context); + } + if (s_surface) { + eglDestroySurface(s_display, s_surface); + } + eglTerminate(s_display); + } +} + +static void _mapKey(struct mInputMap* map, uint32_t binding, int nativeKey, enum GBAKey key) { + mInputBindKey(map, binding, __builtin_ctz(nativeKey), key); +} + +static void _drawStart(void) { + glClear(GL_COLOR_BUFFER_BIT); +} + +static void _drawEnd(void) { + if (frameLimiter || framecount >= framecap) { + eglSwapBuffers(s_display, s_surface); + framecount = 0; + } +} + +static uint32_t _pollInput(const struct mInputMap* map) { + int keys = 0; + hidScanInput(); + u32 padkeys = hidKeysHeld(CONTROLLER_P1_AUTO); + keys |= mInputMapKeyBits(map, AUTO_INPUT, padkeys, 0); + + JoystickPosition jspos; + hidJoystickRead(&jspos, CONTROLLER_P1_AUTO, JOYSTICK_LEFT); + + int l = mInputMapKey(map, AUTO_INPUT, __builtin_ctz(KEY_LSTICK_LEFT)); + int r = mInputMapKey(map, AUTO_INPUT, __builtin_ctz(KEY_LSTICK_RIGHT)); + int u = mInputMapKey(map, AUTO_INPUT, __builtin_ctz(KEY_LSTICK_UP)); + int d = mInputMapKey(map, AUTO_INPUT, __builtin_ctz(KEY_LSTICK_DOWN)); + + if (l == -1) { + l = mInputMapKey(map, AUTO_INPUT, __builtin_ctz(KEY_DLEFT)); + } + if (r == -1) { + r = mInputMapKey(map, AUTO_INPUT, __builtin_ctz(KEY_DRIGHT)); + } + if (u == -1) { + u = mInputMapKey(map, AUTO_INPUT, __builtin_ctz(KEY_DUP)); + } + if (d == -1) { + d = mInputMapKey(map, AUTO_INPUT, __builtin_ctz(KEY_DDOWN)); + } + + if (jspos.dx < -ANALOG_DEADZONE && l != -1) { + keys |= 1 << l; + } + if (jspos.dx > ANALOG_DEADZONE && r != -1) { + keys |= 1 << r; + } + if (jspos.dy < -ANALOG_DEADZONE && d != -1) { + keys |= 1 << d; + } + if (jspos.dy > ANALOG_DEADZONE && u != -1) { + keys |= 1 << u; + } + return keys; +} + +static enum GUICursorState _pollCursor(unsigned* x, unsigned* y) { + hidScanInput(); + if (hidTouchCount() < 1) { + return GUI_CURSOR_NOT_PRESENT; + } + touchPosition touch; + hidTouchRead(&touch, 0); + *x = touch.px; + *y = touch.py; + return GUI_CURSOR_DOWN; +} + + +static void _setup(struct mGUIRunner* runner) { + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_A, GBA_KEY_A); + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_B, GBA_KEY_B); + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_PLUS, GBA_KEY_START); + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_MINUS, GBA_KEY_SELECT); + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_DUP, GBA_KEY_UP); + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_DDOWN, GBA_KEY_DOWN); + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_DLEFT, GBA_KEY_LEFT); + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_DRIGHT, GBA_KEY_RIGHT); + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_L, GBA_KEY_L); + _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_R, GBA_KEY_R); + + runner->core->setVideoBuffer(runner->core, frameBuffer, 256); + runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble.d); + runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation); + runner->core->setAVStream(runner->core, &stream); + + unsigned mode; + if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { + screenMode = mode; + } +} + +static void _gameLoaded(struct mGUIRunner* runner) { + u32 samplerate = audoutGetSampleRate(); + + double ratio = GBAAudioCalculateRatio(1, 60.0, 1); + blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), samplerate * ratio); + blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), samplerate * ratio); + + mCoreConfigGetUIntValue(&runner->config, "fastForwardCap", &framecap); + + unsigned mode; + if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { + screenMode = mode; + } + + rumble.up = 0; + rumble.down = 0; +} + +static void _gameUnloaded(struct mGUIRunner* runner) { + HidVibrationValue values[4]; + memcpy(&values[0], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[1], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[2], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[3], &vibrationStop, sizeof(rumble.value)); + hidSendVibrationValues(vibrationDeviceHandles, values, 4); +} + +static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glUseProgram(program); + glBindVertexArray(vao); + float aspectX = width / (float) runner->params.width; + float aspectY = height / (float) runner->params.height; + float max = 1.f; + switch (screenMode) { + case SM_PA: + if (aspectX > aspectY) { + max = floor(1.0 / aspectX); + } else { + max = floor(1.0 / aspectY); + } + break; + case SM_AF: + if (aspectX > aspectY) { + max = 1.0 / aspectX; + } else { + max = 1.0 / aspectY; + } + break; + case SM_SF: + aspectX = 1.0; + aspectY = 1.0; + break; + } + + aspectX *= max; + aspectY *= max; + + glUniform1i(texLocation, 0); + glUniform2f(dimsLocation, aspectX, aspectY); + glUniform2f(insizeLocation, width, height); + if (!faded) { + glUniform4f(colorLocation, 1.0f, 1.0f, 1.0f, 1.0f); + } else { + glUniform4f(colorLocation, 0.8f, 0.8f, 0.8f, 0.8f); + } + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); +} + +static void _prepareForFrame(struct mGUIRunner* runner) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + frameBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 256 * 256 * 4, GL_MAP_WRITE_BIT); + if (frameBuffer) { + runner->core->setVideoBuffer(runner->core, frameBuffer, 256); + } + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); +} + +static void _drawFrame(struct mGUIRunner* runner, bool faded) { + ++framecount; + if (!frameLimiter && framecount < framecap) { + return; + } + + unsigned width, height; + runner->core->desiredVideoDimensions(runner->core, &width, &height); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, height, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + _drawTex(runner, width, height, faded); + + HidVibrationValue values[4]; + if (rumble.up) { + rumble.value.amp_low = rumble.up / (float) (rumble.up + rumble.down); + rumble.value.amp_high = rumble.up / (float) (rumble.up + rumble.down); + memcpy(&values[0], &rumble.value, sizeof(rumble.value)); + memcpy(&values[1], &rumble.value, sizeof(rumble.value)); + memcpy(&values[2], &rumble.value, sizeof(rumble.value)); + memcpy(&values[3], &rumble.value, sizeof(rumble.value)); + } else { + memcpy(&values[0], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[1], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[2], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[3], &vibrationStop, sizeof(rumble.value)); + } + hidSendVibrationValues(vibrationDeviceHandles, values, 4); + rumble.up = 0; + rumble.down = 0; +} + +static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, unsigned width, unsigned height, bool faded) { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + _drawTex(runner, width, height, faded); +} + +static uint16_t _pollGameInput(struct mGUIRunner* runner) { + return _pollInput(&runner->core->inputMap); +} + +static void _incrementScreenMode(struct mGUIRunner* runner) { + UNUSED(runner); + screenMode = (screenMode + 1) % SM_MAX; + mCoreConfigSetUIntValue(&runner->config, "screenMode", screenMode); +} + +static void _setFrameLimiter(struct mGUIRunner* runner, bool limit) { + UNUSED(runner); + if (!frameLimiter && limit) { + while (enqueuedBuffers > 1) { + AudioOutBuffer* releasedBuffers; + u32 audoutNReleasedBuffers; + audoutWaitPlayFinish(&releasedBuffers, &audoutNReleasedBuffers, 100000000); + enqueuedBuffers -= audoutNReleasedBuffers; + } + } + frameLimiter = limit; + eglSwapInterval(s_surface, limit); +} + +static bool _running(struct mGUIRunner* runner) { + UNUSED(runner); + return appletMainLoop(); +} + +static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { + UNUSED(stream); + AudioOutBuffer* releasedBuffers; + u32 audoutNReleasedBuffers; + audoutGetReleasedAudioOutBuffer(&releasedBuffers, &audoutNReleasedBuffers); + enqueuedBuffers -= audoutNReleasedBuffers; + if (!frameLimiter && enqueuedBuffers >= N_BUFFERS) { + blip_clear(left); + blip_clear(right); + return; + } + if (enqueuedBuffers >= N_BUFFERS - 1 && R_SUCCEEDED(audoutWaitPlayFinish(&releasedBuffers, &audoutNReleasedBuffers, 10000000))) { + enqueuedBuffers -= audoutNReleasedBuffers; + } + + struct GBAStereoSample* samples = audioBuffer[audioBufferActive]; + blip_read_samples(left, &samples[0].left, SAMPLES, true); + blip_read_samples(right, &samples[0].right, SAMPLES, true); + audoutAppendAudioOutBuffer(&audoutBuffer[audioBufferActive]); + audioBufferActive += 1; + audioBufferActive %= N_BUFFERS; + ++enqueuedBuffers; +} + +void _setRumble(struct mRumble* rumble, int enable) { + struct mSwitchRumble* sr = (struct mSwitchRumble*) rumble; + if (enable) { + ++sr->up; + } else { + ++sr->down; + } +} + +int32_t _readTiltX(struct mRotationSource* source) { + UNUSED(source); + SixAxisSensorValues sixaxis; + hidSixAxisSensorValuesRead(&sixaxis, CONTROLLER_P1_AUTO, 1); + return sixaxis.accelerometer.x * 3e8f; +} + +int32_t _readTiltY(struct mRotationSource* source) { + UNUSED(source); + SixAxisSensorValues sixaxis; + hidSixAxisSensorValuesRead(&sixaxis, CONTROLLER_P1_AUTO, 1); + return sixaxis.accelerometer.y * -3e8f; +} + +int32_t _readGyroZ(struct mRotationSource* source) { + UNUSED(source); + SixAxisSensorValues sixaxis; + hidSixAxisSensorValuesRead(&sixaxis, CONTROLLER_P1_AUTO, 1); + return sixaxis.gyroscope.z * 1.1e9f; +} + +static int _batteryState(void) { + u32 charge; + int state = 0; + if (R_SUCCEEDED(psmGetBatteryChargePercentage(&charge))) { + state = (charge + 12) / 25; + } else { + return BATTERY_NOT_PRESENT; + } + ChargerType type; + if (R_SUCCEEDED(psmGetChargerType(&type)) && type) { + state |= BATTERY_CHARGING; + } + return state; +} + +int main(int argc, char* argv[]) { + socketInitializeDefault(); + nxlinkStdio(); + initEgl(); + romfsInit(); + audoutInitialize(); + psmInitialize(); + + struct GUIFont* font = GUIFontCreate(); + + u32 width = 1280; + u32 height = 720; + + glViewport(0, 0, width, height); + glClearColor(0.f, 0.f, 0.f, 1.f); + + glGenTextures(1, &tex); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glGenBuffers(1, &pbo); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + glBufferData(GL_PIXEL_UNPACK_BUFFER, 256 * 256 * 4, NULL, GL_STREAM_DRAW); + frameBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 256 * 256 * 4, GL_MAP_WRITE_BIT); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + program = glCreateProgram(); + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + const GLchar* shaderBuffer[2]; + + shaderBuffer[0] = _gles2Header; + + shaderBuffer[1] = _vertexShader; + glShaderSource(vertexShader, 2, shaderBuffer, NULL); + + shaderBuffer[1] = _fragmentShader; + glShaderSource(fragmentShader, 2, shaderBuffer, NULL); + + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + + glCompileShader(fragmentShader); + + GLint success; + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); + if (!success) { + GLchar msg[512]; + glGetShaderInfoLog(fragmentShader, sizeof(msg), NULL, msg); + puts(msg); + } + + glCompileShader(vertexShader); + + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + if (!success) { + GLchar msg[512]; + glGetShaderInfoLog(vertexShader, sizeof(msg), NULL, msg); + puts(msg); + } + glLinkProgram(program); + + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + + texLocation = glGetUniformLocation(program, "tex"); + colorLocation = glGetUniformLocation(program, "color"); + dimsLocation = glGetUniformLocation(program, "dims"); + insizeLocation = glGetUniformLocation(program, "insize"); + GLuint offsetLocation = glGetAttribLocation(program, "offset"); + + glGenBuffers(1, &vbo); + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(_offsets), _offsets, GL_STATIC_DRAW); + glVertexAttribPointer(offsetLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(offsetLocation); + glBindVertexArray(0); + + rumble.d.setRumble = _setRumble; + rumble.value.freq_low = 120.0; + rumble.value.freq_high = 180.0; + hidInitializeVibrationDevices(&vibrationDeviceHandles[0], 2, CONTROLLER_HANDHELD, TYPE_HANDHELD | TYPE_JOYCON_PAIR); + hidInitializeVibrationDevices(&vibrationDeviceHandles[2], 2, CONTROLLER_PLAYER_1, TYPE_HANDHELD | TYPE_JOYCON_PAIR); + + u32 handles[4]; + hidGetSixAxisSensorHandles(&handles[0], 2, CONTROLLER_PLAYER_1, TYPE_JOYCON_PAIR); + hidGetSixAxisSensorHandles(&handles[2], 1, CONTROLLER_PLAYER_1, TYPE_PROCONTROLLER); + hidGetSixAxisSensorHandles(&handles[3], 1, CONTROLLER_HANDHELD, TYPE_HANDHELD); + hidStartSixAxisSensor(handles[0]); + hidStartSixAxisSensor(handles[1]); + hidStartSixAxisSensor(handles[2]); + hidStartSixAxisSensor(handles[3]); + rotation.readTiltX = _readTiltX; + rotation.readTiltY = _readTiltY; + rotation.readGyroZ = _readGyroZ; + + stream.videoDimensionsChanged = NULL; + stream.postVideoFrame = NULL; + stream.postAudioFrame = NULL; + stream.postAudioBuffer = _postAudioBuffer; + + memset(audioBuffer, 0, sizeof(audioBuffer)); + audioBufferActive = 0; + enqueuedBuffers = 0; + size_t i; + for (i = 0; i < N_BUFFERS; ++i) { + audoutBuffer[i].next = NULL; + audoutBuffer[i].buffer = audioBuffer[i]; + audoutBuffer[i].buffer_size = BUFFER_SIZE; + audoutBuffer[i].data_size = BUFFER_SIZE; + audoutBuffer[i].data_offset = 0; + } + + struct mGUIRunner runner = { + .params = { + width, height, + font, "/", + _drawStart, _drawEnd, + _pollInput, _pollCursor, + _batteryState, + NULL, NULL, + }, + .keySources = (struct GUIInputKeys[]) { + { + .name = "Controller Input", + .id = AUTO_INPUT, + .keyNames = (const char*[]) { + "A", + "B", + "X", + "Y", + "L Stick", + "R Stick", + "L", + "R", + "ZL", + "ZR", + "+", + "-", + "Left", + "Up", + "Right", + "Down", + "L Left", + "L Up", + "L Right", + "L Down", + "R Left", + "R Up", + "R Right", + "R Down", + "SL", + "SR" + }, + .nKeys = 26 + }, + { .id = 0 } + }, + .configExtra = (struct GUIMenuItem[]) { + { + .title = "Screen mode", + .data = "screenMode", + .submenu = 0, + .state = SM_PA, + .validStates = (const char*[]) { + "Pixel-Accurate", + "Aspect-Ratio Fit", + "Stretched", + }, + .nStates = 3 + }, + { + .title = "Fast forward cap", + .data = "fastForwardCap", + .submenu = 0, + .state = 7, + .validStates = (const char*[]) { + "2", "3", "4", "5", "6", "7", "8", "9", + "10", "11", "12", "13", "14", "15", + "20", "30" + }, + .stateMappings = (const struct GUIVariant[]) { + GUI_V_U(2), + GUI_V_U(3), + GUI_V_U(4), + GUI_V_U(5), + GUI_V_U(6), + GUI_V_U(7), + GUI_V_U(8), + GUI_V_U(9), + GUI_V_U(10), + GUI_V_U(11), + GUI_V_U(12), + GUI_V_U(13), + GUI_V_U(14), + GUI_V_U(15), + GUI_V_U(20), + GUI_V_U(30), + }, + .nStates = 16 + }, + }, + .nConfigExtra = 2, + .setup = _setup, + .teardown = NULL, + .gameLoaded = _gameLoaded, + .gameUnloaded = _gameUnloaded, + .prepareForFrame = _prepareForFrame, + .drawFrame = _drawFrame, + .drawScreenshot = _drawScreenshot, + .paused = _gameUnloaded, + .unpaused = _gameLoaded, + .incrementScreenMode = _incrementScreenMode, + .setFrameLimiter = _setFrameLimiter, + .pollGameInput = _pollGameInput, + .running = _running + }; + mGUIInit(&runner, "switch"); + + _mapKey(&runner.params.keyMap, AUTO_INPUT, KEY_A, GUI_INPUT_SELECT); + _mapKey(&runner.params.keyMap, AUTO_INPUT, KEY_B, GUI_INPUT_BACK); + _mapKey(&runner.params.keyMap, AUTO_INPUT, KEY_X, GUI_INPUT_CANCEL); + _mapKey(&runner.params.keyMap, AUTO_INPUT, KEY_DUP, GUI_INPUT_UP); + _mapKey(&runner.params.keyMap, AUTO_INPUT, KEY_DDOWN, GUI_INPUT_DOWN); + _mapKey(&runner.params.keyMap, AUTO_INPUT, KEY_DLEFT, GUI_INPUT_LEFT); + _mapKey(&runner.params.keyMap, AUTO_INPUT, KEY_DRIGHT, GUI_INPUT_RIGHT); + + audoutStartAudioOut(); + + if (argc > 1) { + size_t i; + for (i = 0; runner.keySources[i].id; ++i) { + mInputMapLoad(&runner.params.keyMap, runner.keySources[i].id, mCoreConfigGetInput(&runner.config)); + } + mGUIRun(&runner, argv[1]); + } else { + mGUIRunloop(&runner); + } + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glDeleteBuffers(1, &pbo); + + glDeleteTextures(1, &tex); + glDeleteBuffers(1, &vbo); + glDeleteProgram(program); + glDeleteVertexArrays(1, &vao); + + hidStopSixAxisSensor(handles[0]); + hidStopSixAxisSensor(handles[1]); + hidStopSixAxisSensor(handles[2]); + hidStopSixAxisSensor(handles[3]); + + psmExit(); + audoutExit(); + deinitEgl(); + socketExit(); + return 0; +} diff -Nru mgba-0.6.3+dfsg1/src/platform/switch/memory.c mgba-0.7.0/src/platform/switch/memory.c --- mgba-0.6.3+dfsg1/src/platform/switch/memory.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/switch/memory.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,15 @@ +/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + +void* anonymousMemoryMap(size_t size) { + return malloc(size); +} + +void mappedMemoryFree(void* memory, size_t size) { + UNUSED(size); + free(memory); +} diff -Nru mgba-0.6.3+dfsg1/src/platform/test/fuzz-main.c mgba-0.7.0/src/platform/test/fuzz-main.c --- mgba-0.6.3+dfsg1/src/platform/test/fuzz-main.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/test/fuzz-main.c 2019-01-27 00:06:06.000000000 +0000 @@ -26,14 +26,12 @@ " -F FRAMES Run for the specified number of FRAMES before exiting\n" \ " -N Disable video rendering entirely\n" \ " -O OFFSET Offset to apply savestate overlay\n" \ - " -S FILE Load a savestate when starting the test\n" \ " -V FILE Overlay a second savestate over the loaded savestate\n" \ struct FuzzOpts { bool noVideo; int frames; size_t overlayOffset; - char* savestate; char* ssOverlay; }; @@ -108,9 +106,8 @@ struct VFile* savestateOverlay = 0; size_t overlayOffset; - if (fuzzOpts.savestate) { - savestate = VFileOpen(fuzzOpts.savestate, O_RDONLY); - free(fuzzOpts.savestate); + if (args.savestate) { + savestate = VFileOpen(args.savestate, O_RDONLY); } if (fuzzOpts.ssOverlay) { overlayOffset = fuzzOpts.overlayOffset; @@ -200,9 +197,6 @@ case 'O': opts->overlayOffset = strtoul(arg, 0, 10); return !errno; - case 'S': - opts->savestate = strdup(arg); - return true; case 'V': opts->ssOverlay = strdup(arg); return true; diff -Nru mgba-0.6.3+dfsg1/src/platform/test/perf-main.c mgba-0.7.0/src/platform/test/perf-main.c --- mgba-0.6.3+dfsg1/src/platform/test/perf-main.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/test/perf-main.c 2019-01-27 00:06:06.000000000 +0000 @@ -19,6 +19,9 @@ #ifdef _3DS #include <3ds.h> #endif +#ifdef __SWITCH__ +#include +#endif #include #include @@ -26,11 +29,12 @@ #include #include -#define PERF_OPTIONS "DF:L:NPS:" +#define PERF_OPTIONS "DF:L:NPS:T" #define PERF_USAGE \ "\nBenchmark options:\n" \ " -F FRAMES Run for the specified number of FRAMES before exiting\n" \ " -N Disable video rendering entirely\n" \ + " -T Use threaded video rendering\n" \ " -P CSV output, useful for parsing\n" \ " -S SEC Run for SEC in-game seconds before exiting\n" \ " -L FILE Load a savestate when starting the test\n" \ @@ -38,6 +42,7 @@ struct PerfOpts { bool noVideo; + bool threadedVideo; bool csv; unsigned duration; unsigned frames; @@ -49,6 +54,9 @@ extern bool allocateRomBuffer(void); FS_Archive sdmcArchive; #endif +#ifdef __SWITCH__ +TimeType __nx_time_type = TimeType_LocalSystemClock; +#endif static void _mPerfRunloop(struct mCore* context, int* frames, bool quiet); static void _mPerfShutdown(int signal); @@ -71,6 +79,9 @@ if (!allocateRomBuffer()) { return 1; } +#elif defined(__SWITCH__) + UNUSED(_mPerfShutdown); + consoleInit(NULL); #else signal(SIGINT, _mPerfShutdown); #endif @@ -79,7 +90,7 @@ struct mLogger logger = { .log = _log }; mLogSetDefaultLogger(&logger); - struct PerfOpts perfOpts = { false, false, 0, 0, 0, false }; + struct PerfOpts perfOpts = { false, false, false, 0, 0, 0, false }; struct mSubParser subparser = { .usage = PERF_USAGE, .parse = _parsePerfOpts, @@ -111,6 +122,9 @@ _outputBuffer = malloc(256 * 256 * 4); if (perfOpts.csv) { puts("game_code,frames,duration,renderer"); +#ifdef __SWITCH__ + consoleUpdate(NULL); +#endif } if (perfOpts.server) { didFail = !_mPerfRunServer(args.fname, &args, &perfOpts); @@ -128,6 +142,8 @@ #ifdef _3DS gfxExit(); acExit(); +#elif defined(__SWITCH__) + consoleExit(NULL); #endif return didFail; @@ -150,6 +166,12 @@ mCoreConfigInit(&core->config, "perf"); mCoreConfigLoad(&core->config); + if (perfOpts->threadedVideo) { + mCoreConfigSetOverrideIntValue(&core->config, "threadedVideo", 1); + } else { + mCoreConfigSetOverrideIntValue(&core->config, "threadedVideo", 0); + } + struct mCoreOptions opts = {}; mCoreConfigMap(&core->config, &opts); opts.audioSync = false; @@ -188,6 +210,8 @@ const char* rendererName; if (perfOpts->noVideo) { rendererName = "none"; + } else if (perfOpts->threadedVideo) { + rendererName = "threaded-software"; } else { rendererName = "software"; } @@ -199,6 +223,9 @@ } else { printf("%u frames in %" PRIu64 " microseconds: %g fps (%gx)\n", frames, duration, scaledFrames / duration, scaledFrames / (duration * 60.f)); } +#ifdef __SWITCH__ + consoleUpdate(NULL); +#endif return true; } @@ -223,6 +250,9 @@ if (timeDiff >= 1000) { printf("\033[2K\rCurrent FPS: %g (%gx)", lastFrames / (timeDiff / 1000.0f), lastFrames / (float) (60 * (timeDiff / 1000.0f))); fflush(stdout); +#ifdef __SWITCH__ + consoleUpdate(NULL); +#endif lastEcho = currentTime; lastFrames = 0; } @@ -254,7 +284,10 @@ SocketSend(_socket, header, strlen(header)); } char path[PATH_MAX]; - while (SocketRecv(_socket, path, sizeof(path)) > 0) { + memset(path, 0, sizeof(path)); + ssize_t i; + while ((i = SocketRecv(_socket, path, sizeof(path) - 1)) > 0) { + path[i] = '\0'; char* nl = strchr(path, '\n'); if (nl == path) { break; @@ -265,6 +298,7 @@ if (!_mPerfRunCore(path, args, perfOpts)) { break; } + memset(path, 0, sizeof(path)); } SocketClose(_socket); SocketClose(server); @@ -297,6 +331,9 @@ case 'S': opts->duration = strtoul(arg, 0, 10); return !errno; + case 'T': + opts->threadedVideo = true; + return true; case 'L': opts->savestate = strdup(arg); return true; diff -Nru mgba-0.6.3+dfsg1/src/platform/test/suite-main.c mgba-0.7.0/src/platform/test/suite-main.c --- mgba-0.6.3+dfsg1/src/platform/test/suite-main.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/test/suite-main.c 1970-01-01 00:00:00.000000000 +0000 @@ -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 "util/test/suite.h" - -#include "util/test/util.h" -#include "core/test/core.h" -#ifdef M_CORE_GBA -#include "gba/test/gba.h" -#endif -#ifdef M_CORE_GB -#include "gb/test/gb.h" -#endif - -int main() { - int failures = TestRunUtil(); - failures += TestRunCore(); -#ifdef M_CORE_GBA - failures += TestRunGBA(); -#endif -#ifdef M_CORE_GB - failures += TestRunGB(); -#endif - return failures != 0; -} diff -Nru mgba-0.6.3+dfsg1/src/platform/wii/CMakeLists.txt mgba-0.7.0/src/platform/wii/CMakeLists.txt --- mgba-0.6.3+dfsg1/src/platform/wii/CMakeLists.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/wii/CMakeLists.txt 2019-01-27 00:06:06.000000000 +0000 @@ -3,7 +3,7 @@ find_program(RAW2C raw2c) find_program(WIILOAD wiiload) -set(OS_DEFINES COLOR_16_BIT COLOR_5_6_5 USE_VFS_FILE IOAPI_NO_64) +set(OS_DEFINES COLOR_16_BIT COLOR_5_6_5 USE_VFS_FILE IOAPI_NO_64 FIXED_ROM_BUFFER) list(APPEND CORE_VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-devlist.c) include_directories(${CMAKE_CURRENT_BINARY_DIR}) @@ -40,5 +40,7 @@ DEPENDS ${BINARY_NAME}.dol) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/meta.xml.in ${CMAKE_CURRENT_BINARY_DIR}/meta.xml) + +install(TARGETS ${BINARY_NAME}.elf DESTINATION . COMPONENT ${BINARY_NAME}-dbg) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/meta.xml DESTINATION . COMPONENT ${BINARY_NAME}-wii) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.dol DESTINATION . RENAME boot.dol COMPONENT ${BINARY_NAME}-wii) diff -Nru mgba-0.6.3+dfsg1/src/platform/wii/CMakeToolchain.txt mgba-0.7.0/src/platform/wii/CMakeToolchain.txt --- mgba-0.6.3+dfsg1/src/platform/wii/CMakeToolchain.txt 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/wii/CMakeToolchain.txt 2019-01-27 00:06:06.000000000 +0000 @@ -39,7 +39,7 @@ set(CMAKE_MODULE_LINKER_FLAGS ${link_flags} CACHE INTERNAL "module link flags") set(CMAKE_SHARED_LINKER_FLAGS ${link_flags} CACHE INTERNAL "shared link flags") -set(CMAKE_FIND_ROOT_PATH ${DEVKITPPC}/powerpc-eabi) +set(CMAKE_FIND_ROOT_PATH ${DEVKITPPC}/powerpc-eabi ${DEVKITPRO}/portlibs/ppc) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE INTERNAL "") set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY CACHE INTERNAL "") set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY CACHE INTERNAL "") diff -Nru mgba-0.6.3+dfsg1/src/platform/wii/main.c mgba-0.7.0/src/platform/wii/main.c --- mgba-0.6.3+dfsg1/src/platform/wii/main.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/platform/wii/main.c 2019-01-27 00:06:06.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #define GCN1_INPUT 0x47434E31 @@ -32,7 +33,9 @@ #define CLASSIC_INPUT 0x57494943 #define TEX_W 256 -#define TEX_H 160 +#define TEX_H 224 + +#define ANALOG_DEADZONE 0x30 static void _mapKey(struct mInputMap* map, uint32_t binding, int nativeKey, enum GBAKey key) { mInputBindKey(map, binding, __builtin_ctz(nativeKey), key); @@ -66,6 +69,7 @@ static void _retraceCallback(u32 count); +static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right); static void _audioDMA(void); static void _setRumble(struct mRumble* rumble, int enable); static void _sampleRotation(struct mRotationSource* source); @@ -92,6 +96,7 @@ static s8 WPAD_StickY(u8 chan, u8 right); static void* outputBuffer; +static struct mAVStream stream; static struct mRumble rumble; static struct mRotationSource rotation; static GXRModeObj* vmode; @@ -114,6 +119,9 @@ static int scaleFactor; static unsigned corew, coreh; +uint32_t* romBuffer; +size_t romBufferSize; + static void* framebuffer[2] = { 0, 0 }; static int whichFb = 0; @@ -187,18 +195,18 @@ break; } - free(framebuffer[0]); - free(framebuffer[1]); - VIDEO_SetBlack(true); VIDEO_Configure(vmode); + free(framebuffer[0]); + free(framebuffer[1]); + framebuffer[0] = SYS_AllocateFramebuffer(vmode); framebuffer[1] = SYS_AllocateFramebuffer(vmode); - VIDEO_ClearFrameBuffer(vmode, framebuffer[0], COLOR_BLACK); - VIDEO_ClearFrameBuffer(vmode, framebuffer[1], COLOR_BLACK); + VIDEO_ClearFrameBuffer(vmode, MEM_K0_TO_K1(framebuffer[0]), COLOR_BLACK); + VIDEO_ClearFrameBuffer(vmode, MEM_K0_TO_K1(framebuffer[1]), COLOR_BLACK); - VIDEO_SetNextFramebuffer(framebuffer[whichFb]); + VIDEO_SetNextFramebuffer(MEM_K0_TO_K1(framebuffer[whichFb])); VIDEO_Flush(); VIDEO_WaitVSync(); if (vmode->viTVMode & VI_NON_INTERLACE) { @@ -218,18 +226,9 @@ runner->params.width = vmode->fbWidth * guiScale * wAdjust; runner->params.height = vmode->efbHeight * guiScale * hAdjust; if (runner->core) { - double ratio = GBAAudioCalculateRatio(1,audioSampleRate, 1); + double ratio = GBAAudioCalculateRatio(1, audioSampleRate, 1); blip_set_rates(runner->core->getAudioChannel(runner->core, 0), runner->core->frequency(runner->core), 48000 * ratio); blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), 48000 * ratio); - - runner->core->desiredVideoDimensions(runner->core, &corew, &coreh); - int hfactor = vmode->fbWidth / (corew * wAdjust); - int vfactor = vmode->efbHeight / (coreh * hAdjust); - if (hfactor > vfactor) { - scaleFactor = vfactor; - } else { - scaleFactor = hfactor; - } } } } @@ -247,6 +246,11 @@ AUDIO_RegisterDMACallback(_audioDMA); memset(audioBuffer, 0, sizeof(audioBuffer)); +#ifdef FIXED_ROM_BUFFER + romBufferSize = SIZE_CART0; + romBuffer = SYS_GetArena2Lo(); + SYS_SetArena2Lo((void*)((intptr_t) romBuffer + SIZE_CART0)); +#endif #if !defined(COLOR_16_BIT) && !defined(COLOR_5_6_5) #error This pixel format is unsupported. Please use -DCOLOR_16-BIT -DCOLOR_5_6_5 @@ -308,6 +312,11 @@ rotation.readTiltY = _readTiltY; rotation.readGyroZ = _readGyroZ; + stream.videoDimensionsChanged = NULL; + stream.postVideoFrame = NULL; + stream.postAudioFrame = NULL; + stream.postAudioBuffer = _postAudioBuffer; + struct mGUIRunner runner = { .params = { 720, 480, @@ -460,9 +469,49 @@ "Bilinear (pixelated)", }, .nStates = 3 - } + }, + { + .title = "Horizontal stretch", + .data = "stretchWidth", + .submenu = 0, + .state = 7, + .validStates = (const char*[]) { + "1/2x", "0.6x", "1/3x", "0.7x", "1/4x", "0.8x", "0.9x", "1.0x" + }, + .stateMappings = (const struct GUIVariant[]) { + GUI_V_F(0.5f), + GUI_V_F(0.6f), + GUI_V_F(1.f / 3.f), + GUI_V_F(0.7f), + GUI_V_F(0.75f), + GUI_V_F(0.8f), + GUI_V_F(0.9f), + GUI_V_F(1.0f), + }, + .nStates = 8 + }, + { + .title = "Vertical stretch", + .data = "stretchHeight", + .submenu = 0, + .state = 6, + .validStates = (const char*[]) { + "1/2x", "0.6x", "1/3x", "0.7x", "1/4x", "0.8x", "0.9x", "1.0x" + }, + .stateMappings = (const struct GUIVariant[]) { + GUI_V_F(0.5f), + GUI_V_F(0.6f), + GUI_V_F(1.f / 3.f), + GUI_V_F(0.7f), + GUI_V_F(0.75f), + GUI_V_F(0.8f), + GUI_V_F(0.9f), + GUI_V_F(1.0f), + }, + .nStates = 8 + }, }, - .nConfigExtra = 3, + .nConfigExtra = 5, .setup = _setup, .teardown = 0, .gameLoaded = _gameLoaded, @@ -508,6 +557,15 @@ _mapKey(&runner.params.keyMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_LEFT, GUI_INPUT_LEFT); _mapKey(&runner.params.keyMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_RIGHT, GUI_INPUT_RIGHT); + + float stretch = 0; + if (mCoreConfigGetFloatValue(&runner.config, "stretchWidth", &stretch)) { + wStretch = fminf(1.0f, fmaxf(0.5f, stretch)); + } + if (mCoreConfigGetFloatValue(&runner.config, "stretchHeight", &stretch)) { + hStretch = fminf(1.0f, fmaxf(0.5f, stretch)); + } + if (argc > 1) { size_t i; for (i = 0; runner.keySources[i].id; ++i) { @@ -545,6 +603,25 @@ audioBufferSize = 0; } +static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) { + UNUSED(stream); + int available = blip_samples_avail(left); + if (available + audioBufferSize > SAMPLES) { + available = SAMPLES - audioBufferSize; + } + available &= ~((32 / sizeof(struct GBAStereoSample)) - 1); // Force align to 32 bytes + if (available > 0) { + // These appear to be reversed for AUDIO_InitDMA + blip_read_samples(left, &audioBuffer[currentAudioBuffer][audioBufferSize].right, available, true); + blip_read_samples(right, &audioBuffer[currentAudioBuffer][audioBufferSize].left, available, true); + audioBufferSize += available; + } + if (audioBufferSize == SAMPLES && !AUDIO_GetDMAEnableFlag()) { + _audioDMA(); + AUDIO_StartDMA(); + } +} + static void _drawStart(void) { VIDEO_SetBlack(false); @@ -567,7 +644,7 @@ static void _drawEnd(void) { GX_CopyDisp(framebuffer[whichFb], GX_TRUE); GX_DrawDone(); - VIDEO_SetNextFramebuffer(framebuffer[whichFb]); + VIDEO_SetNextFramebuffer(MEM_K0_TO_K1(framebuffer[whichFb])); VIDEO_Flush(); whichFb = !whichFb; @@ -602,16 +679,16 @@ int y = PAD_StickY(0); int w_x = WPAD_StickX(0, 0); int w_y = WPAD_StickY(0, 0); - if (x < -0x20 || w_x < -0x20) { + if (x < -ANALOG_DEADZONE || w_x < -ANALOG_DEADZONE) { keys |= 1 << GUI_INPUT_LEFT; } - if (x > 0x20 || w_x > 0x20) { + if (x > ANALOG_DEADZONE || w_x > ANALOG_DEADZONE) { keys |= 1 << GUI_INPUT_RIGHT; } - if (y < -0x20 || w_y <- 0x20) { + if (y < -ANALOG_DEADZONE || w_y < -ANALOG_DEADZONE) { keys |= 1 << GUI_INPUT_DOWN; } - if (y > 0x20 || w_y > 0x20) { + if (y > ANALOG_DEADZONE || w_y > ANALOG_DEADZONE) { keys |= 1 << GUI_INPUT_UP; } return keys; @@ -656,6 +733,7 @@ void _setup(struct mGUIRunner* runner) { runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation); runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble); + runner->core->setAVStream(runner->core, &stream); _mapKey(&runner->core->inputMap, GCN1_INPUT, PAD_BUTTON_A, GBA_KEY_A); _mapKey(&runner->core->inputMap, GCN1_INPUT, PAD_BUTTON_B, GBA_KEY_B); @@ -691,10 +769,10 @@ _mapKey(&runner->core->inputMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_FULL_L, GBA_KEY_L); _mapKey(&runner->core->inputMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_FULL_R, GBA_KEY_R); - struct mInputAxis desc = { GBA_KEY_RIGHT, GBA_KEY_LEFT, 0x20, -0x20 }; + struct mInputAxis desc = { GBA_KEY_RIGHT, GBA_KEY_LEFT, ANALOG_DEADZONE, -ANALOG_DEADZONE }; mInputBindAxis(&runner->core->inputMap, GCN1_INPUT, 0, &desc); mInputBindAxis(&runner->core->inputMap, CLASSIC_INPUT, 0, &desc); - desc = (struct mInputAxis) { GBA_KEY_UP, GBA_KEY_DOWN, 0x20, -0x20 }; + desc = (struct mInputAxis) { GBA_KEY_UP, GBA_KEY_DOWN, ANALOG_DEADZONE, -ANALOG_DEADZONE }; mInputBindAxis(&runner->core->inputMap, GCN1_INPUT, 1, &desc); mInputBindAxis(&runner->core->inputMap, CLASSIC_INPUT, 1, &desc); @@ -774,22 +852,7 @@ } void _drawFrame(struct mGUIRunner* runner, bool faded) { - int available = blip_samples_avail(runner->core->getAudioChannel(runner->core, 0)); - if (available + audioBufferSize > SAMPLES) { - available = SAMPLES - audioBufferSize; - } - available &= ~((32 / sizeof(struct GBAStereoSample)) - 1); // Force align to 32 bytes - if (available > 0) { - // These appear to be reversed for AUDIO_InitDMA - blip_read_samples(runner->core->getAudioChannel(runner->core, 0), &audioBuffer[currentAudioBuffer][audioBufferSize].right, available, true); - blip_read_samples(runner->core->getAudioChannel(runner->core, 1), &audioBuffer[currentAudioBuffer][audioBufferSize].left, available, true); - audioBufferSize += available; - } - if (audioBufferSize == SAMPLES && !AUDIO_GetDMAEnableFlag()) { - _audioDMA(); - AUDIO_StartDMA(); - } - + runner->core->desiredVideoDimensions(runner->core, &corew, &coreh); uint32_t color = 0xFFFFFF3F; if (!faded) { color |= 0xC0; @@ -815,9 +878,9 @@ GX_InvalidateTexAll(); GX_LoadTexObj(&tex, GX_TEXMAP0); - GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0); - s16 vertWidth = TEX_W; - s16 vertHeight = TEX_H; + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + s16 vertWidth = corew; + s16 vertHeight = coreh; if (filterMode == FM_LINEAR_2x) { Mtx44 proj; @@ -827,19 +890,19 @@ GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Position2s16(0, TEX_H * 2); GX_Color1u32(0xFFFFFFFF); - GX_TexCoord2s16(0, 1); + GX_TexCoord2f32(0, 1); GX_Position2s16(TEX_W * 2, TEX_H * 2); GX_Color1u32(0xFFFFFFFF); - GX_TexCoord2s16(1, 1); + GX_TexCoord2f32(1, 1); GX_Position2s16(TEX_W * 2, 0); GX_Color1u32(0xFFFFFFFF); - GX_TexCoord2s16(1, 0); + GX_TexCoord2f32(1, 0); GX_Position2s16(0, 0); GX_Color1u32(0xFFFFFFFF); - GX_TexCoord2s16(0, 0); + GX_TexCoord2f32(0, 0); GX_End(); GX_SetTexCopySrc(0, 0, TEX_W * 2, TEX_H * 2); @@ -848,6 +911,14 @@ GX_LoadTexObj(&rescaleTex, GX_TEXMAP0); } + int hfactor = (vmode->fbWidth * wStretch) / (corew * wAdjust); + int vfactor = (vmode->efbHeight * hStretch) / (coreh * hAdjust); + if (hfactor > vfactor) { + scaleFactor = vfactor; + } else { + scaleFactor = hfactor; + } + if (screenMode == SM_PA) { vertWidth *= scaleFactor; vertHeight *= scaleFactor; @@ -862,19 +933,19 @@ GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Position2s16(0, vertHeight); GX_Color1u32(color); - GX_TexCoord2s16(0, 1); + GX_TexCoord2f32(0, coreh / (float) TEX_H); GX_Position2s16(vertWidth, vertHeight); GX_Color1u32(color); - GX_TexCoord2s16(1, 1); + GX_TexCoord2f32(corew / (float) TEX_W, coreh / (float) TEX_H); GX_Position2s16(vertWidth, 0); GX_Color1u32(color); - GX_TexCoord2s16(1, 0); + GX_TexCoord2f32(corew / (float) TEX_W, 0); GX_Position2s16(0, 0); GX_Color1u32(color); - GX_TexCoord2s16(0, 0); + GX_TexCoord2f32(0, 0); GX_End(); } @@ -977,77 +1048,65 @@ } static s8 WPAD_StickX(u8 chan, u8 right) { - float mag = 0.0; - float ang = 0.0; - WPADData *data = WPAD_Data(chan); + struct expansion_t exp; + WPAD_Expansion(chan, &exp); + struct joystick_t* js = NULL; - switch (data->exp.type) { + switch (exp.type) { case WPAD_EXP_NUNCHUK: case WPAD_EXP_GUITARHERO3: if (right == 0) { - mag = data->exp.nunchuk.js.mag; - ang = data->exp.nunchuk.js.ang; + js = &exp.nunchuk.js; } break; case WPAD_EXP_CLASSIC: if (right == 0) { - mag = data->exp.classic.ljs.mag; - ang = data->exp.classic.ljs.ang; + js = &exp.classic.ljs; } else { - mag = data->exp.classic.rjs.mag; - ang = data->exp.classic.rjs.ang; + js = &exp.classic.rjs; } break; default: break; } - /* calculate X value (angle need to be converted into radian) */ - if (mag > 1.0) { - mag = 1.0; - } else if (mag < -1.0) { - mag = -1.0; - } - double val = mag * sinf(M_PI * ang / 180.0f); - - return (s8)(val * 128.0f); + if (!js) { + return 0; + } + int centered = (int) js->pos.x - (int) js->center.x; + int range = js->max.x - js->min.x; + return (centered * 0xFF) / range; } static s8 WPAD_StickY(u8 chan, u8 right) { - float mag = 0.0; - float ang = 0.0; - WPADData *data = WPAD_Data(chan); + struct expansion_t exp; + WPAD_Expansion(chan, &exp); + struct joystick_t* js = NULL; - switch (data->exp.type) { + switch (exp.type) { case WPAD_EXP_NUNCHUK: case WPAD_EXP_GUITARHERO3: if (right == 0) { - mag = data->exp.nunchuk.js.mag; - ang = data->exp.nunchuk.js.ang; + js = &exp.nunchuk.js; } break; case WPAD_EXP_CLASSIC: if (right == 0) { - mag = data->exp.classic.ljs.mag; - ang = data->exp.classic.ljs.ang; + js = &exp.classic.ljs; } else { - mag = data->exp.classic.rjs.mag; - ang = data->exp.classic.rjs.ang; + js = &exp.classic.rjs; } break; default: break; } - /* calculate X value (angle need to be converted into radian) */ - if (mag > 1.0) { - mag = 1.0; - } else if (mag < -1.0) { - mag = -1.0; - } - double val = mag * cosf(M_PI * ang / 180.0f); - - return (s8)(val * 128.0f); + if (!js) { + return 0; + } + int centered = (int) js->pos.y - (int) js->center.y; + int range = js->max.y - js->min.y; + return (centered * 0xFF) / range; } void _retraceCallback(u32 count) { Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/src/platform/windows/setup/setup.ico and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/src/platform/windows/setup/setup.ico differ diff -Nru mgba-0.6.3+dfsg1/src/platform/windows/setup/setup.iss.in mgba-0.7.0/src/platform/windows/setup/setup.iss.in --- mgba-0.6.3+dfsg1/src/platform/windows/setup/setup.iss.in 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/platform/windows/setup/setup.iss.in 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,140 @@ +#define AppName "${PROJECT_NAME}" +#define AppName2 "${BINARY_NAME}" +#define VerMajor ${LIB_VERSION_MAJOR} +#define VerMinor ${LIB_VERSION_MINOR} +#define VerRev ${LIB_VERSION_PATCH} +#define VerBuild ${GIT_REV} +#define Release ${IS_RELEASE} +#define WinBits "${WIN_BITS}" +#define VersionString "${VERSION_STRING}" +#define CleanVersionString "${CLEAN_VERSION_STRING}" +#define SetupDir "${SETUP_DIR}" +#define BinDir "${BIN_DIR}" +#define ResDir "${RES_DIR}" + +#define FullVersion ParseVersion('{#AppName}.exe', VerMajor, VerMinor, VerRev, VerBuild) +#define AppVer Str(VerMajor) + "." + Str(VerMinor) + "." + Str(VerRev) + +[Setup] +SourceDir={#BinDir} +SetupIconFile={#SetupDir}\setup.ico +WizardImageFile={#SetupDir}\wizard-image.bmp + +AppName={#AppName} +AppVersion={#AppVer} +AppPublisher=Jeffrey Pfau +AppPublisherURL=https://mgba.io +AppSupportURL=https://mgba.io +AppUpdatesURL=https://mgba.io +AppReadmeFile={#BinDir}\README.html +OutputDir=.\ +DefaultDirName={pf}\{#AppName} +DefaultGroupName={#AppName} +AllowNoIcons=yes +DirExistsWarning=no +ChangesAssociations=True +AppendDefaultDirName=False +UninstallDisplayIcon={app}\{#AppName}.exe +MinVersion=0,6.0 +AlwaysShowDirOnReadyPage=True +UsePreviousSetupType=True +UsePreviousTasks=True +AlwaysShowGroupOnReadyPage=True +LicenseFile={#BinDir}\LICENSE.txt +#if Release + #define IsRelease = 'yes' + AppVerName={#AppName} {#AppVer} +#else + #define IsRelease = 'no' + AppVerName={#AppName} {#VersionString} (Development build) +#endif +#if '{#WinBits}' == '64' + ArchitecturesInstallIn64BitMode=x64 + ArchitecturesAllows=x64 +#endif +OutputBaseFilename={#AppName}-setup-{#CleanVersionString}-win{#WinBits} +UsePreviousLanguage=False +DisableWelcomePage=False +VersionInfoDescription={#AppName} is an open-source Game Boy Advance emulator +VersionInfoCopyright= 20132018 Jeffrey Pfau +VersionInfoProductName={#AppName} +VersionInfoVersion={#AppVer} +Compression=lzma2/ultra64 +SolidCompression=True +VersionInfoTextVersion={#AppVer} +VersionInfoProductVersion={#AppVer} +VersionInfoProductTextVersion={#AppVer} + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" +Name: "french"; MessagesFile: "compiler:Languages\French.isl" +Name: "german"; MessagesFile: "compiler:Languages\German.isl" +Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl" +Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" +Name: "gbfileassoc"; Description: "{cm:AssocFileExtension,{#AppName},Game Boy}"; GroupDescription: "{cm:FileAssoc}" +Name: "gbcfileassoc"; Description: "{cm:AssocFileExtension,{#AppName},Game Boy Color}"; GroupDescription: "{cm:FileAssoc}" +Name: "sgbfileassoc"; Description: "{cm:AssocFileExtension,{#AppName},Super Game Boy}"; GroupDescription: "{cm:FileAssoc}" +Name: "gbafileassoc"; Description: "{cm:AssocFileExtension,{#AppName},Game Boy Advance}"; GroupDescription: "{cm:FileAssoc}" + +[Files] +Source: "{#BinDir}\qt\{#AppName}.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#BinDir}\sdl\{#AppName2}-sdl.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#BinDir}\CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion isreadme +Source: "{#BinDir}\LICENSE.txt"; DestDir: "{app}\"; Flags: ignoreversion +Source: "{#ResDir}\nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion +Source: "{#BinDir}\README.html"; DestDir: "{app}\"; Flags: ignoreversion isreadme; Languages: english italian spanish +Source: "{#BinDir}\README_DE.html"; DestDir: "{app}\"; DestName: "LIESMICH.html"; Flags: ignoreversion isreadme; Languages: german +Source: "{#ResDir}\shaders\*"; DestDir: "{app}\shaders\"; Flags: ignoreversion recursesubdirs +Source: "{#ResDir}\licenses\*"; DestDir: "{app}\licenses\"; Flags: ignoreversion recursesubdirs + +[Icons] +Name: "{commonstartmenu}\{#AppName}"; Filename: "{app}\{#AppName}.exe" +Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppName}.exe"; Tasks: desktopicon + +[Run] +Filename: "{app}\{#AppName}.exe"; Description: "{cm:LaunchProgram,{#AppName}}"; Flags: nowait postinstall skipifsilent + +[Dirs] +Name: "{app}" + +[CustomMessages] +english.FileAssoc=Register file associations +french.FileAssoc=Register file associations +italian.FileAssoc=Register file associations +spanish.FileAssoc=Register file associations +german.FileAssoc=Dateierweiterungen registrieren + +[Registry] +Root: HKCR; Subkey: ".gb"; ValueType: string; ValueName: ""; ValueData: "Game Boy ROM"; Flags: uninsdeletevalue; Tasks: gbfileassoc +Root: HKCR; Subkey: ".gb\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppName}.exe,0"; Tasks: gbfileassoc +Root: HKCR; Subkey: ".gb\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#AppName}.exe"" ""%1"""; Tasks: gbfileassoc +Root: HKCR; Subkey: ".gbc"; ValueType: string; ValueName: ""; ValueData: "Game Boy Color ROM"; Flags: uninsdeletevalue; Tasks: gbcfileassoc +Root: HKCR; Subkey: ".gbc\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppName}.exe,0"; Tasks: gbcfileassoc +Root: HKCR; Subkey: ".gbc\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#AppName}.exe"" ""%1"""; Tasks: gbcfileassoc +Root: HKCR; Subkey: ".sgb"; ValueType: string; ValueName: ""; ValueData: "Super Game Boy ROM"; Flags: uninsdeletevalue; Tasks: sgbfileassoc +Root: HKCR; Subkey: ".sgb\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppName}.exe,0"; Tasks: sgbfileassoc +Root: HKCR; Subkey: ".sgb\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#AppName}.exe"" ""%1"""; Tasks: sgbfileassoc +Root: HKCR; Subkey: ".gba"; ValueType: string; ValueName: ""; ValueData: "Game Boy Advance ROM"; Flags: uninsdeletevalue; Tasks: gbafileassoc +Root: HKCR; Subkey: ".gba\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppName}.exe,0"; Tasks: gbafileassoc +Root: HKCR; Subkey: ".gba\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#AppName}.exe"" ""%1"""; Tasks: gbafileassoc + +[Code] +var + noReleaseWarning: String; + +procedure InitializeWizard(); + begin + if ExpandConstant('{#IsRelease}') = 'no' then + begin + if ExpandConstant('{language}') = 'english' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'french' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'italian' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'spanish' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'german' then noReleaseWarning := 'Sie mchten eine Entwicklerversion von {#AppName} installieren.' + #13#10#13#10 + 'Entwicklerversionen knnen bislang noch nicht endeckte Fehler beinhalten. Bitte melden Sie alle Fehler, die Sie finden knnen, auf der GitHub-Projektseite.'; + MsgBox(noReleaseWarning, mbInformation, MB_OK); + end; + end; +end. Binary files /tmp/tmpNboOZx/k9ARUtYrFo/mgba-0.6.3+dfsg1/src/platform/windows/setup/wizard-image.bmp and /tmp/tmpNboOZx/UhvOrCf1mT/mgba-0.7.0/src/platform/windows/setup/wizard-image.bmp differ diff -Nru mgba-0.6.3+dfsg1/src/third-party/inih/ini.c mgba-0.7.0/src/third-party/inih/ini.c --- mgba-0.6.3+dfsg1/src/third-party/inih/ini.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/third-party/inih/ini.c 2019-01-27 00:06:06.000000000 +0000 @@ -21,8 +21,8 @@ #include #endif -#define MAX_SECTION 50 -#define MAX_NAME 50 +#define MAX_SECTION 128 +#define MAX_NAME 128 /* Strip whitespace chars off end of given string, in place. Return s. */ static char* rstrip(char* s) diff -Nru mgba-0.6.3+dfsg1/src/util/arm-algo.S mgba-0.7.0/src/util/arm-algo.S --- mgba-0.6.3+dfsg1/src/util/arm-algo.S 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/arm-algo.S 2019-01-27 00:06:06.000000000 +0000 @@ -6,32 +6,6 @@ #if defined(__ARM_NEON) && !defined(PSP2) # r0: Destination # r1: Source -# r2: Number of words to copy as halfwords -.global _to16Bit -_to16Bit: -push {r4-r10} -mov r8, r0 -mov r9, r1 -mov r10, r2 -.L0: -tst r10, #15 -beq .L1 -ldr r0, [r9], #4 -strh r0, [r8], #2 -sub r10, #1 -b .L0 -.L1: -vld4.16 {d0, d1, d2, d3}, [r9]! -vld4.16 {d4, d5, d6, d7}, [r9]! -vst2.16 {d0, d2}, [r8]! -vst2.16 {d4, d6}, [r8]! -subs r10, #16 -bne .L1 -pop {r4-r10} -bx lr - -# r0: Destination -# r1: Source # r2: Width # r3: Height .global _neon2x diff -Nru mgba-0.6.3+dfsg1/src/util/crc32.c mgba-0.7.0/src/util/crc32.c --- mgba-0.6.3+dfsg1/src/util/crc32.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/crc32.c 2019-01-27 00:06:06.000000000 +0000 @@ -48,6 +48,7 @@ BUFFER_SIZE = 1024 }; +#ifndef HAVE_CRC32 static uint32_t crc32Table[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, @@ -93,12 +94,14 @@ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; +#endif uint32_t doCrc32(const void* buf, size_t size) { - return updateCrc32(0, buf, size); + return crc32(0, buf, size); } -uint32_t updateCrc32(uint32_t crc, const void* buf, size_t size) { +#ifndef HAVE_CRC32 +uint32_t crc32(uint32_t crc, const void* buf, size_t size) { const uint8_t* p = buf; crc = ~crc; @@ -108,9 +111,10 @@ return ~crc; } +#endif uint32_t fileCrc32(struct VFile* vf, size_t endOffset) { - char buffer[BUFFER_SIZE]; + uint8_t buffer[BUFFER_SIZE]; size_t blocksize; size_t alreadyRead = 0; if (vf->seek(vf, 0, SEEK_SET) < 0) { @@ -124,7 +128,7 @@ } blocksize = vf->read(vf, buffer, toRead); alreadyRead += blocksize; - crc = updateCrc32(crc, buffer, blocksize); + crc = crc32(crc, buffer, blocksize); if (blocksize < toRead) { return 0; } diff -Nru mgba-0.6.3+dfsg1/src/util/elf-read.c mgba-0.7.0/src/util/elf-read.c --- mgba-0.6.3+dfsg1/src/util/elf-read.c 1970-01-01 00:00:00.000000000 +0000 +++ mgba-0.7.0/src/util/elf-read.c 2019-01-27 00:06:06.000000000 +0000 @@ -0,0 +1,125 @@ +/* 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 + +#ifdef USE_ELF + +#include + +DEFINE_VECTOR(ELFProgramHeaders, Elf32_Phdr); +DEFINE_VECTOR(ELFSectionHeaders, Elf32_Shdr); + +static bool _elfInit = false; + +struct ELF { + Elf* e; + struct VFile* vf; + size_t size; + char* memory; +}; + +struct ELF* ELFOpen(struct VFile* vf) { + if (!_elfInit) { + _elfInit = elf_version(EV_CURRENT) != EV_NONE; + if (!_elfInit) { + return NULL; + } + } + if (!vf) { + return NULL; + } + size_t size = vf->size(vf); + char* memory = vf->map(vf, size, MAP_READ); + if (!memory) { + return NULL; + } + + Elf* e = elf_memory(memory, size); + if (!e || elf_kind(e) != ELF_K_ELF) { + elf_end(e); + vf->unmap(vf, memory, size); + return false; + } + struct ELF* elf = malloc(sizeof(*elf)); + elf->e = e; + elf->vf = vf; + elf->size = size; + elf->memory = memory; + return elf; +} + +void ELFClose(struct ELF* elf) { + elf_end(elf->e); + elf->vf->unmap(elf->vf, elf->memory, elf->size); + free(elf); +} + +void* ELFBytes(struct ELF* elf, size_t* size) { + if (size) { + *size = elf->size; + } + return elf->memory; +} + +uint16_t ELFMachine(struct ELF* elf) { + Elf32_Ehdr* hdr = elf32_getehdr(elf->e); + if (!hdr) { + return 0; + } + return hdr->e_machine; +} + +uint32_t ELFEntry(struct ELF* elf) { + Elf32_Ehdr* hdr = elf32_getehdr(elf->e); + if (!hdr) { + return 0; + } + return hdr->e_entry; +} + +void ELFGetProgramHeaders(struct ELF* elf, struct ELFProgramHeaders* ph) { + ELFProgramHeadersClear(ph); + Elf32_Ehdr* hdr = elf32_getehdr(elf->e); + Elf32_Phdr* phdr = elf32_getphdr(elf->e); + ELFProgramHeadersResize(ph, hdr->e_phnum); + memcpy(ELFProgramHeadersGetPointer(ph, 0), phdr, sizeof(*phdr) * hdr->e_phnum); +} + +void ELFGetSectionHeaders(struct ELF* elf, struct ELFSectionHeaders* sh) { + ELFSectionHeadersClear(sh); + Elf_Scn* section = elf_getscn(elf->e, 0); + do { + *ELFSectionHeadersAppend(sh) = *elf32_getshdr(section); + } while ((section = elf_nextscn(elf->e, section))); +} + +Elf32_Shdr* ELFGetSectionHeader(struct ELF* elf, size_t index) { + Elf_Scn* section = elf_getscn(elf->e, index); + return elf32_getshdr(section); +} + +size_t ELFFindSection(struct ELF* elf, const char* name) { + Elf32_Ehdr* hdr = elf32_getehdr(elf->e); + size_t shstrtab = hdr->e_shstrndx; + if (strcmp(name, ".shstrtab") == 0) { + return shstrtab; + } + Elf_Scn* section = NULL; + while ((section = elf_nextscn(elf->e, section))) { + Elf32_Shdr* shdr = elf32_getshdr(section); + const char* sname = elf_strptr(elf->e, shstrtab, shdr->sh_name); + if (strcmp(sname, name) == 0) { + return elf_ndxscn(section); + } + } + return 0; +} + +const char* ELFGetString(struct ELF* elf, size_t section, size_t string) { + return elf_strptr(elf->e, section, string); +} + +#endif diff -Nru mgba-0.6.3+dfsg1/src/util/gui/file-select.c mgba-0.7.0/src/util/gui/file-select.c --- mgba-0.6.3+dfsg1/src/util/gui/file-select.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/gui/file-select.c 2019-01-27 00:06:06.000000000 +0000 @@ -47,7 +47,7 @@ return strcasecmp(((const struct GUIMenuItem*) a)->title, ((const struct GUIMenuItem*) b)->title); } -static bool _refreshDirectory(struct GUIParams* params, const char* currentPath, struct GUIMenuItemList* currentFiles, bool (*filter)(struct VFile*)) { +static bool _refreshDirectory(struct GUIParams* params, const char* currentPath, struct GUIMenuItemList* currentFiles, bool (*filterName)(const char* name), bool (*filterContents)(struct VFile*)) { _cleanFiles(currentFiles); struct VDir* dir = VDirOpen(currentPath); @@ -64,6 +64,7 @@ uint32_t input = 0; GUIPollInput(params, &input, 0); if (input & (1 << GUI_INPUT_CANCEL)) { + dir->close(dir); return false; } @@ -90,7 +91,7 @@ } else { name = strdup(name); } - *GUIMenuItemListAppend(currentFiles) = (struct GUIMenuItem) { .title = name }; + *GUIMenuItemListAppend(currentFiles) = (struct GUIMenuItem) { .title = name, .data = (void*) de->type(de) }; ++items; } qsort(GUIMenuItemListGetPointer(currentFiles, 1), GUIMenuItemListSize(currentFiles) - 1, sizeof(struct GUIMenuItem), _strpcmp); @@ -102,6 +103,7 @@ uint32_t input = 0; GUIPollInput(params, &input, 0); if (input & (1 << GUI_INPUT_CANCEL)) { + dir->close(dir); return false; } @@ -116,42 +118,48 @@ } params->drawEnd(); } - if (!filter) { + struct GUIMenuItem* testItem = GUIMenuItemListGetPointer(currentFiles, item); + if (testItem->data != (void*) VFS_FILE) { ++item; continue; } - struct VDir* vd = dir->openDir(dir, GUIMenuItemListGetPointer(currentFiles, item)->title); - if (vd) { - vd->close(vd); - ++item; - continue; + bool failed = false; + if (filterName && !filterName(testItem->title)) { + failed = true; } - struct VFile* vf = dir->openFile(dir, GUIMenuItemListGetPointer(currentFiles, item)->title, O_RDONLY); - if (vf) { - if (filter(vf)) { - ++item; + + if (!failed && filterContents) { + struct VFile* vf = dir->openFile(dir, testItem->title, O_RDONLY); + if (!vf) { + failed = true; } else { - free((char*) GUIMenuItemListGetPointer(currentFiles, item)->title); - GUIMenuItemListShift(currentFiles, item, 1); + if (!filterContents(vf)) { + failed = true; + } + vf->close(vf); } - vf->close(vf); - continue; } - ++item; + + if (failed) { + free((char*) testItem->title); + GUIMenuItemListShift(currentFiles, item, 1); + } else { + ++item; + } } dir->close(dir); return true; } -bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool (*filter)(struct VFile*)) { +bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool (*filterName)(const char* name), bool (*filterContents)(struct VFile*)) { struct GUIMenu menu = { .title = "Select file", .subtitle = params->currentPath, .index = params->fileIndex, }; GUIMenuItemListInit(&menu.items, 0); - _refreshDirectory(params, params->currentPath, &menu.items, filter); + _refreshDirectory(params, params->currentPath, &menu.items, filterName, filterContents); while (true) { struct GUIMenuItem* item; @@ -162,8 +170,11 @@ } if (reason == GUI_MENU_EXIT_ACCEPT) { if (params->fileIndex == 0) { + if (strncmp(params->currentPath, params->basePath, PATH_MAX) == 0) { + continue; + } _upDirectory(params->currentPath); - if (!_refreshDirectory(params, params->currentPath, &menu.items, filter)) { + if (!_refreshDirectory(params, params->currentPath, &menu.items, filterName, filterContents)) { break; } } else { @@ -176,7 +187,7 @@ struct GUIMenuItemList newFiles; GUIMenuItemListInit(&newFiles, 0); - if (!_refreshDirectory(params, outPath, &newFiles, filter)) { + if (!_refreshDirectory(params, outPath, &newFiles, filterName, filterContents)) { _cleanFiles(&newFiles); GUIMenuItemListDeinit(&newFiles); _cleanFiles(&menu.items); @@ -197,7 +208,7 @@ break; } _upDirectory(params->currentPath); - if (!_refreshDirectory(params, params->currentPath, &menu.items, filter)) { + if (!_refreshDirectory(params, params->currentPath, &menu.items, filterName, filterContents)) { break; } params->fileIndex = 0; diff -Nru mgba-0.6.3+dfsg1/src/util/gui/menu.c mgba-0.7.0/src/util/gui/menu.c --- mgba-0.6.3+dfsg1/src/util/gui/menu.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/gui/menu.c 2019-01-27 00:06:06.000000000 +0000 @@ -10,6 +10,8 @@ #ifdef _3DS #include <3ds.h> +#elif defined(__SWITCH__) +#include #endif DEFINE_VECTOR(GUIMenuItemList, struct GUIMenuItem); @@ -31,6 +33,10 @@ if (!aptMainLoop()) { return GUI_MENU_EXIT_CANCEL; } +#elif defined(__SWITCH__) + if (!appletMainLoop()) { + return GUI_MENU_EXIT_CANCEL; + } #endif uint32_t newInput = 0; GUIPollInput(params, &newInput, 0); @@ -170,8 +176,8 @@ GUIFontIconMetrics(params->font, GUI_ICON_SCROLLBAR_BUTTON, &right, 0); GUIFontIconMetrics(params->font, GUI_ICON_SCROLLBAR_TRACK, &w, 0); right = (right - w) / 2; + GUIFontDrawIconSize(params->font, params->width - right - 8, top, 0, bottom - top, 0xA0FFFFFF, GUI_ICON_SCROLLBAR_TRACK); GUIFontDrawIcon(params->font, params->width - 8, top, GUI_ALIGN_HCENTER | GUI_ALIGN_BOTTOM, GUI_ORIENT_VMIRROR, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); - GUIFontDrawIconSize(params->font, params->width - right - 8, top, 0, bottom - top, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_TRACK); GUIFontDrawIcon(params->font, params->width - 8, bottom, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON); y = menu->index * (bottom - top - 16) / GUIMenuItemListSize(&menu->items); @@ -254,6 +260,9 @@ return; } int state = params->batteryState(); + if (state == BATTERY_NOT_PRESENT) { + return; + } uint32_t color = 0xFF000000; if (state == (BATTERY_CHARGING | BATTERY_FULL)) { color |= 0xFFC060; diff -Nru mgba-0.6.3+dfsg1/src/util/gui.c mgba-0.7.0/src/util/gui.c --- mgba-0.6.3+dfsg1/src/util/gui.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/gui.c 2019-01-27 00:06:06.000000000 +0000 @@ -5,6 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#define KEY_DELAY 45 +#define KEY_REPEAT 5 + void GUIInit(struct GUIParams* params) { memset(params->inputHistory, 0, sizeof(params->inputHistory)); strncpy(params->currentPath, params->basePath, PATH_MAX); @@ -19,7 +22,7 @@ } else { params->inputHistory[i] = -1; } - if (!params->inputHistory[i] || (params->inputHistory[i] >= 30 && !(params->inputHistory[i] % 5))) { + if (!params->inputHistory[i] || (params->inputHistory[i] >= KEY_DELAY && !(params->inputHistory[i] % KEY_REPEAT))) { newInput |= (1 << i); } } diff -Nru mgba-0.6.3+dfsg1/src/util/patch-ups.c mgba-0.7.0/src/util/patch-ups.c --- mgba-0.6.3+dfsg1/src/util/patch-ups.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/patch-ups.c 2019-01-27 00:06:06.000000000 +0000 @@ -154,7 +154,7 @@ case 0x0: // SourceRead memmove(&writeBuffer[writeLocation], &readBuffer[writeLocation], length); - outputChecksum = updateCrc32(outputChecksum, &writeBuffer[writeLocation], length); + outputChecksum = crc32(outputChecksum, &writeBuffer[writeLocation], length); writeLocation += length; break; case 0x1: @@ -162,7 +162,7 @@ if (patch->vf->read(patch->vf, &writeBuffer[writeLocation], length) != (ssize_t) length) { return false; } - outputChecksum = updateCrc32(outputChecksum, &writeBuffer[writeLocation], length); + outputChecksum = crc32(outputChecksum, &writeBuffer[writeLocation], length); writeLocation += length; break; case 0x2: @@ -177,7 +177,7 @@ return false; } memmove(&writeBuffer[writeLocation], &readBuffer[readSourceLocation], length); - outputChecksum = updateCrc32(outputChecksum, &writeBuffer[writeLocation], length); + outputChecksum = crc32(outputChecksum, &writeBuffer[writeLocation], length); writeLocation += length; readSourceLocation += length; break; @@ -198,7 +198,7 @@ ++writeLocation; ++readTargetLocation; } - outputChecksum = updateCrc32(outputChecksum, &writeBuffer[writeLocation - length], length); + outputChecksum = crc32(outputChecksum, &writeBuffer[writeLocation - length], length); break; } } diff -Nru mgba-0.6.3+dfsg1/src/util/png-io.c mgba-0.7.0/src/util/png-io.c --- mgba-0.6.3+dfsg1/src/util/png-io.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/png-io.c 2019-01-27 00:06:06.000000000 +0000 @@ -38,7 +38,7 @@ return png; } -png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height) { +static png_infop _pngWriteHeader(png_structp png, unsigned width, unsigned height, int type) { png_infop info = png_create_info_struct(png); if (!info) { return 0; @@ -46,23 +46,26 @@ if (setjmp(png_jmpbuf(png))) { return 0; } - png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_set_IHDR(png, info, width, height, 8, type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + return info; +} + +png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height) { + png_infop info = _pngWriteHeader(png, width, height, PNG_COLOR_TYPE_RGB); png_write_info(png, info); return info; } -png_infop PNGWriteHeader8(png_structp png, unsigned width, unsigned height) { - png_infop info = png_create_info_struct(png); - if (!info) { - return 0; - } - if (setjmp(png_jmpbuf(png))) { - return 0; - } - png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); +png_infop PNGWriteHeaderA(png_structp png, unsigned width, unsigned height) { + png_infop info = _pngWriteHeader(png, width, height, PNG_COLOR_TYPE_RGB_ALPHA); + png_write_info(png, info); return info; } +png_infop PNGWriteHeader8(png_structp png, unsigned width, unsigned height) { + return _pngWriteHeader(png, width, height, PNG_COLOR_TYPE_PALETTE); +} + bool PNGWritePalette(png_structp png, png_infop info, const uint32_t* palette, unsigned entries) { if (!palette || !entries) { return false; @@ -128,6 +131,53 @@ return true; } +bool PNGWritePixelsA(png_structp png, unsigned width, unsigned height, unsigned stride, const void* pixels) { + png_bytep row = malloc(sizeof(png_byte) * width * 4); + if (!row) { + return false; + } + const png_byte* pixelData = pixels; + if (setjmp(png_jmpbuf(png))) { + free(row); + return false; + } + unsigned i; + for (i = 0; i < height; ++i) { + unsigned x; + for (x = 0; x < width; ++x) { +#ifdef COLOR_16_BIT + uint16_t c = ((uint16_t*) pixelData)[stride * i + x]; +#ifdef COLOR_5_6_5 + row[x * 4] = (c >> 8) & 0xF8; + row[x * 4 + 1] = (c >> 3) & 0xFC; + row[x * 4 + 2] = (c << 3) & 0xF8; + row[x * 4 + 3] = 0xFF; +#else + row[x * 4] = (c >> 7) & 0xF8; + row[x * 4 + 1] = (c >> 2) & 0xF8; + row[x * 4 + 2] = (c << 3) & 0xF8; + row[x * 4 + 3] = (c >> 15) * 0xFF; +#endif +#else +#ifdef __BIG_ENDIAN__ + row[x * 4] = pixelData[stride * i * 4 + x * 4 + 3]; + row[x * 4 + 1] = pixelData[stride * i * 4 + x * 4 + 2]; + row[x * 4 + 2] = pixelData[stride * i * 4 + x * 4 + 1]; + row[x * 4 + 3] = pixelData[stride * i * 4 + x * 4]; +#else + row[x * 4] = pixelData[stride * i * 4 + x * 4]; + row[x * 4 + 1] = pixelData[stride * i * 4 + x * 4 + 1]; + row[x * 4 + 2] = pixelData[stride * i * 4 + x * 4 + 2]; + row[x * 4 + 3] = pixelData[stride * i * 4 + x * 4 + 3]; +#endif +#endif + } + png_write_row(png, row); + } + free(row); + return true; +} + bool PNGWritePixels8(png_structp png, unsigned width, unsigned height, unsigned stride, const void* pixels) { UNUSED(width); const png_byte* pixelData = pixels; @@ -273,6 +323,81 @@ return true; } +bool PNGReadPixelsA(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride) { + if (setjmp(png_jmpbuf(png))) { + return false; + } + + uint8_t* pixelData = pixels; + unsigned pngHeight = png_get_image_height(png, info); + if (height < pngHeight) { + pngHeight = height; + } + + unsigned pngWidth = png_get_image_width(png, info); + if (width < pngWidth) { + pngWidth = width; + } + + unsigned i; + png_bytep row = malloc(png_get_rowbytes(png, info)); + for (i = 0; i < pngHeight; ++i) { + png_read_row(png, row, 0); + unsigned x; + for (x = 0; x < pngWidth; ++x) { +#ifdef COLOR_16_BIT + uint16_t c = row[x * 4 + 2] >> 3; +#ifdef COLOR_5_6_5 + c |= (row[x * 4 + 1] << 3) & 0x7E0; + c |= (row[x * 4] << 8) & 0xF800; +#else + c |= (row[x * 4 + 1] << 2) & 0x3E0; + c |= (row[x * 4] << 7) & 0x7C00; +#endif + ((uint16_t*) pixelData)[stride * i + x] = c; +#else +#if __BIG_ENDIAN__ + pixelData[stride * i * 4 + x * 4 + 3] = row[x * 4]; + pixelData[stride * i * 4 + x * 4 + 2] = row[x * 4 + 1]; + pixelData[stride * i * 4 + x * 4 + 1] = row[x * 4 + 2]; + pixelData[stride * i * 4 + x * 4] = row[x * 4 + 3]; +#else + pixelData[stride * i * 4 + x * 4] = row[x * 4]; + pixelData[stride * i * 4 + x * 4 + 1] = row[x * 4 + 1]; + pixelData[stride * i * 4 + x * 4 + 2] = row[x * 4 + 2]; + pixelData[stride * i * 4 + x * 4 + 3] = row[x * 4 + 3]; +#endif +#endif + } + } + free(row); + return true; +} + +bool PNGReadPixels8(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride) { + if (setjmp(png_jmpbuf(png))) { + return false; + } + + uint8_t* pixelData = pixels; + unsigned pngHeight = png_get_image_height(png, info); + if (height < pngHeight) { + pngHeight = height; + } + + unsigned pngWidth = png_get_image_width(png, info); + if (width < pngWidth) { + pngWidth = width; + } + + unsigned i; + for (i = 0; i < pngHeight; ++i) { + png_read_row(png, &pixelData[stride * i], 0); + } + return true; +} + + bool PNGReadFooter(png_structp png, png_infop end) { if (setjmp(png_jmpbuf(png))) { return false; diff -Nru mgba-0.6.3+dfsg1/src/util/ring-fifo.c mgba-0.7.0/src/util/ring-fifo.c --- mgba-0.6.3+dfsg1/src/util/ring-fifo.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/ring-fifo.c 2019-01-27 00:06:06.000000000 +0000 @@ -22,6 +22,18 @@ return buffer->capacity; } +size_t RingFIFOSize(const struct RingFIFO* buffer) { + const void* read; + const void* write; + ATOMIC_LOAD(read, buffer->readPtr); + ATOMIC_LOAD(write, buffer->writePtr); + if (read <= write) { + return (uintptr_t) write - (uintptr_t) read; + } else { + return buffer->capacity - (uintptr_t) read + (uintptr_t) write; + } +} + void RingFIFOClear(struct RingFIFO* buffer) { ATOMIC_STORE(buffer->readPtr, buffer->data); ATOMIC_STORE(buffer->writePtr, buffer->data); @@ -33,8 +45,8 @@ ATOMIC_LOAD(end, buffer->readPtr); // Wrap around if we can't fit enough in here - if ((intptr_t) data - (intptr_t) buffer->data + length >= buffer->capacity) { - if (end == buffer->data) { + if ((uintptr_t) data - (uintptr_t) buffer->data + length >= buffer->capacity) { + if (end == buffer->data || end > data) { // Oops! If we wrap now, it'll appear empty return 0; } @@ -65,8 +77,8 @@ ATOMIC_LOAD(end, buffer->writePtr); // Wrap around if we can't fit enough in here - if ((intptr_t) data - (intptr_t) buffer->data + length >= buffer->capacity) { - if (end == data) { + if ((uintptr_t) data - (uintptr_t) buffer->data + length >= buffer->capacity) { + if (end >= data) { // Oops! If we wrap now, it'll appear full return 0; } @@ -78,7 +90,7 @@ uintptr_t bufferEnd = (uintptr_t) buffer->data + buffer->capacity; remaining = bufferEnd - (uintptr_t) data; } else { - remaining = (intptr_t) end - (intptr_t) data; + remaining = (uintptr_t) end - (uintptr_t) data; } // If the pointers touch, it's empty if (remaining < length) { @@ -87,6 +99,6 @@ if (output) { memcpy(output, data, length); } - ATOMIC_STORE(buffer->readPtr, (void*) ((intptr_t) data + length)); + ATOMIC_STORE(buffer->readPtr, (void*) ((uintptr_t) data + length)); return length; } diff -Nru mgba-0.6.3+dfsg1/src/util/test/suite.h mgba-0.7.0/src/util/test/suite.h --- mgba-0.6.3+dfsg1/src/util/test/suite.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/test/suite.h 2019-01-27 00:06:06.000000000 +0000 @@ -12,14 +12,12 @@ #define M_TEST_DEFINE(NAME) static void NAME (void **state ATTRIBUTE_UNUSED) -#define M_TEST_SUITE(NAME) _testSuite_ ## NAME -#define M_TEST_SUITE_RUN(NAME) (printf("\nRunning suite %s\n", # NAME), M_TEST_SUITE(NAME)()) #define M_TEST_SUITE_DEFINE(NAME, ...) M_TEST_SUITE_DEFINE_EX(NAME, NULL, NULL, __VA_ARGS__) #define M_TEST_SUITE_DEFINE_SETUP(NAME, ...) M_TEST_SUITE_DEFINE_EX(NAME, _testSuite_setup_ ## NAME, NULL, __VA_ARGS__) #define M_TEST_SUITE_DEFINE_TEARDOWN(NAME, ...) M_TEST_SUITE_DEFINE_EX(NAME, NULL, _testSuite_teardown_ ## NAME, __VA_ARGS__) #define M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(NAME, ...) M_TEST_SUITE_DEFINE_EX(NAME, _testSuite_setup_ ## NAME, _testSuite_teardown_ ## NAME, __VA_ARGS__) #define M_TEST_SUITE_DEFINE_EX(NAME, SETUP, TEARDOWN, ...) \ - int M_TEST_SUITE(NAME) (void) { \ + int main(void) { \ const static struct CMUnitTest tests[] = { \ __VA_ARGS__ \ }; \ @@ -29,6 +27,4 @@ #define M_TEST_SUITE_SETUP(NAME) static int _testSuite_setup_ ## NAME (void **state ATTRIBUTE_UNUSED) #define M_TEST_SUITE_TEARDOWN(NAME) static int _testSuite_teardown_ ## NAME (void **state ATTRIBUTE_UNUSED) -#define M_TEST_SUITE_DECLARE(NAME) extern int M_TEST_SUITE(NAME) (void) - #endif diff -Nru mgba-0.6.3+dfsg1/src/util/test/util.c mgba-0.7.0/src/util/test/util.c --- mgba-0.6.3+dfsg1/src/util/test/util.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/test/util.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +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(TextCodec); -M_TEST_SUITE_DECLARE(VFS); - -int TestRunUtil(void) { - int failures = 0; - failures += M_TEST_SUITE_RUN(TextCodec); - failures += M_TEST_SUITE_RUN(VFS); - return failures; -} diff -Nru mgba-0.6.3+dfsg1/src/util/test/util.h mgba-0.7.0/src/util/test/util.h --- mgba-0.6.3+dfsg1/src/util/test/util.h 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/test/util.h 1970-01-01 00:00:00.000000000 +0000 @@ -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_UTIL_H -#define TEST_UTIL_H -#include - -int TestRunUtil(void); - -#endif diff -Nru mgba-0.6.3+dfsg1/src/util/vfs/vfs-lzma.c mgba-0.7.0/src/util/vfs/vfs-lzma.c --- mgba-0.6.3+dfsg1/src/util/vfs/vfs-lzma.c 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/src/util/vfs/vfs-lzma.c 2019-01-27 00:06:06.000000000 +0000 @@ -98,6 +98,7 @@ SzArEx_Init(&vd->db); SRes res = SzArEx_Open(&vd->db, &vd->lookStream.s, &vd->allocImp, &vd->allocTempImp); if (res != SZ_OK) { + SzArEx_Free(&vd->db, &vd->allocImp); File_Close(&vd->archiveStream.file); free(vd); return 0; diff -Nru mgba-0.6.3+dfsg1/tools/sanitize-deb.sh mgba-0.7.0/tools/sanitize-deb.sh --- mgba-0.6.3+dfsg1/tools/sanitize-deb.sh 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/tools/sanitize-deb.sh 2019-01-27 00:06:06.000000000 +0000 @@ -17,17 +17,17 @@ while [ $# -gt 0 ]; do DEB=$1 dpkg-deb -R $DEB deb-temp - mv $DEB $DEB~ - sed -i~ s/mgba-// deb-temp/DEBIAN/control PKG=`head -n1 deb-temp/DEBIAN/control | cut -f2 -d ' '` - echo Found pacakge $PKG + echo Found package $PKG case $PKG in - lib$BINARY) + *-base) + PKG=lib$BINARY rmdep sdl rmdep qt ;; - $BINARY-qt) + *-qt) + PKG=$BINARY-qt rmdep libav rmdep libedit rmdep libpng @@ -37,7 +37,8 @@ rmdep zlib adddep lib$BINARY ;; - $BINARY-sdl) + *-sdl) + PKG=$BINARY-sdl rmdep libav rmdep libedit rmdep libpng @@ -55,10 +56,11 @@ sed -i~ "s/,,*/,/g" deb-temp/DEBIAN/control sed -i~ "s/,$//g" deb-temp/DEBIAN/control sed -i~ "/^[^:]*: $/d" deb-temp/DEBIAN/control + sed -i~ "s/^Package: .*$/Package: $PKG/" deb-temp/DEBIAN/control rm deb-temp/DEBIAN/control~ chmod 644 deb-temp/DEBIAN/md5sums chown -R root:root deb-temp - dpkg-deb -b deb-temp $DEB + dpkg-deb -b deb-temp $PKG.deb rm -rf deb-temp shift done diff -Nru mgba-0.6.3+dfsg1/.travis-deps.sh mgba-0.7.0/.travis-deps.sh --- mgba-0.6.3+dfsg1/.travis-deps.sh 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/.travis-deps.sh 2019-01-27 00:06:06.000000000 +0000 @@ -1,12 +1,5 @@ #!/bin/sh if [ $TRAVIS_OS_NAME = "osx" ]; then brew update - brew install qt5 ffmpeg imagemagick sdl2 libzip libpng -else - sudo apt-get clean - sudo apt-get update - sudo apt-get install -y -q cmake libedit-dev libmagickwand-dev \ - libpng-dev libsdl2-dev libzip-dev qtbase5-dev \ - libqt5opengl5-dev qtmultimedia5-dev libavcodec-dev \ - libavutil-dev libavformat-dev libavresample-dev libswscale-dev + brew install qt5 ffmpeg imagemagick sdl2 libedit libelf libpng libzip fi diff -Nru mgba-0.6.3+dfsg1/.travis.yml mgba-0.7.0/.travis.yml --- mgba-0.6.3+dfsg1/.travis.yml 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/.travis.yml 2019-01-27 00:06:06.000000000 +0000 @@ -1,17 +1,31 @@ +if: type = pull_request OR NOT branch =~ /^(master$|optimization)/ OR fork language: c sudo: required +services: +- docker +os: linux +env: +- DOCKER_TAG=ubuntu:xenial +- DOCKER_TAG=ubuntu:bionic +- DOCKER_TAG=ubuntu:cosmic +- DOCKER_TAG=3ds +- DOCKER_TAG=wii +- DOCKER_TAG=vita +- DOCKER_TAG=switch +- DOCKER_TAG=windows:w32 +- DOCKER_TAG=windows:w64 + matrix: include: - - os: linux - dist: trusty - compiler: clang - - os: linux - dist: trusty - compiler: gcc - - os: osx - compiler: clang + - os: osx + compiler: clang + env: DOCKER_TAG= before_install: - - source ./.travis-deps.sh +- '[ -z "$DOCKER_TAG" ] || docker pull mgba/$DOCKER_TAG' +- '[ "$TRAVIS_OS_NAME" != "osx" ] || . ./.travis-deps.sh' +- 'mkdir build && chmod 777 build' -script: mkdir build && cd build && cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 .. && make +script: +- '[ -z "$DOCKER_TAG" ] || docker run -e BUILD_DIR=build -e MAKEFLAGS=-j2 -v $PWD:/home/mgba/src mgba/$DOCKER_TAG' +- '[ "$TRAVIS_OS_NAME" != "osx" ] || (cd build && cmake -DCMAKE_PREFIX_PATH="/usr/local/opt/qt5" .. && make -j2)' diff -Nru mgba-0.6.3+dfsg1/version.cmake mgba-0.7.0/version.cmake --- mgba-0.6.3+dfsg1/version.cmake 2018-04-14 20:49:19.000000000 +0000 +++ mgba-0.7.0/version.cmake 2019-01-27 00:06:06.000000000 +0000 @@ -2,9 +2,9 @@ set(PROJECT_NAME "mGBA") endif() set(LIB_VERSION_MAJOR 0) -set(LIB_VERSION_MINOR 6) -set(LIB_VERSION_PATCH 1) -set(LIB_VERSION_ABI 0.6) +set(LIB_VERSION_MINOR 7) +set(LIB_VERSION_PATCH 0) +set(LIB_VERSION_ABI 0.7) set(LIB_VERSION_STRING ${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${LIB_VERSION_PATCH}) set(SUMMARY "${PROJECT_NAME} Game Boy Advance Emulator") @@ -47,7 +47,7 @@ endif() if(DEFINED PRINT_STRING) - message("${${PRINT_STRING}}") + execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${${PRINT_STRING}}") elseif(NOT VERSION_STRING_CACHE OR NOT VERSION_STRING STREQUAL VERSION_STRING_CACHE) set(VERSION_STRING_CACHE ${VERSION_STRING} CACHE STRING "" FORCE)