mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' into medusa
This commit is contained in:
commit
bf97b7b52e
20
CHANGES
20
CHANGES
|
@ -38,24 +38,44 @@ Features:
|
||||||
- Presets for Game Boy palettes
|
- Presets for Game Boy palettes
|
||||||
- Add Super Game Boy palettes for original Game Boy games
|
- Add Super Game Boy palettes for original Game Boy games
|
||||||
- Tool for converting scanned pictures of e-Reader cards to raw dotcode data
|
- Tool for converting scanned pictures of e-Reader cards to raw dotcode data
|
||||||
|
- Options for muting when inactive, minimized, or for different players in multiplayer
|
||||||
- Cheat code support in homebrew ports
|
- Cheat code support in homebrew ports
|
||||||
- Support for combo "Super Game Boy Color" SGB + GBC ROM hacks
|
- Support for combo "Super Game Boy Color" SGB + GBC ROM hacks
|
||||||
|
- Support for 64 kiB SRAM saves used in some bootlegs
|
||||||
|
- Discord Rich Presence now supports time elapsed
|
||||||
|
- Additional scaling shaders
|
||||||
Emulation fixes:
|
Emulation fixes:
|
||||||
|
- GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032)
|
||||||
- GB Video: Clear VRAM on reset (fixes mgba.io/i/2152)
|
- GB Video: Clear VRAM on reset (fixes mgba.io/i/2152)
|
||||||
|
- GBA: Improve timing when not booting from BIOS
|
||||||
- GBA SIO: Add missing NORMAL8 implementation bits (fixes mgba.io/i/2172)
|
- GBA SIO: Add missing NORMAL8 implementation bits (fixes mgba.io/i/2172)
|
||||||
|
- GBA SIO: Fix missing interrupt on an unattached NORMAL transfer
|
||||||
|
- GBA SIO: Fix SI value for unattached MULTI mode
|
||||||
|
- GBA Memory: Fix prefetch mask when swapping modes within a region
|
||||||
|
- GBA Serialize: Fix loading audio enable bit late (fixes mgba.io/i/2230)
|
||||||
- GBA Video: Revert scanline latching changes (fixes mgba.io/i/2153, mgba.io/i/2149)
|
- GBA Video: Revert scanline latching changes (fixes mgba.io/i/2153, mgba.io/i/2149)
|
||||||
Other fixes:
|
Other fixes:
|
||||||
- 3DS: Fix disabling "wide" mode on 2DS (fixes mgba.io/i/2167)
|
- 3DS: Fix disabling "wide" mode on 2DS (fixes mgba.io/i/2167)
|
||||||
|
- ARM Debugger: Fix disassembly alignment (fixes mgba.io/i/2204)
|
||||||
- Core: Fix memory leak in opening games from the library
|
- Core: Fix memory leak in opening games from the library
|
||||||
|
- Core: Fix memory searches for relative values (fixes mgba.io/i/2135)
|
||||||
|
- Core: Fix portable mode on macOS
|
||||||
|
- Core: Don't attempt to restore rewind diffs past start of rewind
|
||||||
|
- GB Audio: Fix audio channel 4 being slow to deserialize
|
||||||
- GB Core: Fix GBC colors setting breaking default model overrides (fixes mgba.io/i/2161)
|
- GB Core: Fix GBC colors setting breaking default model overrides (fixes mgba.io/i/2161)
|
||||||
- GBA: Fix out of bounds ROM accesses on patched ROMs smaller than 32 MiB
|
- GBA: Fix out of bounds ROM accesses on patched ROMs smaller than 32 MiB
|
||||||
|
- mGUI: Cache save state screenshot validity in state menu (fixes mgba.io/i/2005)
|
||||||
- Qt: Fix infrequent deadlock when using sync to video
|
- Qt: Fix infrequent deadlock when using sync to video
|
||||||
- Qt: Fix applying savetype-only overrides
|
- Qt: Fix applying savetype-only overrides
|
||||||
- Qt: Fix crash in sprite view for partially out-of-bounds sprites (fixes mgba.io/i/2165)
|
- Qt: Fix crash in sprite view for partially out-of-bounds sprites (fixes mgba.io/i/2165)
|
||||||
|
- Qt: Fix having to press controller buttons twice for menu items (fixes mgba.io/i/2143)
|
||||||
|
- Qt: Redo sensor binding to be less fragile
|
||||||
- Util: Fix loading UPS patches that affect the last byte of the file
|
- Util: Fix loading UPS patches that affect the last byte of the file
|
||||||
Misc:
|
Misc:
|
||||||
- Core: Suspend runloop when a core crashes
|
- Core: Suspend runloop when a core crashes
|
||||||
- Qt: Rearrange menus some
|
- Qt: Rearrange menus some
|
||||||
|
- Qt: Clean up cheats dialog
|
||||||
|
- Qt: Only set default controller bindings if loading fails (fixes mgba.io/i/799)
|
||||||
- Util: Improve speed of UPS patch loading
|
- Util: Improve speed of UPS patch loading
|
||||||
|
|
||||||
0.9.1: (2021-04-18)
|
0.9.1: (2021-04-18)
|
||||||
|
|
|
@ -232,7 +232,8 @@ endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
add_definitions(-D_DARWIN_C_SOURCE)
|
add_definitions(-D_DARWIN_C_SOURCE)
|
||||||
if(CMAKE_SYSTEM_VERSION VERSION_GREATER "10.5.8")
|
list(APPEND OS_LIB "-framework Foundation")
|
||||||
|
if(NOT CMAKE_SYSTEM_VERSION VERSION_LESS "10.0") # Darwin 10.x is Mac OS X 10.6
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.6")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.6")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
@ -599,8 +600,7 @@ if(USE_FFMPEG)
|
||||||
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libavcodec-extra|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}")
|
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libavcodec-extra|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}")
|
||||||
endif()
|
endif()
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -framework VideoDecodeAcceleration -framework CoreVideo")
|
list(APPEND DEPENDENCY_LIB "-framework VideoDecodeAcceleration" "-framework CoreVideo")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework VideoDecodeAcceleration -framework CoreVideo")
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ The following mappers are partially supported:
|
||||||
Supported Platforms
|
Supported Platforms
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
- Windows Vista or newer
|
- Windows 7 or newer
|
||||||
- OS X 10.8 (Mountain Lion)[<sup>[4]</sup>](#osxver) or newer
|
- OS X 10.8 (Mountain Lion)[<sup>[4]</sup>](#osxver) or newer
|
||||||
- Linux
|
- Linux
|
||||||
- FreeBSD
|
- FreeBSD
|
||||||
|
|
|
@ -79,7 +79,7 @@ Die folgenden Mapper werden teilweise unterstützt:
|
||||||
Unterstützte Plattformen
|
Unterstützte Plattformen
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
- Windows Vista oder neuer
|
- Windows 7 oder neuer
|
||||||
- OS X 10.8 (Mountain Lion)[<sup>[3]</sup>](#osxver) oder neuer
|
- OS X 10.8 (Mountain Lion)[<sup>[3]</sup>](#osxver) oder neuer
|
||||||
- Linux
|
- Linux
|
||||||
- FreeBSD
|
- FreeBSD
|
||||||
|
|
|
@ -79,7 +79,7 @@ Estos mappers tienen soporte parcial:
|
||||||
Plataformas soportadas
|
Plataformas soportadas
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
- Windows Vista o más reciente
|
- Windows 7 o más reciente
|
||||||
- OS X 10.8 (Mountain Lion)[<sup>[3]</sup>](#osxver) o más reciente
|
- OS X 10.8 (Mountain Lion)[<sup>[3]</sup>](#osxver) o más reciente
|
||||||
- Linux
|
- Linux
|
||||||
- FreeBSD
|
- FreeBSD
|
||||||
|
|
|
@ -77,7 +77,7 @@ mGBA 是一个运行 Game Boy Advance 游戏的模拟器。mGBA 的目标是比
|
||||||
支持平台
|
支持平台
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
- Windows Vista 或更新
|
- Windows 7 或更新
|
||||||
- OS X 10.8(山狮 / Mountain Lion)[<sup>[3]</sup>](#osxver) 或更新
|
- OS X 10.8(山狮 / Mountain Lion)[<sup>[3]</sup>](#osxver) 或更新
|
||||||
- Linux
|
- Linux
|
||||||
- FreeBSD
|
- FreeBSD
|
||||||
|
|
Before Width: | Height: | Size: 528 B After Width: | Height: | Size: 528 B |
Binary file not shown.
|
@ -1,17 +1,17 @@
|
||||||
; this file was created with wlalink by ville helin <vhelin@iki.fi>.
|
; this file was created with wlalink by ville helin <vhelin@iki.fi>.
|
||||||
; wla symbolic information for "/home/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/ram_256Kb.gb".
|
; wla symbolic information for "/home/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/ram_256kb.gb".
|
||||||
|
|
||||||
[labels]
|
[labels]
|
||||||
01:48bd clear_vram
|
01:48c7 clear_vram
|
||||||
01:487a disable_lcd_safe
|
01:4884 disable_lcd_safe
|
||||||
01:4880 disable_lcd_safe@wait_ly_0
|
01:488a disable_lcd_safe@wait_ly_0
|
||||||
01:4898 memcmp
|
01:48a2 memcmp
|
||||||
01:48c7 memcpy
|
01:48d1 memcpy
|
||||||
01:48d0 memset
|
01:48da memset
|
||||||
01:48e0 print_inline_string
|
01:48ea print_inline_string
|
||||||
01:48a6 print_load_font
|
01:48b0 print_load_font
|
||||||
01:48b2 print_newline
|
01:48bc print_newline
|
||||||
01:48d9 print_string
|
01:48e3 print_string
|
||||||
01:47f0 quit
|
01:47f0 quit
|
||||||
01:4805 quit@cb_return
|
01:4805 quit@cb_return
|
||||||
01:480a quit@wait_ly_1
|
01:480a quit@wait_ly_1
|
||||||
|
@ -20,24 +20,24 @@
|
||||||
01:481c quit@wait_ly_4
|
01:481c quit@wait_ly_4
|
||||||
01:4826 quit@success
|
01:4826 quit@success
|
||||||
01:484d quit@failure
|
01:484d quit@failure
|
||||||
01:4862 quit@halt
|
01:486c quit@halt
|
||||||
01:4863 quit@halt_execution_0
|
01:486d quit@halt_execution_0
|
||||||
01:4866 reset_screen
|
01:4870 reset_screen
|
||||||
01:4889 serial_send_byte
|
01:4893 serial_send_byte
|
||||||
01:4000 font
|
01:4000 font
|
||||||
00:0150 main
|
00:0150 main
|
||||||
00:0150 test_round1
|
00:015f test_round1
|
||||||
00:016e test_round2
|
00:017d test_round2
|
||||||
00:01d2 test_round3
|
00:01e1 test_round3
|
||||||
00:0232 test_round4
|
00:0241 test_round4
|
||||||
00:02a0 test_round5
|
00:02af test_round5
|
||||||
00:02fc test_round6
|
00:030b test_round6
|
||||||
00:0330 test_finish
|
00:033f test_finish
|
||||||
00:033a test_finish@quit_inline_1
|
00:0349 test_finish@quit_inline_1
|
||||||
00:034b copy_bank_data
|
00:035a copy_bank_data
|
||||||
00:036a check_bank_data
|
00:0379 check_bank_data
|
||||||
00:038a all_ff
|
00:0399 all_ff
|
||||||
00:039a all_00
|
00:03a9 all_00
|
||||||
00:1000 bank_data
|
00:1000 bank_data
|
||||||
00:1040 clear_ram
|
00:1040 clear_ram
|
||||||
00:1062 fail_round1
|
00:1062 fail_round1
|
||||||
|
@ -52,6 +52,7 @@
|
||||||
00:10f0 fail_round5@quit_inline_6
|
00:10f0 fail_round5@quit_inline_6
|
||||||
00:1107 fail_round6
|
00:1107 fail_round6
|
||||||
00:1111 fail_round6@quit_inline_7
|
00:1111 fail_round6@quit_inline_7
|
||||||
|
00:ff80 memcmp_hram
|
||||||
|
|
||||||
[definitions]
|
[definitions]
|
||||||
0000000a _sizeof_clear_vram
|
0000000a _sizeof_clear_vram
|
||||||
|
@ -63,12 +64,13 @@
|
||||||
0000000c _sizeof_print_load_font
|
0000000c _sizeof_print_load_font
|
||||||
0000000b _sizeof_print_newline
|
0000000b _sizeof_print_newline
|
||||||
00000007 _sizeof_print_string
|
00000007 _sizeof_print_string
|
||||||
00000076 _sizeof_quit
|
00000080 _sizeof_quit
|
||||||
00000014 _sizeof_reset_screen
|
00000014 _sizeof_reset_screen
|
||||||
0000000f _sizeof_serial_send_byte
|
0000000f _sizeof_serial_send_byte
|
||||||
000007f0 _sizeof_font
|
000007f0 _sizeof_font
|
||||||
00000000 _sizeof_test_round1
|
00000020 _sizeof_memcmp_hram
|
||||||
0000001e _sizeof_main
|
0000000f _sizeof_main
|
||||||
|
0000001e _sizeof_test_round1
|
||||||
00000064 _sizeof_test_round2
|
00000064 _sizeof_test_round2
|
||||||
00000060 _sizeof_test_round3
|
00000060 _sizeof_test_round3
|
||||||
0000006e _sizeof_test_round4
|
0000006e _sizeof_test_round4
|
||||||
|
@ -78,7 +80,7 @@
|
||||||
0000001f _sizeof_copy_bank_data
|
0000001f _sizeof_copy_bank_data
|
||||||
00000020 _sizeof_check_bank_data
|
00000020 _sizeof_check_bank_data
|
||||||
00000010 _sizeof_all_ff
|
00000010 _sizeof_all_ff
|
||||||
00000c66 _sizeof_all_00
|
00000c57 _sizeof_all_00
|
||||||
00000040 _sizeof_bank_data
|
00000040 _sizeof_bank_data
|
||||||
00000022 _sizeof_clear_ram
|
00000022 _sizeof_clear_ram
|
||||||
00000021 _sizeof_fail_round1
|
00000021 _sizeof_fail_round1
|
Before Width: | Height: | Size: 528 B After Width: | Height: | Size: 528 B |
Binary file not shown.
|
@ -1,17 +1,17 @@
|
||||||
; this file was created with wlalink by ville helin <vhelin@iki.fi>.
|
; this file was created with wlalink by ville helin <vhelin@iki.fi>.
|
||||||
; wla symbolic information for "/home/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/ram_64Kb.gb".
|
; wla symbolic information for "/home/vicki/Scratch/mooneye-gb/tests/build/emulator-only/mbc1/ram_64kb.gb".
|
||||||
|
|
||||||
[labels]
|
[labels]
|
||||||
01:48bd clear_vram
|
01:48c7 clear_vram
|
||||||
01:487a disable_lcd_safe
|
01:4884 disable_lcd_safe
|
||||||
01:4880 disable_lcd_safe@wait_ly_0
|
01:488a disable_lcd_safe@wait_ly_0
|
||||||
01:4898 memcmp
|
01:48a2 memcmp
|
||||||
01:48c7 memcpy
|
01:48d1 memcpy
|
||||||
01:48d0 memset
|
01:48da memset
|
||||||
01:48e0 print_inline_string
|
01:48ea print_inline_string
|
||||||
01:48a6 print_load_font
|
01:48b0 print_load_font
|
||||||
01:48b2 print_newline
|
01:48bc print_newline
|
||||||
01:48d9 print_string
|
01:48e3 print_string
|
||||||
01:47f0 quit
|
01:47f0 quit
|
||||||
01:4805 quit@cb_return
|
01:4805 quit@cb_return
|
||||||
01:480a quit@wait_ly_1
|
01:480a quit@wait_ly_1
|
||||||
|
@ -20,23 +20,23 @@
|
||||||
01:481c quit@wait_ly_4
|
01:481c quit@wait_ly_4
|
||||||
01:4826 quit@success
|
01:4826 quit@success
|
||||||
01:484d quit@failure
|
01:484d quit@failure
|
||||||
01:4862 quit@halt
|
01:486c quit@halt
|
||||||
01:4863 quit@halt_execution_0
|
01:486d quit@halt_execution_0
|
||||||
01:4866 reset_screen
|
01:4870 reset_screen
|
||||||
01:4889 serial_send_byte
|
01:4893 serial_send_byte
|
||||||
01:4000 font
|
01:4000 font
|
||||||
00:0150 main
|
00:0150 main
|
||||||
00:0150 test_round1
|
00:015f test_round1
|
||||||
00:016e test_round2
|
00:017d test_round2
|
||||||
00:01c2 test_round3
|
00:01d1 test_round3
|
||||||
00:01cb test_round4
|
00:01da test_round4
|
||||||
00:01fb test_round5
|
00:020a test_round5
|
||||||
00:022c test_finish
|
00:023b test_finish
|
||||||
00:0236 test_finish@quit_inline_1
|
00:0245 test_finish@quit_inline_1
|
||||||
00:0247 copy_bank_data
|
00:0256 copy_bank_data
|
||||||
00:025f check_bank_data
|
00:026e check_bank_data
|
||||||
00:0278 all_ff
|
00:0287 all_ff
|
||||||
00:0288 all_00
|
00:0297 all_00
|
||||||
00:1000 bank_data
|
00:1000 bank_data
|
||||||
00:1010 clear_ram
|
00:1010 clear_ram
|
||||||
00:1032 fail_round1
|
00:1032 fail_round1
|
||||||
|
@ -49,6 +49,7 @@
|
||||||
00:109f fail_round4@quit_inline_5
|
00:109f fail_round4@quit_inline_5
|
||||||
00:10b6 fail_round5
|
00:10b6 fail_round5
|
||||||
00:10c0 fail_round5@quit_inline_6
|
00:10c0 fail_round5@quit_inline_6
|
||||||
|
00:ff80 memcmp_hram
|
||||||
|
|
||||||
[definitions]
|
[definitions]
|
||||||
0000000a _sizeof_clear_vram
|
0000000a _sizeof_clear_vram
|
||||||
|
@ -60,12 +61,13 @@
|
||||||
0000000c _sizeof_print_load_font
|
0000000c _sizeof_print_load_font
|
||||||
0000000b _sizeof_print_newline
|
0000000b _sizeof_print_newline
|
||||||
00000007 _sizeof_print_string
|
00000007 _sizeof_print_string
|
||||||
00000076 _sizeof_quit
|
00000080 _sizeof_quit
|
||||||
00000014 _sizeof_reset_screen
|
00000014 _sizeof_reset_screen
|
||||||
0000000f _sizeof_serial_send_byte
|
0000000f _sizeof_serial_send_byte
|
||||||
000007f0 _sizeof_font
|
000007f0 _sizeof_font
|
||||||
00000000 _sizeof_test_round1
|
00000020 _sizeof_memcmp_hram
|
||||||
0000001e _sizeof_main
|
0000000f _sizeof_main
|
||||||
|
0000001e _sizeof_test_round1
|
||||||
00000054 _sizeof_test_round2
|
00000054 _sizeof_test_round2
|
||||||
00000009 _sizeof_test_round3
|
00000009 _sizeof_test_round3
|
||||||
00000030 _sizeof_test_round4
|
00000030 _sizeof_test_round4
|
||||||
|
@ -74,7 +76,7 @@
|
||||||
00000018 _sizeof_copy_bank_data
|
00000018 _sizeof_copy_bank_data
|
||||||
00000019 _sizeof_check_bank_data
|
00000019 _sizeof_check_bank_data
|
||||||
00000010 _sizeof_all_ff
|
00000010 _sizeof_all_ff
|
||||||
00000d78 _sizeof_all_00
|
00000d69 _sizeof_all_00
|
||||||
00000010 _sizeof_bank_data
|
00000010 _sizeof_bank_data
|
||||||
00000022 _sizeof_clear_ram
|
00000022 _sizeof_clear_ram
|
||||||
00000021 _sizeof_fail_round1
|
00000021 _sizeof_fail_round1
|
|
@ -17,13 +17,27 @@ CXX_GUARD_START
|
||||||
#define GUI_V_I(I) (struct GUIVariant) { .type = GUI_VARIANT_INT, .v.i = (I) }
|
#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_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) }
|
#define GUI_V_S(S) (struct GUIVariant) { .type = GUI_VARIANT_STRING, .v.s = (S) }
|
||||||
|
#define GUI_V_P(P) (struct GUIVariant) { .type = GUI_VARIANT_POINTER, .v.p = (P) }
|
||||||
|
|
||||||
|
#define GUIVariantIs(V, T) ((V).type == GUI_VARIANT_##T)
|
||||||
|
#define GUIVariantIsVoid(V) GUIVariantIs(V, VOID)
|
||||||
|
#define GUIVariantIsUInt(V) GUIVariantIs(V, UNSIGNED)
|
||||||
|
#define GUIVariantIsInt(V) GUIVariantIs(V, INT)
|
||||||
|
#define GUIVariantIsFloat(V) GUIVariantIs(V, FLOAT)
|
||||||
|
#define GUIVariantIsString(V) GUIVariantIs(V, STRING)
|
||||||
|
#define GUIVariantIsPointer(V) GUIVariantIs(V, POINTER)
|
||||||
|
|
||||||
|
#define GUIVariantCompareUInt(V, X) (GUIVariantIsUInt(V) && (V).v.u == (X))
|
||||||
|
#define GUIVariantCompareInt(V, X) (GUIVariantIsInt(V) && (V).v.i == (X))
|
||||||
|
#define GUIVariantCompareString(V, X) (GUIVariantIsString(V) && strcmp((V).v.s, (X)) == 0)
|
||||||
|
|
||||||
enum GUIVariantType {
|
enum GUIVariantType {
|
||||||
GUI_VARIANT_VOID = 0,
|
GUI_VARIANT_VOID = 0,
|
||||||
GUI_VARIANT_UNSIGNED,
|
GUI_VARIANT_UNSIGNED,
|
||||||
GUI_VARIANT_INT,
|
GUI_VARIANT_INT,
|
||||||
GUI_VARIANT_FLOAT,
|
GUI_VARIANT_FLOAT,
|
||||||
GUI_VARIANT_STRING
|
GUI_VARIANT_STRING,
|
||||||
|
GUI_VARIANT_POINTER,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GUIVariant {
|
struct GUIVariant {
|
||||||
|
@ -33,13 +47,14 @@ struct GUIVariant {
|
||||||
int i;
|
int i;
|
||||||
float f;
|
float f;
|
||||||
const char* s;
|
const char* s;
|
||||||
|
void* p;
|
||||||
} v;
|
} v;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GUIMenu;
|
struct GUIMenu;
|
||||||
struct GUIMenuItem {
|
struct GUIMenuItem {
|
||||||
const char* title;
|
const char* title;
|
||||||
void* data;
|
struct GUIVariant data;
|
||||||
unsigned state;
|
unsigned state;
|
||||||
const char* const* validStates;
|
const char* const* validStates;
|
||||||
const struct GUIVariant* stateMappings;
|
const struct GUIVariant* stateMappings;
|
||||||
|
|
|
@ -70,7 +70,7 @@ bool mInputQueryHat(const struct mInputMap*, uint32_t type, int id, struct mInpu
|
||||||
void mInputUnbindHat(struct mInputMap*, uint32_t type, int id);
|
void mInputUnbindHat(struct mInputMap*, uint32_t type, int id);
|
||||||
void mInputUnbindAllHats(struct mInputMap*, uint32_t type);
|
void mInputUnbindAllHats(struct mInputMap*, uint32_t type);
|
||||||
|
|
||||||
void mInputMapLoad(struct mInputMap*, uint32_t type, const struct Configuration*);
|
bool mInputMapLoad(struct mInputMap*, uint32_t type, const struct Configuration*);
|
||||||
void mInputMapSave(const struct mInputMap*, uint32_t type, struct Configuration*);
|
void mInputMapSave(const struct mInputMap*, uint32_t type, struct Configuration*);
|
||||||
|
|
||||||
bool mInputProfileLoad(struct mInputMap*, uint32_t type, const struct Configuration*, const char* profile);
|
bool mInputProfileLoad(struct mInputMap*, uint32_t type, const struct Configuration*, const char* profile);
|
||||||
|
|
|
@ -181,6 +181,9 @@ struct GBMemory {
|
||||||
union GBMBCState mbcState;
|
union GBMBCState mbcState;
|
||||||
int currentBank;
|
int currentBank;
|
||||||
int currentBank0;
|
int currentBank0;
|
||||||
|
unsigned cartBusDecay;
|
||||||
|
uint16_t cartBusPc;
|
||||||
|
uint8_t cartBus;
|
||||||
|
|
||||||
uint8_t* wram;
|
uint8_t* wram;
|
||||||
uint8_t* wramBank;
|
uint8_t* wramBank;
|
||||||
|
|
|
@ -157,9 +157,11 @@ mLOG_DECLARE_CATEGORY(GB_STATE);
|
||||||
* | bit 3: IME
|
* | bit 3: IME
|
||||||
* | bit 4: Is HDMA active?
|
* | bit 4: Is HDMA active?
|
||||||
* | bits 5 - 7: Active RTC register
|
* | bits 5 - 7: Active RTC register
|
||||||
* | 0x00196 - 0x00197: Reserved (leave zero)
|
* | 0x00196: Cartridge bus value
|
||||||
|
* | 0x00197: Reserved (leave zero)
|
||||||
* 0x00198 - 0x0019F: Global cycle counter
|
* 0x00198 - 0x0019F: Global cycle counter
|
||||||
* 0x001A0 - 0x0025F: Reserved (leave zero)
|
* 0x001A0 - 0x001A1: Program counter for last cartridge read
|
||||||
|
* 0x001A2 - 0x0025F: Reserved (leave zero)
|
||||||
* 0x00260 - 0x002FF: OAM
|
* 0x00260 - 0x002FF: OAM
|
||||||
* 0x00300 - 0x0037F: I/O memory
|
* 0x00300 - 0x0037F: I/O memory
|
||||||
* 0x00380 - 0x003FE: HRAM
|
* 0x00380 - 0x003FE: HRAM
|
||||||
|
@ -401,12 +403,14 @@ struct GBSerializedState {
|
||||||
};
|
};
|
||||||
|
|
||||||
GBSerializedMemoryFlags flags;
|
GBSerializedMemoryFlags flags;
|
||||||
uint16_t reserved;
|
uint8_t cartBus;
|
||||||
|
uint8_t reserved;
|
||||||
} memory;
|
} memory;
|
||||||
|
|
||||||
uint64_t globalCycles;
|
uint64_t globalCycles;
|
||||||
|
|
||||||
uint32_t reserved[48];
|
uint16_t cartBusPc;
|
||||||
|
uint16_t reserved[95];
|
||||||
|
|
||||||
uint8_t oam[GB_SIZE_OAM];
|
uint8_t oam[GB_SIZE_OAM];
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ enum {
|
||||||
SIZE_CART1 = 0x02000000,
|
SIZE_CART1 = 0x02000000,
|
||||||
SIZE_CART2 = 0x02000000,
|
SIZE_CART2 = 0x02000000,
|
||||||
SIZE_CART_SRAM = 0x00008000,
|
SIZE_CART_SRAM = 0x00008000,
|
||||||
|
SIZE_CART_SRAM512 = 0x00010000,
|
||||||
SIZE_CART_FLASH512 = 0x00010000,
|
SIZE_CART_FLASH512 = 0x00010000,
|
||||||
SIZE_CART_FLASH1M = 0x00020000,
|
SIZE_CART_FLASH1M = 0x00020000,
|
||||||
SIZE_CART_EEPROM = 0x00002000,
|
SIZE_CART_EEPROM = 0x00002000,
|
||||||
|
|
|
@ -24,7 +24,8 @@ enum SavedataType {
|
||||||
SAVEDATA_FLASH512 = 2,
|
SAVEDATA_FLASH512 = 2,
|
||||||
SAVEDATA_FLASH1M = 3,
|
SAVEDATA_FLASH1M = 3,
|
||||||
SAVEDATA_EEPROM = 4,
|
SAVEDATA_EEPROM = 4,
|
||||||
SAVEDATA_EEPROM512 = 5
|
SAVEDATA_EEPROM512 = 5,
|
||||||
|
SAVEDATA_SRAM512 = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SavedataCommand {
|
enum SavedataCommand {
|
||||||
|
@ -110,6 +111,7 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type);
|
||||||
void GBASavedataInitFlash(struct GBASavedata* savedata);
|
void GBASavedataInitFlash(struct GBASavedata* savedata);
|
||||||
void GBASavedataInitEEPROM(struct GBASavedata* savedata);
|
void GBASavedataInitEEPROM(struct GBASavedata* savedata);
|
||||||
void GBASavedataInitSRAM(struct GBASavedata* savedata);
|
void GBASavedataInitSRAM(struct GBASavedata* savedata);
|
||||||
|
void GBASavedataInitSRAM512(struct GBASavedata* savedata);
|
||||||
|
|
||||||
uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address);
|
uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address);
|
||||||
void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8_t value);
|
void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8_t value);
|
||||||
|
|
BIN
res/font-new.png
BIN
res/font-new.png
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1,11 @@
|
||||||
|
[shader]
|
||||||
|
name=Scale2x
|
||||||
|
author=singron
|
||||||
|
description=AdvanceMAME's Scale2x algorithm
|
||||||
|
passes=1
|
||||||
|
|
||||||
|
[pass.0]
|
||||||
|
fragmentShader=scale2x.fs
|
||||||
|
blend=1
|
||||||
|
width=-2
|
||||||
|
height=-2
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* Shader implementation of Scale2x is adapted from https://gist.github.com/singron/3161079 */
|
||||||
|
varying vec2 texCoord;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform vec2 texSize;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// o = offset, the width of a pixel
|
||||||
|
vec2 o = 1.0 / texSize;
|
||||||
|
|
||||||
|
// texel arrangement
|
||||||
|
// A B C
|
||||||
|
// D E F
|
||||||
|
// G H I
|
||||||
|
vec4 B = texture2D(tex, texCoord + vec2( 0.0, o.y));
|
||||||
|
vec4 D = texture2D(tex, texCoord + vec2( -o.x, 0.0));
|
||||||
|
vec4 E = texture2D(tex, texCoord + vec2( 0.0, 0.0));
|
||||||
|
vec4 F = texture2D(tex, texCoord + vec2( o.x, 0.0));
|
||||||
|
vec4 H = texture2D(tex, texCoord + vec2( 0.0, -o.y));
|
||||||
|
vec2 p = texCoord * texSize;
|
||||||
|
// p = the texCoord within a pixel [0...1]
|
||||||
|
p = fract(p);
|
||||||
|
if (p.x > .5) {
|
||||||
|
if (p.y > .5) {
|
||||||
|
// Top Right
|
||||||
|
gl_FragColor = B == F && B != D && F != H ? F : E;
|
||||||
|
} else {
|
||||||
|
// Bottom Right
|
||||||
|
gl_FragColor = H == F && D != H && B != F ? F : E;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (p.y > .5) {
|
||||||
|
// Top Left
|
||||||
|
gl_FragColor = D == B && B != F && D != H ? D : E;
|
||||||
|
} else {
|
||||||
|
// Bottom Left
|
||||||
|
gl_FragColor = D == H && D != B && H != F ? D : E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
[shader]
|
||||||
|
name=Scale4x
|
||||||
|
author=singron, endrift
|
||||||
|
description=AdvanceMAME's Scale4x algorithm
|
||||||
|
passes=1
|
||||||
|
|
||||||
|
[pass.0]
|
||||||
|
fragmentShader=scale4x.fs
|
||||||
|
blend=1
|
||||||
|
width=-4
|
||||||
|
height=-4
|
|
@ -0,0 +1,54 @@
|
||||||
|
/* Shader implementation of Scale2x is adapted from https://gist.github.com/singron/3161079 */
|
||||||
|
varying vec2 texCoord;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform vec2 texSize;
|
||||||
|
|
||||||
|
vec4 scale2x(vec4 pixels[5], vec2 p) {
|
||||||
|
// texel arrangement
|
||||||
|
// x 0 x
|
||||||
|
// 1 2 3
|
||||||
|
// x 4 x
|
||||||
|
// p = the texCoord within a pixel [0...1]
|
||||||
|
p = fract(p);
|
||||||
|
if (p.x > .5) {
|
||||||
|
if (p.y > .5) {
|
||||||
|
// Top Right
|
||||||
|
return pixels[0] == pixels[3] && pixels[0] != pixels[1] && pixels[3] != pixels[4] ? pixels[3] : pixels[2];
|
||||||
|
} else {
|
||||||
|
// Bottom Right
|
||||||
|
return pixels[4] == pixels[3] && pixels[1] != pixels[4] && pixels[0] != pixels[3] ? pixels[3] : pixels[2];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (p.y > .5) {
|
||||||
|
// Top Left
|
||||||
|
return pixels[1] == pixels[0] && pixels[0] != pixels[3] && pixels[1] != pixels[4] ? pixels[1] : pixels[2];
|
||||||
|
} else {
|
||||||
|
// Bottom Left
|
||||||
|
return pixels[1] == pixels[4] && pixels[1] != pixels[0] && pixels[4] != pixels[3] ? pixels[1] : pixels[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 scaleNeighborhood(vec2 p, vec2 x, vec2 o) {
|
||||||
|
vec4 neighborhood[5];
|
||||||
|
neighborhood[0] = texture2D(tex, texCoord + x + vec2( 0.0, o.y));
|
||||||
|
neighborhood[1] = texture2D(tex, texCoord + x + vec2(-o.x, 0.0));
|
||||||
|
neighborhood[2] = texture2D(tex, texCoord + x + vec2( 0.0, 0.0));
|
||||||
|
neighborhood[3] = texture2D(tex, texCoord + x + vec2( o.x, 0.0));
|
||||||
|
neighborhood[4] = texture2D(tex, texCoord + x + vec2( 0.0, -o.y));
|
||||||
|
return scale2x(neighborhood, p + x * texSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// o = offset, the width of a pixel
|
||||||
|
vec2 o = 1.0 / texSize;
|
||||||
|
|
||||||
|
vec2 p = texCoord * texSize;
|
||||||
|
vec4 pixels[5];
|
||||||
|
pixels[0] = scaleNeighborhood(p, vec2( 0.0, o.y / 2.0), o);
|
||||||
|
pixels[1] = scaleNeighborhood(p, vec2(-o.x / 2.0, 0.0), o);
|
||||||
|
pixels[2] = scaleNeighborhood(p, vec2( 0.0, 0.0), o);
|
||||||
|
pixels[3] = scaleNeighborhood(p, vec2( o.x / 2.0, 0.0), o);
|
||||||
|
pixels[4] = scaleNeighborhood(p, vec2( 0.0, -o.y / 2.0), o);
|
||||||
|
gl_FragColor = scale2x(pixels, p * 2.0);
|
||||||
|
}
|
|
@ -101,9 +101,10 @@ static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address
|
||||||
struct mCore* core = debugger->d.core;
|
struct mCore* core = debugger->d.core;
|
||||||
char disassembly[64];
|
char disassembly[64];
|
||||||
struct ARMInstructionInfo info;
|
struct ARMInstructionInfo info;
|
||||||
|
address &= ~(WORD_SIZE_THUMB - 1);
|
||||||
be->printf(be, "%08X: ", address);
|
be->printf(be, "%08X: ", address);
|
||||||
if (mode == MODE_ARM) {
|
if (mode == MODE_ARM) {
|
||||||
uint32_t instruction = core->busRead32(core, address);
|
uint32_t instruction = core->busRead32(core, address & ~(WORD_SIZE_ARM - 1));
|
||||||
ARMDecodeARM(instruction, &info);
|
ARMDecodeARM(instruction, &info);
|
||||||
ARMDisassemble(&info, core->cpu, core->symbolTable, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly));
|
ARMDisassemble(&info, core->cpu, core->symbolTable, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly));
|
||||||
be->printf(be, "%08X\t%s\n", instruction, disassembly);
|
be->printf(be, "%08X\t%s\n", instruction, disassembly);
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <CoreFoundation/CFBundle.h>
|
||||||
|
#include <CoreFoundation/CFString.h>
|
||||||
|
#include <CoreFoundation/CFURL.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PSP2
|
#ifdef PSP2
|
||||||
#include <psp2/io/stat.h>
|
#include <psp2/io/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -274,6 +280,16 @@ void mCoreConfigPortablePath(char* out, size_t outLength) {
|
||||||
out[0] = '\0';
|
out[0] = '\0';
|
||||||
#else
|
#else
|
||||||
getcwd(out, outLength);
|
getcwd(out, outLength);
|
||||||
|
#ifdef __APPLE__
|
||||||
|
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
||||||
|
if (strcmp(out, "/") == 0 && mainBundle) {
|
||||||
|
CFURLRef url = CFBundleCopyBundleURL(mainBundle);
|
||||||
|
CFURLRef suburl = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, url);
|
||||||
|
CFRelease(url);
|
||||||
|
CFURLGetFileSystemRepresentation(suburl, true, (UInt8*) out, outLength);
|
||||||
|
CFRelease(suburl);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
strncat(out, PATH_SEP "portable.ini", outLength - strlen(out));
|
strncat(out, PATH_SEP "portable.ini", outLength - strlen(out));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -578,10 +578,10 @@ void mInputUnbindAllHats(struct mInputMap* map, uint32_t type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mInputMapLoad(struct mInputMap* map, uint32_t type, const struct Configuration* config) {
|
bool mInputMapLoad(struct mInputMap* map, uint32_t type, const struct Configuration* config) {
|
||||||
char sectionName[SECTION_NAME_MAX];
|
char sectionName[SECTION_NAME_MAX];
|
||||||
_makeSectionName(map->info->platformName, sectionName, SECTION_NAME_MAX, type);
|
_makeSectionName(map->info->platformName, sectionName, SECTION_NAME_MAX, type);
|
||||||
_loadAll(map, type, sectionName, config);
|
return _loadAll(map, type, sectionName, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mInputMapSave(const struct mInputMap* map, uint32_t type, struct Configuration* config) {
|
void mInputMapSave(const struct mInputMap* map, uint32_t type, struct Configuration* config) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBl
|
||||||
res->segment = -1; // TODO
|
res->segment = -1; // TODO
|
||||||
res->guessDivisor = 1;
|
res->guessDivisor = 1;
|
||||||
res->guessMultiplier = 1;
|
res->guessMultiplier = 1;
|
||||||
res->oldValue = value32;
|
res->oldValue = mem32[i >> 2];
|
||||||
++found;
|
++found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl
|
||||||
res->segment = -1; // TODO
|
res->segment = -1; // TODO
|
||||||
res->guessDivisor = 1;
|
res->guessDivisor = 1;
|
||||||
res->guessMultiplier = 1;
|
res->guessMultiplier = 1;
|
||||||
res->oldValue = value16;
|
res->oldValue = mem16[i >> 1];
|
||||||
++found;
|
++found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo
|
||||||
res->segment = -1; // TODO
|
res->segment = -1; // TODO
|
||||||
res->guessDivisor = 1;
|
res->guessDivisor = 1;
|
||||||
res->guessMultiplier = 1;
|
res->guessMultiplier = 1;
|
||||||
res->oldValue = value8;
|
res->oldValue = mem8[i];
|
||||||
++found;
|
++found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,42 +248,46 @@ void mCoreMemorySearch(struct mCore* core, const struct mCoreMemorySearchParams*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _testGuess(struct mCore* core, struct mCoreMemorySearchResult* res, const struct mCoreMemorySearchParams* params) {
|
bool _testSpecificGuess(struct mCore* core, struct mCoreMemorySearchResult* res, int64_t opValue, enum mCoreMemorySearchOp op) {
|
||||||
int64_t value;
|
|
||||||
int32_t offset = 0;
|
int32_t offset = 0;
|
||||||
char* end;
|
if (op >= mCORE_MEMORY_SEARCH_DELTA) {
|
||||||
if (params->op >= mCORE_MEMORY_SEARCH_DELTA) {
|
|
||||||
offset = res->oldValue;
|
offset = res->oldValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = strtoll(params->valueStr, &end, 10);
|
res->oldValue += opValue;
|
||||||
if (end) {
|
int64_t value = core->rawRead8(core, res->address, res->segment);
|
||||||
res->oldValue += value;
|
if (_op(value * res->guessDivisor / res->guessMultiplier - offset, opValue, op)) {
|
||||||
if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
|
res->oldValue = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(res->address & 1) && (res->width >= 2 || res->width == -1)) {
|
||||||
|
value = core->rawRead16(core, res->address, res->segment);
|
||||||
|
if (_op(value * res->guessDivisor / res->guessMultiplier - offset, opValue, op)) {
|
||||||
|
res->oldValue = value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!(res->address & 1) && (res->width >= 2 || res->width == -1) && _op(core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
|
}
|
||||||
|
if (!(res->address & 3) && (res->width >= 4 || res->width == -1)) {
|
||||||
|
value = core->rawRead32(core, res->address, res->segment);
|
||||||
|
if (_op(value * res->guessDivisor / res->guessMultiplier - offset, opValue, op)) {
|
||||||
|
res->oldValue = value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!(res->address & 3) && (res->width >= 4 || res->width == -1) && _op(core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
|
}
|
||||||
return true;
|
res->oldValue -= opValue;
|
||||||
}
|
return false;
|
||||||
res->oldValue -= value;
|
}
|
||||||
|
|
||||||
|
bool _testGuess(struct mCore* core, struct mCoreMemorySearchResult* res, const struct mCoreMemorySearchParams* params) {
|
||||||
|
char* end;
|
||||||
|
int64_t value = strtoll(params->valueStr, &end, 10);
|
||||||
|
if (end && _testSpecificGuess(core, res, value, params->op)) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = strtoll(params->valueStr, &end, 16);
|
value = strtoll(params->valueStr, &end, 16);
|
||||||
if (end) {
|
if (end && _testSpecificGuess(core, res, value, params->op)) {
|
||||||
res->oldValue += value;
|
return true;
|
||||||
if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(res->address & 1) && (res->width >= 2 || res->width == -1) && _op(core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(res->address & 3) && (res->width >= 4 || res->width == -1) && _op(core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
res->oldValue -= value;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
DEFINE_VECTOR(mCoreRewindPatches, struct PatchFast);
|
DEFINE_VECTOR(mCoreRewindPatches, struct PatchFast);
|
||||||
|
|
||||||
void _rewindDiff(struct mCoreRewindContext* context);
|
static void _rewindDiff(struct mCoreRewindContext* context);
|
||||||
|
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
THREAD_ENTRY _rewindThread(void* context);
|
THREAD_ENTRY _rewindThread(void* context);
|
||||||
|
@ -136,17 +136,19 @@ bool mCoreRewindRestore(struct mCoreRewindContext* context, struct mCore* core)
|
||||||
}
|
}
|
||||||
--context->current;
|
--context->current;
|
||||||
|
|
||||||
struct PatchFast* patch = mCoreRewindPatchesGetPointer(&context->patchMemory, context->current);
|
if (context->size) {
|
||||||
size_t size2 = context->previousState->size(context->previousState);
|
struct PatchFast* patch = mCoreRewindPatchesGetPointer(&context->patchMemory, context->current);
|
||||||
size_t size = context->currentState->size(context->currentState);
|
size_t size2 = context->previousState->size(context->previousState);
|
||||||
if (size2 < size) {
|
size_t size = context->currentState->size(context->currentState);
|
||||||
size = size2;
|
if (size2 < size) {
|
||||||
|
size = size2;
|
||||||
|
}
|
||||||
|
void* current = context->currentState->map(context->currentState, size, MAP_READ);
|
||||||
|
void* previous = context->previousState->map(context->previousState, size, MAP_WRITE);
|
||||||
|
patch->d.applyPatch(&patch->d, previous, size, current, size);
|
||||||
|
context->currentState->unmap(context->currentState, current, size);
|
||||||
|
context->previousState->unmap(context->previousState, previous, size);
|
||||||
}
|
}
|
||||||
void* current = context->currentState->map(context->currentState, size, MAP_READ);
|
|
||||||
void* previous = context->previousState->map(context->previousState, size, MAP_WRITE);
|
|
||||||
patch->d.applyPatch(&patch->d, previous, size, current, size);
|
|
||||||
context->currentState->unmap(context->currentState, current, size);
|
|
||||||
context->previousState->unmap(context->previousState, previous, size);
|
|
||||||
struct VFile* nextState = context->previousState;
|
struct VFile* nextState = context->previousState;
|
||||||
context->previousState = context->currentState;
|
context->previousState = context->currentState;
|
||||||
context->currentState = nextState;
|
context->currentState = nextState;
|
||||||
|
|
|
@ -35,19 +35,19 @@ static void mGUIShowCheatSet(struct mGUIRunner* runner, struct mCheatDevice* dev
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Add line",
|
.title = "Add line",
|
||||||
.data = (void*) CHEAT_ADD_LINE,
|
.data = GUI_V_U(CHEAT_ADD_LINE),
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Rename",
|
.title = "Rename",
|
||||||
.data = (void*) CHEAT_RENAME,
|
.data = GUI_V_U(CHEAT_RENAME),
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Delete",
|
.title = "Delete",
|
||||||
.data = (void*) CHEAT_DELETE,
|
.data = GUI_V_U(CHEAT_DELETE),
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Back",
|
.title = "Back",
|
||||||
.data = 0,
|
.data = GUI_V_V,
|
||||||
};
|
};
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -56,11 +56,11 @@ static void mGUIShowCheatSet(struct mGUIRunner* runner, struct mCheatDevice* dev
|
||||||
struct GUIMenuItem* item;
|
struct GUIMenuItem* item;
|
||||||
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &menu, &item);
|
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &menu, &item);
|
||||||
set->enabled = GUIMenuItemListGetPointer(&menu.items, 0)->state;
|
set->enabled = GUIMenuItemListGetPointer(&menu.items, 0)->state;
|
||||||
if (reason != GUI_MENU_EXIT_ACCEPT || !item->data) {
|
if (reason != GUI_MENU_EXIT_ACCEPT || GUIVariantIsVoid(item->data)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum mGUICheatAction action = (enum mGUICheatAction) item->data;
|
enum mGUICheatAction action = (enum mGUICheatAction) item->data.v.u;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case CHEAT_ADD_LINE:
|
case CHEAT_ADD_LINE:
|
||||||
strlcpy(keyboard.title, "Add line", sizeof(keyboard.title));
|
strlcpy(keyboard.title, "Add line", sizeof(keyboard.title));
|
||||||
|
@ -108,7 +108,7 @@ void mGUIShowCheats(struct mGUIRunner* runner) {
|
||||||
struct mCheatSet* set = *mCheatSetsGetPointer(&device->cheats, i);
|
struct mCheatSet* set = *mCheatSetsGetPointer(&device->cheats, i);
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = set->name,
|
.title = set->name,
|
||||||
.data = set,
|
.data = GUI_V_P(set),
|
||||||
.state = set->enabled,
|
.state = set->enabled,
|
||||||
.validStates = offOn,
|
.validStates = offOn,
|
||||||
.nStates = 2
|
.nStates = 2
|
||||||
|
@ -116,11 +116,11 @@ void mGUIShowCheats(struct mGUIRunner* runner) {
|
||||||
}
|
}
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Add new cheat set",
|
.title = "Add new cheat set",
|
||||||
.data = 0,
|
.data = GUI_V_V,
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Back",
|
.title = "Back",
|
||||||
.data = (void*) -1,
|
.data = GUI_V_I(-1),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GUIMenuItem* item;
|
struct GUIMenuItem* item;
|
||||||
|
@ -131,11 +131,11 @@ void mGUIShowCheats(struct mGUIRunner* runner) {
|
||||||
set->enabled = item->state;
|
set->enabled = item->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reason != GUI_MENU_EXIT_ACCEPT || item->data == (void*) -1) {
|
if (reason != GUI_MENU_EXIT_ACCEPT || GUIVariantCompareInt(item->data, -1)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
struct mCheatSet* set = NULL;
|
struct mCheatSet* set = NULL;
|
||||||
if (!item->data) {
|
if (GUIVariantIsVoid(item->data)) {
|
||||||
struct GUIKeyboardParams keyboard;
|
struct GUIKeyboardParams keyboard;
|
||||||
GUIKeyboardParamsInit(&keyboard);
|
GUIKeyboardParamsInit(&keyboard);
|
||||||
keyboard.maxLen = 50;
|
keyboard.maxLen = 50;
|
||||||
|
@ -146,7 +146,7 @@ void mGUIShowCheats(struct mGUIRunner* runner) {
|
||||||
mCheatAddSet(device, set);
|
mCheatAddSet(device, set);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
set = item->data;
|
set = item->data.v.p;
|
||||||
}
|
}
|
||||||
if (set) {
|
if (set) {
|
||||||
mGUIShowCheatSet(runner, device, set);
|
mGUIShowCheatSet(runner, device, set);
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
#define GUI_MAX_INPUTS 7
|
#define GUI_MAX_INPUTS 7
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CONFIG_REMAP,
|
||||||
|
CONFIG_SAVE,
|
||||||
|
};
|
||||||
|
|
||||||
static bool _biosNamed(const char* name) {
|
static bool _biosNamed(const char* name) {
|
||||||
char ext[PATH_MAX + 1] = {};
|
char ext[PATH_MAX + 1] = {};
|
||||||
separatePath(name, NULL, NULL, ext);
|
separatePath(name, NULL, NULL, ext);
|
||||||
|
@ -45,7 +50,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
GUIMenuItemListInit(&menu.items, 0);
|
GUIMenuItemListInit(&menu.items, 0);
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Frameskip",
|
.title = "Frameskip",
|
||||||
.data = "frameskip",
|
.data = GUI_V_S("frameskip"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 0,
|
.state = 0,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -55,7 +60,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Show framerate",
|
.title = "Show framerate",
|
||||||
.data = "fpsCounter",
|
.data = GUI_V_S("fpsCounter"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = false,
|
.state = false,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -65,7 +70,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Show status OSD",
|
.title = "Show status OSD",
|
||||||
.data = "showOSD",
|
.data = GUI_V_S("showOSD"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = true,
|
.state = true,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -75,7 +80,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Autosave state",
|
.title = "Autosave state",
|
||||||
.data = "autosave",
|
.data = GUI_V_S("autosave"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = true,
|
.state = true,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -85,7 +90,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Autoload state",
|
.title = "Autoload state",
|
||||||
.data = "autoload",
|
.data = GUI_V_S("autoload"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = true,
|
.state = true,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -95,7 +100,17 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Mute",
|
.title = "Mute",
|
||||||
.data = "mute",
|
.data = GUI_V_S("mute"),
|
||||||
|
.submenu = 0,
|
||||||
|
.state = false,
|
||||||
|
.validStates = (const char*[]) {
|
||||||
|
"Off", "On"
|
||||||
|
},
|
||||||
|
.nStates = 2
|
||||||
|
};
|
||||||
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
|
.title = "Fast forward mute",
|
||||||
|
.data = GUI_V_S("fastForwardMute"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = false,
|
.state = false,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -105,7 +120,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Use BIOS if found",
|
.title = "Use BIOS if found",
|
||||||
.data = "useBios",
|
.data = GUI_V_S("useBios"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = true,
|
.state = true,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -116,26 +131,26 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Select GBA BIOS path",
|
.title = "Select GBA BIOS path",
|
||||||
.data = "gba.bios",
|
.data = GUI_V_S("gba.bios"),
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#ifdef M_CORE_GB
|
#ifdef M_CORE_GB
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Select GB BIOS path",
|
.title = "Select GB BIOS path",
|
||||||
.data = "gb.bios",
|
.data = GUI_V_S("gb.bios"),
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Select GBC BIOS path",
|
.title = "Select GBC BIOS path",
|
||||||
.data = "gbc.bios",
|
.data = GUI_V_S("gbc.bios"),
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Select SGB BIOS path",
|
.title = "Select SGB BIOS path",
|
||||||
.data = "sgb.bios",
|
.data = GUI_V_S("sgb.bios"),
|
||||||
};
|
};
|
||||||
struct GUIMenuItem* palette = GUIMenuItemListAppend(&menu.items);
|
struct GUIMenuItem* palette = GUIMenuItemListAppend(&menu.items);
|
||||||
*palette = (struct GUIMenuItem) {
|
*palette = (struct GUIMenuItem) {
|
||||||
.title = "GB palette",
|
.title = "GB palette",
|
||||||
.data = "gb.pal",
|
.data = GUI_V_S("gb.pal"),
|
||||||
};
|
};
|
||||||
const struct GBColorPreset* colorPresets;
|
const struct GBColorPreset* colorPresets;
|
||||||
palette->nStates = GBColorPresetList(&colorPresets);
|
palette->nStates = GBColorPresetList(&colorPresets);
|
||||||
|
@ -147,7 +162,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
#endif
|
#endif
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Interframe blending",
|
.title = "Interframe blending",
|
||||||
.data = "interframeBlending",
|
.data = GUI_V_S("interframeBlending"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = false,
|
.state = false,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -158,7 +173,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
#if defined(M_CORE_GBA) && (defined(GEKKO) || defined(__SWITCH__) || defined(PSP2))
|
#if defined(M_CORE_GBA) && (defined(GEKKO) || defined(__SWITCH__) || defined(PSP2))
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Enable GBP features",
|
.title = "Enable GBP features",
|
||||||
.data = "gba.forceGbp",
|
.data = GUI_V_S("gba.forceGbp"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = false,
|
.state = false,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -170,7 +185,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
#ifdef M_CORE_GB
|
#ifdef M_CORE_GB
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Enable SGB features",
|
.title = "Enable SGB features",
|
||||||
.data = "sgb.model",
|
.data = GUI_V_S("sgb.model"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = true,
|
.state = true,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -184,7 +199,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Enable SGB borders",
|
.title = "Enable SGB borders",
|
||||||
.data = "sgb.borders",
|
.data = GUI_V_S("sgb.borders"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = true,
|
.state = true,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -194,7 +209,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Crop SGB borders",
|
.title = "Crop SGB borders",
|
||||||
.data = "sgb.borderCrop",
|
.data = GUI_V_S("sgb.borderCrop"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = false,
|
.state = false,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -214,7 +229,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
}
|
}
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Remap controls",
|
.title = "Remap controls",
|
||||||
.data = "*REMAP",
|
.data = GUI_V_U(CONFIG_REMAP),
|
||||||
.state = 0,
|
.state = 0,
|
||||||
.validStates = i ? mapNames : 0,
|
.validStates = i ? mapNames : 0,
|
||||||
.nStates = i
|
.nStates = i
|
||||||
|
@ -225,11 +240,11 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
}
|
}
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Save",
|
.title = "Save",
|
||||||
.data = "*SAVE",
|
.data = GUI_V_U(CONFIG_SAVE),
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Cancel",
|
.title = "Cancel",
|
||||||
.data = 0,
|
.data = GUI_V_V,
|
||||||
};
|
};
|
||||||
enum GUIMenuExitReason reason;
|
enum GUIMenuExitReason reason;
|
||||||
char gbaBiosPath[256] = "";
|
char gbaBiosPath[256] = "";
|
||||||
|
@ -242,59 +257,63 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
struct GUIMenuItem* item;
|
struct GUIMenuItem* item;
|
||||||
for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) {
|
for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) {
|
||||||
item = GUIMenuItemListGetPointer(&menu.items, i);
|
item = GUIMenuItemListGetPointer(&menu.items, i);
|
||||||
if (!item->validStates || !item->data) {
|
if (!item->validStates || GUIVariantIsVoid(item->data)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (item->stateMappings) {
|
if (GUIVariantIsString(item->data)) {
|
||||||
size_t j;
|
if (item->stateMappings) {
|
||||||
for (j = 0; j < item->nStates; ++j) {
|
size_t j;
|
||||||
const struct GUIVariant* v = &item->stateMappings[j];
|
for (j = 0; j < item->nStates; ++j) {
|
||||||
struct GUIVariant test;
|
const struct GUIVariant* v = &item->stateMappings[j];
|
||||||
switch (v->type) {
|
struct GUIVariant test;
|
||||||
case GUI_VARIANT_VOID:
|
switch (v->type) {
|
||||||
if (!mCoreConfigGetValue(&runner->config, item->data)) {
|
case GUI_VARIANT_VOID:
|
||||||
item->state = j;
|
if (!mCoreConfigGetValue(&runner->config, item->data.v.s)) {
|
||||||
|
item->state = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GUI_VARIANT_UNSIGNED:
|
||||||
|
if (mCoreConfigGetUIntValue(&runner->config, item->data.v.s, &test.v.u) && test.v.u == v->v.u) {
|
||||||
|
item->state = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GUI_VARIANT_INT:
|
||||||
|
if (mCoreConfigGetIntValue(&runner->config, item->data.v.s, &test.v.i) && test.v.i == v->v.i) {
|
||||||
|
item->state = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GUI_VARIANT_FLOAT:
|
||||||
|
if (mCoreConfigGetFloatValue(&runner->config, item->data.v.s, &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.v.s);
|
||||||
|
if (test.v.s && strcmp(test.v.s, v->v.s) == 0) {
|
||||||
|
item->state = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GUI_VARIANT_POINTER:
|
||||||
break;
|
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.v.s, &item->state);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
mCoreConfigGetUIntValue(&runner->config, item->data, &item->state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
reason = GUIShowMenu(&runner->params, &menu, &item);
|
reason = GUIShowMenu(&runner->params, &menu, &item);
|
||||||
if (reason != GUI_MENU_EXIT_ACCEPT || !item->data) {
|
if (reason != GUI_MENU_EXIT_ACCEPT || GUIVariantIsVoid(item->data)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!strcmp(item->data, "*SAVE")) {
|
if (GUIVariantCompareUInt(item->data, CONFIG_SAVE)) {
|
||||||
if (gbaBiosPath[0]) {
|
if (gbaBiosPath[0]) {
|
||||||
mCoreConfigSetValue(&runner->config, "gba.bios", gbaBiosPath);
|
mCoreConfigSetValue(&runner->config, "gba.bios", gbaBiosPath);
|
||||||
}
|
}
|
||||||
|
@ -309,30 +328,32 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
}
|
}
|
||||||
for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) {
|
for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) {
|
||||||
item = GUIMenuItemListGetPointer(&menu.items, i);
|
item = GUIMenuItemListGetPointer(&menu.items, i);
|
||||||
if (!item->validStates || !item->data || ((const char*) item->data)[0] == '*') {
|
if (!item->validStates || !GUIVariantIsString(item->data)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (item->stateMappings) {
|
if (item->stateMappings) {
|
||||||
const struct GUIVariant* v = &item->stateMappings[item->state];
|
const struct GUIVariant* v = &item->stateMappings[item->state];
|
||||||
switch (v->type) {
|
switch (v->type) {
|
||||||
case GUI_VARIANT_VOID:
|
case GUI_VARIANT_VOID:
|
||||||
mCoreConfigSetValue(&runner->config, item->data, NULL);
|
mCoreConfigSetValue(&runner->config, item->data.v.s, NULL);
|
||||||
break;
|
break;
|
||||||
case GUI_VARIANT_UNSIGNED:
|
case GUI_VARIANT_UNSIGNED:
|
||||||
mCoreConfigSetUIntValue(&runner->config, item->data, v->v.u);
|
mCoreConfigSetUIntValue(&runner->config, item->data.v.s, v->v.u);
|
||||||
break;
|
break;
|
||||||
case GUI_VARIANT_INT:
|
case GUI_VARIANT_INT:
|
||||||
mCoreConfigSetUIntValue(&runner->config, item->data, v->v.i);
|
mCoreConfigSetUIntValue(&runner->config, item->data.v.s, v->v.i);
|
||||||
break;
|
break;
|
||||||
case GUI_VARIANT_FLOAT:
|
case GUI_VARIANT_FLOAT:
|
||||||
mCoreConfigSetFloatValue(&runner->config, item->data, v->v.f);
|
mCoreConfigSetFloatValue(&runner->config, item->data.v.s, v->v.f);
|
||||||
break;
|
break;
|
||||||
case GUI_VARIANT_STRING:
|
case GUI_VARIANT_STRING:
|
||||||
mCoreConfigSetValue(&runner->config, item->data, v->v.s);
|
mCoreConfigSetValue(&runner->config, item->data.v.s, v->v.s);
|
||||||
|
break;
|
||||||
|
case GUI_VARIANT_POINTER:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef M_CORE_GB
|
#ifdef M_CORE_GB
|
||||||
} else if (!strcmp(item->data, "gb.pal")) {
|
} else if (GUIVariantCompareString(item->data, "gb.pal")) {
|
||||||
const struct GBColorPreset* preset = &colorPresets[item->state];
|
const struct GBColorPreset* preset = &colorPresets[item->state];
|
||||||
mCoreConfigSetUIntValue(&runner->config, "gb.pal[0]", preset->colors[0] & 0xFFFFFF);
|
mCoreConfigSetUIntValue(&runner->config, "gb.pal[0]", preset->colors[0] & 0xFFFFFF);
|
||||||
mCoreConfigSetUIntValue(&runner->config, "gb.pal[1]", preset->colors[1] & 0xFFFFFF);
|
mCoreConfigSetUIntValue(&runner->config, "gb.pal[1]", preset->colors[1] & 0xFFFFFF);
|
||||||
|
@ -346,10 +367,10 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
mCoreConfigSetUIntValue(&runner->config, "gb.pal[9]", preset->colors[9] & 0xFFFFFF);
|
mCoreConfigSetUIntValue(&runner->config, "gb.pal[9]", preset->colors[9] & 0xFFFFFF);
|
||||||
mCoreConfigSetUIntValue(&runner->config, "gb.pal[10]", preset->colors[10] & 0xFFFFFF);
|
mCoreConfigSetUIntValue(&runner->config, "gb.pal[10]", preset->colors[10] & 0xFFFFFF);
|
||||||
mCoreConfigSetUIntValue(&runner->config, "gb.pal[11]", preset->colors[11] & 0xFFFFFF);
|
mCoreConfigSetUIntValue(&runner->config, "gb.pal[11]", preset->colors[11] & 0xFFFFFF);
|
||||||
mCoreConfigSetUIntValue(&runner->config, item->data, item->state);
|
mCoreConfigSetUIntValue(&runner->config, "gb.pal", item->state);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
mCoreConfigSetUIntValue(&runner->config, item->data, item->state);
|
mCoreConfigSetUIntValue(&runner->config, item->data.v.s, item->state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (runner->keySources) {
|
if (runner->keySources) {
|
||||||
|
@ -363,11 +384,11 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
mCoreLoadForeignConfig(runner->core, &runner->config);
|
mCoreLoadForeignConfig(runner->core, &runner->config);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!strcmp(item->data, "*REMAP")) {
|
if (GUIVariantCompareUInt(item->data, CONFIG_REMAP)) {
|
||||||
mGUIRemapKeys(&runner->params, &runner->core->inputMap, &runner->keySources[item->state]);
|
mGUIRemapKeys(&runner->params, &runner->core->inputMap, &runner->keySources[item->state]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(item->data, "gba.bios")) {
|
if (GUIVariantCompareString(item->data, "gba.bios")) {
|
||||||
// TODO: show box if failed
|
// TODO: show box if failed
|
||||||
if (!GUISelectFile(&runner->params, gbaBiosPath, sizeof(gbaBiosPath), _biosNamed, GBAIsBIOS, NULL)) {
|
if (!GUISelectFile(&runner->params, gbaBiosPath, sizeof(gbaBiosPath), _biosNamed, GBAIsBIOS, NULL)) {
|
||||||
gbaBiosPath[0] = '\0';
|
gbaBiosPath[0] = '\0';
|
||||||
|
@ -375,21 +396,21 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#ifdef M_CORE_GB
|
#ifdef M_CORE_GB
|
||||||
if (!strcmp(item->data, "gb.bios")) {
|
if (GUIVariantCompareString(item->data, "gb.bios")) {
|
||||||
// TODO: show box if failed
|
// TODO: show box if failed
|
||||||
if (!GUISelectFile(&runner->params, gbBiosPath, sizeof(gbBiosPath), _biosNamed, GBIsBIOS, NULL)) {
|
if (!GUISelectFile(&runner->params, gbBiosPath, sizeof(gbBiosPath), _biosNamed, GBIsBIOS, NULL)) {
|
||||||
gbBiosPath[0] = '\0';
|
gbBiosPath[0] = '\0';
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(item->data, "gbc.bios")) {
|
if (GUIVariantCompareString(item->data, "gbc.bios")) {
|
||||||
// TODO: show box if failed
|
// TODO: show box if failed
|
||||||
if (!GUISelectFile(&runner->params, gbcBiosPath, sizeof(gbcBiosPath), _biosNamed, GBIsBIOS, NULL)) {
|
if (!GUISelectFile(&runner->params, gbcBiosPath, sizeof(gbcBiosPath), _biosNamed, GBIsBIOS, NULL)) {
|
||||||
gbcBiosPath[0] = '\0';
|
gbcBiosPath[0] = '\0';
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(item->data, "sgb.bios")) {
|
if (GUIVariantCompareString(item->data, "sgb.bios")) {
|
||||||
// TODO: show box if failed
|
// TODO: show box if failed
|
||||||
if (!GUISelectFile(&runner->params, sgbBiosPath, sizeof(sgbBiosPath), _biosNamed, GBIsBIOS, NULL)) {
|
if (!GUISelectFile(&runner->params, sgbBiosPath, sizeof(sgbBiosPath), _biosNamed, GBIsBIOS, NULL)) {
|
||||||
sgbBiosPath[0] = '\0';
|
sgbBiosPath[0] = '\0';
|
||||||
|
|
|
@ -42,6 +42,11 @@ enum {
|
||||||
|
|
||||||
#define RUNNER_STATE(X) ((X) << 16)
|
#define RUNNER_STATE(X) ((X) << 16)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SCREENSHOT_VALID = 0x10000,
|
||||||
|
SCREENSHOT_INVALID = 0x20000,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct mInputPlatformInfo _mGUIKeyInfo = {
|
static const struct mInputPlatformInfo _mGUIKeyInfo = {
|
||||||
.platformName = "gui",
|
.platformName = "gui",
|
||||||
.keyId = (const char*[GUI_INPUT_MAX]) {
|
.keyId = (const char*[GUI_INPUT_MAX]) {
|
||||||
|
@ -107,39 +112,49 @@ static void _drawBackground(struct GUIBackground* background, void* context) {
|
||||||
|
|
||||||
static void _drawState(struct GUIBackground* background, void* id) {
|
static void _drawState(struct GUIBackground* background, void* id) {
|
||||||
struct mGUIBackground* gbaBackground = (struct mGUIBackground*) background;
|
struct mGUIBackground* gbaBackground = (struct mGUIBackground*) background;
|
||||||
int stateId = ((int) id) >> 16;
|
unsigned stateId = ((uint32_t) id) >> 16;
|
||||||
if (gbaBackground->p->drawScreenshot) {
|
if (gbaBackground->p->drawScreenshot) {
|
||||||
unsigned w, h;
|
unsigned w, h;
|
||||||
gbaBackground->p->core->desiredVideoDimensions(gbaBackground->p->core, &w, &h);
|
gbaBackground->p->core->desiredVideoDimensions(gbaBackground->p->core, &w, &h);
|
||||||
if (gbaBackground->screenshot && gbaBackground->screenshotId == (int) id) {
|
size_t size = w * h * BYTES_PER_PIXEL;
|
||||||
gbaBackground->p->drawScreenshot(gbaBackground->p, gbaBackground->screenshot, w, h, true);
|
if (size != gbaBackground->imageSize) {
|
||||||
|
mappedMemoryFree(gbaBackground->image, gbaBackground->imageSize);
|
||||||
|
gbaBackground->image = NULL;
|
||||||
|
}
|
||||||
|
if (gbaBackground->image && gbaBackground->screenshotId == (stateId | SCREENSHOT_VALID)) {
|
||||||
|
gbaBackground->p->drawScreenshot(gbaBackground->p, gbaBackground->image, w, h, true);
|
||||||
return;
|
return;
|
||||||
}
|
} else if (gbaBackground->screenshotId != (stateId | SCREENSHOT_INVALID)) {
|
||||||
struct VFile* vf = mCoreGetState(gbaBackground->p->core, stateId, false);
|
struct VFile* vf = mCoreGetState(gbaBackground->p->core, stateId, false);
|
||||||
color_t* pixels = gbaBackground->screenshot;
|
color_t* pixels = gbaBackground->image;
|
||||||
if (!pixels) {
|
if (!pixels) {
|
||||||
pixels = anonymousMemoryMap(w * h * 4);
|
pixels = anonymousMemoryMap(size);
|
||||||
gbaBackground->screenshot = pixels;
|
gbaBackground->image = pixels;
|
||||||
}
|
gbaBackground->imageSize = size;
|
||||||
bool success = false;
|
}
|
||||||
if (vf && isPNG(vf) && pixels) {
|
bool success = false;
|
||||||
png_structp png = PNGReadOpen(vf, PNG_HEADER_BYTES);
|
if (vf && isPNG(vf) && pixels) {
|
||||||
png_infop info = png_create_info_struct(png);
|
png_structp png = PNGReadOpen(vf, PNG_HEADER_BYTES);
|
||||||
png_infop end = png_create_info_struct(png);
|
png_infop info = png_create_info_struct(png);
|
||||||
if (png && info && end) {
|
png_infop end = png_create_info_struct(png);
|
||||||
success = PNGReadHeader(png, info);
|
if (png && info && end) {
|
||||||
success = success && PNGReadPixels(png, info, pixels, w, h, w);
|
success = PNGReadHeader(png, info);
|
||||||
success = success && PNGReadFooter(png, end);
|
success = success && PNGReadPixels(png, info, pixels, w, h, w);
|
||||||
|
success = success && PNGReadFooter(png, end);
|
||||||
|
}
|
||||||
|
PNGReadClose(png, info, end);
|
||||||
|
}
|
||||||
|
if (vf) {
|
||||||
|
vf->close(vf);
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
|
gbaBackground->p->drawScreenshot(gbaBackground->p, pixels, w, h, true);
|
||||||
|
gbaBackground->screenshotId = stateId | SCREENSHOT_VALID;
|
||||||
|
} else {
|
||||||
|
gbaBackground->screenshotId = stateId | SCREENSHOT_INVALID;
|
||||||
}
|
}
|
||||||
PNGReadClose(png, info, end);
|
|
||||||
}
|
}
|
||||||
if (vf) {
|
if (gbaBackground->p->drawFrame && gbaBackground->screenshotId == (stateId | SCREENSHOT_INVALID)) {
|
||||||
vf->close(vf);
|
|
||||||
}
|
|
||||||
if (success) {
|
|
||||||
gbaBackground->p->drawScreenshot(gbaBackground->p, pixels, w, h, true);
|
|
||||||
gbaBackground->screenshotId = (int) id;
|
|
||||||
} else if (gbaBackground->p->drawFrame) {
|
|
||||||
gbaBackground->p->drawFrame(gbaBackground->p, true);
|
gbaBackground->p->drawFrame(gbaBackground->p, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,7 +330,7 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
.draw = _drawState
|
.draw = _drawState
|
||||||
},
|
},
|
||||||
.p = runner,
|
.p = runner,
|
||||||
.screenshot = 0,
|
.image = 0,
|
||||||
.screenshotId = 0
|
.screenshotId = 0
|
||||||
};
|
};
|
||||||
struct GUIMenu pauseMenu = {
|
struct GUIMenu pauseMenu = {
|
||||||
|
@ -336,38 +351,38 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
GUIMenuItemListInit(&pauseMenu.items, 0);
|
GUIMenuItemListInit(&pauseMenu.items, 0);
|
||||||
GUIMenuItemListInit(&stateSaveMenu.items, 9);
|
GUIMenuItemListInit(&stateSaveMenu.items, 9);
|
||||||
GUIMenuItemListInit(&stateLoadMenu.items, 10);
|
GUIMenuItemListInit(&stateLoadMenu.items, 10);
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Unpause", .data = (void*) RUNNER_CONTINUE };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Unpause", .data = GUI_V_U(RUNNER_CONTINUE) };
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Save state", .submenu = &stateSaveMenu };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Save state", .submenu = &stateSaveMenu };
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Load state", .submenu = &stateLoadMenu };
|
*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 1", .data = GUI_V_U(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 2", .data = GUI_V_U(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 3", .data = GUI_V_U(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 4", .data = GUI_V_U(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 5", .data = GUI_V_U(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 6", .data = GUI_V_U(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 7", .data = GUI_V_U(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 8", .data = GUI_V_U(RUNNER_SAVE_STATE | RUNNER_STATE(8)) };
|
||||||
*GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = (void*) (RUNNER_SAVE_STATE | RUNNER_STATE(9)) };
|
*GUIMenuItemListAppend(&stateSaveMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = GUI_V_U(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 = "Autosave", .data = GUI_V_U(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 1", .data = GUI_V_U(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 2", .data = GUI_V_U(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 3", .data = GUI_V_U(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 4", .data = GUI_V_U(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 5", .data = GUI_V_U(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 6", .data = GUI_V_U(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 7", .data = GUI_V_U(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 8", .data = GUI_V_U(RUNNER_LOAD_STATE | RUNNER_STATE(8)) };
|
||||||
*GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = (void*) (RUNNER_LOAD_STATE | RUNNER_STATE(9)) };
|
*GUIMenuItemListAppend(&stateLoadMenu.items) = (struct GUIMenuItem) { .title = "State 9", .data = GUI_V_U(RUNNER_LOAD_STATE | RUNNER_STATE(9)) };
|
||||||
|
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Take screenshot", .data = (void*) RUNNER_SCREENSHOT };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Take screenshot", .data = GUI_V_U(RUNNER_SCREENSHOT) };
|
||||||
if (runner->params.getText) {
|
if (runner->params.getText) {
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Cheats", .data = (void*) RUNNER_CHEATS };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Cheats", .data = GUI_V_U(RUNNER_CHEATS) };
|
||||||
}
|
}
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Configure", .data = (void*) RUNNER_CONFIG };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Configure", .data = GUI_V_U(RUNNER_CONFIG) };
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Reset game", .data = (void*) RUNNER_RESET };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Reset game", .data = GUI_V_U(RUNNER_RESET) };
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Exit game", .data = (void*) RUNNER_EXIT };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Exit game", .data = GUI_V_U(RUNNER_EXIT) };
|
||||||
|
|
||||||
runner->params.drawStart();
|
runner->params.drawStart();
|
||||||
if (runner->params.guiPrepare) {
|
if (runner->params.guiPrepare) {
|
||||||
|
@ -455,6 +470,12 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
int drawFps = false;
|
int drawFps = false;
|
||||||
mCoreConfigGetIntValue(&runner->config, "fpsCounter", &drawFps);
|
mCoreConfigGetIntValue(&runner->config, "fpsCounter", &drawFps);
|
||||||
|
|
||||||
|
int mute = false;
|
||||||
|
mCoreConfigGetIntValue(&runner->config, "mute", &mute);
|
||||||
|
|
||||||
|
int fastForwardMute = false;
|
||||||
|
mCoreConfigGetIntValue(&runner->config, "fastForwardMute", &fastForwardMute);
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
|
@ -506,21 +527,33 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
if (guiKeys & (1 << mGUI_INPUT_SCREENSHOT)) {
|
if (guiKeys & (1 << mGUI_INPUT_SCREENSHOT)) {
|
||||||
mCoreTakeScreenshot(runner->core);
|
mCoreTakeScreenshot(runner->core);
|
||||||
}
|
}
|
||||||
|
bool muteTogglePressed = guiKeys & (1 << mGUI_INPUT_MUTE_TOGGLE);
|
||||||
|
if (muteTogglePressed) {
|
||||||
|
mute = !mute;
|
||||||
|
mCoreConfigSetUIntValue(&runner->config, "mute", mute);
|
||||||
|
runner->core->reloadConfigOption(runner->core, "mute", &runner->config);
|
||||||
|
}
|
||||||
if (runner->setFrameLimiter) {
|
if (runner->setFrameLimiter) {
|
||||||
if (guiKeys & (1 << mGUI_INPUT_FAST_FORWARD_TOGGLE)) {
|
if (guiKeys & (1 << mGUI_INPUT_FAST_FORWARD_TOGGLE)) {
|
||||||
fastForward = !fastForward;
|
fastForward = !fastForward;
|
||||||
}
|
}
|
||||||
if (fastForward || (heldKeys & (1 << mGUI_INPUT_FAST_FORWARD_HELD))) {
|
bool fastForwarding = fastForward || (heldKeys & (1 << mGUI_INPUT_FAST_FORWARD_HELD));
|
||||||
|
if (fastForwarding) {
|
||||||
|
if (fastForwardMute && !mute && !muteTogglePressed) {
|
||||||
|
mCoreConfigSetUIntValue(&runner->core->config, "mute", fastForwardMute);
|
||||||
|
runner->core->reloadConfigOption(runner->core, "mute", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
runner->setFrameLimiter(runner, false);
|
runner->setFrameLimiter(runner, false);
|
||||||
} else {
|
} else {
|
||||||
runner->setFrameLimiter(runner, true);
|
runner->setFrameLimiter(runner, true);
|
||||||
|
|
||||||
|
if (fastForwardMute && !mute && !muteTogglePressed) {
|
||||||
|
mCoreConfigSetUIntValue(&runner->core->config, "mute", !fastForwardMute);
|
||||||
|
runner->core->reloadConfigOption(runner->core, "mute", NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (guiKeys & (1 << mGUI_INPUT_MUTE_TOGGLE)) {
|
|
||||||
int mute = !runner->core->opts.mute;
|
|
||||||
mCoreConfigSetUIntValue(&runner->config, "mute", mute);
|
|
||||||
runner->core->reloadConfigOption(runner->core, "mute", &runner->config);
|
|
||||||
}
|
|
||||||
uint16_t keys = runner->pollGameInput(runner);
|
uint16_t keys = runner->pollGameInput(runner);
|
||||||
if (runner->prepareForFrame) {
|
if (runner->prepareForFrame) {
|
||||||
runner->prepareForFrame(runner);
|
runner->prepareForFrame(runner);
|
||||||
|
@ -600,8 +633,8 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
uint32_t keys = 0xFFFFFFFF; // Huge hack to avoid an extra variable!
|
uint32_t keys = 0xFFFFFFFF; // Huge hack to avoid an extra variable!
|
||||||
struct GUIMenuItem* item;
|
struct GUIMenuItem* item;
|
||||||
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &pauseMenu, &item);
|
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &pauseMenu, &item);
|
||||||
if (reason == GUI_MENU_EXIT_ACCEPT) {
|
if (reason == GUI_MENU_EXIT_ACCEPT && item->data.type == GUI_VARIANT_UNSIGNED) {
|
||||||
switch (((int) item->data) & RUNNER_COMMAND_MASK) {
|
switch (item->data.v.u & RUNNER_COMMAND_MASK) {
|
||||||
case RUNNER_EXIT:
|
case RUNNER_EXIT:
|
||||||
running = false;
|
running = false;
|
||||||
keys = 0;
|
keys = 0;
|
||||||
|
@ -610,10 +643,10 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
runner->core->reset(runner->core);
|
runner->core->reset(runner->core);
|
||||||
break;
|
break;
|
||||||
case RUNNER_SAVE_STATE:
|
case RUNNER_SAVE_STATE:
|
||||||
mCoreSaveState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_METADATA);
|
mCoreSaveState(runner->core, item->data.v.u >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_METADATA);
|
||||||
break;
|
break;
|
||||||
case RUNNER_LOAD_STATE:
|
case RUNNER_LOAD_STATE:
|
||||||
mCoreLoadState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_RTC);
|
mCoreLoadState(runner->core, item->data.v.u >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_RTC);
|
||||||
break;
|
break;
|
||||||
case RUNNER_SCREENSHOT:
|
case RUNNER_SCREENSHOT:
|
||||||
mCoreTakeScreenshot(runner->core);
|
mCoreTakeScreenshot(runner->core);
|
||||||
|
@ -651,6 +684,8 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
}
|
}
|
||||||
mCoreConfigGetIntValue(&runner->config, "fpsCounter", &drawFps);
|
mCoreConfigGetIntValue(&runner->config, "fpsCounter", &drawFps);
|
||||||
mCoreConfigGetIntValue(&runner->config, "showOSD", &showOSD);
|
mCoreConfigGetIntValue(&runner->config, "showOSD", &showOSD);
|
||||||
|
mCoreConfigGetIntValue(&runner->config, "mute", &mute);
|
||||||
|
mCoreConfigGetIntValue(&runner->config, "fastForwardMute", &fastForwardMute);
|
||||||
#ifdef M_CORE_GB
|
#ifdef M_CORE_GB
|
||||||
if (runner->core->platform(runner->core) == mPLATFORM_GB) {
|
if (runner->core->platform(runner->core) == mPLATFORM_GB) {
|
||||||
runner->core->reloadConfigOption(runner->core, "gb.pal", &runner->config);
|
runner->core->reloadConfigOption(runner->core, "gb.pal", &runner->config);
|
||||||
|
@ -676,10 +711,8 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
mLOG(GUI_RUNNER, DEBUG, "Unloading game...");
|
mLOG(GUI_RUNNER, DEBUG, "Unloading game...");
|
||||||
runner->core->unloadROM(runner->core);
|
runner->core->unloadROM(runner->core);
|
||||||
drawState.screenshotId = 0;
|
drawState.screenshotId = 0;
|
||||||
if (drawState.screenshot) {
|
if (drawState.image) {
|
||||||
unsigned w, h;
|
mappedMemoryFree(drawState.image, drawState.imageSize);
|
||||||
runner->core->desiredVideoDimensions(runner->core, &w, &h);
|
|
||||||
mappedMemoryFree(drawState.screenshot, w * h * 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runner->config.port) {
|
if (runner->config.port) {
|
||||||
|
|
|
@ -31,8 +31,10 @@ struct mGUIBackground {
|
||||||
struct GUIBackground d;
|
struct GUIBackground d;
|
||||||
struct mGUIRunner* p;
|
struct mGUIRunner* p;
|
||||||
|
|
||||||
color_t* screenshot;
|
color_t* image;
|
||||||
int screenshotId;
|
size_t imageSize;
|
||||||
|
|
||||||
|
unsigned screenshotId;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mCore;
|
struct mCore;
|
||||||
|
|
|
@ -21,12 +21,12 @@ void mGUIRemapKeys(struct GUIParams* params, struct mInputMap* map, const struct
|
||||||
size_t i;
|
size_t i;
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Game keys:",
|
.title = "Game keys:",
|
||||||
.data = 0,
|
.data = GUI_V_V,
|
||||||
};
|
};
|
||||||
for (i = 0; i < map->info->nKeys; ++i) {
|
for (i = 0; i < map->info->nKeys; ++i) {
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = map->info->keyId[i],
|
.title = map->info->keyId[i],
|
||||||
.data = (void*) (GUI_INPUT_MAX + i + 1),
|
.data = GUI_V_U(GUI_INPUT_MAX + i + 1),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = mInputQueryBinding(map, keys->id, i) + 1,
|
.state = mInputQueryBinding(map, keys->id, i) + 1,
|
||||||
.validStates = keyNames,
|
.validStates = keyNames,
|
||||||
|
@ -35,7 +35,7 @@ void mGUIRemapKeys(struct GUIParams* params, struct mInputMap* map, const struct
|
||||||
}
|
}
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Interface keys:",
|
.title = "Interface keys:",
|
||||||
.data = 0,
|
.data = GUI_V_V,
|
||||||
};
|
};
|
||||||
for (i = 0; i < params->keyMap.info->nKeys; ++i) {
|
for (i = 0; i < params->keyMap.info->nKeys; ++i) {
|
||||||
if (!params->keyMap.info->keyId[i]) {
|
if (!params->keyMap.info->keyId[i]) {
|
||||||
|
@ -43,7 +43,7 @@ void mGUIRemapKeys(struct GUIParams* params, struct mInputMap* map, const struct
|
||||||
}
|
}
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = params->keyMap.info->keyId[i],
|
.title = params->keyMap.info->keyId[i],
|
||||||
.data = (void*) i + 1,
|
.data = GUI_V_U(i + 1),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = mInputQueryBinding(¶ms->keyMap, keys->id, i) + 1,
|
.state = mInputQueryBinding(¶ms->keyMap, keys->id, i) + 1,
|
||||||
.validStates = keyNames,
|
.validStates = keyNames,
|
||||||
|
@ -52,30 +52,30 @@ void mGUIRemapKeys(struct GUIParams* params, struct mInputMap* map, const struct
|
||||||
}
|
}
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Save",
|
.title = "Save",
|
||||||
.data = (void*) (GUI_INPUT_MAX + map->info->nKeys + 2),
|
.data = GUI_V_I(-2),
|
||||||
};
|
};
|
||||||
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
*GUIMenuItemListAppend(&menu.items) = (struct GUIMenuItem) {
|
||||||
.title = "Cancel",
|
.title = "Cancel",
|
||||||
.data = 0,
|
.data = GUI_V_I(-1),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GUIMenuItem* item;
|
struct GUIMenuItem* item;
|
||||||
while (true) {
|
while (true) {
|
||||||
enum GUIMenuExitReason reason;
|
enum GUIMenuExitReason reason;
|
||||||
reason = GUIShowMenu(params, &menu, &item);
|
reason = GUIShowMenu(params, &menu, &item);
|
||||||
if (reason != GUI_MENU_EXIT_ACCEPT || !item->data) {
|
if (reason != GUI_MENU_EXIT_ACCEPT || GUIVariantCompareInt(item->data, -1)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (item->data == (void*) (GUI_INPUT_MAX + map->info->nKeys + 2)) {
|
if (GUIVariantCompareInt(item->data, -2)) {
|
||||||
for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) {
|
for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) {
|
||||||
item = GUIMenuItemListGetPointer(&menu.items, i);
|
item = GUIMenuItemListGetPointer(&menu.items, i);
|
||||||
if ((uintptr_t) item->data < 1) {
|
if (!GUIVariantIsUInt(item->data)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((uintptr_t) item->data < GUI_INPUT_MAX + 1) {
|
if (item->data.v.u < GUI_INPUT_MAX + 1) {
|
||||||
mInputBindKey(¶ms->keyMap, keys->id, item->state - 1, (uintptr_t) item->data - 1);
|
mInputBindKey(¶ms->keyMap, keys->id, item->state - 1, item->data.v.u - 1);
|
||||||
} else if ((uintptr_t) item->data < GUI_INPUT_MAX + map->info->nKeys + 1) {
|
} else if (item->data.v.u < GUI_INPUT_MAX + map->info->nKeys + 1) {
|
||||||
mInputBindKey(map, keys->id, item->state - 1, (uintptr_t) item->data - GUI_INPUT_MAX - 1);
|
mInputBindKey(map, keys->id, item->state - 1, item->data.v.u - GUI_INPUT_MAX - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -724,6 +724,7 @@ void GBIODeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
||||||
|
|
||||||
gb->audio.enable = GBAudioEnableGetEnable(*gb->audio.nr52);
|
gb->audio.enable = GBAudioEnableGetEnable(*gb->audio.nr52);
|
||||||
if (gb->audio.enable) {
|
if (gb->audio.enable) {
|
||||||
|
gb->audio.playingCh1 = false;
|
||||||
GBIOWrite(gb, GB_REG_NR10, gb->memory.io[GB_REG_NR10]);
|
GBIOWrite(gb, GB_REG_NR10, gb->memory.io[GB_REG_NR10]);
|
||||||
GBIOWrite(gb, GB_REG_NR11, gb->memory.io[GB_REG_NR11]);
|
GBIOWrite(gb, GB_REG_NR11, gb->memory.io[GB_REG_NR11]);
|
||||||
GBIOWrite(gb, GB_REG_NR12, gb->memory.io[GB_REG_NR12]);
|
GBIOWrite(gb, GB_REG_NR12, gb->memory.io[GB_REG_NR12]);
|
||||||
|
@ -731,12 +732,14 @@ void GBIODeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
||||||
gb->audio.ch1.control.frequency &= 0xFF;
|
gb->audio.ch1.control.frequency &= 0xFF;
|
||||||
gb->audio.ch1.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[GB_REG_NR14] << 8);
|
gb->audio.ch1.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[GB_REG_NR14] << 8);
|
||||||
gb->audio.ch1.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[GB_REG_NR14] << 8);
|
gb->audio.ch1.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[GB_REG_NR14] << 8);
|
||||||
|
gb->audio.playingCh2 = false;
|
||||||
GBIOWrite(gb, GB_REG_NR21, gb->memory.io[GB_REG_NR21]);
|
GBIOWrite(gb, GB_REG_NR21, gb->memory.io[GB_REG_NR21]);
|
||||||
GBIOWrite(gb, GB_REG_NR22, gb->memory.io[GB_REG_NR22]);
|
GBIOWrite(gb, GB_REG_NR22, gb->memory.io[GB_REG_NR22]);
|
||||||
GBIOWrite(gb, GB_REG_NR23, gb->memory.io[GB_REG_NR23]);
|
GBIOWrite(gb, GB_REG_NR23, gb->memory.io[GB_REG_NR23]);
|
||||||
gb->audio.ch2.control.frequency &= 0xFF;
|
gb->audio.ch2.control.frequency &= 0xFF;
|
||||||
gb->audio.ch2.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[GB_REG_NR24] << 8);
|
gb->audio.ch2.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[GB_REG_NR24] << 8);
|
||||||
gb->audio.ch2.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[GB_REG_NR24] << 8);
|
gb->audio.ch2.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[GB_REG_NR24] << 8);
|
||||||
|
gb->audio.playingCh3 = false;
|
||||||
GBIOWrite(gb, GB_REG_NR30, gb->memory.io[GB_REG_NR30]);
|
GBIOWrite(gb, GB_REG_NR30, gb->memory.io[GB_REG_NR30]);
|
||||||
GBIOWrite(gb, GB_REG_NR31, gb->memory.io[GB_REG_NR31]);
|
GBIOWrite(gb, GB_REG_NR31, gb->memory.io[GB_REG_NR31]);
|
||||||
GBIOWrite(gb, GB_REG_NR32, gb->memory.io[GB_REG_NR32]);
|
GBIOWrite(gb, GB_REG_NR32, gb->memory.io[GB_REG_NR32]);
|
||||||
|
@ -744,6 +747,7 @@ void GBIODeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
||||||
gb->audio.ch3.rate &= 0xFF;
|
gb->audio.ch3.rate &= 0xFF;
|
||||||
gb->audio.ch3.rate |= GBAudioRegisterControlGetRate(gb->memory.io[GB_REG_NR34] << 8);
|
gb->audio.ch3.rate |= GBAudioRegisterControlGetRate(gb->memory.io[GB_REG_NR34] << 8);
|
||||||
gb->audio.ch3.stop = GBAudioRegisterControlGetStop(gb->memory.io[GB_REG_NR34] << 8);
|
gb->audio.ch3.stop = GBAudioRegisterControlGetStop(gb->memory.io[GB_REG_NR34] << 8);
|
||||||
|
gb->audio.playingCh4 = false;
|
||||||
GBIOWrite(gb, GB_REG_NR41, gb->memory.io[GB_REG_NR41]);
|
GBIOWrite(gb, GB_REG_NR41, gb->memory.io[GB_REG_NR41]);
|
||||||
GBIOWrite(gb, GB_REG_NR42, gb->memory.io[GB_REG_NR42]);
|
GBIOWrite(gb, GB_REG_NR42, gb->memory.io[GB_REG_NR42]);
|
||||||
GBIOWrite(gb, GB_REG_NR43, gb->memory.io[GB_REG_NR43]);
|
GBIOWrite(gb, GB_REG_NR43, gb->memory.io[GB_REG_NR43]);
|
||||||
|
|
|
@ -322,6 +322,7 @@ void GBMBCInit(struct GB* gb) {
|
||||||
}
|
}
|
||||||
gb->memory.mbcRead = NULL;
|
gb->memory.mbcRead = NULL;
|
||||||
gb->memory.directSramAccess = true;
|
gb->memory.directSramAccess = true;
|
||||||
|
gb->memory.cartBusDecay = 4;
|
||||||
switch (gb->memory.mbcType) {
|
switch (gb->memory.mbcType) {
|
||||||
case GB_MBC_NONE:
|
case GB_MBC_NONE:
|
||||||
gb->memory.mbcWrite = _GBMBCNone;
|
gb->memory.mbcWrite = _GBMBCNone;
|
||||||
|
@ -442,6 +443,9 @@ void GBMBCInit(struct GB* gb) {
|
||||||
void GBMBCReset(struct GB* gb) {
|
void GBMBCReset(struct GB* gb) {
|
||||||
gb->memory.currentBank0 = 0;
|
gb->memory.currentBank0 = 0;
|
||||||
gb->memory.romBank = &gb->memory.rom[GB_SIZE_CART_BANK0];
|
gb->memory.romBank = &gb->memory.rom[GB_SIZE_CART_BANK0];
|
||||||
|
gb->memory.cartBus = 0xFF;
|
||||||
|
gb->memory.cartBusPc = 0;
|
||||||
|
gb->memory.cartBusDecay = 1;
|
||||||
|
|
||||||
memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState));
|
memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState));
|
||||||
GBMBCInit(gb);
|
GBMBCInit(gb);
|
||||||
|
|
|
@ -51,12 +51,17 @@ static const uint8_t _blockedRegion[1] = { 0xFF };
|
||||||
|
|
||||||
static void _pristineCow(struct GB* gba);
|
static void _pristineCow(struct GB* gba);
|
||||||
|
|
||||||
static uint8_t GBFastLoad8(struct SM83Core* cpu, uint16_t address) {
|
static uint8_t GBCartLoad8(struct SM83Core* cpu, uint16_t address) {
|
||||||
if (UNLIKELY(address >= cpu->memory.activeRegionEnd)) {
|
if (UNLIKELY(address >= cpu->memory.activeRegionEnd)) {
|
||||||
cpu->memory.setActiveRegion(cpu, address);
|
cpu->memory.setActiveRegion(cpu, address);
|
||||||
return cpu->memory.cpuLoad8(cpu, address);
|
return cpu->memory.cpuLoad8(cpu, address);
|
||||||
}
|
}
|
||||||
return cpu->memory.activeRegion[address & cpu->memory.activeMask];
|
struct GB* gb = (struct GB*) cpu->master;
|
||||||
|
struct GBMemory* memory = &gb->memory;
|
||||||
|
memory->cartBusPc = address;
|
||||||
|
uint8_t value = cpu->memory.activeRegion[address & cpu->memory.activeMask];
|
||||||
|
memory->cartBus = value;
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBSetActiveRegion(struct SM83Core* cpu, uint16_t address) {
|
static void GBSetActiveRegion(struct SM83Core* cpu, uint16_t address) {
|
||||||
|
@ -67,7 +72,7 @@ static void GBSetActiveRegion(struct SM83Core* cpu, uint16_t address) {
|
||||||
case GB_REGION_CART_BANK0 + 1:
|
case GB_REGION_CART_BANK0 + 1:
|
||||||
case GB_REGION_CART_BANK0 + 2:
|
case GB_REGION_CART_BANK0 + 2:
|
||||||
case GB_REGION_CART_BANK0 + 3:
|
case GB_REGION_CART_BANK0 + 3:
|
||||||
cpu->memory.cpuLoad8 = GBFastLoad8;
|
cpu->memory.cpuLoad8 = GBCartLoad8;
|
||||||
cpu->memory.activeRegion = memory->romBase;
|
cpu->memory.activeRegion = memory->romBase;
|
||||||
cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1;
|
cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1;
|
||||||
cpu->memory.activeMask = GB_SIZE_CART_BANK0 - 1;
|
cpu->memory.activeMask = GB_SIZE_CART_BANK0 - 1;
|
||||||
|
@ -88,7 +93,7 @@ static void GBSetActiveRegion(struct SM83Core* cpu, uint16_t address) {
|
||||||
cpu->memory.cpuLoad8 = GBLoad8;
|
cpu->memory.cpuLoad8 = GBLoad8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cpu->memory.cpuLoad8 = GBFastLoad8;
|
cpu->memory.cpuLoad8 = GBCartLoad8;
|
||||||
if (gb->memory.mbcType != GB_MBC6) {
|
if (gb->memory.mbcType != GB_MBC6) {
|
||||||
cpu->memory.activeRegion = memory->romBank;
|
cpu->memory.activeRegion = memory->romBank;
|
||||||
cpu->memory.activeRegionEnd = GB_BASE_VRAM;
|
cpu->memory.activeRegionEnd = GB_BASE_VRAM;
|
||||||
|
@ -238,24 +243,31 @@ uint8_t GBLoad8(struct SM83Core* cpu, uint16_t address) {
|
||||||
case GB_REGION_CART_BANK0 + 2:
|
case GB_REGION_CART_BANK0 + 2:
|
||||||
case GB_REGION_CART_BANK0 + 3:
|
case GB_REGION_CART_BANK0 + 3:
|
||||||
if (address >= memory->romSize) {
|
if (address >= memory->romSize) {
|
||||||
return 0xFF;
|
memory->cartBus = 0xFF;
|
||||||
|
} else {
|
||||||
|
memory->cartBus = memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)];
|
||||||
}
|
}
|
||||||
return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)];
|
memory->cartBusPc = cpu->pc;
|
||||||
|
return memory->cartBus;
|
||||||
case GB_REGION_CART_BANK1 + 2:
|
case GB_REGION_CART_BANK1 + 2:
|
||||||
case GB_REGION_CART_BANK1 + 3:
|
case GB_REGION_CART_BANK1 + 3:
|
||||||
if (memory->mbcType == GB_MBC6) {
|
if (memory->mbcType == GB_MBC6) {
|
||||||
return memory->mbcState.mbc6.romBank1[address & (GB_SIZE_CART_HALFBANK - 1)];
|
memory->cartBus = memory->mbcState.mbc6.romBank1[address & (GB_SIZE_CART_HALFBANK - 1)];
|
||||||
|
memory->cartBusPc = cpu->pc;
|
||||||
|
return memory->cartBus;
|
||||||
}
|
}
|
||||||
// Fall through
|
// Fall through
|
||||||
case GB_REGION_CART_BANK1:
|
case GB_REGION_CART_BANK1:
|
||||||
case GB_REGION_CART_BANK1 + 1:
|
case GB_REGION_CART_BANK1 + 1:
|
||||||
if (address >= memory->romSize) {
|
if (address >= memory->romSize) {
|
||||||
return 0xFF;
|
memory->cartBus = 0xFF;
|
||||||
|
} else if ((memory->mbcType & GB_UNL_BBD) == GB_UNL_BBD) {
|
||||||
|
memory->cartBus = memory->mbcRead(memory, address);
|
||||||
|
} else {
|
||||||
|
memory->cartBus = memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
|
||||||
}
|
}
|
||||||
if ((memory->mbcType & GB_UNL_BBD) == GB_UNL_BBD) {
|
memory->cartBusPc = cpu->pc;
|
||||||
return memory->mbcRead(memory, address);
|
return memory->cartBus;
|
||||||
}
|
|
||||||
return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
|
|
||||||
case GB_REGION_VRAM:
|
case GB_REGION_VRAM:
|
||||||
case GB_REGION_VRAM + 1:
|
case GB_REGION_VRAM + 1:
|
||||||
if (gb->video.mode != 3) {
|
if (gb->video.mode != 3) {
|
||||||
|
@ -265,15 +277,18 @@ uint8_t GBLoad8(struct SM83Core* cpu, uint16_t address) {
|
||||||
case GB_REGION_EXTERNAL_RAM:
|
case GB_REGION_EXTERNAL_RAM:
|
||||||
case GB_REGION_EXTERNAL_RAM + 1:
|
case GB_REGION_EXTERNAL_RAM + 1:
|
||||||
if (memory->rtcAccess) {
|
if (memory->rtcAccess) {
|
||||||
return memory->rtcRegs[memory->activeRtcReg];
|
memory->cartBus = memory->rtcRegs[memory->activeRtcReg];
|
||||||
} else if (memory->mbcRead) {
|
} else if (memory->mbcRead) {
|
||||||
return memory->mbcRead(memory, address);
|
memory->cartBus = memory->mbcRead(memory, address);
|
||||||
} else if (memory->sramAccess && memory->sram) {
|
} else if (memory->sramAccess && memory->sram) {
|
||||||
return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
|
memory->cartBus = memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
|
||||||
} else if (memory->mbcType == GB_HuC3) {
|
} else if (memory->mbcType == GB_HuC3) {
|
||||||
return 0x01; // TODO: Is this supposed to be the current SRAM bank?
|
memory->cartBus = 0x01; // TODO: Is this supposed to be the current SRAM bank?
|
||||||
|
} else if (cpu->tMultiplier * (cpu->pc - memory->cartBusPc) >= memory->cartBusDecay) {
|
||||||
|
memory->cartBus = 0xFF;
|
||||||
}
|
}
|
||||||
return 0xFF;
|
memory->cartBusPc = cpu->pc;
|
||||||
|
return memory->cartBus;
|
||||||
case GB_REGION_WORKING_RAM_BANK0:
|
case GB_REGION_WORKING_RAM_BANK0:
|
||||||
case GB_REGION_WORKING_RAM_BANK0 + 2:
|
case GB_REGION_WORKING_RAM_BANK0 + 2:
|
||||||
return memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
|
return memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
|
||||||
|
@ -705,6 +720,9 @@ void GBMemorySerialize(const struct GB* gb, struct GBSerializedState* state) {
|
||||||
flags = GBSerializedMemoryFlagsSetActiveRtcReg(flags, memory->activeRtcReg);
|
flags = GBSerializedMemoryFlagsSetActiveRtcReg(flags, memory->activeRtcReg);
|
||||||
STORE_16LE(flags, 0, &state->memory.flags);
|
STORE_16LE(flags, 0, &state->memory.flags);
|
||||||
|
|
||||||
|
state->memory.cartBus = memory->cartBus;
|
||||||
|
STORE_16LE(memory->cartBusPc, 0, &state->cartBusPc);
|
||||||
|
|
||||||
switch (memory->mbcType) {
|
switch (memory->mbcType) {
|
||||||
case GB_MBC1:
|
case GB_MBC1:
|
||||||
state->memory.mbc1.mode = memory->mbcState.mbc1.mode;
|
state->memory.mbc1.mode = memory->mbcState.mbc1.mode;
|
||||||
|
@ -784,6 +802,9 @@ void GBMemoryDeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
||||||
memory->isHdma = GBSerializedMemoryFlagsGetIsHdma(flags);
|
memory->isHdma = GBSerializedMemoryFlagsGetIsHdma(flags);
|
||||||
memory->activeRtcReg = GBSerializedMemoryFlagsGetActiveRtcReg(flags);
|
memory->activeRtcReg = GBSerializedMemoryFlagsGetActiveRtcReg(flags);
|
||||||
|
|
||||||
|
memory->cartBus = state->memory.cartBus;
|
||||||
|
LOAD_16LE(memory->cartBusPc, 0, &state->cartBusPc);
|
||||||
|
|
||||||
switch (memory->mbcType) {
|
switch (memory->mbcType) {
|
||||||
case GB_MBC1:
|
case GB_MBC1:
|
||||||
memory->mbcState.mbc1.mode = state->memory.mbc1.mode;
|
memory->mbcState.mbc1.mode = state->memory.mbc1.mode;
|
||||||
|
|
|
@ -265,8 +265,10 @@ void GBASkipBIOS(struct GBA* gba) {
|
||||||
} else {
|
} else {
|
||||||
cpu->gprs[ARM_PC] = BASE_WORKING_RAM + 0xC0;
|
cpu->gprs[ARM_PC] = BASE_WORKING_RAM + 0xC0;
|
||||||
}
|
}
|
||||||
gba->video.vcount = 0x7D;
|
gba->video.vcount = 0x7E;
|
||||||
gba->memory.io[REG_VCOUNT >> 1] = 0x7D;
|
gba->memory.io[REG_VCOUNT >> 1] = 0x7E;
|
||||||
|
mTimingDeschedule(&gba->timing, &gba->video.event);
|
||||||
|
mTimingSchedule(&gba->timing, &gba->video.event, 117);
|
||||||
gba->memory.io[REG_POSTFLG >> 1] = 1;
|
gba->memory.io[REG_POSTFLG >> 1] = 1;
|
||||||
ARMWritePC(cpu);
|
ARMWritePC(cpu);
|
||||||
}
|
}
|
||||||
|
|
|
@ -973,6 +973,8 @@ void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||||
|
GBAAudioWriteSOUNDCNT_X(&gba->audio, state->io[REG_SOUNDCNT_X >> 1]);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < REG_MAX; i += 2) {
|
for (i = 0; i < REG_MAX; i += 2) {
|
||||||
if (_isWSpecialRegister[i >> 1]) {
|
if (_isWSpecialRegister[i >> 1]) {
|
||||||
|
@ -1003,7 +1005,6 @@ void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||||
LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
|
LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
|
||||||
LOAD_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
|
LOAD_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
|
||||||
}
|
}
|
||||||
GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
|
|
||||||
gba->sio.siocnt = gba->memory.io[REG_SIOCNT >> 1];
|
gba->sio.siocnt = gba->memory.io[REG_SIOCNT >> 1];
|
||||||
GBASIOWriteRCNT(&gba->sio, gba->memory.io[REG_RCNT >> 1]);
|
GBASIOWriteRCNT(&gba->sio, gba->memory.io[REG_RCNT >> 1]);
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,7 @@ void GBAMemoryReset(struct GBA* gba) {
|
||||||
memset(gba->memory.io, 0, sizeof(gba->memory.io));
|
memset(gba->memory.io, 0, sizeof(gba->memory.io));
|
||||||
GBAAdjustWaitstates(gba, 0);
|
GBAAdjustWaitstates(gba, 0);
|
||||||
|
|
||||||
|
gba->memory.activeRegion = -1;
|
||||||
gba->memory.agbPrintProtect = 0;
|
gba->memory.agbPrintProtect = 0;
|
||||||
gba->memory.agbPrintBase = 0;
|
gba->memory.agbPrintBase = 0;
|
||||||
memset(&gba->memory.agbPrintCtx, 0, sizeof(gba->memory.agbPrintCtx));
|
memset(&gba->memory.agbPrintCtx, 0, sizeof(gba->memory.agbPrintCtx));
|
||||||
|
@ -266,6 +267,11 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
|
||||||
gba->lastJump = address;
|
gba->lastJump = address;
|
||||||
memory->lastPrefetchedPc = 0;
|
memory->lastPrefetchedPc = 0;
|
||||||
if (newRegion == memory->activeRegion) {
|
if (newRegion == memory->activeRegion) {
|
||||||
|
if (cpu->cpsr.t) {
|
||||||
|
cpu->memory.activeMask |= WORD_SIZE_THUMB;
|
||||||
|
} else {
|
||||||
|
cpu->memory.activeMask &= -WORD_SIZE_ARM;
|
||||||
|
}
|
||||||
if (newRegion < REGION_CART0 || (address & (SIZE_CART0 - 1)) < memory->romSize) {
|
if (newRegion < REGION_CART0 || (address & (SIZE_CART0 - 1)) < memory->romSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -717,6 +723,8 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
value = GBASavedataReadFlash(&memory->savedata, address);
|
value = GBASavedataReadFlash(&memory->savedata, address);
|
||||||
} else if (memory->hw.devices & HW_TILT) {
|
} else if (memory->hw.devices & HW_TILT) {
|
||||||
value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK);
|
value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK);
|
||||||
|
} else if (memory->savedata.type == SAVEDATA_SRAM512) {
|
||||||
|
value = memory->savedata.data[address & (SIZE_CART_SRAM512 - 1)];
|
||||||
} else {
|
} else {
|
||||||
mLOG(GBA_MEM, GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
|
mLOG(GBA_MEM, GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
|
||||||
value = 0xFF;
|
value = 0xFF;
|
||||||
|
@ -1070,6 +1078,9 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
|
||||||
memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
|
memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
|
||||||
} else if (memory->hw.devices & HW_TILT) {
|
} else if (memory->hw.devices & HW_TILT) {
|
||||||
GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
|
GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
|
||||||
|
} else if (memory->savedata.type == SAVEDATA_SRAM512) {
|
||||||
|
memory->savedata.data[address & (SIZE_CART_SRAM512 - 1)] = value;
|
||||||
|
memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
|
||||||
} else {
|
} else {
|
||||||
mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
|
mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,9 @@ bool GBAOverrideFind(const struct Configuration* config, struct GBACartridgeOver
|
||||||
if (strcasecmp(savetype, "SRAM") == 0) {
|
if (strcasecmp(savetype, "SRAM") == 0) {
|
||||||
found = true;
|
found = true;
|
||||||
override->savetype = SAVEDATA_SRAM;
|
override->savetype = SAVEDATA_SRAM;
|
||||||
|
} else if (strcasecmp(savetype, "SRAM512") == 0) {
|
||||||
|
found = true;
|
||||||
|
override->savetype = SAVEDATA_SRAM512;
|
||||||
} else if (strcasecmp(savetype, "EEPROM") == 0) {
|
} else if (strcasecmp(savetype, "EEPROM") == 0) {
|
||||||
found = true;
|
found = true;
|
||||||
override->savetype = SAVEDATA_EEPROM;
|
override->savetype = SAVEDATA_EEPROM;
|
||||||
|
@ -288,6 +291,9 @@ void GBAOverrideSave(struct Configuration* config, const struct GBACartridgeOver
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
savetype = "SRAM";
|
savetype = "SRAM";
|
||||||
break;
|
break;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
savetype = "SRAM512";
|
||||||
|
break;
|
||||||
case SAVEDATA_EEPROM:
|
case SAVEDATA_EEPROM:
|
||||||
savetype = "EEPROM";
|
savetype = "EEPROM";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -68,6 +68,9 @@ void GBASavedataDeinit(struct GBASavedata* savedata) {
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
|
mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
|
||||||
break;
|
break;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
mappedMemoryFree(savedata->data, SIZE_CART_SRAM512);
|
||||||
|
break;
|
||||||
case SAVEDATA_FLASH512:
|
case SAVEDATA_FLASH512:
|
||||||
mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
|
mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
|
||||||
break;
|
break;
|
||||||
|
@ -124,6 +127,8 @@ bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
|
||||||
switch (savedata->type) {
|
switch (savedata->type) {
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
return out->write(out, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
|
return out->write(out, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
return out->write(out, savedata->data, SIZE_CART_SRAM512) == SIZE_CART_SRAM512;
|
||||||
case SAVEDATA_FLASH512:
|
case SAVEDATA_FLASH512:
|
||||||
return out->write(out, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
|
return out->write(out, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
|
||||||
case SAVEDATA_FLASH1M:
|
case SAVEDATA_FLASH1M:
|
||||||
|
@ -153,6 +158,8 @@ size_t GBASavedataSize(const struct GBASavedata* savedata) {
|
||||||
switch (savedata->type) {
|
switch (savedata->type) {
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
return SIZE_CART_SRAM;
|
return SIZE_CART_SRAM;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
return SIZE_CART_SRAM512;
|
||||||
case SAVEDATA_FLASH512:
|
case SAVEDATA_FLASH512:
|
||||||
return SIZE_CART_FLASH512;
|
return SIZE_CART_FLASH512;
|
||||||
case SAVEDATA_FLASH1M:
|
case SAVEDATA_FLASH1M:
|
||||||
|
@ -233,6 +240,9 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type)
|
||||||
case SAVEDATA_SRAM:
|
case SAVEDATA_SRAM:
|
||||||
GBASavedataInitSRAM(savedata);
|
GBASavedataInitSRAM(savedata);
|
||||||
break;
|
break;
|
||||||
|
case SAVEDATA_SRAM512:
|
||||||
|
GBASavedataInitSRAM512(savedata);
|
||||||
|
break;
|
||||||
case SAVEDATA_FORCE_NONE:
|
case SAVEDATA_FORCE_NONE:
|
||||||
savedata->type = SAVEDATA_FORCE_NONE;
|
savedata->type = SAVEDATA_FORCE_NONE;
|
||||||
break;
|
break;
|
||||||
|
@ -322,6 +332,30 @@ void GBASavedataInitSRAM(struct GBASavedata* savedata) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GBASavedataInitSRAM512(struct GBASavedata* savedata) {
|
||||||
|
if (savedata->type == SAVEDATA_AUTODETECT) {
|
||||||
|
savedata->type = SAVEDATA_SRAM512;
|
||||||
|
} else {
|
||||||
|
mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
off_t end;
|
||||||
|
if (!savedata->vf) {
|
||||||
|
end = 0;
|
||||||
|
savedata->data = anonymousMemoryMap(SIZE_CART_SRAM512);
|
||||||
|
} else {
|
||||||
|
end = savedata->vf->size(savedata->vf);
|
||||||
|
if (end < SIZE_CART_SRAM512) {
|
||||||
|
savedata->vf->truncate(savedata->vf, SIZE_CART_SRAM512);
|
||||||
|
}
|
||||||
|
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_SRAM512, savedata->mapMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end < SIZE_CART_SRAM512) {
|
||||||
|
memset(&savedata->data[end], 0xFF, SIZE_CART_SRAM512 - end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) {
|
uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) {
|
||||||
if (savedata->command == FLASH_COMMAND_ID) {
|
if (savedata->command == FLASH_COMMAND_ID) {
|
||||||
if (savedata->type == SAVEDATA_FLASH512) {
|
if (savedata->type == SAVEDATA_FLASH512) {
|
||||||
|
|
|
@ -158,6 +158,7 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||||
mLOG(GBA_STATE, WARN, "Savestate has unaligned PC and is probably corrupted");
|
mLOG(GBA_STATE, WARN, "Savestate has unaligned PC and is probably corrupted");
|
||||||
gba->cpu->gprs[ARM_PC] &= ~1;
|
gba->cpu->gprs[ARM_PC] &= ~1;
|
||||||
}
|
}
|
||||||
|
gba->memory.activeRegion = -1;
|
||||||
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
||||||
if (state->biosPrefetch) {
|
if (state->biosPrefetch) {
|
||||||
LOAD_32(gba->memory.biosPrefetch, 0, &state->biosPrefetch);
|
LOAD_32(gba->memory.biosPrefetch, 0, &state->biosPrefetch);
|
||||||
|
|
|
@ -141,6 +141,7 @@ bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver) {
|
||||||
case SIO_MULTI:
|
case SIO_MULTI:
|
||||||
ATOMIC_SUB(node->p->attachedMulti, 1);
|
ATOMIC_SUB(node->p->attachedMulti, 1);
|
||||||
break;
|
break;
|
||||||
|
case SIO_NORMAL_8:
|
||||||
case SIO_NORMAL_32:
|
case SIO_NORMAL_32:
|
||||||
ATOMIC_SUB(node->p->attachedNormal, 1);
|
ATOMIC_SUB(node->p->attachedNormal, 1);
|
||||||
break;
|
break;
|
||||||
|
@ -179,10 +180,14 @@ static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver
|
||||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value);
|
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value);
|
||||||
|
|
||||||
enum mLockstepPhase transferActive;
|
enum mLockstepPhase transferActive;
|
||||||
|
int attached;
|
||||||
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
|
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
|
||||||
|
ATOMIC_LOAD(attached, node->p->d.attached);
|
||||||
|
|
||||||
|
driver->p->siocnt = GBASIOMultiplayerSetSlave(driver->p->siocnt, node->id || attached < 2);
|
||||||
|
|
||||||
if (value & 0x0080 && transferActive == TRANSFER_IDLE) {
|
if (value & 0x0080 && transferActive == TRANSFER_IDLE) {
|
||||||
if (!node->id && GBASIOMultiplayerIsReady(node->d.p->siocnt)) {
|
if (!node->id && attached > 1 && GBASIOMultiplayerIsReady(node->d.p->siocnt)) {
|
||||||
mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id);
|
mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id);
|
||||||
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
|
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
|
||||||
ATOMIC_STORE(node->p->d.transferCycles, GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][node->p->d.attached - 1]);
|
ATOMIC_STORE(node->p->d.transferCycles, GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][node->p->d.attached - 1]);
|
||||||
|
@ -442,11 +447,22 @@ static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* user,
|
||||||
struct GBASIOLockstepNode* node = user;
|
struct GBASIOLockstepNode* node = user;
|
||||||
mLockstepLock(&node->p->d);
|
mLockstepLock(&node->p->d);
|
||||||
|
|
||||||
int32_t cycles = 0;
|
int32_t cycles = cycles = node->nextEvent;
|
||||||
node->nextEvent -= cyclesLate;
|
node->nextEvent -= cyclesLate;
|
||||||
node->eventDiff += cyclesLate;
|
node->eventDiff += cyclesLate;
|
||||||
if (node->p->d.attached < 2) {
|
if (node->p->d.attached < 2) {
|
||||||
cycles = GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][0];
|
switch (node->mode) {
|
||||||
|
case SIO_MULTI:
|
||||||
|
cycles = GBASIOCyclesPerTransfer[GBASIOMultiplayerGetBaud(node->d.p->siocnt)][0];
|
||||||
|
break;
|
||||||
|
case SIO_NORMAL_8:
|
||||||
|
case SIO_NORMAL_32:
|
||||||
|
if (node->nextEvent <= 0) {
|
||||||
|
cycles = _masterUpdate(node);
|
||||||
|
node->eventDiff = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else if (node->nextEvent <= 0) {
|
} else if (node->nextEvent <= 0) {
|
||||||
if (!node->id) {
|
if (!node->id) {
|
||||||
cycles = _masterUpdate(node);
|
cycles = _masterUpdate(node);
|
||||||
|
@ -455,8 +471,6 @@ static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* user,
|
||||||
cycles += node->p->d.useCycles(&node->p->d, node->id, node->eventDiff);
|
cycles += node->p->d.useCycles(&node->p->d, node->id, node->eventDiff);
|
||||||
}
|
}
|
||||||
node->eventDiff = 0;
|
node->eventDiff = 0;
|
||||||
} else {
|
|
||||||
cycles = node->nextEvent;
|
|
||||||
}
|
}
|
||||||
if (cycles > 0) {
|
if (cycles > 0) {
|
||||||
node->nextEvent = 0;
|
node->nextEvent = 0;
|
||||||
|
|
|
@ -72,7 +72,7 @@ void GBAVideoReset(struct GBAVideo* video) {
|
||||||
} else {
|
} else {
|
||||||
// TODO: Verify exact scanline on hardware
|
// TODO: Verify exact scanline on hardware
|
||||||
video->vcount = 0x7E;
|
video->vcount = 0x7E;
|
||||||
nextEvent = 170;
|
nextEvent = 117;
|
||||||
}
|
}
|
||||||
video->p->memory.io[REG_VCOUNT >> 1] = video->vcount;
|
video->p->memory.io[REG_VCOUNT >> 1] = video->vcount;
|
||||||
|
|
||||||
|
|
|
@ -954,7 +954,7 @@ int main() {
|
||||||
.configExtra = (struct GUIMenuItem[]) {
|
.configExtra = (struct GUIMenuItem[]) {
|
||||||
{
|
{
|
||||||
.title = "Screen mode",
|
.title = "Screen mode",
|
||||||
.data = "screenMode",
|
.data = GUI_V_S("screenMode"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = SM_PA_TOP,
|
.state = SM_PA_TOP,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -969,7 +969,7 @@ int main() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Filtering",
|
.title = "Filtering",
|
||||||
.data = "filterMode",
|
.data = GUI_V_S("filterMode"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = FM_LINEAR_2x,
|
.state = FM_LINEAR_2x,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -981,7 +981,7 @@ int main() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Screen darkening",
|
.title = "Screen darkening",
|
||||||
.data = "darkenMode",
|
.data = GUI_V_S("darkenMode"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = DM_NATIVE,
|
.state = DM_NATIVE,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -994,7 +994,7 @@ int main() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Camera",
|
.title = "Camera",
|
||||||
.data = "camera",
|
.data = GUI_V_S("camera"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 1,
|
.state = 1,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <mgba/gb/core.h>
|
#include <mgba/gb/core.h>
|
||||||
#include <mgba/internal/gb/gb.h>
|
#include <mgba/internal/gb/gb.h>
|
||||||
#include <mgba/internal/gb/mbc.h>
|
#include <mgba/internal/gb/mbc.h>
|
||||||
|
#include <mgba/internal/gb/overrides.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
#include <mgba/gba/core.h>
|
#include <mgba/gba/core.h>
|
||||||
|
@ -146,6 +147,38 @@ static void _initRumble(void) {
|
||||||
rumbleInitDone = true;
|
rumbleInitDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef M_CORE_GB
|
||||||
|
static void _updateGbPal(void) {
|
||||||
|
struct retro_variable var;
|
||||||
|
var.key = "mgba_gb_colors";
|
||||||
|
var.value = 0;
|
||||||
|
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||||
|
const struct GBColorPreset* presets;
|
||||||
|
size_t listSize = GBColorPresetList(&presets);
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < listSize; ++i) {
|
||||||
|
if (strcmp(presets[i].name, var.value) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[0]", presets[i].colors[0] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[1]", presets[i].colors[1] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[2]", presets[i].colors[2] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[3]", presets[i].colors[3] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[4]", presets[i].colors[4] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[5]", presets[i].colors[5] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[6]", presets[i].colors[6] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[7]", presets[i].colors[7] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[8]", presets[i].colors[8] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[9]", presets[i].colors[9] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[10]", presets[i].colors[10] & 0xFFFFFF);
|
||||||
|
mCoreConfigSetUIntValue(&core->config, "gb.pal[11]", presets[i].colors[11] & 0xFFFFFF);
|
||||||
|
core->reloadConfigOption(core, "gb.pal", NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void _reloadSettings(void) {
|
static void _reloadSettings(void) {
|
||||||
struct mCoreOptions opts = {
|
struct mCoreOptions opts = {
|
||||||
.useBios = true,
|
.useBios = true,
|
||||||
|
@ -177,6 +210,14 @@ static void _reloadSettings(void) {
|
||||||
mCoreConfigSetDefaultValue(&core->config, "sgb.model", modelName);
|
mCoreConfigSetDefaultValue(&core->config, "sgb.model", modelName);
|
||||||
mCoreConfigSetDefaultValue(&core->config, "cgb.model", modelName);
|
mCoreConfigSetDefaultValue(&core->config, "cgb.model", modelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var.key = "mgba_sgb_borders";
|
||||||
|
var.value = 0;
|
||||||
|
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||||
|
mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", strcmp(var.value, "ON") == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateGbPal();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var.key = "mgba_use_bios";
|
var.key = "mgba_use_bios";
|
||||||
|
@ -191,14 +232,6 @@ static void _reloadSettings(void) {
|
||||||
opts.skipBios = strcmp(var.value, "ON") == 0;
|
opts.skipBios = strcmp(var.value, "ON") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef M_CORE_GB
|
|
||||||
var.key = "mgba_sgb_borders";
|
|
||||||
var.value = 0;
|
|
||||||
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
|
||||||
mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", strcmp(var.value, "ON") == 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var.key = "mgba_frameskip";
|
var.key = "mgba_frameskip";
|
||||||
var.value = 0;
|
var.value = 0;
|
||||||
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||||
|
@ -248,6 +281,22 @@ unsigned retro_api_version(void) {
|
||||||
void retro_set_environment(retro_environment_t env) {
|
void retro_set_environment(retro_environment_t env) {
|
||||||
environCallback = env;
|
environCallback = env;
|
||||||
|
|
||||||
|
#ifdef M_CORE_GB
|
||||||
|
const struct GBColorPreset* presets;
|
||||||
|
size_t listSize = GBColorPresetList(&presets);
|
||||||
|
|
||||||
|
size_t colorOpt;
|
||||||
|
for (colorOpt = 0; option_defs_us[colorOpt].key; ++colorOpt) {
|
||||||
|
if (strcmp(option_defs_us[colorOpt].key, "mgba_gb_colors") == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < listSize && i < RETRO_NUM_CORE_OPTION_VALUES_MAX; ++i) {
|
||||||
|
option_defs_us[colorOpt].values[i].value = presets[i].name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
libretro_set_core_options(environCallback);
|
libretro_set_core_options(environCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,6 +478,10 @@ void retro_run(void) {
|
||||||
mCoreConfigSetIntValue(&core->config, "frameskip", strtol(var.value, NULL, 10));
|
mCoreConfigSetIntValue(&core->config, "frameskip", strtol(var.value, NULL, 10));
|
||||||
core->reloadConfigOption(core, "frameskip", NULL);
|
core->reloadConfigOption(core, "frameskip", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef M_CORE_GB
|
||||||
|
_updateGbPal();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
keys = 0;
|
keys = 0;
|
||||||
|
|
|
@ -186,6 +186,17 @@ struct retro_core_option_definition option_defs_us[] = {
|
||||||
},
|
},
|
||||||
"OFF"
|
"OFF"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"mgba_gb_colors",
|
||||||
|
"Set default Game Boy palette",
|
||||||
|
"Selects which palette is used for Game Boy games that are not Game Boy Color or Super Game Boy compatible, or if the model is forced to Game Boy.",
|
||||||
|
{
|
||||||
|
// This list is populated at runtime
|
||||||
|
{ "Grayscale", NULL },
|
||||||
|
{ NULL, NULL },
|
||||||
|
},
|
||||||
|
"Grayscale"
|
||||||
|
},
|
||||||
{ NULL, NULL, NULL, {{0}}, NULL },
|
{ NULL, NULL, NULL, {{0}}, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ int main() {
|
||||||
.configExtra = (struct GUIMenuItem[]) {
|
.configExtra = (struct GUIMenuItem[]) {
|
||||||
{
|
{
|
||||||
.title = "Screen mode",
|
.title = "Screen mode",
|
||||||
.data = "screenMode",
|
.data = GUI_V_S("screenMode"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 0,
|
.state = 0,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -173,7 +173,7 @@ int main() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Camera",
|
.title = "Camera",
|
||||||
.data = "camera",
|
.data = GUI_V_S("camera"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 1,
|
.state = 1,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
|
|
@ -87,7 +87,13 @@ void ActionMapper::rebuildMenu(const QString& menu, QMenu* qmenu, QWidget* conte
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
QObject::connect(action, &Action::enabled, qaction, &QAction::setEnabled);
|
QObject::connect(action, &Action::enabled, qaction, &QAction::setEnabled);
|
||||||
QObject::connect(action, &Action::activated, qaction, &QAction::setChecked);
|
QObject::connect(action, &Action::activated, [qaction, action](bool active) {
|
||||||
|
if (qaction->isCheckable()) {
|
||||||
|
qaction->setChecked(active);
|
||||||
|
} else if (active) {
|
||||||
|
action->setActive(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
QObject::connect(action, &Action::destroyed, qaction, &QAction::deleteLater);
|
QObject::connect(action, &Action::destroyed, qaction, &QAction::deleteLater);
|
||||||
if (shortcut) {
|
if (shortcut) {
|
||||||
QObject::connect(shortcut, &Shortcut::shortcutChanged, qaction, [qaction](int shortcut) {
|
QObject::connect(shortcut, &Shortcut::shortcutChanged, qaction, [qaction](int shortcut) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ void AssetInfo::addCustomProperty(const QString& id, const QString& visibleName)
|
||||||
QLabel* value = new QLabel;
|
QLabel* value = new QLabel;
|
||||||
value->setFont(GBAApp::app()->monospaceFont());
|
value->setFont(GBAApp::app()->monospaceFont());
|
||||||
value->setAlignment(Qt::AlignRight);
|
value->setAlignment(Qt::AlignRight);
|
||||||
|
value->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
|
||||||
newLayout->addWidget(value);
|
newLayout->addWidget(value);
|
||||||
m_customProperties[id] = value;
|
m_customProperties[id] = value;
|
||||||
int index = customLocation();
|
int index = customLocation();
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -74,6 +74,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -96,7 +99,7 @@
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -162,6 +165,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">0x00 (00)</string>
|
<string notr="true">0x00 (00)</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -169,6 +175,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">0x00 (00)</string>
|
<string notr="true">0x00 (00)</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -176,6 +185,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">0x00 (00)</string>
|
<string notr="true">0x00 (00)</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -142,7 +142,7 @@
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QRadioButton" name="gateBattleChip">
|
<widget class="QRadioButton" name="gateBattleChip">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Ba&ttleChip Gate</string>
|
<string notr="true">Ba&ttleChip Gate</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -152,14 +152,14 @@
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QRadioButton" name="gateProgress">
|
<widget class="QRadioButton" name="gateProgress">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Progress &Gate</string>
|
<string notr="true">Progress &Gate</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QRadioButton" name="gateBeastLink">
|
<widget class="QRadioButton" name="gateBeastLink">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Beast &Link Gate</string>
|
<string notr="true">Beast &Link Gate</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
#include "GBAApp.h"
|
#include "GBAApp.h"
|
||||||
#include "CoreController.h"
|
#include "CoreController.h"
|
||||||
|
|
||||||
|
#include <QBoxLayout>
|
||||||
|
#include <QButtonGroup>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QPushButton>
|
#include <QRadioButton>
|
||||||
|
|
||||||
#include <mgba/core/cheats.h>
|
#include <mgba/core/cheats.h>
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
|
@ -30,58 +32,30 @@ CheatsView::CheatsView(std::shared_ptr<CoreController> controller, QWidget* pare
|
||||||
|
|
||||||
m_ui.cheatList->installEventFilter(this);
|
m_ui.cheatList->installEventFilter(this);
|
||||||
m_ui.cheatList->setModel(&m_model);
|
m_ui.cheatList->setModel(&m_model);
|
||||||
|
m_ui.codeEntry->setFont(GBAApp::app()->monospaceFont());
|
||||||
|
|
||||||
connect(m_ui.load, &QPushButton::clicked, this, &CheatsView::load);
|
connect(m_ui.load, &QAbstractButton::clicked, this, &CheatsView::load);
|
||||||
connect(m_ui.save, &QPushButton::clicked, this, &CheatsView::save);
|
connect(m_ui.save, &QAbstractButton::clicked, this, &CheatsView::save);
|
||||||
connect(m_ui.addSet, &QPushButton::clicked, this, &CheatsView::addSet);
|
connect(m_ui.addSet, &QAbstractButton::clicked, this, &CheatsView::addSet);
|
||||||
connect(m_ui.remove, &QPushButton::clicked, this, &CheatsView::removeSet);
|
connect(m_ui.remove, &QAbstractButton::clicked, this, &CheatsView::removeSet);
|
||||||
|
connect(m_ui.add, &QAbstractButton::clicked, this, &CheatsView::enterCheat);
|
||||||
connect(controller.get(), &CoreController::stopping, this, &CheatsView::close);
|
connect(controller.get(), &CoreController::stopping, this, &CheatsView::close);
|
||||||
connect(controller.get(), &CoreController::stateLoaded, &m_model, &CheatsModel::invalidated);
|
connect(controller.get(), &CoreController::stateLoaded, &m_model, &CheatsModel::invalidated);
|
||||||
|
|
||||||
QPushButton* add;
|
|
||||||
switch (controller->platform()) {
|
switch (controller->platform()) {
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
case mPLATFORM_GBA:
|
case mPLATFORM_GBA:
|
||||||
connect(m_ui.add, &QPushButton::clicked, [this]() {
|
registerCodeType(tr("Autodetect (recommended)"), GBA_CHEAT_AUTODETECT);
|
||||||
enterCheat(GBA_CHEAT_AUTODETECT);
|
registerCodeType(QLatin1String("GameShark"), GBA_CHEAT_GAMESHARK);
|
||||||
});
|
registerCodeType(QLatin1String("Action Replay MAX"), GBA_CHEAT_PRO_ACTION_REPLAY);
|
||||||
|
registerCodeType(QLatin1String("CodeBreaker"), GBA_CHEAT_CODEBREAKER);
|
||||||
add = new QPushButton(tr("Add GameShark"));
|
|
||||||
m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
|
|
||||||
connect(add, &QPushButton::clicked, [this]() {
|
|
||||||
enterCheat(GBA_CHEAT_GAMESHARK);
|
|
||||||
});
|
|
||||||
|
|
||||||
add = new QPushButton(tr("Add Pro Action Replay"));
|
|
||||||
m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
|
|
||||||
connect(add, &QPushButton::clicked, [this]() {
|
|
||||||
enterCheat(GBA_CHEAT_PRO_ACTION_REPLAY);
|
|
||||||
});
|
|
||||||
|
|
||||||
add = new QPushButton(tr("Add CodeBreaker"));
|
|
||||||
m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
|
|
||||||
connect(add, &QPushButton::clicked, [this]() {
|
|
||||||
enterCheat(GBA_CHEAT_CODEBREAKER);
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef M_CORE_GB
|
#ifdef M_CORE_GB
|
||||||
case mPLATFORM_GB:
|
case mPLATFORM_GB:
|
||||||
connect(m_ui.add, &QPushButton::clicked, [this]() {
|
registerCodeType(tr("Autodetect (recommended)"), GB_CHEAT_AUTODETECT);
|
||||||
enterCheat(GB_CHEAT_AUTODETECT);
|
registerCodeType(QLatin1String("GameShark"), GB_CHEAT_GAMESHARK);
|
||||||
});
|
registerCodeType(QLatin1String("Game Genie"), GB_CHEAT_GAME_GENIE);
|
||||||
|
|
||||||
add = new QPushButton(tr("Add GameShark"));
|
|
||||||
m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
|
|
||||||
connect(add, &QPushButton::clicked, [this]() {
|
|
||||||
enterCheat(GB_CHEAT_GAMESHARK);
|
|
||||||
});
|
|
||||||
|
|
||||||
add = new QPushButton(tr("Add GameGenie"));
|
|
||||||
m_ui.gridLayout->addWidget(add, m_ui.gridLayout->rowCount(), 2, 1, 2);
|
|
||||||
connect(add, &QPushButton::clicked, [this]() {
|
|
||||||
enterCheat(GB_CHEAT_GAME_GENIE);
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
@ -127,6 +101,7 @@ void CheatsView::addSet() {
|
||||||
mCheatSet* set = m_controller->cheatDevice()->createSet(m_controller->cheatDevice(), nullptr);
|
mCheatSet* set = m_controller->cheatDevice()->createSet(m_controller->cheatDevice(), nullptr);
|
||||||
m_model.addSet(set);
|
m_model.addSet(set);
|
||||||
m_ui.cheatList->selectionModel()->select(m_model.index(m_model.rowCount() - 1, 0, QModelIndex()), QItemSelectionModel::ClearAndSelect);
|
m_ui.cheatList->selectionModel()->select(m_model.index(m_model.rowCount() - 1, 0, QModelIndex()), QItemSelectionModel::ClearAndSelect);
|
||||||
|
enterCheat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheatsView::removeSet() {
|
void CheatsView::removeSet() {
|
||||||
|
@ -140,7 +115,21 @@ void CheatsView::removeSet() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheatsView::enterCheat(int codeType) {
|
void CheatsView::registerCodeType(const QString& label, int type) {
|
||||||
|
QRadioButton* add = new QRadioButton(label);
|
||||||
|
m_ui.typeLayout->addWidget(add);
|
||||||
|
connect(add, &QAbstractButton::clicked, [this, type]() {
|
||||||
|
m_codeType = type;
|
||||||
|
});
|
||||||
|
if (!m_typeGroup) {
|
||||||
|
m_typeGroup = new QButtonGroup(this);
|
||||||
|
m_codeType = type;
|
||||||
|
add->setChecked(true);
|
||||||
|
}
|
||||||
|
m_typeGroup->addButton(add);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatsView::enterCheat() {
|
||||||
mCheatSet* set = nullptr;
|
mCheatSet* set = nullptr;
|
||||||
QModelIndexList selection = m_ui.cheatList->selectionModel()->selectedIndexes();
|
QModelIndexList selection = m_ui.cheatList->selectionModel()->selectedIndexes();
|
||||||
QModelIndex index;
|
QModelIndex index;
|
||||||
|
@ -163,7 +152,7 @@ void CheatsView::enterCheat(int codeType) {
|
||||||
QStringList cheats = m_ui.codeEntry->toPlainText().split('\n', QString::SkipEmptyParts);
|
QStringList cheats = m_ui.codeEntry->toPlainText().split('\n', QString::SkipEmptyParts);
|
||||||
for (const QString& string : cheats) {
|
for (const QString& string : cheats) {
|
||||||
m_model.beginAppendRow(index);
|
m_model.beginAppendRow(index);
|
||||||
mCheatAddLine(set, string.toUtf8().constData(), codeType);
|
mCheatAddLine(set, string.toUtf8().constData(), m_codeType);
|
||||||
m_model.endAppendRow();
|
m_model.endAppendRow();
|
||||||
}
|
}
|
||||||
if (set->refresh) {
|
if (set->refresh) {
|
||||||
|
|
|
@ -33,13 +33,17 @@ private slots:
|
||||||
void save();
|
void save();
|
||||||
void addSet();
|
void addSet();
|
||||||
void removeSet();
|
void removeSet();
|
||||||
|
void enterCheat();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void enterCheat(int codeType);
|
void registerCodeType(const QString& label, int type);
|
||||||
|
|
||||||
Ui::CheatsView m_ui;
|
Ui::CheatsView m_ui;
|
||||||
std::shared_ptr<CoreController> m_controller;
|
std::shared_ptr<CoreController> m_controller;
|
||||||
CheatsModel m_model;
|
CheatsModel m_model;
|
||||||
|
QButtonGroup* m_typeGroup = nullptr;
|
||||||
|
|
||||||
|
int m_codeType = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,60 +6,18 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>629</width>
|
<width>520</width>
|
||||||
<height>428</height>
|
<height>455</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Cheats</string>
|
<string>Cheats</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout" columnstretch="3,0,0,0">
|
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,1,0,0" columnstretch="4,0,0">
|
||||||
<item row="2" column="2" colspan="2">
|
<item row="0" column="0" rowspan="7">
|
||||||
<widget class="QPushButton" name="remove">
|
|
||||||
<property name="text">
|
|
||||||
<string>Remove</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2" colspan="2">
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="3">
|
|
||||||
<widget class="QPushButton" name="save">
|
|
||||||
<property name="text">
|
|
||||||
<string>Save</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QPushButton" name="load">
|
|
||||||
<property name="text">
|
|
||||||
<string>Load</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2" colspan="2">
|
|
||||||
<widget class="QPushButton" name="addSet">
|
|
||||||
<property name="text">
|
|
||||||
<string>Add New Set</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="2" colspan="2">
|
|
||||||
<widget class="QPushButton" name="add">
|
|
||||||
<property name="text">
|
|
||||||
<string>Add</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" rowspan="7" colspan="2">
|
|
||||||
<widget class="QTreeView" name="cheatList">
|
<widget class="QTreeView" name="cheatList">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
|
@ -75,18 +33,51 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="2" rowspan="2" colspan="2">
|
<item row="0" column="1" colspan="2">
|
||||||
|
<widget class="QPushButton" name="addSet">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add New Code</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QPushButton" name="load">
|
||||||
|
<property name="text">
|
||||||
|
<string>Load</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="save">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1" colspan="2">
|
||||||
|
<widget class="QPushButton" name="remove">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1" colspan="2">
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1" colspan="2">
|
||||||
<widget class="QPlainTextEdit" name="codeEntry">
|
<widget class="QPlainTextEdit" name="codeEntry">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
<horstretch>1</horstretch>
|
<horstretch>1</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="tabChangesFocus">
|
||||||
<font>
|
<bool>true</bool>
|
||||||
<family>Courier New</family>
|
|
||||||
</font>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="lineWrapMode">
|
<property name="lineWrapMode">
|
||||||
<enum>QPlainTextEdit::NoWrap</enum>
|
<enum>QPlainTextEdit::NoWrap</enum>
|
||||||
|
@ -96,6 +87,21 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="1" colspan="2">
|
||||||
|
<widget class="QPushButton" name="add">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add Lines</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1" colspan="2">
|
||||||
|
<widget class="QGroupBox" name="typeBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Code type</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="typeLayout"/>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
|
|
|
@ -529,6 +529,21 @@ void CoreController::forceFastForward(bool enable) {
|
||||||
emit fastForwardChanged(enable || m_fastForward);
|
emit fastForwardChanged(enable || m_fastForward);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CoreController::overrideMute(bool override) {
|
||||||
|
m_mute = override;
|
||||||
|
|
||||||
|
Interrupter interrupter(this);
|
||||||
|
mCore* core = m_threadContext.core;
|
||||||
|
if (m_mute) {
|
||||||
|
core->opts.mute = true;
|
||||||
|
} else {
|
||||||
|
int fakeBool = 0;
|
||||||
|
mCoreConfigGetIntValue(&core->config, "mute", &fakeBool);
|
||||||
|
core->opts.mute = fakeBool;
|
||||||
|
}
|
||||||
|
core->reloadConfigOption(core, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void CoreController::loadState(int slot) {
|
void CoreController::loadState(int slot) {
|
||||||
if (slot > 0 && slot != m_stateSlot) {
|
if (slot > 0 && slot != m_stateSlot) {
|
||||||
m_stateSlot = slot;
|
m_stateSlot = slot;
|
||||||
|
@ -1046,7 +1061,7 @@ void CoreController::updateFastForward() {
|
||||||
m_threadContext.core->opts.volume = m_fastForwardVolume;
|
m_threadContext.core->opts.volume = m_fastForwardVolume;
|
||||||
}
|
}
|
||||||
if (m_fastForwardMute >= 0) {
|
if (m_fastForwardMute >= 0) {
|
||||||
m_threadContext.core->opts.mute = m_fastForwardMute;
|
m_threadContext.core->opts.mute = m_fastForwardMute || m_mute;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we aren't holding the fast forward button
|
// If we aren't holding the fast forward button
|
||||||
|
|
|
@ -141,6 +141,8 @@ public slots:
|
||||||
void setFastForward(bool);
|
void setFastForward(bool);
|
||||||
void forceFastForward(bool);
|
void forceFastForward(bool);
|
||||||
|
|
||||||
|
void overrideMute(bool);
|
||||||
|
|
||||||
void loadState(int slot = 0);
|
void loadState(int slot = 0);
|
||||||
void loadState(const QString& path, int flags = -1);
|
void loadState(const QString& path, int flags = -1);
|
||||||
void loadState(QIODevice* iodev, int flags = -1);
|
void loadState(QIODevice* iodev, int flags = -1);
|
||||||
|
@ -272,6 +274,8 @@ private:
|
||||||
float m_fastForwardHeldRatio = -1.f;
|
float m_fastForwardHeldRatio = -1.f;
|
||||||
float m_fpsTarget;
|
float m_fpsTarget;
|
||||||
|
|
||||||
|
bool m_mute;
|
||||||
|
|
||||||
InputController* m_inputController = nullptr;
|
InputController* m_inputController = nullptr;
|
||||||
LogController* m_log = nullptr;
|
LogController* m_log = nullptr;
|
||||||
MultiplayerController* m_multiplayer = nullptr;
|
MultiplayerController* m_multiplayer = nullptr;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "DebuggerConsole.h"
|
#include "DebuggerConsole.h"
|
||||||
|
|
||||||
#include "DebuggerConsoleController.h"
|
#include "DebuggerConsoleController.h"
|
||||||
|
#include "GBAApp.h"
|
||||||
|
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
@ -18,6 +19,8 @@ DebuggerConsole::DebuggerConsole(DebuggerConsoleController* controller, QWidget*
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
|
|
||||||
m_ui.prompt->installEventFilter(this);
|
m_ui.prompt->installEventFilter(this);
|
||||||
|
m_ui.log->setFont(GBAApp::app()->monospaceFont());
|
||||||
|
m_ui.prompt->setFont(GBAApp::app()->monospaceFont());
|
||||||
|
|
||||||
connect(m_ui.prompt, &QLineEdit::returnPressed, this, &DebuggerConsole::postLine);
|
connect(m_ui.prompt, &QLineEdit::returnPressed, this, &DebuggerConsole::postLine);
|
||||||
connect(controller, &DebuggerConsoleController::log, this, &DebuggerConsole::log);
|
connect(controller, &DebuggerConsoleController::log, this, &DebuggerConsole::log);
|
||||||
|
@ -81,4 +84,4 @@ bool DebuggerConsole::eventFilter(QObject*, QEvent* event) {
|
||||||
m_ui.prompt->setText(m_history[m_history.size() - m_historyOffset]);
|
m_ui.prompt->setText(m_history[m_history.size() - m_historyOffset]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,6 @@
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLineEdit" name="prompt">
|
<widget class="QLineEdit" name="prompt">
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Source Code Pro</family>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="placeholderText">
|
<property name="placeholderText">
|
||||||
<string>Enter command (try `help` for more info)</string>
|
<string>Enter command (try `help` for more info)</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -35,11 +30,6 @@
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="0" column="0" colspan="2">
|
||||||
<widget class="QPlainTextEdit" name="log">
|
<widget class="QPlainTextEdit" name="log">
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Source Code Pro</family>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "DiscordCoordinator.h"
|
#include "DiscordCoordinator.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
#include "CoreController.h"
|
#include "CoreController.h"
|
||||||
#include "GBAApp.h"
|
#include "GBAApp.h"
|
||||||
|
|
||||||
|
@ -31,6 +33,11 @@ static void updatePresence() {
|
||||||
discordPresence.details = s_title.toUtf8().constData();
|
discordPresence.details = s_title.toUtf8().constData();
|
||||||
discordPresence.instance = 1;
|
discordPresence.instance = 1;
|
||||||
discordPresence.largeImageKey = "mgba";
|
discordPresence.largeImageKey = "mgba";
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
|
||||||
|
discordPresence.startTimestamp = QDateTime::currentSecsSinceEpoch();
|
||||||
|
#else
|
||||||
|
discordPresence.startTimestamp = QDateTime::currentMSecsSinceEpoch() / 1000;
|
||||||
|
#endif
|
||||||
Discord_UpdatePresence(&discordPresence);
|
Discord_UpdatePresence(&discordPresence);
|
||||||
} else {
|
} else {
|
||||||
Discord_ClearPresence();
|
Discord_ClearPresence();
|
||||||
|
|
|
@ -447,12 +447,12 @@ void PainterGL::draw() {
|
||||||
m_delayTimer.start();
|
m_delayTimer.start();
|
||||||
} else {
|
} else {
|
||||||
if (sync->audioWait || sync->videoFrameWait) {
|
if (sync->audioWait || sync->videoFrameWait) {
|
||||||
while (m_delayTimer.nsecsElapsed() + 2000000 < 1000000000 / sync->fpsTarget) {
|
while (m_delayTimer.nsecsElapsed() + 1'000'000 < 1'000'000'000 / sync->fpsTarget) {
|
||||||
QThread::usleep(500);
|
QThread::usleep(500);
|
||||||
}
|
}
|
||||||
forceRedraw = true;
|
forceRedraw = true;
|
||||||
} else if (!forceRedraw) {
|
} else if (!forceRedraw) {
|
||||||
forceRedraw = m_delayTimer.nsecsElapsed() + 2000000 >= 1000000000 / m_surface->screen()->refreshRate();
|
forceRedraw = m_delayTimer.nsecsElapsed() + 1'000'000 >= 1'000'000'000 / m_surface->screen()->refreshRate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mCoreSyncWaitFrameEnd(sync);
|
mCoreSyncWaitFrameEnd(sync);
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>0x0000</string>
|
<string>0x0000</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -173,6 +173,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -199,6 +202,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -246,6 +252,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -272,6 +281,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -283,6 +295,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">+0.00</string>
|
<string notr="true">+0.00</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
|
@ -290,6 +305,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">+1.00</string>
|
<string notr="true">+1.00</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
|
@ -304,6 +322,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">+1.00</string>
|
<string notr="true">+1.00</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
|
@ -324,6 +345,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">+0.00</string>
|
<string notr="true">+0.00</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -405,6 +429,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Off</string>
|
<string>Off</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -439,6 +466,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -473,9 +503,6 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
|
||||||
<string>Return, Ctrl+R</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -564,6 +591,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Normal</string>
|
<string>Normal</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -669,6 +699,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -143,7 +143,17 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>EEPROM</string>
|
<string>EEPROM 8kB</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>EEPROM 512 bytes</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>SRAM 64kB (bootlegs only)</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
|
@ -211,6 +211,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">0x00 (00)</string>
|
<string notr="true">0x00 (00)</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -218,6 +221,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">0x00 (00)</string>
|
<string notr="true">0x00 (00)</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -225,6 +231,9 @@
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">0x00 (00)</string>
|
<string notr="true">0x00 (00)</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -274,6 +283,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -284,6 +296,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -294,6 +309,9 @@
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
<string>{TITLE}</string>
|
<string>{TITLE}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
<string>{ID}</string>
|
<string>{ID}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
<string>{SIZE}</string>
|
<string>{SIZE}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -104,7 +104,7 @@
|
||||||
<string>{CRC}</string>
|
<string>{CRC}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -98,6 +98,7 @@ ReportView::ReportView(QWidget* parent)
|
||||||
QString description = m_ui.description->text();
|
QString description = m_ui.description->text();
|
||||||
description.replace("{projectName}", QLatin1String(projectName));
|
description.replace("{projectName}", QLatin1String(projectName));
|
||||||
m_ui.description->setText(description);
|
m_ui.description->setText(description);
|
||||||
|
m_ui.fileView->setFont(GBAApp::app()->monospaceFont());
|
||||||
|
|
||||||
connect(m_ui.fileList, &QListWidget::currentTextChanged, this, &ReportView::setShownReport);
|
connect(m_ui.fileList, &QListWidget::currentTextChanged, this, &ReportView::setShownReport);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,6 @@
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Monospace</family>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::TextEditorInteraction</set>
|
<set>Qt::TextEditorInteraction</set>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -79,14 +79,11 @@ void SensorView::setController(std::shared_ptr<CoreController> controller) {
|
||||||
void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) {
|
void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) {
|
||||||
connect(button, &QAbstractButton::toggled, [this, button, setter](bool checked) {
|
connect(button, &QAbstractButton::toggled, [this, button, setter](bool checked) {
|
||||||
if (!checked) {
|
if (!checked) {
|
||||||
m_jiggered = nullptr;
|
m_button = nullptr;
|
||||||
} else {
|
} else {
|
||||||
button->setFocus();
|
button->setFocus();
|
||||||
m_jiggered = [this, button, setter](int axis) {
|
m_button = button;
|
||||||
(m_input->*setter)(axis);
|
m_setter = setter;
|
||||||
button->setChecked(false);
|
|
||||||
button->clearFocus();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
button->installEventFilter(this);
|
button->installEventFilter(this);
|
||||||
|
@ -106,8 +103,12 @@ bool SensorView::eventFilter(QObject*, QEvent* event) {
|
||||||
if (event->type() == GamepadAxisEvent::Type()) {
|
if (event->type() == GamepadAxisEvent::Type()) {
|
||||||
GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
|
GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
|
||||||
gae->accept();
|
gae->accept();
|
||||||
if (m_jiggered && gae->direction() != GamepadAxisEvent::NEUTRAL && gae->isNew()) {
|
if (m_button && gae->direction() != GamepadAxisEvent::NEUTRAL && gae->isNew()) {
|
||||||
m_jiggered(gae->axis());
|
m_button->removeEventFilter(this);
|
||||||
|
m_button->clearFocus();
|
||||||
|
m_button->setChecked(false);
|
||||||
|
(m_input->*m_setter)(gae->axis());
|
||||||
|
m_button = nullptr;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,9 @@ private slots:
|
||||||
private:
|
private:
|
||||||
Ui::SensorView m_ui;
|
Ui::SensorView m_ui;
|
||||||
|
|
||||||
std::function<void(int)> m_jiggered;
|
QAbstractButton* m_button = nullptr;
|
||||||
|
void (InputController::*m_setter)(int);
|
||||||
|
|
||||||
std::shared_ptr<CoreController> m_controller;
|
std::shared_ptr<CoreController> m_controller;
|
||||||
InputController* m_input;
|
InputController* m_input;
|
||||||
mRotationSource* m_rotation;
|
mRotationSource* m_rotation;
|
||||||
|
|
|
@ -423,6 +423,8 @@ void SettingsView::updateConfig() {
|
||||||
saveSetting("suspendScreensaver", m_ui.suspendScreensaver);
|
saveSetting("suspendScreensaver", m_ui.suspendScreensaver);
|
||||||
saveSetting("pauseOnFocusLost", m_ui.pauseOnFocusLost);
|
saveSetting("pauseOnFocusLost", m_ui.pauseOnFocusLost);
|
||||||
saveSetting("pauseOnMinimize", m_ui.pauseOnMinimize);
|
saveSetting("pauseOnMinimize", m_ui.pauseOnMinimize);
|
||||||
|
saveSetting("muteOnFocusLost", m_ui.muteOnFocusLost);
|
||||||
|
saveSetting("muteOnMinimize", m_ui.muteOnMinimize);
|
||||||
saveSetting("savegamePath", m_ui.savegamePath);
|
saveSetting("savegamePath", m_ui.savegamePath);
|
||||||
saveSetting("savestatePath", m_ui.savestatePath);
|
saveSetting("savestatePath", m_ui.savestatePath);
|
||||||
saveSetting("screenshotPath", m_ui.screenshotPath);
|
saveSetting("screenshotPath", m_ui.screenshotPath);
|
||||||
|
@ -534,6 +536,14 @@ void SettingsView::updateConfig() {
|
||||||
emit languageChanged();
|
emit languageChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_ui.multiplayerAudioAll->isChecked()) {
|
||||||
|
m_controller->setQtOption("multiplayerAudio", "all");
|
||||||
|
} else if (m_ui.multiplayerAudio1->isChecked()) {
|
||||||
|
m_controller->setQtOption("multiplayerAudio", "p1");
|
||||||
|
} else if (m_ui.multiplayerAudioActive->isChecked()) {
|
||||||
|
m_controller->setQtOption("multiplayerAudio", "active");
|
||||||
|
}
|
||||||
|
|
||||||
int hwaccelVideo = m_controller->getOption("hwaccelVideo").toInt();
|
int hwaccelVideo = m_controller->getOption("hwaccelVideo").toInt();
|
||||||
saveSetting("hwaccelVideo", m_ui.hwaccelVideo->currentIndex());
|
saveSetting("hwaccelVideo", m_ui.hwaccelVideo->currentIndex());
|
||||||
if (hwaccelVideo != m_ui.hwaccelVideo->currentIndex()) {
|
if (hwaccelVideo != m_ui.hwaccelVideo->currentIndex()) {
|
||||||
|
@ -767,6 +777,15 @@ void SettingsView::reloadConfig() {
|
||||||
m_ui.videoScaleSize->setText(tr("(%1×%2)").arg(GBA_VIDEO_HORIZONTAL_PIXELS * value).arg(GBA_VIDEO_VERTICAL_PIXELS * value));
|
m_ui.videoScaleSize->setText(tr("(%1×%2)").arg(GBA_VIDEO_HORIZONTAL_PIXELS * value).arg(GBA_VIDEO_VERTICAL_PIXELS * value));
|
||||||
});
|
});
|
||||||
loadSetting("videoScale", m_ui.videoScale, 1);
|
loadSetting("videoScale", m_ui.videoScale, 1);
|
||||||
|
|
||||||
|
QString multiplayerAudio = m_controller->getQtOption("multiplayerAudio").toString();
|
||||||
|
if (multiplayerAudio == QLatin1String("p1")) {
|
||||||
|
m_ui.multiplayerAudio1->setChecked(true);
|
||||||
|
} else if (multiplayerAudio == QLatin1String("active")) {
|
||||||
|
m_ui.multiplayerAudioActive->setChecked(true);
|
||||||
|
} else {
|
||||||
|
m_ui.multiplayerAudioAll->setChecked(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsView::addPage(const QString& name, QWidget* view, Page index) {
|
void SettingsView::addPage(const QString& name, QWidget* view, Page index) {
|
||||||
|
|
|
@ -313,21 +313,61 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="2">
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_43">
|
||||||
|
<property name="text">
|
||||||
|
<string>Audio in multiplayer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QRadioButton" name="multiplayerAudioAll">
|
||||||
|
<property name="text">
|
||||||
|
<string>All windows</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">multiplayerAudio</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QRadioButton" name="multiplayerAudio1">
|
||||||
|
<property name="text">
|
||||||
|
<string>Player 1 window only</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">multiplayerAudio</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QRadioButton" name="multiplayerAudioActive">
|
||||||
|
<property name="text">
|
||||||
|
<string>Currently active player window</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">multiplayerAudio</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0" colspan="2">
|
||||||
<widget class="Line" name="line_4">
|
<widget class="Line" name="line_4">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="9" column="0">
|
||||||
<widget class="QLabel" name="label_10">
|
<widget class="QLabel" name="label_10">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Display driver:</string>
|
<string>Display driver:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="9" column="1">
|
||||||
<widget class="QComboBox" name="displayDriver">
|
<widget class="QComboBox" name="displayDriver">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
@ -337,14 +377,14 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="10" column="0">
|
||||||
<widget class="QLabel" name="label_9">
|
<widget class="QLabel" name="label_9">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Frameskip:</string>
|
<string>Frameskip:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="10" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_12">
|
<widget class="QLabel" name="label_12">
|
||||||
|
@ -365,14 +405,14 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0">
|
<item row="11" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>FPS target:</string>
|
<string>FPS target:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="1">
|
<item row="11" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDoubleSpinBox" name="fpsTarget">
|
<widget class="QDoubleSpinBox" name="fpsTarget">
|
||||||
|
@ -399,28 +439,28 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="1">
|
<item row="12" column="1">
|
||||||
<widget class="QPushButton" name="nativeGB">
|
<widget class="QPushButton" name="nativeGB">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Native (59.7275)</string>
|
<string>Native (59.7275)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="0" colspan="2">
|
<item row="13" column="0" colspan="2">
|
||||||
<widget class="Line" name="line_5">
|
<widget class="Line" name="line_5">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="11" column="0">
|
<item row="14" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Sync:</string>
|
<string>Sync:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="11" column="1">
|
<item row="14" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="videoSync">
|
<widget class="QCheckBox" name="videoSync">
|
||||||
|
@ -438,28 +478,28 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="12" column="1">
|
<item row="15" column="1">
|
||||||
<widget class="QCheckBox" name="lockAspectRatio">
|
<widget class="QCheckBox" name="lockAspectRatio">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Lock aspect ratio</string>
|
<string>Lock aspect ratio</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="13" column="1">
|
<item row="16" column="1">
|
||||||
<widget class="QCheckBox" name="lockIntegerScaling">
|
<widget class="QCheckBox" name="lockIntegerScaling">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Force integer scaling</string>
|
<string>Force integer scaling</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="14" column="1">
|
<item row="17" column="1">
|
||||||
<widget class="QCheckBox" name="interframeBlending">
|
<widget class="QCheckBox" name="interframeBlending">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Interframe blending</string>
|
<string>Interframe blending</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="15" column="1">
|
<item row="18" column="1">
|
||||||
<widget class="QCheckBox" name="resampleVideo">
|
<widget class="QCheckBox" name="resampleVideo">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bilinear filtering</string>
|
<string>Bilinear filtering</string>
|
||||||
|
@ -556,18 +596,22 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="1">
|
<item row="8" column="1">
|
||||||
<widget class="QCheckBox" name="pauseOnFocusLost">
|
<layout class="QHBoxLayout" name="horizontalLayout_21">
|
||||||
<property name="text">
|
<item>
|
||||||
<string>Pause when inactive</string>
|
<widget class="QCheckBox" name="pauseOnFocusLost">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>Pause</string>
|
||||||
</item>
|
</property>
|
||||||
<item row="9" column="1">
|
</widget>
|
||||||
<widget class="QCheckBox" name="pauseOnMinimize">
|
</item>
|
||||||
<property name="text">
|
<item>
|
||||||
<string>Pause when minimized</string>
|
<widget class="QCheckBox" name="muteOnFocusLost">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>Mute</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="10" column="0" colspan="2">
|
<item row="10" column="0" colspan="2">
|
||||||
<widget class="Line" name="line_17">
|
<widget class="Line" name="line_17">
|
||||||
|
@ -684,6 +728,38 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_24">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="pauseOnMinimize">
|
||||||
|
<property name="text">
|
||||||
|
<string>Pause</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="muteOnMinimize">
|
||||||
|
<property name="text">
|
||||||
|
<string>Mute</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_41">
|
||||||
|
<property name="text">
|
||||||
|
<string>When inactive:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QLabel" name="label_42">
|
||||||
|
<property name="text">
|
||||||
|
<string>When minimized:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="emulation">
|
<widget class="QWidget" name="emulation">
|
||||||
|
@ -2218,5 +2294,6 @@
|
||||||
</connections>
|
</connections>
|
||||||
<buttongroups>
|
<buttongroups>
|
||||||
<buttongroup name="gbColors"/>
|
<buttongroup name="gbColors"/>
|
||||||
|
<buttongroup name="multiplayerAudio"/>
|
||||||
</buttongroups>
|
</buttongroups>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -250,6 +250,11 @@ void Window::resizeFrame(const QSize& size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::updateMultiplayerActive(bool active) {
|
||||||
|
m_multiActive = active;
|
||||||
|
updateMute();
|
||||||
|
}
|
||||||
|
|
||||||
void Window::setConfig(ConfigController* config) {
|
void Window::setConfig(ConfigController* config) {
|
||||||
m_config = config;
|
m_config = config;
|
||||||
}
|
}
|
||||||
|
@ -282,6 +287,7 @@ void Window::reloadConfig() {
|
||||||
if (m_audioProcessor) {
|
if (m_audioProcessor) {
|
||||||
m_audioProcessor->configure(m_config);
|
m_audioProcessor->configure(m_config);
|
||||||
}
|
}
|
||||||
|
updateMute();
|
||||||
m_display->resizeContext();
|
m_display->resizeContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,12 +679,17 @@ void Window::resizeEvent(QResizeEvent*) {
|
||||||
|
|
||||||
void Window::showEvent(QShowEvent* event) {
|
void Window::showEvent(QShowEvent* event) {
|
||||||
if (m_wasOpened) {
|
if (m_wasOpened) {
|
||||||
if (event->spontaneous() && m_config->getOption("pauseOnMinimize").toInt() && m_controller) {
|
if (event->spontaneous() && m_controller) {
|
||||||
focusCheck();
|
focusCheck();
|
||||||
if (m_autoresume) {
|
if (m_config->getOption("pauseOnMinimize").toInt() && m_autoresume) {
|
||||||
m_controller->setPaused(false);
|
m_controller->setPaused(false);
|
||||||
m_autoresume = false;
|
m_autoresume = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_config->getOption("muteOnMinimize").toInt()) {
|
||||||
|
m_inactiveMute = false;
|
||||||
|
updateMute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -709,13 +720,18 @@ void Window::hideEvent(QHideEvent* event) {
|
||||||
if (!event->spontaneous()) {
|
if (!event->spontaneous()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m_config->getOption("pauseOnMinimize").toInt() || !m_controller) {
|
if (!m_controller) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m_controller->isPaused()) {
|
|
||||||
|
if (m_config->getOption("pauseOnMinimize").toInt() && !m_controller->isPaused()) {
|
||||||
m_autoresume = true;
|
m_autoresume = true;
|
||||||
m_controller->setPaused(true);
|
m_controller->setPaused(true);
|
||||||
}
|
}
|
||||||
|
if (m_config->getOption("muteOnMinimize").toInt()) {
|
||||||
|
m_inactiveMute = true;
|
||||||
|
updateMute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::closeEvent(QCloseEvent* event) {
|
void Window::closeEvent(QCloseEvent* event) {
|
||||||
|
@ -737,6 +753,13 @@ void Window::closeEvent(QCloseEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::focusInEvent(QFocusEvent*) {
|
void Window::focusInEvent(QFocusEvent*) {
|
||||||
|
for (Window* window : GBAApp::app()->windows()) {
|
||||||
|
if (window != this) {
|
||||||
|
window->updateMultiplayerActive(false);
|
||||||
|
} else {
|
||||||
|
updateMultiplayerActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
m_display->forceDraw();
|
m_display->forceDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1873,15 +1896,25 @@ Action* Window::addGameAction(const QString& visibleName, const QString& name, A
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::focusCheck() {
|
void Window::focusCheck() {
|
||||||
if (!m_config->getOption("pauseOnFocusLost").toInt() || !m_controller) {
|
if (!m_controller) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (QGuiApplication::focusWindow() && m_autoresume) {
|
if (m_config->getOption("pauseOnFocusLost").toInt()) {
|
||||||
m_controller->setPaused(false);
|
if (QGuiApplication::focusWindow() && m_autoresume) {
|
||||||
m_autoresume = false;
|
m_controller->setPaused(false);
|
||||||
} else if (!QGuiApplication::focusWindow() && !m_controller->isPaused()) {
|
m_autoresume = false;
|
||||||
m_autoresume = true;
|
} else if (!QGuiApplication::focusWindow() && !m_controller->isPaused()) {
|
||||||
m_controller->setPaused(true);
|
m_autoresume = true;
|
||||||
|
m_controller->setPaused(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_config->getOption("muteOnFocusLost").toInt()) {
|
||||||
|
if (QGuiApplication::focusWindow()) {
|
||||||
|
m_inactiveMute = false;
|
||||||
|
} else {
|
||||||
|
m_inactiveMute = true;
|
||||||
|
}
|
||||||
|
updateMute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2020,6 +2053,26 @@ void Window::attachDisplay() {
|
||||||
m_display->startDrawing(m_controller);
|
m_display->startDrawing(m_controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::updateMute() {
|
||||||
|
if (!m_controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mute = m_inactiveMute;
|
||||||
|
|
||||||
|
if (!mute) {
|
||||||
|
QString multiplayerAudio = m_config->getQtOption("multiplayerAudio").toString();
|
||||||
|
if (multiplayerAudio == QLatin1String("p1")) {
|
||||||
|
MultiplayerController* multiplayer = m_controller->multiplayerController();
|
||||||
|
mute = multiplayer && multiplayer->attached() > 1 && multiplayer->playerId(m_controller.get());
|
||||||
|
} else if (multiplayerAudio == QLatin1String("active")) {
|
||||||
|
mute = !m_multiActive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_controller->overrideMute(mute);
|
||||||
|
}
|
||||||
|
|
||||||
void Window::setLogo() {
|
void Window::setLogo() {
|
||||||
m_screenWidget->setPixmap(m_logo);
|
m_screenWidget->setPixmap(m_logo);
|
||||||
m_screenWidget->setCenteredAspectRatio(m_logo.width(), m_logo.height());
|
m_screenWidget->setCenteredAspectRatio(m_logo.width(), m_logo.height());
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
void resizeFrame(const QSize& size);
|
void resizeFrame(const QSize& size);
|
||||||
|
|
||||||
void updateMultiplayerStatus(bool canOpenAnother) { m_multiWindow->setEnabled(canOpenAnother); }
|
void updateMultiplayerStatus(bool canOpenAnother) { m_multiWindow->setEnabled(canOpenAnother); }
|
||||||
|
void updateMultiplayerActive(bool active);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void startDrawing();
|
void startDrawing();
|
||||||
|
@ -145,6 +146,7 @@ private slots:
|
||||||
void focusCheck();
|
void focusCheck();
|
||||||
|
|
||||||
void updateFrame();
|
void updateFrame();
|
||||||
|
void updateMute();
|
||||||
|
|
||||||
void setLogo();
|
void setLogo();
|
||||||
|
|
||||||
|
@ -224,6 +226,9 @@ private:
|
||||||
|
|
||||||
bool m_hitUnimplementedBiosCall;
|
bool m_hitUnimplementedBiosCall;
|
||||||
|
|
||||||
|
bool m_inactiveMute = false;
|
||||||
|
bool m_multiActive = true;
|
||||||
|
|
||||||
std::unique_ptr<OverrideView> m_overrideView;
|
std::unique_ptr<OverrideView> m_overrideView;
|
||||||
std::unique_ptr<SensorView> m_sensorView;
|
std::unique_ptr<SensorView> m_sensorView;
|
||||||
std::unique_ptr<DolphinConnector> m_dolphinView;
|
std::unique_ptr<DolphinConnector> m_dolphinView;
|
||||||
|
|
|
@ -59,6 +59,7 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
|
||||||
mSDLInitEvents(&s_sdlEvents);
|
mSDLInitEvents(&s_sdlEvents);
|
||||||
}
|
}
|
||||||
++s_sdlInited;
|
++s_sdlInited;
|
||||||
|
m_sdlPlayer.bindings = &m_inputMap;
|
||||||
updateJoysticks();
|
updateJoysticks();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -272,34 +273,45 @@ void InputController::setConfiguration(ConfigController* config) {
|
||||||
if (!m_playerAttached) {
|
if (!m_playerAttached) {
|
||||||
m_playerAttached = mSDLAttachPlayer(&s_sdlEvents, &m_sdlPlayer);
|
m_playerAttached = mSDLAttachPlayer(&s_sdlEvents, &m_sdlPlayer);
|
||||||
}
|
}
|
||||||
loadConfiguration(SDL_BINDING_BUTTON);
|
if (!loadConfiguration(SDL_BINDING_BUTTON)) {
|
||||||
|
mSDLInitBindingsGBA(&m_inputMap);
|
||||||
|
}
|
||||||
loadProfile(SDL_BINDING_BUTTON, profileForType(SDL_BINDING_BUTTON));
|
loadProfile(SDL_BINDING_BUTTON, profileForType(SDL_BINDING_BUTTON));
|
||||||
#endif
|
#endif
|
||||||
restoreModel();
|
restoreModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputController::loadConfiguration(uint32_t type) {
|
bool InputController::loadConfiguration(uint32_t type) {
|
||||||
if (!m_activeKeyInfo) {
|
if (!m_activeKeyInfo) {
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
if (!mInputMapLoad(&m_inputMap, type, m_config->input())) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
mInputMapLoad(&m_inputMap, type, m_config->input());
|
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (m_playerAttached) {
|
if (m_playerAttached) {
|
||||||
mSDLPlayerLoadConfig(&m_sdlPlayer, m_config->input());
|
mSDLPlayerLoadConfig(&m_sdlPlayer, m_config->input());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputController::loadProfile(uint32_t type, const QString& profile) {
|
bool InputController::loadProfile(uint32_t type, const QString& profile) {
|
||||||
if (profile.isEmpty()) {
|
if (profile.isEmpty()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
const InputProfile* ip = InputProfile::findProfile(profile);
|
bool loaded = mInputProfileLoad(&m_inputMap, type, m_config->input(), profile.toUtf8().constData());
|
||||||
if (ip) {
|
recalibrateAxes();
|
||||||
ip->apply(this);
|
if (!loaded) {
|
||||||
|
const InputProfile* ip = InputProfile::findProfile(profile);
|
||||||
|
if (ip) {
|
||||||
|
ip->apply(this);
|
||||||
|
loaded = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
recalibrateAxes();
|
recalibrateAxes();
|
||||||
emit profileLoaded(profile);
|
emit profileLoaded(profile);
|
||||||
|
return loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputController::saveConfiguration() {
|
void InputController::saveConfiguration() {
|
||||||
|
|
|
@ -73,8 +73,8 @@ public:
|
||||||
|
|
||||||
void setConfiguration(ConfigController* config);
|
void setConfiguration(ConfigController* config);
|
||||||
void saveConfiguration();
|
void saveConfiguration();
|
||||||
void loadConfiguration(uint32_t type);
|
bool loadConfiguration(uint32_t type);
|
||||||
void loadProfile(uint32_t type, const QString& profile);
|
bool loadProfile(uint32_t type, const QString& profile);
|
||||||
void saveConfiguration(uint32_t type);
|
void saveConfiguration(uint32_t type);
|
||||||
void saveProfile(uint32_t type, const QString& profile);
|
void saveProfile(uint32_t type, const QString& profile);
|
||||||
const char* profileForType(uint32_t type);
|
const char* profileForType(uint32_t type);
|
||||||
|
|
|
@ -106,6 +106,7 @@ VFile* LibraryController::selectedVFile() {
|
||||||
QByteArray filenameUtf8(entry.filename.toUtf8());
|
QByteArray filenameUtf8(entry.filename.toUtf8());
|
||||||
libentry.base = baseUtf8.constData();
|
libentry.base = baseUtf8.constData();
|
||||||
libentry.filename = filenameUtf8.constData();
|
libentry.filename = filenameUtf8.constData();
|
||||||
|
libentry.platform = mPLATFORM_NONE;
|
||||||
return mLibraryOpenVFile(m_library.get(), &libentry);
|
return mLibraryOpenVFile(m_library.get(), &libentry);
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -56,12 +56,12 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ArchiveInspector.ui" line="14"/>
|
<location filename="../ArchiveInspector.ui" line="14"/>
|
||||||
<source>Open in archive...</source>
|
<source>Open in archive...</source>
|
||||||
<translation>In Archiv öffnen …</translation>
|
<translation>In Archiv öffnen …</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ArchiveInspector.ui" line="20"/>
|
<location filename="../ArchiveInspector.ui" line="20"/>
|
||||||
<source>Loading...</source>
|
<source>Loading...</source>
|
||||||
<translation>Laden …</translation>
|
<translation>Laden …</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
@ -69,12 +69,12 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
||||||
<message>
|
<message>
|
||||||
<location filename="../AssetTile.ui" line="41"/>
|
<location filename="../AssetTile.ui" line="41"/>
|
||||||
<source>Tile #</source>
|
<source>Tile #</source>
|
||||||
<translation>Tile Nr.</translation>
|
<translation>Tile #</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../AssetTile.ui" line="65"/>
|
<location filename="../AssetTile.ui" line="65"/>
|
||||||
<source>Palette #</source>
|
<source>Palette #</source>
|
||||||
<translation>Palette Nr.</translation>
|
<translation>Palette #</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../AssetTile.ui" line="86"/>
|
<location filename="../AssetTile.ui" line="86"/>
|
||||||
|
@ -1071,7 +1071,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
||||||
<message>
|
<message>
|
||||||
<location filename="../OverrideView.ui" line="519"/>
|
<location filename="../OverrideView.ui" line="519"/>
|
||||||
<source>Palette preset</source>
|
<source>Palette preset</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Paletten-Voreinstellung</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
@ -4252,7 +4252,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
||||||
<message>
|
<message>
|
||||||
<location filename="../Window.cpp" line="1184"/>
|
<location filename="../Window.cpp" line="1184"/>
|
||||||
<source>Convert e-Reader card image to raw...</source>
|
<source>Convert e-Reader card image to raw...</source>
|
||||||
<translation>Lesegerät-Kartenbild in Rohdaten umwandeln …</translation>
|
<translation>Lesegerät-Kartenbild in Rohdaten umwandeln …</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../Window.cpp" line="1188"/>
|
<location filename="../Window.cpp" line="1188"/>
|
||||||
|
@ -5357,37 +5357,37 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1852"/>
|
<location filename="../SettingsView.ui" line="1852"/>
|
||||||
<source>Default color palette only</source>
|
<source>Default color palette only</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Nur Standard-Farbpalette</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1862"/>
|
<location filename="../SettingsView.ui" line="1862"/>
|
||||||
<source>SGB color palette if available</source>
|
<source>SGB color palette if available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>SGB-Farbpalette, sofern verfügbar</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1872"/>
|
<location filename="../SettingsView.ui" line="1872"/>
|
||||||
<source>GBC color palette if available</source>
|
<source>GBC color palette if available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>GBC-Farbpalette, sofern verfügbar</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1882"/>
|
<location filename="../SettingsView.ui" line="1882"/>
|
||||||
<source>SGB (preferred) or GBC color palette if available</source>
|
<source>SGB (preferred) or GBC color palette if available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>SGB (bevorzugt) oder GBC-Farbpalette, sofern verfügbar</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1895"/>
|
<location filename="../SettingsView.ui" line="1895"/>
|
||||||
<source>Game Boy Camera</source>
|
<source>Game Boy Camera</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Game Boy Camera</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1901"/>
|
<location filename="../SettingsView.ui" line="1901"/>
|
||||||
<source>Driver:</source>
|
<source>Driver:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Treiber:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1918"/>
|
<location filename="../SettingsView.ui" line="1918"/>
|
||||||
<source>Source:</source>
|
<source>Source:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Quelle:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="405"/>
|
<location filename="../SettingsView.ui" line="405"/>
|
||||||
|
@ -5448,42 +5448,42 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1502"/>
|
<location filename="../SettingsView.ui" line="1502"/>
|
||||||
<source>Models</source>
|
<source>Models</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Modelle</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1508"/>
|
<location filename="../SettingsView.ui" line="1508"/>
|
||||||
<source>GB only:</source>
|
<source>GB only:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Nur GB:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1518"/>
|
<location filename="../SettingsView.ui" line="1518"/>
|
||||||
<source>SGB compatible:</source>
|
<source>SGB compatible:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>SGB-kompatibel:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1528"/>
|
<location filename="../SettingsView.ui" line="1528"/>
|
||||||
<source>GBC only:</source>
|
<source>GBC only:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Nur GBC:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1538"/>
|
<location filename="../SettingsView.ui" line="1538"/>
|
||||||
<source>GBC compatible:</source>
|
<source>GBC compatible:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>GBC-kompatibel:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1548"/>
|
<location filename="../SettingsView.ui" line="1548"/>
|
||||||
<source>SGB and GBC compatible:</source>
|
<source>SGB and GBC compatible:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>SGB- und GBC-kompatibel:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1568"/>
|
<location filename="../SettingsView.ui" line="1568"/>
|
||||||
<source>Game Boy palette</source>
|
<source>Game Boy palette</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Game Boy-Palette</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1574"/>
|
<location filename="../SettingsView.ui" line="1574"/>
|
||||||
<source>Preset:</source>
|
<source>Preset:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Voreinstellungen:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="879"/>
|
<location filename="../SettingsView.ui" line="879"/>
|
||||||
|
@ -5538,7 +5538,7 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd.</translation
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="886"/>
|
<location filename="../SettingsView.ui" line="886"/>
|
||||||
<source>Enable VBA bug compatibility in ROM hacks</source>
|
<source>Enable VBA bug compatibility in ROM hacks</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>VBA-Bug-Kompatibilität in ROM-Hacks aktivieren</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="982"/>
|
<location filename="../SettingsView.ui" line="982"/>
|
||||||
|
|
|
@ -5286,37 +5286,37 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1852"/>
|
<location filename="../SettingsView.ui" line="1852"/>
|
||||||
<source>Default color palette only</source>
|
<source>Default color palette only</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Sólo paleta de colores predeterminada</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1862"/>
|
<location filename="../SettingsView.ui" line="1862"/>
|
||||||
<source>SGB color palette if available</source>
|
<source>SGB color palette if available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Paleta de color SGB si está disponible</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1872"/>
|
<location filename="../SettingsView.ui" line="1872"/>
|
||||||
<source>GBC color palette if available</source>
|
<source>GBC color palette if available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Paleta de color GBC si está disponible</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1882"/>
|
<location filename="../SettingsView.ui" line="1882"/>
|
||||||
<source>SGB (preferred) or GBC color palette if available</source>
|
<source>SGB (preferred) or GBC color palette if available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Paleta de colores SGB (preferida) o GBC si está disponible</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1895"/>
|
<location filename="../SettingsView.ui" line="1895"/>
|
||||||
<source>Game Boy Camera</source>
|
<source>Game Boy Camera</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Cámara Game Boy</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1901"/>
|
<location filename="../SettingsView.ui" line="1901"/>
|
||||||
<source>Driver:</source>
|
<source>Driver:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Controlador:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1918"/>
|
<location filename="../SettingsView.ui" line="1918"/>
|
||||||
<source>Source:</source>
|
<source>Source:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Fuente:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="405"/>
|
<location filename="../SettingsView.ui" line="405"/>
|
||||||
|
@ -5362,12 +5362,12 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="886"/>
|
<location filename="../SettingsView.ui" line="886"/>
|
||||||
<source>Enable VBA bug compatibility in ROM hacks</source>
|
<source>Enable VBA bug compatibility in ROM hacks</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Activar modo de compatibilidad VBA en ROM hacks</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1574"/>
|
<location filename="../SettingsView.ui" line="1574"/>
|
||||||
<source>Preset:</source>
|
<source>Preset:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Ajustes:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="602"/>
|
<location filename="../SettingsView.ui" line="602"/>
|
||||||
|
@ -5662,37 +5662,37 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1502"/>
|
<location filename="../SettingsView.ui" line="1502"/>
|
||||||
<source>Models</source>
|
<source>Models</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Modelos</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1508"/>
|
<location filename="../SettingsView.ui" line="1508"/>
|
||||||
<source>GB only:</source>
|
<source>GB only:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Sólo GB:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1518"/>
|
<location filename="../SettingsView.ui" line="1518"/>
|
||||||
<source>SGB compatible:</source>
|
<source>SGB compatible:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Compatible con SGB:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1528"/>
|
<location filename="../SettingsView.ui" line="1528"/>
|
||||||
<source>GBC only:</source>
|
<source>GBC only:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Sólo GBC:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1538"/>
|
<location filename="../SettingsView.ui" line="1538"/>
|
||||||
<source>GBC compatible:</source>
|
<source>GBC compatible:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Compatible con GBC:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1548"/>
|
<location filename="../SettingsView.ui" line="1548"/>
|
||||||
<source>SGB and GBC compatible:</source>
|
<source>SGB and GBC compatible:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Compatible con SGB y GBC:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1568"/>
|
<location filename="../SettingsView.ui" line="1568"/>
|
||||||
<source>Game Boy palette</source>
|
<source>Game Boy palette</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Paleta de Game Boy</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1584"/>
|
<location filename="../SettingsView.ui" line="1584"/>
|
||||||
|
|
|
@ -1047,12 +1047,12 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../OverrideView.ui" line="342"/>
|
<location filename="../OverrideView.ui" line="342"/>
|
||||||
<source>Sprite Colors 1</source>
|
<source>Sprite Colors 1</source>
|
||||||
<translation>Couleurs du Sprite nº 1</translation>
|
<translation>Couleurs du Sprite nº 1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../OverrideView.ui" line="349"/>
|
<location filename="../OverrideView.ui" line="349"/>
|
||||||
<source>Sprite Colors 2</source>
|
<source>Sprite Colors 2</source>
|
||||||
<translation>Couleurs du Sprite nº 2</translation>
|
<translation>Couleurs du Sprite nº 2</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../OverrideView.ui" line="519"/>
|
<location filename="../OverrideView.ui" line="519"/>
|
||||||
|
@ -1184,7 +1184,7 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../AboutScreen.cpp" line="77"/>
|
<location filename="../AboutScreen.cpp" line="77"/>
|
||||||
<source>2021</source>
|
<source>2021</source>
|
||||||
<translation type="unfinished">2021</translation>
|
<translation>2021</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
@ -1446,17 +1446,17 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="40"/>
|
<location filename="../IOViewer.cpp" line="40"/>
|
||||||
<source>Mode 0: 4 tile layers</source>
|
<source>Mode 0: 4 tile layers</source>
|
||||||
<translation>Mode 0 : 4 couches de tuile</translation>
|
<translation>Mode 0 : 4 couches de tuile</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="41"/>
|
<location filename="../IOViewer.cpp" line="41"/>
|
||||||
<source>Mode 1: 2 tile layers + 1 rotated/scaled tile layer</source>
|
<source>Mode 1: 2 tile layers + 1 rotated/scaled tile layer</source>
|
||||||
<translation>Mode 1 : 2 couches de tuiles + 1 couche de tuiles pivotée / mise à l'échelle</translation>
|
<translation>Mode 1 : 2 couches de tuiles + 1 couche de tuiles pivotée / mise à l'échelle</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="42"/>
|
<location filename="../IOViewer.cpp" line="42"/>
|
||||||
<source>Mode 2: 2 rotated/scaled tile layers</source>
|
<source>Mode 2: 2 rotated/scaled tile layers</source>
|
||||||
<translation>Mode 2 : 2 couches de tuiles pivotées / mises à l'échelle</translation>
|
<translation>Mode 2 : 2 couches de tuiles pivotées / mises à l'échelle</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="43"/>
|
<location filename="../IOViewer.cpp" line="43"/>
|
||||||
|
@ -1501,22 +1501,22 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="54"/>
|
<location filename="../IOViewer.cpp" line="54"/>
|
||||||
<source>Enable background 0</source>
|
<source>Enable background 0</source>
|
||||||
<translation>Activer l'arrière-plan nº 0</translation>
|
<translation>Activer l'arrière-plan nº 0</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="55"/>
|
<location filename="../IOViewer.cpp" line="55"/>
|
||||||
<source>Enable background 1</source>
|
<source>Enable background 1</source>
|
||||||
<translation>Activer l'arrière-plan nº 1</translation>
|
<translation>Activer l'arrière-plan nº 1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="56"/>
|
<location filename="../IOViewer.cpp" line="56"/>
|
||||||
<source>Enable background 2</source>
|
<source>Enable background 2</source>
|
||||||
<translation>Activer l'arrière-plan nº 2</translation>
|
<translation>Activer l'arrière-plan nº 2</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="57"/>
|
<location filename="../IOViewer.cpp" line="57"/>
|
||||||
<source>Enable background 3</source>
|
<source>Enable background 3</source>
|
||||||
<translation>Activer l'arrière-plan nº 3</translation>
|
<translation>Activer l'arrière-plan nº 3</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="58"/>
|
<location filename="../IOViewer.cpp" line="58"/>
|
||||||
|
@ -1526,12 +1526,12 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="59"/>
|
<location filename="../IOViewer.cpp" line="59"/>
|
||||||
<source>Enable Window 0</source>
|
<source>Enable Window 0</source>
|
||||||
<translation>Activer la fenêtre nº 0</translation>
|
<translation>Activer la fenêtre nº 0</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="60"/>
|
<location filename="../IOViewer.cpp" line="60"/>
|
||||||
<source>Enable Window 1</source>
|
<source>Enable Window 1</source>
|
||||||
<translation>Actvier la fenêtre nº 1</translation>
|
<translation>Actvier la fenêtre nº 1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="61"/>
|
<location filename="../IOViewer.cpp" line="61"/>
|
||||||
|
@ -1728,82 +1728,82 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="249"/>
|
<location filename="../IOViewer.cpp" line="249"/>
|
||||||
<source>Window 0 enable BG 0</source>
|
<source>Window 0 enable BG 0</source>
|
||||||
<translation>La fenêtre nº 0 active l'arrière plan nº 0</translation>
|
<translation>La fenêtre nº 0 active l'arrière plan nº 0</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="250"/>
|
<location filename="../IOViewer.cpp" line="250"/>
|
||||||
<source>Window 0 enable BG 1</source>
|
<source>Window 0 enable BG 1</source>
|
||||||
<translation>La fenêtre nº 0 active l'arrière plan nº 1</translation>
|
<translation>La fenêtre nº 0 active l'arrière plan nº 1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="251"/>
|
<location filename="../IOViewer.cpp" line="251"/>
|
||||||
<source>Window 0 enable BG 2</source>
|
<source>Window 0 enable BG 2</source>
|
||||||
<translation>La fenêtre nº 0 active l'arrière plan nº 2</translation>
|
<translation>La fenêtre nº 0 active l'arrière plan nº 2</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="252"/>
|
<location filename="../IOViewer.cpp" line="252"/>
|
||||||
<source>Window 0 enable BG 3</source>
|
<source>Window 0 enable BG 3</source>
|
||||||
<translation>La fenêtre nº 0 active l'arrière plan nº 3</translation>
|
<translation>La fenêtre nº 0 active l'arrière plan nº 3</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="253"/>
|
<location filename="../IOViewer.cpp" line="253"/>
|
||||||
<source>Window 0 enable OBJ</source>
|
<source>Window 0 enable OBJ</source>
|
||||||
<translation>La fenêtre nº 0 active l'OBJ</translation>
|
<translation>La fenêtre nº 0 active l'OBJ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="254"/>
|
<location filename="../IOViewer.cpp" line="254"/>
|
||||||
<source>Window 0 enable blend</source>
|
<source>Window 0 enable blend</source>
|
||||||
<translation>La fenêtre nº 0 active le mixage</translation>
|
<translation>La fenêtre nº 0 active le mixage</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="255"/>
|
<location filename="../IOViewer.cpp" line="255"/>
|
||||||
<source>Window 1 enable BG 0</source>
|
<source>Window 1 enable BG 0</source>
|
||||||
<translation>La fenêtre nº 1 active l'arrière plan nº 0</translation>
|
<translation>La fenêtre nº 1 active l'arrière plan nº 0</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="256"/>
|
<location filename="../IOViewer.cpp" line="256"/>
|
||||||
<source>Window 1 enable BG 1</source>
|
<source>Window 1 enable BG 1</source>
|
||||||
<translation>La fenêtre nº 1 active l'arrière plan nº 1</translation>
|
<translation>La fenêtre nº 1 active l'arrière plan nº 1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="257"/>
|
<location filename="../IOViewer.cpp" line="257"/>
|
||||||
<source>Window 1 enable BG 2</source>
|
<source>Window 1 enable BG 2</source>
|
||||||
<translation>La fenêtre nº 1 active l'arrière plan nº 2</translation>
|
<translation>La fenêtre nº 1 active l'arrière plan nº 2</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="258"/>
|
<location filename="../IOViewer.cpp" line="258"/>
|
||||||
<source>Window 1 enable BG 3</source>
|
<source>Window 1 enable BG 3</source>
|
||||||
<translation>La fenêtre nº 1 active l'arrière plan nº 3</translation>
|
<translation>La fenêtre nº 1 active l'arrière plan nº 3</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="259"/>
|
<location filename="../IOViewer.cpp" line="259"/>
|
||||||
<source>Window 1 enable OBJ</source>
|
<source>Window 1 enable OBJ</source>
|
||||||
<translation>La fenêtre nº 1 active l'OBJ</translation>
|
<translation>La fenêtre nº 1 active l'OBJ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="260"/>
|
<location filename="../IOViewer.cpp" line="260"/>
|
||||||
<source>Window 1 enable blend</source>
|
<source>Window 1 enable blend</source>
|
||||||
<translation>La fenêtre nº 1 active le mixage</translation>
|
<translation>La fenêtre nº 1 active le mixage</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="264"/>
|
<location filename="../IOViewer.cpp" line="264"/>
|
||||||
<source>Outside window enable BG 0</source>
|
<source>Outside window enable BG 0</source>
|
||||||
<translation>La fenêtre extérieure active l'arrière plan nº 0</translation>
|
<translation>La fenêtre extérieure active l'arrière plan nº 0</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="265"/>
|
<location filename="../IOViewer.cpp" line="265"/>
|
||||||
<source>Outside window enable BG 1</source>
|
<source>Outside window enable BG 1</source>
|
||||||
<translation>La fenêtre extérieure active l'arrière plan nº 1</translation>
|
<translation>La fenêtre extérieure active l'arrière plan nº 1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="266"/>
|
<location filename="../IOViewer.cpp" line="266"/>
|
||||||
<source>Outside window enable BG 2</source>
|
<source>Outside window enable BG 2</source>
|
||||||
<translation>La fenêtre extérieure active l'arrière plan nº 2</translation>
|
<translation>La fenêtre extérieure active l'arrière plan nº 2</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="267"/>
|
<location filename="../IOViewer.cpp" line="267"/>
|
||||||
<source>Outside window enable BG 3</source>
|
<source>Outside window enable BG 3</source>
|
||||||
<translation>La fenêtre extérieure active l'arrière plan nº 3</translation>
|
<translation>La fenêtre extérieure active l'arrière plan nº 3</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="268"/>
|
<location filename="../IOViewer.cpp" line="268"/>
|
||||||
|
@ -1981,7 +1981,7 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<location filename="../IOViewer.cpp" line="330"/>
|
<location filename="../IOViewer.cpp" line="330"/>
|
||||||
<location filename="../IOViewer.cpp" line="1101"/>
|
<location filename="../IOViewer.cpp" line="1101"/>
|
||||||
<source>Sweep time (in 1/128s)</source>
|
<source>Sweep time (in 1/128s)</source>
|
||||||
<translation>Durée de balayage (en 1/128 s)</translation>
|
<translation>Durée de balayage (en 1/128 s)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="334"/>
|
<location filename="../IOViewer.cpp" line="334"/>
|
||||||
|
@ -2090,28 +2090,28 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<location filename="../IOViewer.cpp" line="376"/>
|
<location filename="../IOViewer.cpp" line="376"/>
|
||||||
<location filename="../IOViewer.cpp" line="1158"/>
|
<location filename="../IOViewer.cpp" line="1158"/>
|
||||||
<source>0%</source>
|
<source>0%</source>
|
||||||
<translation>0 %</translation>
|
<translation>0 %</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="377"/>
|
<location filename="../IOViewer.cpp" line="377"/>
|
||||||
<location filename="../IOViewer.cpp" line="434"/>
|
<location filename="../IOViewer.cpp" line="434"/>
|
||||||
<location filename="../IOViewer.cpp" line="1159"/>
|
<location filename="../IOViewer.cpp" line="1159"/>
|
||||||
<source>100%</source>
|
<source>100%</source>
|
||||||
<translation>100 %</translation>
|
<translation>100 %</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="378"/>
|
<location filename="../IOViewer.cpp" line="378"/>
|
||||||
<location filename="../IOViewer.cpp" line="433"/>
|
<location filename="../IOViewer.cpp" line="433"/>
|
||||||
<location filename="../IOViewer.cpp" line="1160"/>
|
<location filename="../IOViewer.cpp" line="1160"/>
|
||||||
<source>50%</source>
|
<source>50%</source>
|
||||||
<translation>50 %</translation>
|
<translation>50 %</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="379"/>
|
<location filename="../IOViewer.cpp" line="379"/>
|
||||||
<location filename="../IOViewer.cpp" line="432"/>
|
<location filename="../IOViewer.cpp" line="432"/>
|
||||||
<location filename="../IOViewer.cpp" line="1161"/>
|
<location filename="../IOViewer.cpp" line="1161"/>
|
||||||
<source>25%</source>
|
<source>25%</source>
|
||||||
<translation>25 %</translation>
|
<translation>25 %</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="380"/>
|
<location filename="../IOViewer.cpp" line="380"/>
|
||||||
|
@ -2119,7 +2119,7 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<location filename="../IOViewer.cpp" line="382"/>
|
<location filename="../IOViewer.cpp" line="382"/>
|
||||||
<location filename="../IOViewer.cpp" line="383"/>
|
<location filename="../IOViewer.cpp" line="383"/>
|
||||||
<source>75%</source>
|
<source>75%</source>
|
||||||
<translation>75 %</translation>
|
<translation>75 %</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="405"/>
|
<location filename="../IOViewer.cpp" line="405"/>
|
||||||
|
@ -2944,17 +2944,17 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="1016"/>
|
<location filename="../IOViewer.cpp" line="1016"/>
|
||||||
<source>4.19MHz</source>
|
<source>4.19MHz</source>
|
||||||
<translation>4,19 MHz</translation>
|
<translation>4,19 MHz</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="1017"/>
|
<location filename="../IOViewer.cpp" line="1017"/>
|
||||||
<source>8.38MHz</source>
|
<source>8.38MHz</source>
|
||||||
<translation>8,38 MHz</translation>
|
<translation>8,38 MHz</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="1018"/>
|
<location filename="../IOViewer.cpp" line="1018"/>
|
||||||
<source>16.78MHz</source>
|
<source>16.78MHz</source>
|
||||||
<translation>16,78 MHz</translation>
|
<translation>16,78 MHz</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../IOViewer.cpp" line="1020"/>
|
<location filename="../IOViewer.cpp" line="1020"/>
|
||||||
|
@ -3407,7 +3407,7 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../LogController.cpp" line="68"/>
|
<location filename="../LogController.cpp" line="68"/>
|
||||||
<source>[%1] %2: %3</source>
|
<source>[%1] %2: %3</source>
|
||||||
<translation>[%1] %2 : %3</translation>
|
<translation>[%1] %2 : %3</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../LogController.cpp" line="79"/>
|
<location filename="../LogController.cpp" line="79"/>
|
||||||
|
@ -4836,7 +4836,7 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ROMInfo.ui" line="26"/>
|
<location filename="../ROMInfo.ui" line="26"/>
|
||||||
<source>Game name:</source>
|
<source>Game name:</source>
|
||||||
<translation>Nom du jeu :</translation>
|
<translation>Nom du jeu :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ROMInfo.ui" line="33"/>
|
<location filename="../ROMInfo.ui" line="33"/>
|
||||||
|
@ -5271,7 +5271,7 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="371"/>
|
<location filename="../SettingsView.ui" line="371"/>
|
||||||
<source>FPS target:</source>
|
<source>FPS target:</source>
|
||||||
<translation>IPS ciblée :</translation>
|
<translation>IPS ciblée :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="396"/>
|
<location filename="../SettingsView.ui" line="396"/>
|
||||||
|
@ -5727,7 +5727,7 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1671"/>
|
<location filename="../SettingsView.ui" line="1671"/>
|
||||||
<source>Default sprite colors 1:</source>
|
<source>Default sprite colors 1:</source>
|
||||||
<translation>Couleurs par défaut de la sprite nº 1 :</translation>
|
<translation>Couleurs par défaut de la sprite nº 1 :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1758"/>
|
<location filename="../SettingsView.ui" line="1758"/>
|
||||||
|
@ -5737,17 +5737,17 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd.</
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1502"/>
|
<location filename="../SettingsView.ui" line="1502"/>
|
||||||
<source>Game Boy-only model:</source>
|
<source>Game Boy-only model:</source>
|
||||||
<translation>Modèle Game Boy uniquement :</translation>
|
<translation>Modèle Game Boy uniquement :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1522"/>
|
<location filename="../SettingsView.ui" line="1522"/>
|
||||||
<source>Game Boy Color-only model:</source>
|
<source>Game Boy Color-only model:</source>
|
||||||
<translation>Modèle Game Boy uniquement :</translation>
|
<translation>Modèle Game Boy uniquement :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SettingsView.ui" line="1532"/>
|
<location filename="../SettingsView.ui" line="1532"/>
|
||||||
<source>Game Boy/Game Boy Color model:</source>
|
<source>Game Boy/Game Boy Color model:</source>
|
||||||
<translation>Modèle Game Boy / Game Boy Color :</translation>
|
<translation>Modèle Game Boy / Game Boy Color :</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -48,8 +48,10 @@ endif()
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
list(APPEND SDL_LIBRARY imm32 setupapi version winmm)
|
list(APPEND SDL_LIBRARY imm32 setupapi version winmm)
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework AppKit -framework AudioUnit -framework Carbon -framework CoreAudio -framework AudioToolbox -framework ForceFeedback -framework IOKit")
|
list(APPEND SDL_LIBRARY "-framework AppKit" "-framework AudioUnit" "-framework Carbon" "-framework CoreAudio" "-framework AudioToolbox" "-framework ForceFeedback" "-framework IOKit")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE)
|
if(NOT CMAKE_SYSTEM_VERSION VERSION_LESS "17.0") # Darwin 17.x is macOS 10.13
|
||||||
|
list(APPEND SDL_LIBRARY "-framework Metal")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT SDLMAIN_LIBRARY)
|
if(NOT SDLMAIN_LIBRARY)
|
||||||
|
|
|
@ -924,7 +924,7 @@ int main(int argc, char* argv[]) {
|
||||||
.configExtra = (struct GUIMenuItem[]) {
|
.configExtra = (struct GUIMenuItem[]) {
|
||||||
{
|
{
|
||||||
.title = "Screen mode",
|
.title = "Screen mode",
|
||||||
.data = "screenMode",
|
.data = GUI_V_S("screenMode"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = SM_PA,
|
.state = SM_PA,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -936,7 +936,7 @@ int main(int argc, char* argv[]) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Fast forward cap",
|
.title = "Fast forward cap",
|
||||||
.data = "fastForwardCap",
|
.data = GUI_V_S("fastForwardCap"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 7,
|
.state = 7,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -966,7 +966,7 @@ int main(int argc, char* argv[]) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "GPU-accelerated renderer",
|
.title = "GPU-accelerated renderer",
|
||||||
.data = "hwaccelVideo",
|
.data = GUI_V_S("hwaccelVideo"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 0,
|
.state = 0,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -977,7 +977,7 @@ int main(int argc, char* argv[]) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Hi-res scaling (requires GPU rendering)",
|
.title = "Hi-res scaling (requires GPU rendering)",
|
||||||
.data = "videoScale",
|
.data = GUI_V_S("videoScale"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 0,
|
.state = 0,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -1000,7 +1000,7 @@ int main(int argc, char* argv[]) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Use built-in brightness sensor for Boktai",
|
.title = "Use built-in brightness sensor for Boktai",
|
||||||
.data = "useLightSensor",
|
.data = GUI_V_S("useLightSensor"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = illuminanceAvailable,
|
.state = illuminanceAvailable,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
|
|
@ -490,7 +490,7 @@ int main(int argc, char* argv[]) {
|
||||||
.configExtra = (struct GUIMenuItem[]) {
|
.configExtra = (struct GUIMenuItem[]) {
|
||||||
{
|
{
|
||||||
.title = "Video mode",
|
.title = "Video mode",
|
||||||
.data = "videoMode",
|
.data = GUI_V_S("videoMode"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 0,
|
.state = 0,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -503,7 +503,7 @@ int main(int argc, char* argv[]) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Screen mode",
|
.title = "Screen mode",
|
||||||
.data = "screenMode",
|
.data = GUI_V_S("screenMode"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 0,
|
.state = 0,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -514,7 +514,7 @@ int main(int argc, char* argv[]) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Filtering",
|
.title = "Filtering",
|
||||||
.data = "filter",
|
.data = GUI_V_S("filter"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 0,
|
.state = 0,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -526,7 +526,7 @@ int main(int argc, char* argv[]) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Horizontal stretch",
|
.title = "Horizontal stretch",
|
||||||
.data = "stretchWidth",
|
.data = GUI_V_S("stretchWidth"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 7,
|
.state = 7,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
@ -546,7 +546,7 @@ int main(int argc, char* argv[]) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.title = "Vertical stretch",
|
.title = "Vertical stretch",
|
||||||
.data = "stretchHeight",
|
.data = GUI_V_S("stretchHeight"),
|
||||||
.submenu = 0,
|
.submenu = 0,
|
||||||
.state = 6,
|
.state = 6,
|
||||||
.validStates = (const char*[]) {
|
.validStates = (const char*[]) {
|
||||||
|
|
|
@ -94,7 +94,7 @@ static bool _refreshDirectory(struct GUIParams* params, const char* currentPath,
|
||||||
} else {
|
} else {
|
||||||
name = strdup(name);
|
name = strdup(name);
|
||||||
}
|
}
|
||||||
*GUIMenuItemListAppend(currentFiles) = (struct GUIMenuItem) { .title = name, .data = (void*) de->type(de) };
|
*GUIMenuItemListAppend(currentFiles) = (struct GUIMenuItem) { .title = name, .data = GUI_V_U(de->type(de)) };
|
||||||
++items;
|
++items;
|
||||||
}
|
}
|
||||||
qsort(GUIMenuItemListGetPointer(currentFiles, 1), GUIMenuItemListSize(currentFiles) - 1, sizeof(struct GUIMenuItem), _strpcmp);
|
qsort(GUIMenuItemListGetPointer(currentFiles, 1), GUIMenuItemListSize(currentFiles) - 1, sizeof(struct GUIMenuItem), _strpcmp);
|
||||||
|
@ -124,7 +124,7 @@ static bool _refreshDirectory(struct GUIParams* params, const char* currentPath,
|
||||||
params->drawEnd();
|
params->drawEnd();
|
||||||
}
|
}
|
||||||
struct GUIMenuItem* testItem = GUIMenuItemListGetPointer(currentFiles, item);
|
struct GUIMenuItem* testItem = GUIMenuItemListGetPointer(currentFiles, item);
|
||||||
if (testItem->data != (void*) VFS_FILE) {
|
if (!GUIVariantCompareUInt(testItem->data, VFS_FILE)) {
|
||||||
++item;
|
++item;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
|
||||||
if (reason != GUI_MENU_EXIT_BACK) {
|
if (reason != GUI_MENU_EXIT_BACK) {
|
||||||
return reason;
|
return reason;
|
||||||
}
|
}
|
||||||
} else if ((*item)->validStates && !(*item)->data) {
|
} else if ((*item)->validStates && !(*item)->data.v.p) {
|
||||||
_itemNext(*item, true);
|
_itemNext(*item, true);
|
||||||
} else {
|
} else {
|
||||||
return GUI_MENU_EXIT_ACCEPT;
|
return GUI_MENU_EXIT_ACCEPT;
|
||||||
|
@ -152,7 +152,7 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
|
||||||
|
|
||||||
params->drawStart();
|
params->drawStart();
|
||||||
if (menu->background) {
|
if (menu->background) {
|
||||||
menu->background->draw(menu->background, GUIMenuItemListGetPointer(&menu->items, menu->index)->data);
|
menu->background->draw(menu->background, GUIMenuItemListGetPointer(&menu->items, menu->index)->data.v.p);
|
||||||
}
|
}
|
||||||
if (params->guiPrepare) {
|
if (params->guiPrepare) {
|
||||||
params->guiPrepare();
|
params->guiPrepare();
|
||||||
|
|
Loading…
Reference in New Issue