Compare commits

...

310 Commits

Author SHA1 Message Date
Lior Halphon 8a234a25a3 Add silence detection to eliminate rounding artifacts when playing nothing but frequencies above Nyquist. Fixes #394 2025-08-18 21:27:01 +03:00
Lior Halphon 5b88346537 Work around an MSVCRT limitation, fixes cheat import on SDL Windows, fixes #716 2025-08-03 16:54:04 +03:00
Lior Halphon 20e5e18122 Update version to v1.0.2 2025-08-01 00:49:49 +03:00
Lior Halphon b948a1f3fd Fix Solarium beta 4 regressions 2025-08-01 00:49:41 +03:00
Lior Halphon 8215c03d62 Update assets.car, screw this format 2025-07-29 22:49:27 +03:00
Lior Halphon 8b2af8adf1 Replace non-car iOS icons with the correct versions 2025-07-27 19:09:35 +03:00
Lior Halphon 00f772b29d Merge branch 'master' of github.com:LIJI32/SameBoy 2025-07-27 13:23:58 +03:00
Lior Halphon 4107198548
Merge pull request #715 from MaddTheSane/patch-2
Update GBViewController.m
2025-07-27 12:26:34 +03:00
C.W. Betts e997ce0ce7
Update GBViewController.m
-[GBViewController didRotateFromInterfaceOrientation:] seems to want [super ...] called to it.
2025-07-26 23:14:45 -06:00
Lior Halphon 58c946f249 Fix accelerometer auto-rotating on iOS 16 and newer 2025-07-27 03:10:17 +03:00
Lior Halphon 0b57886491 Add an icon to hotswap 2025-07-23 23:42:34 +03:00
Lior Halphon 2db60c2b3f Add the missing camera entitlement even on unnotarized releases that don't use the hardened runtime 2025-07-23 23:42:19 +03:00
Lior Halphon f54bfae01f Make headers a target 2025-07-23 00:18:51 +03:00
Lior Halphon c40221abb6 Allow using the DISABLE_* flags when building specific subsets of the lib target 2025-07-22 23:32:00 +03:00
Lior Halphon eb38034b76 Ask for confirmation before reset 2025-07-22 00:10:19 +03:00
Lior Halphon c6a968ed74 Make sure to display an alert if saving a state failed 2025-07-22 00:03:37 +03:00
Lior Halphon e69f6b8579 Bug fix: GB_save_state always returned success 2025-07-21 23:53:54 +03:00
Lior Halphon cfbc7b481a An attempt to mitigate #703, don't reload the ROM or save states if not required; don't assume a new ROM if state failed to load 2025-07-21 23:45:06 +03:00
Lior Halphon 1dfcdffa71 Properly handled Inbox and Boot ROMs in GBROMManager 2025-07-20 22:44:09 +03:00
Lior Halphon 5b983bc7ad Minor optimization 2025-07-20 21:58:36 +03:00
Lior Halphon 634b90e4fc Fix rounding errors in calls to band_limited_update, tweak BL synth parameters. Should greatly improve audio quality, fixes #713 2025-07-18 13:53:02 +03:00
Lior Halphon b31cca77be Use a sinc filter 2025-07-18 13:32:25 +03:00
Lior Halphon 5b17b41e07 Escape translocation on launch so we can update ourselves. 2025-07-12 04:16:31 +03:00
Lior Halphon 239e0462c3 Use proper hooks 2025-07-12 01:25:40 +03:00
Lior Halphon 8505f00cdf Fix BL-synth master wave generation, that wasn't a square step... affects #713 2025-07-12 01:17:47 +03:00
Lior Halphon 08d58aa992 Fix a bug where controller-triggered rewind doesn't resume after reaching the buffer end 2025-07-11 23:14:03 +03:00
Lior Halphon 8cce6f7b13 Another macOS Regressionville™ bugfix 2025-07-11 18:19:19 +03:00
Lior Halphon ec8baa6329 Allow specifying a custom ibtool path 2025-07-11 18:03:36 +03:00
Lior Halphon 9bd84978cf Work around more Solarium bugs 2025-07-11 17:59:32 +03:00
Lior Halphon aa0fe30d5c Don't update the icon after an update on macOS 26, it's broken 2025-07-11 17:59:13 +03:00
Lior Halphon 6d6aafe887 Fix scrolling view in newer macOS versions 2025-07-11 14:46:16 +03:00
Lior Halphon 003e8914b1
Merge pull request #711 from MaddTheSane/patch-2
Update GBViewController.m
2025-07-08 00:06:08 +03:00
Lior Halphon d7e1672ae7 Always define typeof to __typeof__, unless targeting C23. Fixes #710 2025-07-08 00:04:07 +03:00
C.W. Betts 1157ff0f36
Update GBViewController.m
Use CGDataProviderCreateWithCFData instead of CGDataProviderCreateWithData.
2025-07-07 13:52:02 -06:00
Lior Halphon bdd4522ca9 Migrate the Windows build from GNUWin to Git Bash and ezwinports's Make 2025-07-07 22:34:45 +03:00
Lior Halphon 4abb5f3539 Fix AGB mixing – the bias should only be applied if the channel is connected to a terminal 2025-07-05 16:37:48 +03:00
Lior Halphon aff7f1706c Add turbo cap options to the core and frontends, improve frame skipping, replace iOS' turbo speed option with the new turbo cap. Addresses #708. 2025-07-04 14:41:34 +03:00
Lior Halphon 33d237706e
Merge pull request #709 from joshrad-dev/master
Add ability to save to photos on iOS
2025-06-29 23:05:20 +03:00
Lior Halphon a39efd31cf Change the default macOS palette to be the same as the other frontends 2025-06-29 22:42:45 +03:00
Lior Halphon 69bb4c3e95 Fix various iPadOS bugs 2025-06-29 20:17:05 +03:00
Lior Halphon ae2d68aaf3 iPad menu support 2025-06-29 18:48:47 +03:00
Lior Halphon e381ebd1ea Refine the tip animation 2025-06-28 21:29:26 +03:00
Lior Halphon 34c29b052e UI fixes in the cheats screen 2025-06-28 20:55:30 +03:00
Lior Halphon 4ebb108ae1 Fix it harder, remove UIGlassEffect as it's still very buggy 2025-06-28 15:58:39 +03:00
Lior Halphon d1da91da7c Fix tip rotation 2025-06-28 15:46:02 +03:00
Lior Halphon 490d63b26f Fix build break 2025-06-28 15:44:16 +03:00
Lior Halphon be63d7eaa3 Revert this hack, broken on iPhones. Maybe Apple will fix this regression eventually (lulz no) 2025-06-28 15:13:05 +03:00
Lior Halphon 15588a065f Fixed a bug where ROMs were moved instead of copied and vice versa, fixes #701 2025-06-28 15:04:14 +03:00
Lior Halphon d52a50353d Update the tips visuals 2025-06-28 14:40:42 +03:00
Lior Halphon 5d70f93920 Very basic iPad menu support 2025-06-28 13:58:43 +03:00
Lior Halphon f3cbc1990e Allow building on older SDKs 2025-06-28 13:06:38 +03:00
Lior Halphon 583c234953 Various iOS Ui improvements, especially on iOS 26 2025-06-28 00:11:46 +03:00
Lior Halphon 3f744254fd Update iOS settings icons, add liquid glass overlay 2025-06-27 17:02:55 +03:00
Lior Halphon 7abedaed4c Fix a bug where cheat search remains open after closing a ROM 2025-06-26 21:36:26 +03:00
Lior Halphon 42ffbd18d0 Fix a bug where a GBS file will not correctly play the first track unless explicitly switching to it. Reloading a GBS file is disabled because it's not supported. 2025-06-26 20:57:47 +03:00
Lior Halphon 8508eb7b7c Fix Mavericks regressions 2025-06-24 22:44:39 +03:00
Lior Halphon 00000971d7 Describe addresses correctly in unbanked portions of RAM and ROM 2025-06-24 21:53:18 +03:00
Lior Halphon 58bd40b833 Work around gazillion Solarium bugs 2025-06-24 21:29:58 +03:00
Lior Halphon cbaf5c4c4a Avoid non-main-thread calls 2025-06-24 21:29:05 +03:00
Lior Halphon 67d338164b Make text field insets work on macOS 26 2025-06-22 23:34:41 +03:00
Jawshoeadan 7bf8145a91 Add save to photos key in info.plist for GB camera pictures 2025-06-21 13:22:31 -07:00
Lior Halphon e043279500 Update the Cocoa UI to support Solarium (Memory viewer still not updated due to AppKit regression, let's see what the next beta has to say) 2025-06-21 14:50:12 +03:00
Lior Halphon 9d6f378d21 Add Icon Composer based icon for macOS 26 2025-06-13 22:54:10 +03:00
Lior Halphon bfb1092cbb Fix cheat search crashing on carts without RAM 2025-06-10 01:19:29 +03:00
Lior Halphon 282140822e Fix compatibility issues with macOS 26 NIB loading 2025-06-10 00:22:14 +03:00
Lior Halphon 19a1e3ec1a Add a vsync as an option to SDL, fixes #335 2025-06-08 20:19:09 +03:00
Lior Halphon 1ad8bad18c Add iOS rapid buttons, closes #702 2025-06-08 19:28:42 +03:00
Lior Halphon 9577cbce85 Added the option to force integer scaling to the Cocoa port (SDL had it for ages), closes #699 2025-06-08 11:51:34 +03:00
Lior Halphon 6dd2f609f2 Make the debugger console larger by default, fix misaligned line 2025-06-08 01:43:17 +03:00
Lior Halphon 976fe7a337 The sideview shouldn't automatically scroll 2025-06-08 01:30:17 +03:00
Lior Halphon 1400bd40e8 Slightly alter the behavior of the print command so values don't get zero-padding by default, fixes #687 2025-06-08 01:25:30 +03:00
Lior Halphon 6a97192e8c Slightly refine the last fix 2025-06-07 18:58:31 +03:00
Lior Halphon 42732b20eb Restore Alt+Zoom behavior 2025-06-07 18:49:45 +03:00
Lior Halphon f0a672c39e Make sure the CPU graph advanced correctly even in turbo mode 2025-06-07 14:24:35 +03:00
Lior Halphon d211120312 Make 100% CPU frames appear red 2025-06-07 14:11:10 +03:00
Lior Halphon 6ab1be654b Add CPU load graph to Cocoa, closes #654 2025-06-06 23:10:57 +03:00
Lior Halphon f706988171 Add CPU usage command (#654) 2025-06-06 19:26:25 +03:00
Lior Halphon bed9f8220c
Merge pull request #706 from Estus-Dev/Specify-size-of-block-header's-length-field
Specify size of block header's length field
2025-06-04 20:33:23 +03:00
Estus 750112f6dd
docs: specify size of block header's length field 2025-06-04 11:21:48 -06:00
Lior Halphon 63a02d90bc
Merge pull request #568 from hitomi-nakayama/warn-sdl-init-error
Warn user about SDL initialization failure
2025-06-02 23:40:54 +03:00
Lior Halphon 795fba1320
Merge branch 'master' into warn-sdl-init-error 2025-06-02 23:40:40 +03:00
Lior Halphon 1923c324d9 Slightly alter iOS behavior 2025-06-02 21:21:39 +03:00
Lior Halphon 6a24b9206f Remove the navigation string since it doesn't fit 2025-06-02 21:21:23 +03:00
Marcus Ziadé 30a8c4bf42 Add Vim menu navigation 2025-05-26 21:46:31 +03:00
Lior Halphon 152e242485 Fixed incorrect processing of GameShark codes 2025-05-26 00:51:16 +03:00
Lior Halphon c4e6161959
Merge pull request #681 from Jan200101/PR/mime-location
correct mimetype location to follow the shared mime info specification
2025-05-25 12:33:20 +03:00
Jan200101 1951df3476
correct mimetype location to follow the shared mime info specification 2025-04-27 16:16:13 +02:00
Lior Halphon 1cf84a5436 Ubuntu 20.04 is dead soon, replace with 22.04 2025-04-08 20:43:21 +03:00
Lior Halphon 81c29fa371 Make gb.h compatible with ANSI C++, fixes #698 2025-04-08 20:39:12 +03:00
Lior Halphon 8b27952680
Merge pull request #697 from bentley/libdl
Don’t look for libdl on OpenBSD
2025-04-05 13:26:43 +03:00
Anthony J. Bentley 3c58deb46f Don’t look for libdl on OpenBSD 2025-04-05 03:18:25 -06:00
Lior Halphon 0fc08d93be Update copyright to 2025 and version to 1.0.1 2025-04-04 23:58:28 +03:00
Lior Halphon cd82311c54 Apply auto-resizing also to border mode change 2025-04-04 14:16:54 +03:00
Lior Halphon bf9212bcff Increase the number of band-limited phases to reduce overtones in high-pitched sounds 2025-04-04 13:27:20 +03:00
Lior Halphon dfd3b42929
Merge pull request #695 from nik012003/master
Add missing break statements in mbc7 writes
2025-04-04 13:03:35 +03:00
nik012003 18edb65680 Add break statements in mbc7 writes 2025-04-04 02:09:18 +02:00
Lior Halphon 3468d5de7e Probably a better fix 2025-04-04 01:11:27 +03:00
Lior Halphon d146b3a309 Why do I end up writing these 2025-04-03 23:52:04 +03:00
Lior Halphon 71d4e60c57 Fix several iOS crashes 2025-04-03 23:37:11 +03:00
Lior Halphon 8f21c8ed66 Fixed a bug that caused ROMs to run without a window upon changing an emulated revision 2025-04-02 23:43:27 +03:00
Lior Halphon 3ad28b7a8d Fix old compilers 2025-04-02 00:31:53 +03:00
Lior Halphon edce971d8c Optimize SGB FM synthesis, downgrade the sample rate of synthesis when rendering at high rates. 2025-04-02 00:27:07 +03:00
Lior Halphon 6d9ab972d0 Allow libretro to output audio for both Game Boys 2025-03-31 00:14:15 +03:00
Lior Halphon ed7d0546a3 Drop the Unicode character, RA can't display it with some fonts 2025-03-31 00:01:23 +03:00
Lior Halphon 474caaccd5 The relevant RA issue is long fixed by now 2025-03-30 22:12:04 +03:00
Lior Halphon 1d7ecb7f1b ^C before loading a ROM quits again 2025-03-30 19:41:07 +03:00
Lior Halphon 8c30a7c90c Fixed a bug where changing a model does not immediately restart upon exiting the emulation menu 2025-03-30 19:34:24 +03:00
Lior Halphon 2b89923a6f SDL now automatically resizes the window upon loading a ROM if it was not manually resized by the user 2025-03-30 00:52:56 +03:00
Lior Halphon 8a0ff891bd Fix build on Clang 20 2025-03-29 23:04:44 +03:00
Lior Halphon 9359f7a2d9 Fix SGB attribute and tile transfers on BE platforms, fixes #693 2025-03-29 19:12:35 +03:00
Lior Halphon f1d52c53d3 Allow using joysticks as faux analog controllers 2025-03-29 14:52:01 +03:00
Lior Halphon 9096f629c9 Fix double ^C quit on non-Windows SDL builds 2025-03-28 13:11:26 +03:00
Lior Halphon d50f9df974 Reset while being paused in SDL now unpauses 2025-03-28 13:11:04 +03:00
Lior Halphon 15215000f9 Major improvements to the SDL debugging interface, especially on Windows
1. No more separate EXE for the debugger version, the console can be freely opened at any time with ^C, and closed freely without terminating the emulator
2. On all platforms, the SDL emulator window is no longer unresponsive while the debugger is waiting for an input
3. Pressing keys in the emulator window while the debugger is waiting for inputs will trigger a terminal bell
4. Async debugging now supports Windows 7, 8.x, and earlier builds of Windows 10
2025-03-27 23:45:51 +02:00
Lior Halphon 4e35048f46 Make it possible to build SameBoy for Windows while linking against Windows' msvct.dll 2025-03-23 23:18:17 +02:00
Lior Halphon e2b22a0df6 Make it possible to disable rounded corners on Windows 11 2025-03-23 21:34:05 +02:00
Lior Halphon 9c958a1cb4 More accurate OAM randomization 2025-03-21 22:52:55 +02:00
Lior Halphon 3cb04e88d1 Remove HH integration 2025-03-15 13:22:55 +02:00
Lior Halphon 917b62785c The watchpoint command now outputs the watchpoint type upon adding one 2025-03-15 12:56:51 +02:00
Lior Halphon 7b511dd76b Document rPGB 2025-03-15 12:56:51 +02:00
Lior Halphon 04cd94de3f Delegate audio downsampling to the libretro frontend, except on the Wii U. Fixes #677. 2025-03-15 12:56:51 +02:00
Lior Halphon da0380c32d Fix libretro boot ROM building 2025-03-15 12:56:51 +02:00
Lior Halphon e76088cde2 I need somebody to love me as much as GitHub loves deprecating upload-artifacts majors 2025-03-15 12:56:51 +02:00
Jan200101 abf108f6b8 add missing include for toupper and isxdigit 2025-03-15 12:56:51 +02:00
Jan200101 fab91444dd strip thumbnailer on release builds, don't strip on install 2025-03-15 12:56:51 +02:00
Lior Halphon 9442a2a8e8 Fix CI, fix library building 2025-03-15 12:56:51 +02:00
Lior Halphon 9793e15f4d Fix the vertical layout being broken on certain iPad resolutions. Minor improvements to other iPad layouts. Fixes #678 2025-03-15 12:56:51 +02:00
Rangi42 670540116a Use `ldh [c]`, not `ld [c]` 2025-03-15 12:56:51 +02:00
Lior Halphon 1354b77373 Oops 2025-03-15 12:56:51 +02:00
Lior Halphon 63e081e9c2 Fix the Pink Pop theme, it had mismatching colors and settings 2025-03-15 12:56:51 +02:00
Lior Halphon 4d28af4fcf Make palettes upgradable in the Cocoa frontend, fixes #672. Slightly improve palette editor UI. 2025-03-15 12:56:51 +02:00
Lior Halphon a659de9960 Update Makefile to support BSD's install, fixes #671 2025-03-15 12:56:51 +02:00
Lior Halphon d6b7157a0c Update version to 1.0 2025-03-15 12:56:51 +02:00
Lior Halphon 48cc359f0c Fix Windows build 2025-03-15 12:56:51 +02:00
Lior Halphon 6549684e1f Make libsameboy installable, including pkg-config support. Closes #662 2025-03-15 12:56:51 +02:00
Lior Halphon 150855f2e9 Sync with the App Store branch 2025-03-15 12:56:51 +02:00
Lior Halphon 215a690e92 Don't display this warning on MBC2/7 games 2025-03-15 12:56:51 +02:00
Lior Halphon 1d5cb77464 Fix bugs that degraded Quick Look quality 2025-03-15 12:56:51 +02:00
Lior Halphon b5761c29d5 Fix missing resolutions 2025-03-15 12:56:51 +02:00
Lior Halphon 7994869b1f Minor fixes and oopsies 2025-03-15 12:56:51 +02:00
Lior Halphon ac54d5b7ec Update Quick Look to support macOS 15 2025-03-15 12:56:51 +02:00
Lior Halphon 9df4f22873 Fix Quick Look 2025-03-15 12:56:51 +02:00
Lior Halphon d049dfe983 Allow changing the debugger input field's font and size 2025-03-15 12:56:51 +02:00
Lior Halphon 4c904d11ff Handle single-color OBP values better in the object viewer 2025-03-15 12:56:51 +02:00
Lior Halphon aa5fc484d1 Fix m3_lcdc_obj_en_change_variant.gb 2025-03-15 12:56:51 +02:00
Lior Halphon 849ae42b99 Fix m3_scx_high_5_bits on DMG 2025-03-15 12:56:51 +02:00
Lior Halphon fe72561a8f Oops, 1.0 isn't ready for release yet 2025-03-15 12:56:31 +02:00
Lior Halphon e5950aa4ef Fix it harder 2024-12-01 19:17:36 +02:00
Lior Halphon 5180e8e03b Fix Linux so builds 2024-12-01 19:06:35 +02:00
Lior Halphon 67dee21804 Fix typos, remove broken and unused macro 2024-12-01 18:58:23 +02:00
Lior Halphon 007d3b2555 Allow building libsameboy as a dynamic lib 2024-12-01 18:57:47 +02:00
Lior Halphon 9ff3bffddd Fix thread assertion in GB_set_sample_rate, should make GB_set_clock_multiplier thread-safe. Fix missing memset. 2024-11-30 00:10:46 +02:00
Lior Halphon 12859683b7 Missing super calls 2024-11-30 00:10:01 +02:00
Lior Halphon 27a064caff Make `GB_serial_set_data_bit` a bit more thread safe 2024-11-24 20:58:12 +02:00
Lior Halphon b4fc2ff7ba Move things around some more 2024-11-24 14:36:12 +02:00
Lior Halphon fe2c868d6c Fix iOS 11/12 builds 2024-11-23 21:03:34 +02:00
Lior Halphon 150f0fcad4 Add a fourth, virtual zoom factor for triple camera iPhones that have a large difference between their zoom factors. Closes #663 2024-11-23 20:55:44 +02:00
Lior Halphon a39b1913b8 Much thread, very safety 2024-11-23 16:23:08 +02:00
Lior Halphon 1ab690ba18 Dead code 2024-11-23 15:47:06 +02:00
Lior Halphon c3d83eae22 Missing assertion in GB_safe_read_memory 2024-11-23 15:45:54 +02:00
Lior Halphon 117da602ca Prevent the rewind buffer from being reset unexpectedly on iOS 2024-11-23 13:54:50 +02:00
Lior Halphon a0c5b6f97a Various optimizations 2024-11-23 00:16:42 +02:00
Lior Halphon 7e071e463d Improve band-limited synth 2024-11-21 21:12:30 +02:00
Lior Halphon ad2360b5c3 Fix tester and Xdg thumbnailer build 2024-11-21 20:24:20 +02:00
Lior Halphon ee3f37b39c Fix button colors in some themes 2024-11-21 19:54:45 +02:00
Lior Halphon ebfc877c1c Fixed a bug that resulted in crashes if the ROM list changed while the library was open. 2024-11-21 17:52:31 +02:00
Lior Halphon 8f9e1e9ea5 Prevent certain APIs from returning 0 despite failing 2024-11-21 17:51:27 +02:00
Lior Halphon 1bf57ece70 Fix iOS builds 2024-11-21 17:51:08 +02:00
Lior Halphon 29d8cca511 Keep moving and renaming things 2024-11-16 22:53:06 +02:00
Lior Halphon 14cf76776a Fix an exception when closing a window with open panels 2024-11-16 17:32:13 +02:00
Lior Halphon f1f97f0692 Make STRUCT_VERSION internal 2024-11-16 17:16:58 +02:00
Lior Halphon 0b5be876b3 Missing _t from types 2024-11-16 17:15:51 +02:00
Lior Halphon fdc39f9bd6 Rename GB_log_attributes to GB_log_attributes_t 2024-11-16 16:53:06 +02:00
Lior Halphon 14e486017a Move things around 2024-11-16 15:19:47 +02:00
Lior Halphon 3bee0deda5 Warn when loading ROMs with RAM sizes less than a bank 2024-11-16 14:33:13 +02:00
Lior Halphon 101e894314 Fixed a rounding error when applying the high-pass filter on high sample rate 2024-11-16 13:59:38 +02:00
Lior Halphon 2e6ff5fd9f Disable filtering on raw audio output 2024-11-16 12:31:45 +02:00
Lior Halphon 2b3ec9d991 Missing nounroll 2024-11-16 02:23:11 +02:00
Lior Halphon 375fb4388c Swap the box filter with band-limited synthesis, fixed a regression that prevented filtering of square waves in some scenarios. Fixes #669 2024-11-16 01:03:14 +02:00
Lior Halphon fc76063ec0 File associations & icons on Windows, use a manifest for themed dialogs 2024-11-15 16:17:42 +02:00
Lior Halphon 6568cca6bb Forgot to update the FreeDesktop icons 2024-11-10 20:21:09 +02:00
Lior Halphon d386ca8726 Retouch the cartridge icons 2024-11-10 20:05:32 +02:00
Lior Halphon f21761338c Allow the Cocoa frontend to pick a monospace font 2024-11-09 17:04:10 +02:00
Lior Halphon 41af62d793 Fix volume being too low in "Always On" audio mode. Fixes #667, fixes #664 2024-11-08 23:54:12 +02:00
Lior Halphon 2dfde867a9 Syncing with the App Store branch 2024-11-08 14:53:16 +02:00
Lior Halphon 6efefab526
Merge pull request #668 from lxgr/lxgr/fix-camera-aspect
Fix macOS camera aspect ratio
2024-11-03 22:30:14 +02:00
Lukas Ribisch 207dc993d4 Fix macOS camera aspect ratio 2024-11-03 11:55:25 -05:00
Lior Halphon 52d5169cc8 Fix A+B combo regression 2024-10-13 14:36:11 +03:00
Lior Halphon 73a6d35f73 Support building SameBoy on Haiku 2024-10-05 14:00:33 +03:00
Lior Halphon 2498456bcc Fix release iOS builds 2024-10-04 15:40:13 +03:00
Lior Halphon ec65cfd942 Fix SDL build on macOS 2024-10-04 15:33:19 +03:00
Lior Halphon 122549d3cd Merge branch 'master' of github.com:LIJI32/SameBoy 2024-10-03 16:21:18 +03:00
Lior Halphon e13048d07b Improve ISX compatibility 2024-10-03 16:21:10 +03:00
Lior Halphon 6eeba2f6f6 Share code between the main Cocoa binary and QuickLook 2024-09-27 16:19:58 +03:00
Lior Halphon 1fac8870d4
Merge pull request #658 from RSilicon/ARC
Remove xpc_release for ARC
2024-09-22 23:09:38 +03:00
Rose 741637e625 Remove xpc_release for ARC
xpc objects are handled by ARC.
2024-09-22 16:07:09 -04:00
Lior Halphon 73168aa7f2
Merge pull request #657 from RSilicon/More
Fix some clang-tidy warnings
2024-09-22 23:00:21 +03:00
Rose 7e5996df82 Fix some clang-tidy warnings
- Use nil, not NULL for objects
- Call Objective-C release instead of CFRelease (unless like we are hacking around ARC, which we are not)
- xpc_release to release xpc objects.
2024-09-22 15:54:26 -04:00
Lior Halphon 52de44049c Better horizontal layouts on notched iPhones 2024-09-22 14:58:51 +03:00
Lior Halphon f5c7c4443d
Merge pull request #656 from RSilicon/Drawing
Modifier masks are NSUInteger
2024-09-22 14:01:04 +03:00
Lior Halphon db5fa8df4c Change the button style in the palette editor 2024-09-22 12:25:25 +03:00
Lior Halphon 177859bec6 New palettes 2024-09-22 12:21:32 +03:00
Lior Halphon bd3799d431 Fix glitchy palette import on macOS 2024-09-22 11:57:50 +03:00
Rose e533b59759 Modifier masks are NSUInteger 2024-09-21 20:30:11 -04:00
Lior Halphon 38e2760531 Add the ability to create no palettes 2024-09-22 01:23:30 +03:00
Lior Halphon 447cdf2672 Allow editing existing palettes 2024-09-21 21:59:21 +03:00
Lior Halphon 062d44e065 Allow import and export of palettes 2024-09-20 17:50:15 +03:00
Lior Halphon f33f3f6951 Basic palette management 2024-09-19 23:25:26 +03:00
Lior Halphon 291887cd10 Fix model swapping and reset 2024-09-19 22:45:54 +03:00
Lior Halphon 8ded1ca3b3 Move the palette picker to its own class 2024-09-19 21:02:59 +03:00
Lior Halphon 2aa4726e01 Add missing Info.plist item 2024-09-15 22:21:32 +03:00
Lior Halphon 3a7e5ecac5 Fix iOS build 2024-09-15 21:46:33 +03:00
Lior Halphon 5d952565c9 Switch to a pre-built Assets.car file iOS icons, add dark and tinted (iOS 18) icons 2024-09-15 21:46:29 +03:00
Lior Halphon 42be4ef827 Add flat CRT shader 2024-09-15 20:49:49 +03:00
Lior Halphon 1931c2830f Syncing with the App Store branch (iCloud support) 2024-09-15 00:08:54 +03:00
Lior Halphon 8cb94e7a8b
Merge pull request #655 from MaddTheSane/patch-2
Fix a memory leak in GBLoadROMTableViewController.m
2024-09-13 03:56:04 +03:00
C.W. Betts 8c8e59cd81
Update GBLoadROMTableViewController.m
Fix a memory leak with UTTypeCopyAllTagsWithClass.
2024-09-12 17:49:06 -06:00
Lior Halphon ece40bcf0e Fix multi touch 2024-09-12 21:06:11 +03:00
Lior Halphon 392bc8c0d9 Move HomeBrew Hub to a tab bar 2024-09-07 17:39:38 +03:00
Lior Halphon 8e3d8c4a18 Fix zip selection 2024-09-07 01:27:26 +03:00
Lior Halphon 92f425655d iOS cheats support 2024-09-07 01:25:11 +03:00
Lior Halphon 50a56a4b68 UI fixes 2024-09-01 01:38:00 +03:00
Lior Halphon 11f70c09af Use spaces rather than tabs for the iOS plist 2024-08-31 21:09:05 +03:00
Lior Halphon a372b2ec0f Printer emulation in iOS 2024-08-31 21:06:31 +03:00
Lior Halphon 7127e3e068 Remove IDE shit 2024-08-31 15:43:27 +03:00
Lior Halphon f1b187d512 Use … instead of ... 2024-08-31 15:34:19 +03:00
Lior Halphon 11b9c4fab7 Minor text alignment issues 2024-08-31 15:05:50 +03:00
Lior Halphon b88a3a02a9 Fix the cheat window's appearance in Mavericks 2024-08-31 14:59:05 +03:00
Lior Halphon 619792db7f Fix link cable support is macOS 10.13 and older 2024-08-31 13:54:22 +03:00
Lior Halphon bd5d01c0a4 Game Genie has a space 2024-08-31 13:42:18 +03:00
Lior Halphon 4647c55949 Add new iOS tip 2024-08-30 17:06:26 +03:00
Lior Halphon d97c2fb701 Add Rapid A/B to Cocoa and SDL, closes #589 2024-08-30 16:12:31 +03:00
Lior Halphon d4c715b5f0 Associate panels with their document windows 2024-08-29 21:52:55 +03:00
Lior Halphon 8dda5ee098 Always center windows in Cocoa 2024-08-29 20:59:32 +03:00
Lior Halphon 5b33cebca9 Fix iOS and lib builds 2024-08-29 01:26:13 +03:00
Lior Halphon 6178ff2a78 Cheat Search API, Cheat Search in Cocoa, and new cheats window layout 2024-08-29 01:11:47 +03:00
Lior Halphon fc508427b8 More workarounds for the UTI bugs 2024-08-26 20:45:49 +03:00
Lior Halphon 430e42fa72 Prevent the "Mute" menu item from being incorrectly displayed as marked while paused 2024-08-25 18:03:01 +03:00
Lior Halphon c7c54abb6b Remove auto-generated IDE crap 2024-08-25 17:55:48 +03:00
Lior Halphon b6c6b9ed54 Automatic model selection in the Cocoa and SDL frontends, closes #648 2024-08-25 14:36:48 +03:00
Lior Halphon f0bab07f26 Allow controllers to switch the iOS frontend to full screen mode 2024-08-24 20:02:16 +03:00
Lior Halphon 645ef429bc Oops 2024-08-23 14:25:18 +03:00
Lior Halphon a7d977a5c5 Improved AirPlay mirroring 2024-08-23 14:20:53 +03:00
Lior Halphon 795d772c83 Allow deleting ROMs from the context menu in the iOS version 2024-08-18 19:28:27 +03:00
Lior Halphon 2b2bb3569b Add ZIP import support to the iOS version 2024-08-18 19:19:01 +03:00
Lior Halphon fb8508ea20 Fix an issue that could make the logo incorrectly positioned on a potential new iPhone model 2024-08-17 19:35:41 +03:00
Lior Halphon 461083523a Correctly emulate LYC edge cases when emulating CGB-0 to CGB-C in double speed mode 2024-08-16 20:51:40 +03:00
Lior Halphon b8e32e6d53 More accurate window emulation, especially in double speed mode 2024-08-13 21:11:38 +03:00
Lior Halphon d5c6ed9510 Correctly list removed breakpoints/watchpoints 2024-08-10 19:38:54 +03:00
Lior Halphon 47cdefd3d0 Minor adjustments to the CGB WX glitch 2024-08-02 20:45:17 +03:00
Lior Halphon 53fc5a74ed CoreHaptics is trash. 2024-07-31 00:58:30 +03:00
Lior Halphon 035291b955 Fix the comparison operators having the wrong priority 2024-07-27 22:39:56 +03:00
Lior Halphon 5f71ec4974 Slightly more accurate 2024-07-26 14:04:41 +03:00
Lior Halphon 5eb0e5d605 Minor regression fix 2024-07-26 02:43:31 +03:00
Lior Halphon b1ea179513 Improve various edge cases of window emulation, improve the emulation of the last quirk 2024-07-25 22:32:28 +03:00
Lior Halphon d34579e3bb Window accuracy improvements, implement a new CGB window glitch 2024-07-21 23:38:40 +03:00
Lior Halphon 64cf389edf Simplify wx=166 code 2024-07-14 13:00:39 +03:00
Lior Halphon 0c9cf8d594 Build fix 2024-07-13 17:11:39 +03:00
Lior Halphon 44b70bf275 Improve WX=166 accuracy on pre-CGB models 2024-07-13 17:06:29 +03:00
Lior Halphon 06c6ce7d65 More accurate fetcher timings. More accurate visual glitches in Mr. Chin's Gourmet Paradise; Turrican. 2024-07-11 00:21:04 +03:00
Lior Halphon 9d4d535758 Merge remote-tracking branch 'xdg-thumbnailer/xdg-thumbnailer' 2024-07-08 19:49:41 +03:00
ISSOtm 136e11cc13 Avoid using GNU-isms in `make install`
For macOS compat
2024-07-08 01:19:01 +02:00
Lior Halphon 18206718e3 Adjustment to SCX's write conflict implementation 2024-07-08 00:18:27 +03:00
Lior Halphon c3e3fb91cc Improve PPU timings in CGB revision 0 to C. These revisions are no longer marked as experimental. 2024-07-08 00:00:27 +03:00
Lior Halphon a4525c3336 Slightly improve OAM read blocking timing 2024-07-07 16:09:53 +03:00
Lior Halphon 5dbddb344d Size expects an integer 2024-07-06 15:44:01 +03:00
Lior Halphon a66d4ea64c Minor adjustments 2024-07-06 15:29:04 +03:00
Lior Halphon 3dad68618e Fix build on macOS 2024-07-06 15:03:41 +03:00
ISSOtm 366c374461 Switch to "west `const`" instead of "east `const`" 2024-07-05 22:27:30 +02:00
ISSOtm 6e1112157c Address review comments 2024-07-05 22:16:06 +02:00
ISSOtm 488f17941f Add forgotten theme name when installing FreeDesktop icons
*facepalm*
2024-07-04 23:51:49 +02:00
ISSOtm 1dde5c1ce1 Have `make install` install the thumbnailer file as well 2024-07-04 23:39:32 +02:00
ISSOtm 17f1b91b8c Fix and simplify `make install`
`install` does not operate recursively on directories.

Exclude the `sameboy` executable from that copy,
and use a single `install` command to perform all of it.

The icon names are in the `NxN` format, including the target dirs.
2024-07-04 23:34:48 +02:00
ISSOtm 4f25521cba Improve MIME type description a little 2024-07-04 23:18:00 +02:00
ISSOtm 64ad67d5a5 Avoid overriding globs used to detect MIME types 2024-07-04 22:36:32 +02:00
ISSOtm a26c57d582 Use `icons` directory for icons instead of legacy `pixmaps` 2024-07-04 22:34:34 +02:00
ISSOtm 64d45dd23a Only strip the correct file on install 2024-07-04 22:14:59 +02:00
ISSOtm 8e2769b946 Clean up `make install` 2024-07-04 22:00:27 +02:00
ISSOtm 4cc34f97ec Scrap all of that, and use the undocumented spec that everyone actually uses 2024-07-04 20:02:51 +02:00
ISSOtm 323f3e89b7 Generate thumbnails under the appropriate path 2024-07-04 11:14:13 +02:00
Lior Halphon 482b9a1562 Cherrypick libretro/SameBoy#91 2024-07-03 23:38:34 +03:00
ISSOtm c6103d23fa Address review comments 2024-06-29 22:26:49 +02:00
ISSOtm 0b6a73f380 Implement image compositing and rendering
Not saving to the correct place yet, but almost there!
2024-06-28 16:14:58 +02:00
ISSOtm d873abfadf Switch to embedding cartridge templates and boot ROM as GResources
Also set up gdk-pixbuf in the Makefile, which will be used for image ops
2024-06-27 02:27:07 +02:00
ISSOtm 446fc15521 Emulate the ROM to be thumbnailed
Now all that's left is actually rendering that!
2024-06-27 00:00:32 +02:00
ISSOtm b3cecf2413 Implement the "plumbing" around thumbnail generation
Only the actual thumbnail generation is left!
2024-06-26 22:59:03 +02:00
ISSOtm e4ceb3d93b Begin implementing thumbnailer for Linux 2024-06-26 09:59:47 +02:00
Lior Halphon cee486ab11 Merge pull request #433 2024-06-21 16:52:41 +03:00
Lior Halphon 407e540638 Fix conflicts between controller-triggered run modes and swipe-triggered run-mode. Fixes #640 2024-06-28 17:42:53 +03:00
Lior Halphon 8db2490077 Merge pull request #642 from logicalmoody/master 2024-06-28 16:55:16 +03:00
Lior Halphon d42aad2b84 Minor stylistic changes 2024-06-28 16:54:20 +03:00
Cal Moody 3bf94d281a fix issues with change camera button 2024-06-26 19:06:05 -04:00
Cal Moody 66da5fd530 move camera change button into @available check; fix change camera button position 2024-06-26 15:02:24 -04:00
Cal Moody 5c21c5e985 fix spacing 2024-06-25 22:31:47 -04:00
Cal Moody 25576899d8 add support for changing which back camera is being used 2024-06-25 22:27:16 -04:00
Lior Halphon d07b199668 Improve audio anti-aliasing, allow 2MHz output 2024-06-23 20:10:22 +03:00
Lior Halphon ad5ca0dcf0 Switch to 2MHz units in apu_cycles 2024-06-23 15:23:29 +03:00
Lior Halphon 9991c3b0b4 Permanent workaround for an SDK/Clang/ld bug – fixes compatibility with 10.9 and 10.10 when linking against 14.x SDKs 2024-06-22 19:37:04 +03:00
Lior Halphon c9dfc86291 Style fixes 2024-06-21 16:51:51 +03:00
Lior Halphon 2bf5819c36 Merge branch 'master' into console_flash 2024-06-22 16:28:13 +03:00
Lior Halphon 08178c9f3a
Merge pull request #638 from Rangi42/bootroms
Update bootrom code with the latest hardware.inc
2024-06-21 01:20:35 +03:00
Lior Halphon 3581945d85
Use a variable rather than a macro 2024-06-21 01:19:31 +03:00
Rangi42 77b7f861f3 Make review changes 2024-06-20 18:15:07 -04:00
Rangi42 9588cf44aa Update bootrom code with the latest hardware.inc 2024-06-20 13:15:03 -04:00
Lior Halphon 3116f63e37
Merge pull request #631 from laamaa/bugfix/wayland_crash_on_exit
call SDL_Quit() on exit to prevent a crash on app exit with linux/wayland
2024-06-19 20:02:41 +03:00
Lior Halphon 496baafbf9
Explicit void casts is kind of unnecessary for a function that generally never fails. 2024-06-19 20:02:24 +03:00
Jonne Kokkonen 7f110c4415
Add notes to SDL_Quit atexit call
Co-authored-by: Eldred Habert <eldredhabert0@gmail.com>
2024-06-15 20:33:26 +03:00
Jonne Kokkonen ee3878e43a call SDL_Quit() on exit to prevent a crash on wayland 2024-06-02 20:57:46 +03:00
Hitomi Nakayama d267d83cec Added warning for SDL init failure 2023-10-12 17:57:33 -07:00
Anders cead58471d
Don't determine if there is a real console with AllocConsole 2022-02-02 22:22:31 +01:00
306 changed files with 12876 additions and 4441 deletions

1
.gitattributes vendored
View File

@ -7,4 +7,5 @@ HexFiend/* linguist-vendored
Core/*.h linguist-language=C
SDL/*.h linguist-language=C
Windows/*.h linguist-language=C
XdgThumbnailer/*.h linguist-language=C
Cocoa/*.h linguist-language=Objective-C

View File

@ -1,7 +1,7 @@
case `echo $1 | cut -d '-' -f 1` in
ubuntu)
sudo apt-get -qq update
sudo apt-get install -yq bison libpng-dev pkg-config libsdl2-dev
sudo apt-get install -yq bison libpng-dev pkg-config libsdl2-dev libgdk-pixbuf2.0-dev
(
cd `mktemp -d`
curl -L https://github.com/rednex/rgbds/archive/v0.6.0.zip > rgbds.zip

View File

@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, ubuntu-20.04]
os: [macos-latest, ubuntu-latest, ubuntu-22.04]
cc: [gcc, clang]
include:
- os: macos-latest
@ -35,7 +35,7 @@ jobs:
run: |
./.github/actions/sanity_tests.sh
- name: Upload binaries
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: sameboy-canary-${{ matrix.os }}-${{ matrix.cc }}
path: |

View File

@ -5,8 +5,8 @@
@property (nonatomic, strong) void (^renderBlock)(UInt32 sampleRate, UInt32 nFrames, GB_sample_t *buffer);
@property (nonatomic, readonly) UInt32 rate;
@property (nonatomic, readonly, getter=isPlaying) bool playing;
-(void) start;
-(void) stop;
-(id) initWithRendererBlock:(void (^)(UInt32 sampleRate, UInt32 nFrames, GB_sample_t *buffer)) block
- (void)start;
- (void)stop;
- (id)initWithRendererBlock:(void (^)(UInt32 sampleRate, UInt32 nFrames, GB_sample_t *buffer)) block
andSampleRate:(UInt32) rate;
@end

View File

@ -23,7 +23,7 @@ static OSStatus render(
AudioComponentInstance audioUnit;
}
-(id) initWithRendererBlock:(void (^)(UInt32 sampleRate, UInt32 nFrames, GB_sample_t *buffer)) block
- (id)initWithRendererBlock:(void (^)(UInt32 sampleRate, UInt32 nFrames, GB_sample_t *buffer)) block
andSampleRate:(UInt32) rate
{
if (!(self = [super init])) {

View File

@ -32,5 +32,5 @@ typedef enum {
- (void) createInternalView;
- (uint32_t *)currentBuffer;
- (uint32_t *)previousBuffer;
- (instancetype)mirroredView;
@end

View File

@ -6,10 +6,13 @@
unsigned _currentBuffer;
GB_frame_blending_mode_t _frameBlendingMode;
bool _oddFrame;
GBViewBase *_parent;
__weak GBViewBase *_child;
}
- (void)screenSizeChanged
{
if (_parent) return;
if (_imageBuffers[0]) free(_imageBuffers[0]);
if (_imageBuffers[1]) free(_imageBuffers[1]);
if (_imageBuffers[2]) free(_imageBuffers[2]);
@ -23,12 +26,15 @@
- (void)flip
{
if (_parent) return;
_currentBuffer = (_currentBuffer + 1) % self.numberOfBuffers;
_oddFrame = GB_is_odd_frame(_gb);
[_child flip];
}
- (unsigned) numberOfBuffers
{
assert(!_parent);
return _frameBlendingMode? 3 : 2;
}
@ -39,16 +45,23 @@
- (uint32_t *)currentBuffer
{
if (GB_unlikely(_parent)) {
return [_parent currentBuffer];
}
return _imageBuffers[_currentBuffer];
}
- (uint32_t *)previousBuffer
{
if (GB_unlikely(_parent)) {
return [_parent previousBuffer];
}
return _imageBuffers[(_currentBuffer + 2) % self.numberOfBuffers];
}
- (uint32_t *) pixels
{
assert(!_parent);
return _imageBuffers[(_currentBuffer + 1) % self.numberOfBuffers];
}
@ -56,10 +69,14 @@
{
_frameBlendingMode = frameBlendingMode;
[self setNeedsDisplay];
[_child setNeedsDisplay];
}
- (GB_frame_blending_mode_t)frameBlendingMode
{
if (GB_unlikely(_parent)) {
return [_parent frameBlendingMode];
}
if (_frameBlendingMode == GB_FRAME_BLENDING_MODE_ACCURATE) {
if (!_gb || GB_is_sgb(_gb)) {
return GB_FRAME_BLENDING_MODE_SIMPLE;
@ -71,6 +88,7 @@
- (void)dealloc
{
if (_parent) return;
free(_imageBuffers[0]);
free(_imageBuffers[1]);
free(_imageBuffers[2]);
@ -82,4 +100,22 @@
[self setNeedsDisplay:true];
}
#endif
- (void)setGb:(GB_gameboy_t *)gb
{
assert(!_parent);
_gb = gb;
if (_child) {
_child->_gb = gb;
}
}
- (instancetype)mirroredView
{
if (_child) return _child;
GBViewBase *ret = [[self.class alloc] initWithFrame:self.bounds];
ret->_parent = self;
ret->_gb = _gb;
return _child = ret;
}
@end

View File

@ -25,6 +25,7 @@ static const vector_float2 rect[] =
vector_float2 _outputResolution;
id<MTLCommandBuffer> _commandBuffer;
bool _waitedForFrame;
_Atomic unsigned _pendingFrames;
}
+ (bool)isSupported
@ -236,8 +237,11 @@ static const vector_float2 rect[] =
- (void)flip
{
[super flip];
if (_pendingFrames == 2) return;
_pendingFrames++;
dispatch_async(dispatch_get_main_queue(), ^{
[(MTKView *)self.internalView draw];
_pendingFrames--;
});
}

View File

@ -22,9 +22,9 @@ BESS works by appending a detectable footer at the end of an existing save state
BESS uses a block format where each block contains the following header:
| Offset | Content |
|--------|---------------------------------------|
| 0 | A four-letter ASCII identifier |
| 4 | Length of the block, excluding header |
|--------|-----------------------------------------------------------|
| 0 | A four-letter ASCII identifier |
| 4 | Length of the block as a 32-bit integer, excluding header |
Every block is followed by another block, until the END block is reached. If an implementation encounters an unsupported block, it should be completely ignored (Should not have any effect and should not trigger a failure).
@ -256,4 +256,4 @@ Other than previously specified required fail conditions, an implementation is f
* An invalid length of MBC (not a multiple of 3)
* A write outside the $0000-$7FFF and $A000-$BFFF ranges in the MBC block
* An SGB block on a save state targeting another model
* An END block with non-zero length
* An END block with non-zero length

View File

@ -1,2 +1,2 @@
DEF AGB = 1
include "cgb_boot.asm"
DEF AGB = 1
include "cgb_boot.asm"

View File

@ -1,2 +1,2 @@
DEF CGB0 = 1
include "cgb_boot.asm"
DEF CGB0 = 1
include "cgb_boot.asm"

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +1,2 @@
DEF FAST = 1
include "cgb_boot.asm"
DEF FAST = 1
include "cgb_boot.asm"

View File

@ -1,14 +1,14 @@
; SameBoy DMG bootstrap ROM
INCLUDE "hardware.inc"
include "sameboot.inc"
SECTION "BootCode", ROM0[$0]
SECTION "BootCode", ROM0[$0000]
Start:
; Init stack pointer
ld sp, $fffe
ld sp, $FFFE
; Clear memory VRAM
ld hl, $8000
ld hl, _VRAM
xor a
.clearVRAMLoop
@ -17,24 +17,25 @@ Start:
jr z, .clearVRAMLoop
; Init Audio
ld a, $80
ld a, AUDENA_ON
ldh [rNR52], a
assert AUDENA_ON == AUDLEN_DUTY_50
ldh [rNR11], a
ld a, $f3
ldh [rNR12], a
ldh [rNR51], a
ld a, $F3
ldh [rNR12], a ; Envelope $F, decreasing, sweep $3
ldh [rNR51], a ; Channels 1+2+3+4 left, channels 1+2 right
ld a, $77
ldh [rNR50], a
ldh [rNR50], a ; Volume $7, left and right
; Init BG palette
ld a, $54
ld a, %01_01_01_00
ldh [rBGP], a
; Load logo from ROM.
; A nibble represents a 4-pixels line, 2 bytes represent a 4x4 tile, scaled to 8x8.
; Tiles are ordered left to right, top to bottom.
ld de, $104 ; Logo start
ld hl, $8010 ; This is where we load the tiles in VRAM
ld de, NintendoLogo
ld hl, _VRAM + $10 ; This is where we load the tiles in VRAM
.loadLogoLoop
ld a, [de] ; Read 2 rows
@ -43,45 +44,45 @@ Start:
call DoubleBitsAndWriteRow
inc de
ld a, e
xor $34 ; End of logo
xor LOW(NintendoLogoEnd)
jr nz, .loadLogoLoop
; Load trademark symbol
ld de, TrademarkSymbol
ld c,$08
ld c, TrademarkSymbolEnd - TrademarkSymbol
.loadTrademarkSymbolLoop:
ld a,[de]
ld a, [de]
inc de
ldi [hl],a
ldi [hl], a
inc hl
dec c
jr nz, .loadTrademarkSymbolLoop
; Set up tilemap
ld a,$19 ; Trademark symbol
ld [$9910], a ; ... put in the superscript position
ld hl,$992f ; Bottom right corner of the logo
ld c,$c ; Tiles in a logo row
ld a, $19 ; Trademark symbol tile ID
ld [_SCRN0 + 8 * SCRN_VX_B + 16], a ; ... put in the superscript position
ld hl, _SCRN0 + 9 * SCRN_VX_B + 15 ; Bottom right corner of the logo
ld c, 12 ; Tiles in a logo row
.tilemapLoop
dec a
jr z, .tilemapDone
ldd [hl], a
dec c
jr nz, .tilemapLoop
ld l,$0f ; Jump to top row
ld l, $0F ; Jump to top row
jr .tilemapLoop
.tilemapDone
ld a, 30
ldh [rSCY], a
; Turn on LCD
ld a, $91
ld a, LCDCF_ON | LCDCF_BLK01 | LCDCF_BGON
ldh [rLCDC], a
ld d, (-119) & $FF
ld d, LOW(-119)
ld c, 15
.animate
call WaitFrame
ld a, d
@ -94,41 +95,41 @@ Start:
ld a, c
cp 8
jr nz, .noPaletteChange
ld a, $A8
ld a, %10_10_10_00
ldh [rBGP], a
.noPaletteChange
dec c
jr nz, .animate
ld a, $fc
ld a, %11_11_11_00
ldh [rBGP], a
; Play first sound
ld a, $83
call PlaySound
ld b, 5
call WaitBFrames
; Play second sound
ld a, $c1
ld a, $C1
call PlaySound
; Wait ~1 second
ld b, 60
call WaitBFrames
; Set registers to match the original DMG boot
IF DEF(MGB)
ld hl, $FFB0
lb hl, BOOTUP_A_MGB, %10110000
ELSE
ld hl, $01B0
lb hl, BOOTUP_A_DMG, %10110000
ENDC
push hl
pop af
ld hl, $014D
ld bc, $0013
ld de, $00D8
ld hl, HeaderChecksum
lb bc, 0, LOW(rNR13) ; $0013
lb de, 0, $D8 ; $00D8
; Boot the game
jp BootGame
@ -155,7 +156,7 @@ DoubleBitsAndWriteRow:
WaitFrame:
push hl
ld hl, $FF0F
ld hl, rIF
res 0, [hl]
.wait
bit 0, [hl]
@ -171,14 +172,25 @@ WaitBFrames:
PlaySound:
ldh [rNR13], a
ld a, $87
ld a, AUDHIGH_RESTART | $7
ldh [rNR14], a
ret
TrademarkSymbol:
db $3c,$42,$b9,$a5,$b9,$a5,$42,$3c
pusho
opt b.X
db %..XXXX..
db %.X....X.
db %X.XXX..X
db %X.X..X.X
db %X.XXX..X
db %X.X..X.X
db %.X....X.
db %..XXXX..
popo
TrademarkSymbolEnd:
SECTION "BootGame", ROM0[$fe]
SECTION "BootGame", ROM0[$00FE]
BootGame:
ldh [rBANK], a ; unmap boot ROM
ldh [rBANK], a ; unmap boot ROM

View File

@ -1,9 +1,16 @@
;*
;* Gameboy Hardware definitions
;* https://github.com/gbdev/hardware.inc
;*
;* Based on Jones' hardware.inc
;* And based on Carsten Sorensen's ideas.
;*
;* To the extent possible under law, the authors of this work have
;* waived all copyright and related or neighboring rights to the work.
;* See https://creativecommons.org/publicdomain/zero/1.0/ for details.
;*
;* SPDX-License-Identifier: CC0-1.0
;*
;* Rev 1.1 - 15-Jul-97 : Added define check
;* Rev 1.2 - 18-Jul-97 : Added revision check macro
;* Rev 1.3 - 19-Jul-97 : Modified for RGBASM V1.05
@ -31,6 +38,17 @@
;* Rev 4.3 - 07-Nov-21 : Deprecate VRAM address constants (Eievui)
;* Rev 4.4 - 11-Jan-22 : Deprecate VRAM CART_SRAM_2KB constant (avivace)
;* Rev 4.5 - 03-Mar-22 : Added bit number definitions for OCPS, BCPS and LCDC (sukus)
;* Rev 4.6 - 15-Jun-22 : Added MBC3 registers and special values
;* Rev 4.7.0 - 27-Jun-22 : Added alternate names for some constants
;* Rev 4.7.1 - 05-Jul-22 : Added RPB_LED_ON constant
;* Rev 4.8.0 - 25-Oct-22 : Changed background addressing constants (zlago)
;* Rev 4.8.1 - 29-Apr-23 : Added rOPRI (rbong)
;* Rev 4.9.0 - 24-Jun-23 : Added definitions for interrupt vectors (sukus)
;* Rev 4.9.1 - 11-Sep-23 : Added repository link and CC0 waiver notice
; NOTE: REVISION NUMBER CHANGES MUST BE REFLECTED
; IN `rev_Check_hardware_inc` BELOW!
IF __RGBDS_MAJOR__ == 0 && __RGBDS_MINOR__ < 5
FAIL "This version of 'hardware.inc' requires RGBDS version 0.5.0 or later."
@ -41,14 +59,31 @@ ENDC
IF !DEF(HARDWARE_INC)
DEF HARDWARE_INC EQU 1
; Usage: rev_Check_hardware_inc <min_ver>
; Examples: rev_Check_hardware_inc 4.1.2
; rev_Check_hardware_inc 4.1 (equivalent to 4.1.0)
; rev_Check_hardware_inc 4 (equivalent to 4.0.0)
MACRO rev_Check_hardware_inc
;NOTE: REVISION NUMBER CHANGES MUST BE ADDED
;TO SECOND PARAMETER IN FOLLOWING LINE.
IF \1 > 4.5 ;PUT REVISION NUMBER HERE
WARN "Version \1 or later of 'hardware.inc' is required."
DEF CUR_VER equs "4,9,1" ; ** UPDATE THIS LINE WHEN CHANGING THE REVISION NUMBER **
DEF MIN_VER equs STRRPL("\1", ".", ",")
DEF INTERNAL_CHK equs """MACRO ___internal
IF \\1 != \\4 || \\2 < \\5 || (\\2 == \\5 && \\3 < \\6)
FAIL "Version \\1.\\2.\\3 of 'hardware.inc' is incompatible with requested version \\4.\\5.\\6"
ENDC
\nENDM"""
INTERNAL_CHK
___internal {CUR_VER}, {MIN_VER},0,0
PURGE CUR_VER, MIN_VER, INTERNAL_CHK, ___internal
ENDM
;***************************************************************************
;*
;* General memory region constants
;*
;***************************************************************************
DEF _VRAM EQU $8000 ; $8000->$9FFF
DEF _SCRN0 EQU $9800 ; $9800->$9BFF
DEF _SCRN1 EQU $9C00 ; $9C00->$9FFF
@ -60,17 +95,80 @@ DEF _IO EQU $FF00 ; $FF00->$FF7F,$FFFF
DEF _AUD3WAVERAM EQU $FF30 ; $FF30->$FF3F
DEF _HRAM EQU $FF80 ; $FF80->$FFFE
; *** MBC5 Equates ***
DEF rRAMG EQU $0000 ; $0000->$1fff
DEF rROMB0 EQU $2000 ; $2000->$2fff
DEF rROMB1 EQU $3000 ; $3000->$3fff - If more than 256 ROM banks are present.
DEF rRAMB EQU $4000 ; $4000->$5fff - Bit 3 enables rumble (if present)
;***************************************************************************
;*
;* MBC registers
;*
;***************************************************************************
; *** Common ***
; --
; -- RAMG ($0000-$1FFF)
; -- Controls whether access to SRAM (and the MBC3 RTC registers) is allowed (W)
; --
DEF rRAMG EQU $0000
DEF CART_SRAM_ENABLE EQU $0A
DEF CART_SRAM_DISABLE EQU $00
; --
; -- ROMB0 ($2000-$3FFF)
; -- Selects which ROM bank is mapped to the ROMX space ($4000-$7FFF) (W)
; --
; -- The range of accepted values, as well as the behavior of writing $00,
; -- varies depending on the MBC.
; --
DEF rROMB0 EQU $2000
; --
; -- RAMB ($4000-$5FFF)
; -- Selects which SRAM bank is mapped to the SRAM space ($A000-$BFFF) (W)
; --
; -- The range of accepted values varies depending on the cartridge configuration.
; --
DEF rRAMB EQU $4000
; *** MBC3-specific registers ***
; Write one of these to rRAMG to map the corresponding RTC register to all SRAM space
DEF RTC_S EQU $08 ; Seconds (0-59)
DEF RTC_M EQU $09 ; Minutes (0-59)
DEF RTC_H EQU $0A ; Hours (0-23)
DEF RTC_DL EQU $0B ; Lower 8 bits of Day Counter ($00-$FF)
DEF RTC_DH EQU $0C ; Bit 7 - Day Counter Carry Bit (1=Counter Overflow)
; Bit 6 - Halt (0=Active, 1=Stop Timer)
; Bit 0 - Most significant bit of Day Counter (Bit 8)
; --
; -- RTCLATCH ($6000-$7FFF)
; -- Write $00 then $01 to latch the current time into the RTC registers (W)
; --
DEF rRTCLATCH EQU $6000
; *** MBC5-specific register ***
; --
; -- ROMB1 ($3000-$3FFF)
; -- A 9th bit that "extends" ROMB0 if more than 256 banks are present (W)
; --
; -- Also note that rROMB0 thus only spans $2000-$2FFF.
; --
DEF rROMB1 EQU $3000
; Bit 3 of RAMB enables the rumble motor (if any)
DEF CART_RUMBLE_ON EQU 1 << 3
;***************************************************************************
;*
;* Custom registers
;* Memory-mapped registers
;*
;***************************************************************************
@ -105,9 +203,9 @@ DEF rSB EQU $FF01
; --
DEF rSC EQU $FF02
DEF SCF_START EQU %10000000 ;Transfer Start Flag (1=Transfer in progress, or requested)
DEF SCF_SPEED EQU %00000010 ;Clock Speed (0=Normal, 1=Fast) ** CGB Mode Only **
DEF SCF_SOURCE EQU %00000001 ;Shift Clock (0=External Clock, 1=Internal Clock)
DEF SCF_START EQU %10000000 ; Transfer Start Flag (1=Transfer in progress, or requested)
DEF SCF_SPEED EQU %00000010 ; Clock Speed (0=Normal, 1=Fast) ** CGB Mode Only **
DEF SCF_SOURCE EQU %00000001 ; Shift Clock (0=External Clock, 1=Internal Clock)
DEF SCB_START EQU 7
DEF SCB_SPEED EQU 1
@ -444,8 +542,8 @@ DEF LCDCF_WIN9800 EQU %00000000 ; Window Tile Map Display Select
DEF LCDCF_WIN9C00 EQU %01000000 ; Window Tile Map Display Select
DEF LCDCF_WINOFF EQU %00000000 ; Window Display
DEF LCDCF_WINON EQU %00100000 ; Window Display
DEF LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select
DEF LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select
DEF LCDCF_BLK21 EQU %00000000 ; BG & Window Tile Data Select
DEF LCDCF_BLK01 EQU %00010000 ; BG & Window Tile Data Select
DEF LCDCF_BG9800 EQU %00000000 ; BG Tile Map Display Select
DEF LCDCF_BG9C00 EQU %00001000 ; BG Tile Map Display Select
DEF LCDCF_OBJ8 EQU %00000000 ; OBJ Construction
@ -458,7 +556,7 @@ DEF LCDCF_BGON EQU %00000001 ; BG Display
DEF LCDCB_ON EQU 7 ; LCD Control Operation
DEF LCDCB_WIN9C00 EQU 6 ; Window Tile Map Display Select
DEF LCDCB_WINON EQU 5 ; Window Display
DEF LCDCB_BG8000 EQU 4 ; BG & Window Tile Data Select
DEF LCDCB_BLKS EQU 4 ; BG & Window Tile Data Select
DEF LCDCB_BG9C00 EQU 3 ; BG Tile Map Display Select
DEF LCDCB_OBJ16 EQU 2 ; OBJ Construction
DEF LCDCB_OBJON EQU 1 ; OBJ Display
@ -661,39 +759,65 @@ DEF RPF_DATAIN EQU %00000010 ; 0=Receiving IR Signal, 1=Normal
DEF RPF_WRITE_HI EQU %00000001
DEF RPF_WRITE_LO EQU %00000000
DEF RPB_LED_ON EQU 0
DEF RPB_DATAIN EQU 1
; --
; -- BCPS ($FF68)
; -- Background Color Palette Specification (R/W)
; -- BCPS/BGPI ($FF68)
; -- Background Color Palette Specification (aka Background Palette Index) (R/W)
; --
DEF rBCPS EQU $FF68
DEF rBGPI EQU rBCPS
DEF BCPSF_AUTOINC EQU %10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing)
DEF BCPSB_AUTOINC EQU 7
DEF BGPIF_AUTOINC EQU BCPSF_AUTOINC
DEF BGPIB_AUTOINC EQU BCPSB_AUTOINC
; --
; -- BCPD ($FF69)
; -- Background Color Palette Data (R/W)
; -- BCPD/BGPD ($FF69)
; -- Background Color Palette Data (aka Background Palette Data) (R/W)
; --
DEF rBCPD EQU $FF69
DEF rBGPD EQU rBCPD
; --
; -- OCPS ($FF6A)
; -- Object Color Palette Specification (R/W)
; -- OCPS/OBPI ($FF6A)
; -- Object Color Palette Specification (aka Object Background Palette Index) (R/W)
; --
DEF rOCPS EQU $FF6A
DEF rOBPI EQU rOCPS
DEF OCPSF_AUTOINC EQU %10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing)
DEF OCPSB_AUTOINC EQU 7
DEF OBPIF_AUTOINC EQU OCPSF_AUTOINC
DEF OBPIB_AUTOINC EQU OCPSB_AUTOINC
; --
; -- OCPD ($FF6B)
; -- Object Color Palette Data (R/W)
; -- OCPD/OBPD ($FF6B)
; -- Object Color Palette Data (aka Object Background Palette Data) (R/W)
; --
DEF rOCPD EQU $FF6B
DEF rOBPD EQU rOCPD
; --
; -- OPRI ($FF6C)
; -- Object Priority Mode (R/W)
; -- CGB Only
; --
; -- Priority can be changed only from the boot ROM
; --
DEF rOPRI EQU $FF6C
DEF OPRI_OAM EQU 0 ; Prioritize objects by location in OAM (CGB Mode default)
DEF OPRI_COORD EQU 1 ; Prioritize objects by x-coordinate (Non-CGB Mode default)
; --
@ -726,17 +850,6 @@ DEF rPCM12 EQU $FF76
DEF rPCM34 EQU $FF77
; SameBoy additions
DEF rKEY0 EQU $FF4C
DEF rBANK EQU $FF50
DEF rOPRI EQU $FF6C
DEF rJOYP EQU rP1
DEF rBGPI EQU rBCPS
DEF rBGPD EQU rBCPD
DEF rOBPI EQU rOCPS
DEF rOBPD EQU rOCPD
; --
; -- IE ($FFFF)
; -- Interrupt Enable (R/W)
@ -790,7 +903,6 @@ DEF AUDENV_DOWN EQU %00000000
; -- Can be used with AUD1HIGH, AUD2HIGH, AUD3HIGH
; -- See AUD1HIGH for more info
; --
DEF AUDHIGH_RESTART EQU %10000000
DEF AUDHIGH_LENGTH_ON EQU %01000000
DEF AUDHIGH_LENGTH_OFF EQU %00000000
@ -814,10 +926,33 @@ DEF BOOTUP_B_AGB EQU %00000001 ; GBA, GBA SP, Game Boy Player, or New GBA S
;***************************************************************************
;*
;* Cart related
;* Interrupt vector addresses
;*
;***************************************************************************
DEF INT_HANDLER_VBLANK EQU $0040
DEF INT_HANDLER_STAT EQU $0048
DEF INT_HANDLER_TIMER EQU $0050
DEF INT_HANDLER_SERIAL EQU $0058
DEF INT_HANDLER_JOYPAD EQU $0060
;***************************************************************************
;*
;* Header
;*
;***************************************************************************
;*
;* Nintendo scrolling logo
;* (Code won't work on a real GameBoy)
;* (if next lines are altered.)
MACRO NINTENDO_LOGO
DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D
DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E
ENDM
; $0143 Color GameBoy compatibility code
DEF CART_COMPATIBLE_DMG EQU $00
DEF CART_COMPATIBLE_DMG_GBC EQU $80
@ -878,9 +1013,6 @@ DEF CART_SRAM_8KB EQU 2 ; 1 bank
DEF CART_SRAM_32KB EQU 3 ; 4 banks
DEF CART_SRAM_128KB EQU 4 ; 16 banks
DEF CART_SRAM_ENABLE EQU $0A
DEF CART_SRAM_DISABLE EQU $00
; $014A Destination code
DEF CART_DEST_JAPANESE EQU $00
DEF CART_DEST_NON_JAPANESE EQU $01
@ -918,7 +1050,7 @@ DEF PADB_A EQU $0
;***************************************************************************
DEF SCRN_X EQU 160 ; Width of screen in pixels
DEF SCRN_Y EQU 144 ; Height of screen in pixels
DEF SCRN_Y EQU 144 ; Height of screen in pixels. Also corresponds to the value in LY at the beginning of VBlank.
DEF SCRN_X_B EQU 20 ; Width of screen in bytes
DEF SCRN_Y_B EQU 18 ; Height of screen in bytes
@ -966,16 +1098,6 @@ DEF OAMB_PAL1 EQU 4 ; Palette number; 0,1 (DMG)
DEF OAMB_BANK1 EQU 3 ; Bank number; 0,1 (GBC)
;*
;* Nintendo scrolling logo
;* (Code won't work on a real GameBoy)
;* (if next lines are altered.)
MACRO NINTENDO_LOGO
DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D
DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E
ENDM
; Deprecated constants. Please avoid using.
DEF IEF_LCDC EQU %00000010 ; LCDC (see STAT)
@ -983,6 +1105,9 @@ DEF _VRAM8000 EQU _VRAM
DEF _VRAM8800 EQU _VRAM+$800
DEF _VRAM9000 EQU _VRAM+$1000
DEF CART_SRAM_2KB EQU 1 ; 1 incomplete bank
DEF LCDCF_BG8800 EQU %00000000 ; BG & Window Tile Data Select
DEF LCDCF_BG8000 EQU %00010000 ; BG & Window Tile Data Select
DEF LCDCB_BG8000 EQU 4 ; BG & Window Tile Data Select
ENDC ;HARDWARE_INC

View File

@ -1,2 +1,2 @@
DEF MGB = 1
include "dmg_boot.asm"
DEF MGB = 1
include "dmg_boot.asm"

40
BootROMs/sameboot.inc Normal file
View File

@ -0,0 +1,40 @@
IF !DEF(SAMEBOY_INC)
DEF SAMEBOY_INC EQU 1
include "hardware.inc"
DEF rKEY0 EQU $FF4C
DEF rBANK EQU $FF50
DEF rJOYP EQU rP1
MACRO lb ; r16, high, low
ld \1, LOW(\2) << 8 | LOW(\3)
ENDM
MACRO header_section ; name, address
PUSHS
SECTION "\1", ROM0[\2]
\1:
POPS
ENDM
header_section EntryPoint, $0100
header_section NintendoLogo, $0104
header_section NintendoLogoEnd, $0134
header_section Title, $0134
header_section ManufacturerCode, $013F
header_section CGBFlag, $0143
header_section NewLicenseeCode, $0144
header_section SGBFlag, $0146
header_section CartridgeType, $0147
header_section ROMSize, $0148
header_section RAMSize, $0149
header_section DestinationCode, $014A
header_section OldLicenseeCode, $014B
header_section MaskRomVersion, $014C
header_section HeaderChecksum, $014D
header_section GlobalChecksum, $014E
ENDC

View File

@ -1,2 +1,2 @@
DEF SGB2 = 1
include "sgb_boot.asm"
DEF SGB2 = 1
include "sgb_boot.asm"

View File

@ -1,14 +1,14 @@
; SameBoy SGB bootstrap ROM
INCLUDE "hardware.inc"
include "sameboot.inc"
SECTION "BootCode", ROM0[$0]
SECTION "BootCode", ROM0[$0000]
Start:
; Init stack pointer
ld sp, $fffe
ld sp, $FFFE
; Clear memory VRAM
ld hl, $8000
ld hl, _VRAM
xor a
.clearVRAMLoop
@ -17,24 +17,25 @@ Start:
jr z, .clearVRAMLoop
; Init Audio
ld a, $80
ld a, AUDENA_ON
ldh [rNR52], a
assert AUDENA_ON == AUDLEN_DUTY_50
ldh [rNR11], a
ld a, $f3
ldh [rNR12], a
ldh [rNR51], a
ld a, $F3
ldh [rNR12], a ; Envelope $F, decreasing, sweep $3
ldh [rNR51], a ; Channels 1+2+3+4 left, channels 1+2 right
ld a, $77
ldh [rNR50], a
ldh [rNR50], a ; Volume $7, left and right
; Init BG palette to white
ld a, $0
ld a, %00_00_00_00
ldh [rBGP], a
; Load logo from ROM.
; A nibble represents a 4-pixels line, 2 bytes represent a 4x4 tile, scaled to 8x8.
; Tiles are ordered left to right, top to bottom.
ld de, $104 ; Logo start
ld hl, $8010 ; This is where we load the tiles in VRAM
ld de, NintendoLogo
ld hl, _VRAM + $10 ; This is where we load the tiles in VRAM
.loadLogoLoop
ld a, [de] ; Read 2 rows
@ -43,82 +44,82 @@ Start:
call DoubleBitsAndWriteRow
inc de
ld a, e
xor $34 ; End of logo
xor LOW(NintendoLogoEnd)
jr nz, .loadLogoLoop
; Load trademark symbol
ld de, TrademarkSymbol
ld c,$08
ld c, TrademarkSymbolEnd - TrademarkSymbol
.loadTrademarkSymbolLoop:
ld a,[de]
ld a, [de]
inc de
ldi [hl],a
ldi [hl], a
inc hl
dec c
jr nz, .loadTrademarkSymbolLoop
; Set up tilemap
ld a,$19 ; Trademark symbol
ld [$9910], a ; ... put in the superscript position
ld hl,$992f ; Bottom right corner of the logo
ld c,$c ; Tiles in a logo row
ld a, $19 ; Trademark symbol tile ID
ld [_SCRN0 + 8 * SCRN_VX_B + 16], a ; ... put in the superscript position
ld hl, _SCRN0 + 9 * SCRN_VX_B + 15 ; Bottom right corner of the logo
ld c, 12 ; Tiles in a logo row
.tilemapLoop
dec a
jr z, .tilemapDone
ldd [hl], a
dec c
jr nz, .tilemapLoop
ld l,$0f ; Jump to top row
ld l, $0F ; Jump to top row
jr .tilemapLoop
.tilemapDone
; Turn on LCD
ld a, $91
ld a, LCDCF_ON | LCDCF_BLK01 | LCDCF_BGON
ldh [rLCDC], a
ld a, $f1 ; Packet magic, increases by 2 for every packet
ldh [_HRAM], a
ld hl, $104 ; Header start
ld a, $F1 ; Packet magic, increases by 2 for every packet
ldh [hCommand], a
ld hl, NintendoLogo ; Header start
xor a
ld c, a ; JOYP
.sendCommand
xor a
ld [c], a
ldh [c], a
ld a, $30
ld [c], a
ldh a, [_HRAM]
ldh [c], a
ldh a, [hCommand]
call SendByte
push hl
ld b, $e
ld b, 14
ld d, 0
.checksumLoop
call ReadHeaderByte
add d
ld d, a
dec b
jr nz, .checksumLoop
; Send checksum
call SendByte
pop hl
ld b, $e
ld b, 14
.sendLoop
call ReadHeaderByte
call SendByte
dec b
jr nz, .sendLoop
; Done bit
ld a, $20
ld [c], a
ldh [c], a
ld a, $30
ld [c], a
ldh [c], a
; Wait 4 frames
ld e, 4
ld a, 1
@ -126,41 +127,41 @@ Start:
xor a
.waitLoop
ldh [rIF], a
db $76 ; halt, compatible with rgbds 0.5-0.8
halt
nop
dec e
jr nz, .waitLoop
ldh [rIE], a
; Update command
ldh a, [_HRAM]
ldh a, [hCommand]
add 2
ldh [_HRAM], a
ldh [hCommand], a
ld a, $58
cp l
jr nz, .sendCommand
; Write to sound registers for DMG compatibility
ld c, $13
ld a, $c1
ld [c], a
ld c, LOW(rNR13)
ld a, $C1
ldh [c], a
inc c
ld a, 7
ld [c], a
ld a, $7
ldh [c], a
; Init BG palette
ld a, $fc
ld a, %11_11_11_00
ldh [rBGP], a
; Set registers to match the original SGB boot
IF DEF(SGB2)
ld a, $FF
ld a, BOOTUP_A_MGB
ELSE
ld a, 1
ld a, BOOTUP_A_DMG
ENDC
ld hl, $c060
ld hl, $C060
; Boot the game
jp BootGame
@ -184,9 +185,9 @@ SendByte:
jr c, .zeroBit
add a ; 10 -> 20
.zeroBit
ld [c], a
ldh [c], a
ld a, $30
ld [c], a
ldh [c], a
dec d
ret z
jr .loop
@ -212,8 +213,23 @@ DoubleBitsAndWriteRow:
ret
TrademarkSymbol:
db $3c,$42,$b9,$a5,$b9,$a5,$42,$3c
pusho
opt b.X
db %..XXXX..
db %.X....X.
db %X.XXX..X
db %X.X..X.X
db %X.XXX..X
db %X.X..X.X
db %.X....X.
db %..XXXX..
popo
TrademarkSymbolEnd:
SECTION "BootGame", ROM0[$fe]
SECTION "BootGame", ROM0[$00FE]
BootGame:
ldh [rBANK], a
ldh [rBANK], a
SECTION "HRAM", HRAM[_HRAM]
hCommand:
ds 1

BIN
Cocoa/Assets.car Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 584 B

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

253
Cocoa/CheatSearch.xib Normal file
View File

@ -0,0 +1,253 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="24093.7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="24093.7"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="GBCheatSearchController">
<connections>
<outlet property="addCheatButton" destination="o1I-5D-V4k" id="lRE-uQ-vul"/>
<outlet property="conditionField" destination="XN7-BO-THS" id="vzh-y2-CcN"/>
<outlet property="conditionTypeButton" destination="6RO-h8-lZ8" id="5wx-NY-lbK"/>
<outlet property="dataTypeButton" destination="5Db-vP-S60" id="wdR-m7-fEI"/>
<outlet property="operandField" destination="Q42-Vu-TJW" id="hRn-67-UmU"/>
<outlet property="resultsLabel" destination="wbN-MX-lEy" id="gJB-fD-eKK"/>
<outlet property="tableView" destination="fSU-85-fVM" id="1kO-kP-yBb"/>
<outlet property="window" destination="QvC-M9-y7g" id="g09-DO-GsE"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Cheat Search" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="GBPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="372"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
<value key="minSize" type="size" width="480" height="372"/>
<value key="maxSize" type="size" width="480" height="99999"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="480" height="372"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Fvf-Co-5Ga">
<rect key="frame" x="-1" y="155" width="482" height="218"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" drawsBackground="NO" id="1kJ-HR-keu">
<rect key="frame" x="1" y="1" width="480" height="216"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" tableStyle="plain" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" headerView="oyv-sh-ulk" id="fSU-85-fVM">
<rect key="frame" x="0.0" y="0.0" width="480" height="188"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="17" height="0.0"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="AutomaticTableColumnIdentifier.0" editable="NO" width="143" minWidth="40" maxWidth="1000" id="8z0-o5-dNI">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Address">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" controlSize="large" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" title="Text Cell" id="bmG-fw-HDR" customClass="GBCenteredTextCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn identifier="AutomaticTableColumnIdentifier.1" editable="NO" width="143" minWidth="40" maxWidth="1000" id="mBc-yv-f00">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Previous Value">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" controlSize="large" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" title="Text Cell" id="BSe-S3-KNH" customClass="GBCenteredTextCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn width="143" minWidth="10" maxWidth="3.4028234663852886e+38" id="F7j-ck-3H0">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Current Value">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tableHeaderCell>
<textFieldCell key="dataCell" controlSize="large" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="wjH-Ei-6hv" customClass="GBCenteredTextCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
</tableColumns>
<connections>
<outlet property="dataSource" destination="-2" id="Yqt-V5-OkG"/>
<outlet property="delegate" destination="-2" id="TRM-gh-TG4"/>
</connections>
</tableView>
</subviews>
<nil key="backgroundColor"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="ZbQ-IG-kyP">
<rect key="frame" x="1" y="201" width="480" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="wK3-8v-kAQ">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" wantsLayer="YES" id="oyv-sh-ulk">
<rect key="frame" x="0.0" y="0.0" width="480" height="28"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KdM-lW-WbP">
<rect key="frame" x="371" y="24" width="96" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="push" title="Search" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="t4Y-Ud-mJm">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="search:" target="-2" id="7pG-JY-vEF"/>
</connections>
</button>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fTv-nr-5FT">
<rect key="frame" x="6" y="95" width="124" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" alignment="right" title="Search Condition:" id="9C2-Xp-JIA">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vMd-zb-8jT">
<rect key="frame" x="6" y="64" width="124" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" alignment="right" title="Expression:" id="Jgg-sA-jjs">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5Db-vP-S60">
<rect key="frame" x="133" y="120" width="197" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<popUpButtonCell key="cell" type="push" title="8-Bit" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="al4-Jb-OJB" id="dkg-V5-wsX">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="message"/>
<menu key="menu" id="e5r-qR-pg7">
<items>
<menuItem title="8-Bit" state="on" id="al4-Jb-OJB"/>
<menuItem title="16-Bit" tag="1" id="G2m-fU-8Lt"/>
<menuItem title="16-Bit (Big Endian)" tag="3" id="JRa-DB-dyG"/>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6RO-h8-lZ8">
<rect key="frame" x="133" y="89" width="197" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<popUpButtonCell key="cell" type="push" title="Is Equal To…" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Vfb-Dg-Jkb" id="DPm-QO-c64">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="message"/>
<menu key="menu" id="Kg9-Rd-1GQ">
<items>
<menuItem title="Any" id="cEg-eI-4hb"/>
<menuItem title="Is Equal To…" state="on" id="Vfb-Dg-Jkb"/>
<menuItem title="Is Different From…" id="JDg-d9-5Ux"/>
<menuItem title="Is Greater Than…" id="Rir-w0-737"/>
<menuItem title="Is Equal or Greater Than…" id="Lvo-pV-Syt"/>
<menuItem title="Is Less Than…" id="VUW-DY-2cI"/>
<menuItem title="Is Equal or Less Than…" id="rDN-UF-tIo"/>
<menuItem title="Did Change" id="JdI-CW-E8H"/>
<menuItem title="Did Not Change" id="sWc-Yz-Cve"/>
<menuItem title="Did Increase" id="LHF-Lf-7tK"/>
<menuItem title="Did Decrease" id="8s2-8n-aQO"/>
<menuItem title="Custom…" id="8xc-2v-YQj"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="conditionChanged:" target="-2" id="KF9-vz-yNC"/>
</connections>
</popUpButton>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Q42-Vu-TJW">
<rect key="frame" x="334" y="93" width="126" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" continuous="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" title="$0" drawsBackground="YES" usesSingleLineMode="YES" id="WDs-GG-7Lc">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<action selector="search:" target="-2" id="BDa-5j-qEz"/>
<outlet property="delegate" destination="-2" id="1bO-hp-igc"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XN7-BO-THS">
<rect key="frame" x="136" y="62" width="324" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" enabled="NO" sendsActionOnEndEditing="YES" borderStyle="bezel" title="new == ($0)" drawsBackground="YES" usesSingleLineMode="YES" id="Krh-8w-4ug">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<action selector="search:" target="-2" id="sv5-eX-Kb9"/>
</connections>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tBa-6c-9AY">
<rect key="frame" x="13" y="24" width="96" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="push" title="Reset" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Pge-SU-Y1n">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="reset:" target="-2" id="KCy-Ob-tlg"/>
</connections>
</button>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wbN-MX-lEy">
<rect key="frame" x="-3" y="4" width="486" height="14"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" alignment="center" title="Status" id="CM3-4U-qao">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="o1I-5D-V4k">
<rect key="frame" x="264" y="24" width="110" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="push" title="Add Cheat" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="GGV-nm-ASn">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="addCheat:" target="-2" id="7ax-kM-TeV"/>
</connections>
</button>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="veO-Qn-0Sz">
<rect key="frame" x="6" y="126" width="124" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Data Type:" id="KuT-rz-eHm">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</view>
<contentBorderThickness minY="22"/>
<point key="canvasLocation" x="161" y="182"/>
</window>
</objects>
</document>

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 231 B

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 B

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 448 B

View File

@ -3,9 +3,22 @@
#import "GBImageView.h"
#import "GBSplitView.h"
#import "GBVisualizerView.h"
#import "GBCPUView.h"
#import "GBOSDView.h"
#import "GBDebuggerButton.h"
enum model {
MODEL_NONE,
MODEL_DMG,
MODEL_CGB,
MODEL_AGB,
MODEL_SGB,
MODEL_MGB,
MODEL_AUTO,
MODEL_QUICK_RESET = -1,
};
@class GBCheatWindowController;
@class GBPaletteView;
@class GBObjectView;
@ -67,14 +80,19 @@
@property IBOutlet GBDebuggerButton *debuggerNextButton;
@property IBOutlet GBDebuggerButton *debuggerStepButton;
@property IBOutlet GBDebuggerButton *debuggerFinishButton;
@property (strong) IBOutlet GBDebuggerButton *debuggerBackstepButton;
@property IBOutlet GBDebuggerButton *debuggerBackstepButton;
@property IBOutlet NSScrollView *debuggerScrollView;
@property IBOutlet NSView *debugBar;
@property IBOutlet GBCPUView *cpuView;
@property IBOutlet NSTextField *cpuCounter;
+ (NSImage *) imageFromData:(NSData *)data width:(NSUInteger) width height:(NSUInteger) height scale:(double) scale;
-(uint8_t) readMemory:(uint16_t) addr;
-(void) writeMemory:(uint16_t) addr value:(uint8_t)value;
-(void) performAtomicBlock: (void (^)())block;
-(void) connectLinkCable:(NSMenuItem *)sender;
-(int)loadStateFile:(const char *)path noErrorOnNotFound:(bool)noErrorOnFileNotFound;
- (void) performAtomicBlock: (void (^)())block;
- (void) connectLinkCable:(NSMenuItem *)sender;
- (int)loadStateFile:(const char *)path noErrorOnNotFound:(bool)noErrorOnFileNotFound;
- (NSString *)captureOutputForBlock: (void (^)())block;
- (NSFont *)debuggerFontOfSize:(unsigned)size;
@end

View File

@ -11,6 +11,7 @@
#import "GBTerminalTextFieldCell.h"
#import "BigSurToolbar.h"
#import "GBPaletteEditorController.h"
#import "GBCheatSearchController.h"
#import "GBObjectView.h"
#import "GBPaletteView.h"
#import "GBHexStatusBarRepresenter.h"
@ -48,16 +49,6 @@
/* Todo: The general Objective-C coding style conflicts with SameBoy's. This file needs a cleanup. */
/* Todo: Split into category files! This is so messy!!! */
enum model {
MODEL_NONE,
MODEL_DMG,
MODEL_CGB,
MODEL_AGB,
MODEL_SGB,
MODEL_MGB,
MODEL_QUICK_RESET = -1,
};
@interface Document ()
@property GBAudioClient *audioClient;
@ -100,6 +91,7 @@ enum model {
bool _logToSideView;
bool _shouldClearSideView;
enum model _currentModel;
bool _usesAutoModel;
bool _rewind;
bool _modelsChanging;
@ -126,6 +118,8 @@ enum model {
NSDate *_fileModificationTime;
__weak NSThread *_emulationThread;
GBCheatSearchController *_cheatSearchController;
}
static void boot_rom_load(GB_gameboy_t *gb, GB_boot_rom_t type)
@ -140,7 +134,7 @@ static void vblank(GB_gameboy_t *gb, GB_vblank_type_t type)
[self vblankWithType:type];
}
static void consoleLog(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes)
static void consoleLog(GB_gameboy_t *gb, const char *string, GB_log_attributes_t attributes)
{
Document *self = (__bridge Document *)GB_get_user_data(gb);
[self log:string withAttributes: attributes];
@ -263,6 +257,7 @@ static void debuggerReloadCallback(GB_gameboy_t *gb)
case MODEL_NONE:
case MODEL_QUICK_RESET:
case MODEL_AUTO:
case MODEL_CGB:
return (GB_model_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"GBCGBModel"];
@ -293,6 +288,7 @@ static void debuggerReloadCallback(GB_gameboy_t *gb)
GB_set_user_data(&_gb, (__bridge void *)(self));
GB_set_boot_rom_load_callback(&_gb, (GB_boot_rom_load_callback_t)boot_rom_load);
GB_set_vblank_callback(&_gb, (GB_vblank_callback_t) vblank);
GB_set_enable_skipped_frame_vblank_callbacks(&_gb, true);
GB_set_log_callback(&_gb, (GB_log_callback_t) consoleLog);
GB_set_input_callback(&_gb, (GB_input_callback_t) consoleInput);
GB_set_async_input_callback(&_gb, (GB_input_callback_t) asyncConsoleInput);
@ -303,7 +299,7 @@ static void debuggerReloadCallback(GB_gameboy_t *gb)
GB_apu_set_sample_callback(&_gb, audioCallback);
GB_set_rumble_callback(&_gb, rumbleCallback);
GB_set_infrared_callback(&_gb, infraredStateChanged);
GB_set_debugger_reload_callback(&_gb, debuggerReloadCallback);
GB_debugger_set_reload_callback(&_gb, debuggerReloadCallback);
GB_gameboy_t *gb = &_gb;
__unsafe_unretained Document *weakSelf = self;
@ -322,7 +318,7 @@ static void debuggerReloadCallback(GB_gameboy_t *gb)
GB_set_border_mode(&_gb, (GB_border_mode_t) [[NSUserDefaults standardUserDefaults] integerForKey:@"GBBorderMode"]);
[self observeStandardDefaultsKey:@"GBBorderMode" withBlock:^(NSNumber *value) {
_borderModeChanged = true;
weakSelf->_borderModeChanged = true;
}];
[self observeStandardDefaultsKey:@"GBHighpassFilter" withBlock:^(NSNumber *value) {
@ -342,6 +338,20 @@ static void debuggerReloadCallback(GB_gameboy_t *gb)
[self observeStandardDefaultsKey:@"GBRumbleMode" withBlock:^(NSNumber *value) {
GB_set_rumble_mode(gb, value.unsignedIntValue);
}];
[self observeStandardDefaultsKey:@"GBDebuggerFont" withBlock:^(NSString *value) {
[weakSelf updateFonts];
}];
[self observeStandardDefaultsKey:@"GBDebuggerFontSize" withBlock:^(NSString *value) {
[weakSelf updateFonts];
}];
[self observeStandardDefaultsKey:@"GBTurboCap" withBlock:^(NSNumber *value) {
if (!_master) {
GB_set_turbo_cap(gb, value.doubleValue);
}
}];
}
- (void)updateMinSize
@ -356,11 +366,29 @@ static void debuggerReloadCallback(GB_gameboy_t *gb)
- (void)vblankWithType:(GB_vblank_type_t)type
{
if (type == GB_VBLANK_TYPE_SKIPPED_FRAME) {
double frameUsage = GB_debugger_get_frame_cpu_usage(&_gb);
[_cpuView addSample:frameUsage];
return;
}
if (_gbsVisualizer) {
dispatch_async(dispatch_get_main_queue(), ^{
[_gbsVisualizer setNeedsDisplay:true];
});
}
double frameUsage = GB_debugger_get_frame_cpu_usage(&_gb);
[_cpuView addSample:frameUsage];
if (self.consoleWindow.visible) {
double secondUsage = GB_debugger_get_second_cpu_usage(&_gb);
dispatch_async(dispatch_get_main_queue(), ^{
[_cpuView setNeedsDisplay:true];
_cpuCounter.stringValue = [NSString stringWithFormat:@"%.2f%%", secondUsage * 100];
});
}
if (type != GB_VBLANK_TYPE_REPEAT) {
[self.view flip];
if (_borderModeChanged) {
@ -677,15 +705,46 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
GB_load_boot_rom(&_gb, [path UTF8String]);
}
- (enum model)bestModelForROM
{
uint8_t *rom = GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_ROM, NULL, NULL);
if (!rom) return MODEL_CGB;
if (rom[0x143] & 0x80) { // Has CGB features
return MODEL_CGB;
}
if (rom[0x146] == 3) { // Has SGB features
return MODEL_SGB;
}
if (rom[0x14B] == 1) { // Nintendo-licensed (most likely has boot ROM palettes)
return MODEL_CGB;
}
if (rom[0x14B] == 0x33 &&
rom[0x144] == '0' &&
rom[0x145] == '1') { // Ditto
return MODEL_CGB;
}
return MODEL_DMG;
}
- (IBAction)reset:(id)sender
{
[self stop];
size_t old_width = GB_get_screen_width(&_gb);
if ([sender tag] != MODEL_NONE) {
if ([sender tag] > MODEL_NONE) {
/* User explictly selected a model, save the preference */
_currentModel = (enum model)[sender tag];
_usesAutoModel = _currentModel == MODEL_AUTO;
[[NSUserDefaults standardUserDefaults] setInteger:_currentModel forKey:@"GBEmulatedModel"];
}
/* Reload the ROM, SAV and SYM files */
[self loadROM];
if ([sender tag] == MODEL_QUICK_RESET) {
GB_quick_reset(&_gb);
}
@ -696,21 +755,12 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
if (old_width != GB_get_screen_width(&_gb)) {
[self.view screenSizeChanged];
}
[self updateMinSize];
if ([sender tag] > MODEL_NONE) {
/* User explictly selected a model, save the preference */
[[NSUserDefaults standardUserDefaults] setBool:_currentModel == MODEL_DMG forKey:@"EmulateDMG"];
[[NSUserDefaults standardUserDefaults] setBool:_currentModel == MODEL_SGB forKey:@"EmulateSGB"];
[[NSUserDefaults standardUserDefaults] setBool:_currentModel == MODEL_AGB forKey:@"EmulateAGB"];
[[NSUserDefaults standardUserDefaults] setBool:_currentModel == MODEL_MGB forKey:@"EmulateMGB"];
}
/* Reload the ROM, SAV and SYM files */
[self loadROM];
[self start];
if (_gbsTracks) {
[self changeGBSTrack:sender];
}
if (_hexController) {
/* Verify bank sanity, especially when switching models. */
@ -750,11 +800,92 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
}
}
- (NSFont *)debuggerFontOfSize:(unsigned)size
{
if (!size) {
size = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBDebuggerFontSize"];
}
bool retry = false;
again:;
NSString *selectedFont = [[NSUserDefaults standardUserDefaults] stringForKey:@"GBDebuggerFont"];
if (@available(macOS 10.15, *)) {
if ([selectedFont isEqual:@"SF Mono"]) {
return [NSFont monospacedSystemFontOfSize:size weight:NSFontWeightRegular];
}
}
NSFont *ret = [NSFont fontWithName:selectedFont size:size];
if (ret) return ret;
if (retry) {
return [NSFont userFixedPitchFontOfSize:size];
}
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"GBDebuggerFont"];
retry = true;
goto again;
}
- (void)updateFonts
{
_hexController.font = [self debuggerFontOfSize:12];
[self.paletteView reloadData:self];
[self.objectView reloadData:self];
NSFont *newFont = [self debuggerFontOfSize:0];
NSFont *newBoldFont = [[NSFontManager sharedFontManager] convertFont:newFont toHaveTrait:NSBoldFontMask];
self.debuggerSideViewInput.font = newFont;
unsigned inputHeight = MAX(ceil([@" " sizeWithAttributes:@{
NSFontAttributeName: newFont
}].height) + 6, 26);
NSRect frame = _consoleInput.frame;
unsigned oldHeight = frame.size.height;
frame.size.height = inputHeight;
_consoleInput.frame = frame;
frame = _debugBar.frame;
frame.origin.y += (signed)(inputHeight - oldHeight);
_debugBar.frame = frame;
frame = _debuggerScrollView.frame;
frame.origin.y += (signed)(inputHeight - oldHeight);
frame.size.height -= (signed)(inputHeight - oldHeight);
_debuggerScrollView.frame = frame;
_consoleInput.font = newFont;
for (NSTextView *view in @[_debuggerSideView, _consoleOutput]) {
NSMutableAttributedString *newString = view.attributedString.mutableCopy;
[view.attributedString enumerateAttribute:NSFontAttributeName
inRange:NSMakeRange(0, view.attributedString.length)
options:0
usingBlock:^(NSFont *value, NSRange range, BOOL *stop) {
if ([[NSFontManager sharedFontManager] fontNamed:value.fontName hasTraits:NSBoldFontMask]) {
[newString addAttributes:@{
NSFontAttributeName: newBoldFont
} range:range];
}
else {
[newString addAttributes:@{
NSFontAttributeName: newFont
} range:range];
}
}];
[view.textStorage setAttributedString:newString];
}
[_consoleOutput scrollToEndOfDocument:nil];
}
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
[super windowControllerDidLoadNib:aController];
// Interface Builder bug?
[self.consoleWindow setContentSize:self.consoleWindow.minSize];
[self.consoleWindow setContentSize:self.consoleWindow.frame.size];
/* Close Open Panels, if any */
for (NSWindow *window in [[NSApplication sharedApplication] windows]) {
if ([window isKindOfClass:[NSOpenPanel class]]) {
@ -765,7 +896,7 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
NSMutableParagraphStyle *paragraph_style = [[NSMutableParagraphStyle alloc] init];
[paragraph_style setLineSpacing:2];
self.debuggerSideViewInput.font = [NSFont userFixedPitchFontOfSize:12];
self.debuggerSideViewInput.font = [self debuggerFontOfSize:0];
self.debuggerSideViewInput.textColor = [NSColor whiteColor];
self.debuggerSideViewInput.defaultParagraphStyle = paragraph_style;
[self.debuggerSideViewInput setString:@"registers\nbacktrace\n"];
@ -792,9 +923,16 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
[self.vramWindow setFrame:vram_window_rect display:true animate:false];
self.consoleWindow.title = [NSString stringWithFormat:@"Debug Console %@", [self.fileURL.path lastPathComponent]];
self.memoryWindow.title = [NSString stringWithFormat:@"Memory %@", [self.fileURL.path lastPathComponent]];
self.vramWindow.title = [NSString stringWithFormat:@"VRAM Viewer %@", [self.fileURL.path lastPathComponent]];
if (@available(macOS 11.0, *)) {
self.consoleWindow.subtitle = [self.fileURL.path lastPathComponent];
self.memoryWindow.subtitle = [self.fileURL.path lastPathComponent];
self.vramWindow.subtitle = [self.fileURL.path lastPathComponent];
}
else {
self.consoleWindow.title = [NSString stringWithFormat:@"Debug Console %@", [self.fileURL.path lastPathComponent]];
self.memoryWindow.title = [NSString stringWithFormat:@"Memory %@", [self.fileURL.path lastPathComponent]];
self.vramWindow.title = [NSString stringWithFormat:@"VRAM Viewer %@", [self.fileURL.path lastPathComponent]];
}
self.consoleWindow.level = NSNormalWindowLevel;
@ -871,19 +1009,10 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
[self observeStandardDefaultsKey:@"GBVolume" withBlock:^(id newValue) {
weakSelf->_volume = [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBVolume"];
}];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateDMG"]) {
_currentModel = MODEL_DMG;
}
else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateSGB"]) {
_currentModel = MODEL_SGB;
}
else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateMGB"]) {
_currentModel = MODEL_MGB;
}
else {
_currentModel = [[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateAGB"]? MODEL_AGB : MODEL_CGB;
}
_currentModel = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBEmulatedModel"];
_usesAutoModel = _currentModel == MODEL_AUTO;
[self initCommon];
self.view.gb = &_gb;
@ -900,9 +1029,10 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
}
}
- (void) initMemoryView
- (void)initMemoryView
{
_hexController = [[HFController alloc] init];
_hexController.font = [self debuggerFontOfSize:12];
[_hexController setBytesPerColumn:1];
[_hexController setEditMode:HFOverwriteMode];
@ -946,6 +1076,16 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
[self.memoryView addSubview:layoutView];
self.memoryView = layoutView;
CGSize contentSize = _memoryWindow.contentView.frame.size;
while (_hexController.bytesPerLine < 16) {
contentSize.width += 4;
[_memoryWindow setContentSize:contentSize];
}
while (_hexController.bytesPerLine > 16) {
contentSize.width -= 4;
[_memoryWindow setContentSize:contentSize];
}
self.memoryBankItem.enabled = false;
}
@ -1045,6 +1185,17 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
if (@available(macOS 10.10, *)) {
_mainWindow.titlebarAppearsTransparent = true;
}
if (@available(macOS 26.0, *)) {
// There's a new minimum width for segmented controls in Solarium
NSRect frame = _gbsNextPrevButton.frame;
frame.origin.x -= 16;
_gbsNextPrevButton.frame = frame;
frame = _gbsTracks.frame;
frame.size.width -= 16;
_gbsTracks.frame = frame;
}
}
- (bool)isCartContainer
@ -1125,7 +1276,7 @@ static bool is_path_writeable(const char *path)
return true;
}
- (int) loadROM
- (int)loadROM
{
__block int ret = 0;
NSString *fileName = self.romPath;
@ -1159,7 +1310,7 @@ static bool is_path_writeable(const char *path)
}
}
GB_load_battery(&_gb, self.savPath.UTF8String);
GB_load_cheats(&_gb, self.chtPath.UTF8String);
GB_load_cheats(&_gb, self.chtPath.UTF8String, true);
dispatch_async(dispatch_get_main_queue(), ^{
[self.cheatWindowController cheatsUpdated];
});
@ -1177,6 +1328,9 @@ static bool is_path_writeable(const char *path)
[GBWarningPopover popoverWithContents:rom_warnings onWindow:self.mainWindow];
}
_fileModificationTime = [[NSFileManager defaultManager] attributesOfItemAtPath:fileName error:nil][NSFileModificationDate];
if (_usesAutoModel) {
_currentModel = [self bestModelForROM];
}
return ret;
}
@ -1206,6 +1360,7 @@ static bool is_path_writeable(const char *path)
[self.vramWindow close];
[self.printerFeedWindow close];
[self.cheatsWindow close];
[_cheatSearchController.window close];
[super close];
}
@ -1215,6 +1370,8 @@ static bool is_path_writeable(const char *path)
GB_debugger_break(&_gb);
[self start];
[self.consoleWindow makeKeyAndOrderFront:nil];
double secondUsage = GB_debugger_get_second_cpu_usage(&_gb);
_cpuCounter.stringValue = [NSString stringWithFormat:@"%.2f%%", secondUsage * 100];
[self.consoleInput becomeFirstResponder];
}
@ -1243,14 +1400,19 @@ static bool is_path_writeable(const char *path)
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)anItem
{
if ([anItem action] == @selector(mute:)) {
[(NSMenuItem *)anItem setState:!_audioClient.isPlaying];
if (_running) {
[(NSMenuItem *)anItem setState:!_audioClient.isPlaying];
}
else {
[(NSMenuItem *)anItem setState:[[NSUserDefaults standardUserDefaults] boolForKey:@"Mute"]];
}
}
else if ([anItem action] == @selector(togglePause:)) {
[(NSMenuItem *)anItem setState:self.isPaused];
return !GB_debugger_is_stopped(&_gb);
}
else if ([anItem action] == @selector(reset:) && anItem.tag != MODEL_NONE && anItem.tag != MODEL_QUICK_RESET) {
[(NSMenuItem *)anItem setState:anItem.tag == _currentModel];
[(NSMenuItem *)anItem setState:(anItem.tag == _currentModel) || (anItem.tag == MODEL_AUTO && _usesAutoModel)];
}
else if ([anItem action] == @selector(interrupt:)) {
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]) {
@ -1291,6 +1453,9 @@ static bool is_path_writeable(const char *path)
else if ([anItem action] == @selector(decreaseWindowSize:)) {
return [self newRect:NULL forWindow:_mainWindow action:GBWindowResizeActionDecrease];
}
else if ([anItem action] == @selector(reloadROM:)) {
return !_gbsTracks;
}
return [super validateUserInterfaceItem:anItem];
}
@ -1432,7 +1597,9 @@ enum GBWindowResizeAction
[self reloadVRAMData: nil];
[textView.textStorage appendAttributedString:_pendingConsoleOutput];
[textView scrollToEndOfDocument:nil];
if (!_logToSideView) {
[textView scrollToEndOfDocument:nil];
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]) {
[self.consoleWindow orderFront:nil];
}
@ -1441,7 +1608,7 @@ enum GBWindowResizeAction
[_consoleOutputLock unlock];
}
- (void) log: (const char *) string withAttributes: (GB_log_attributes) attributes
- (void)log:(const char *)string withAttributes:(GB_log_attributes_t)attributes
{
NSString *nsstring = @(string); // For ref-counting
if (_capturedOutput) {
@ -1450,7 +1617,7 @@ enum GBWindowResizeAction
}
NSFont *font = [NSFont userFixedPitchFontOfSize:12];
NSFont *font = [self debuggerFontOfSize:0];
NSUnderlineStyle underline = NSUnderlineStyleNone;
if (attributes & GB_LOG_BOLD) {
font = [[NSFontManager sharedFontManager] convertFont:font toHaveTrait:NSBoldFontMask];
@ -1490,7 +1657,9 @@ enum GBWindowResizeAction
- (IBAction)showConsoleWindow:(id)sender
{
[self.consoleWindow orderBack:nil];
[self.consoleWindow orderFront:nil];
double secondUsage = GB_debugger_get_second_cpu_usage(&_gb);
_cpuCounter.stringValue = [NSString stringWithFormat:@"%.2f%%", secondUsage * 100];
}
- (void)queueDebuggerCommand:(NSString *)command
@ -1691,18 +1860,6 @@ enum GBWindowResizeAction
[self log:log withAttributes:0];
}
- (uint8_t) readMemory:(uint16_t)addr
{
while (!GB_is_inited(&_gb));
return GB_safe_read_memory(&_gb, addr);
}
- (void) writeMemory:(uint16_t)addr value:(uint8_t)value
{
while (!GB_is_inited(&_gb));
GB_write_memory(&_gb, addr, value);
}
- (void)performAtomicBlock: (void (^)())block
{
while (!GB_is_inited(&_gb));
@ -1763,6 +1920,11 @@ enum GBWindowResizeAction
if (self.memoryWindow.isVisible) {
[_hexController reloadData];
}
if (_cheatSearchController.window.isVisible) {
if ([_cheatSearchController.tableView editedColumn] != 2) {
[_cheatSearchController.tableView reloadData];
}
}
}
- (IBAction) reloadVRAMData: (id) sender
@ -1847,124 +2009,130 @@ enum GBWindowResizeAction
- (IBAction)hexGoTo:(id)sender
{
NSString *expression = [sender stringValue];
__block uint16_t addr = 0;
__block uint16_t bank = 0;
__block bool fail = false;
NSString *error = [self captureOutputForBlock:^{
uint16_t addr;
uint16_t bank;
if (GB_debugger_evaluate(&_gb, [[sender stringValue] UTF8String], &addr, &bank)) {
return;
if (GB_debugger_evaluate(&_gb, [expression UTF8String], &addr, &bank)) {
fail = true;
}
if (bank != (typeof(bank))-1) {
GB_memory_mode_t mode = [(GBMemoryByteArray *)(_hexController.byteArray) mode];
if (addr < 0x4000) {
if (bank == 0) {
if (mode != GBMemoryROM && mode != GBMemoryEntireSpace) {
mode = GBMemoryEntireSpace;
}
}
else {
addr |= 0x4000;
mode = GBMemoryROM;
}
}
else if (addr < 0x8000) {
mode = GBMemoryROM;
}
else if (addr < 0xA000) {
mode = GBMemoryVRAM;
}
else if (addr < 0xC000) {
mode = GBMemoryExternalRAM;
}
else if (addr < 0xD000) {
if (mode != GBMemoryRAM && mode != GBMemoryEntireSpace) {
mode = GBMemoryEntireSpace;
}
}
else if (addr < 0xE000) {
mode = GBMemoryRAM;
}
else {
mode = GBMemoryEntireSpace;
}
[_memorySpaceButton selectItemAtIndex:mode];
[self hexUpdateSpace:_memorySpaceButton.cell];
[_memoryBankInput setStringValue:[NSString stringWithFormat:@"$%02x", bank]];
[self hexUpdateBank:_memoryBankInput];
}
addr -= _lineRep.valueOffset;
if (addr >= _hexController.byteArray.length) {
GB_log(&_gb, "Value $%04x is out of range.\n", addr);
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
[_hexController setSelectedContentsRanges:@[[HFRangeWrapper withRange:HFRangeMake(addr, 0)]]];
[_hexController _ensureVisibilityOfLocation:addr];
for (HFRepresenter *representer in _hexController.representers) {
if ([representer isKindOfClass:[HFHexTextRepresenter class]]) {
[self.memoryWindow makeFirstResponder:representer.view];
break;
}
}
});
}];
if (error) {
NSBeep();
[GBWarningPopover popoverWithContents:error onView:sender];
}
if (fail) return;
if (bank != (typeof(bank))-1) {
GB_memory_mode_t mode = [(GBMemoryByteArray *)(_hexController.byteArray) mode];
if (addr < 0x4000) {
if (bank == 0) {
if (mode != GBMemoryROM && mode != GBMemoryEntireSpace) {
mode = GBMemoryEntireSpace;
}
}
else {
addr |= 0x4000;
mode = GBMemoryROM;
}
}
else if (addr < 0x8000) {
mode = GBMemoryROM;
}
else if (addr < 0xA000) {
mode = GBMemoryVRAM;
}
else if (addr < 0xC000) {
mode = GBMemoryExternalRAM;
}
else if (addr < 0xD000) {
if (mode != GBMemoryRAM && mode != GBMemoryEntireSpace) {
mode = GBMemoryEntireSpace;
}
}
else if (addr < 0xE000) {
mode = GBMemoryRAM;
}
else {
mode = GBMemoryEntireSpace;
}
[_memorySpaceButton selectItemAtIndex:mode];
[self hexUpdateSpace:_memorySpaceButton.cell];
[_memoryBankInput setStringValue:[NSString stringWithFormat:@"$%02x", bank]];
[self hexUpdateBank:_memoryBankInput];
}
addr -= _lineRep.valueOffset;
if (addr >= _hexController.byteArray.length) {
GB_log(&_gb, "Value $%04x is out of range.\n", addr);
return;
}
[_hexController setSelectedContentsRanges:@[[HFRangeWrapper withRange:HFRangeMake(addr, 0)]]];
[_hexController _ensureVisibilityOfLocation:addr];
for (HFRepresenter *representer in _hexController.representers) {
if ([representer isKindOfClass:[HFHexTextRepresenter class]]) {
[self.memoryWindow makeFirstResponder:representer.view];
break;
}
}
}
- (void)hexUpdateBank:(NSControl *)sender ignoreErrors: (bool)ignore_errors
{
NSString *expression = [sender stringValue];
__block uint16_t addr, bank;
__block bool fail = false;
NSString *error = [self captureOutputForBlock:^{
uint16_t addr, bank;
if (GB_debugger_evaluate(&_gb, [[sender stringValue] UTF8String], &addr, &bank)) {
if (GB_debugger_evaluate(&_gb, [expression UTF8String], &addr, &bank)) {
fail = true;
return;
}
if (bank == (uint16_t) -1) {
bank = addr;
}
uint16_t n_banks = 1;
switch ([(GBMemoryByteArray *)(_hexController.byteArray) mode]) {
case GBMemoryROM: {
size_t rom_size;
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_ROM, &rom_size, NULL);
n_banks = rom_size / 0x4000;
break;
}
case GBMemoryVRAM:
n_banks = GB_is_cgb(&_gb) ? 2 : 1;
break;
case GBMemoryExternalRAM: {
size_t ram_size;
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_CART_RAM, &ram_size, NULL);
n_banks = (ram_size + 0x1FFF) / 0x2000;
break;
}
case GBMemoryRAM:
n_banks = GB_is_cgb(&_gb) ? 8 : 1;
break;
case GBMemoryEntireSpace:
break;
}
bank %= n_banks;
[sender setStringValue:[NSString stringWithFormat:@"$%x", bank]];
[(GBMemoryByteArray *)(_hexController.byteArray) setSelectedBank:bank];
_statusRep.bankForDescription = bank;
dispatch_async(dispatch_get_main_queue(), ^{
[_hexController reloadData];
});
}];
if (error && !ignore_errors) {
NSBeep();
[GBWarningPopover popoverWithContents:error onView:sender];
}
if (fail) return;
if (bank == (uint16_t) -1) {
bank = addr;
}
uint16_t n_banks = 1;
switch ([(GBMemoryByteArray *)(_hexController.byteArray) mode]) {
case GBMemoryROM: {
size_t rom_size;
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_ROM, &rom_size, NULL);
n_banks = rom_size / 0x4000;
break;
}
case GBMemoryVRAM:
n_banks = GB_is_cgb(&_gb) ? 2 : 1;
break;
case GBMemoryExternalRAM: {
size_t ram_size;
GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_CART_RAM, &ram_size, NULL);
n_banks = (ram_size + 0x1FFF) / 0x2000;
break;
}
case GBMemoryRAM:
n_banks = GB_is_cgb(&_gb) ? 8 : 1;
break;
case GBMemoryEntireSpace:
break;
}
bank %= n_banks;
[(GBMemoryByteArray *)(_hexController.byteArray) setSelectedBank:bank];
_statusRep.bankForDescription = bank;
[sender setStringValue:[NSString stringWithFormat:@"$%x", bank]];
[_hexController reloadData];
}
- (IBAction)hexUpdateBank:(NSControl *)sender
@ -2002,9 +2170,8 @@ enum GBWindowResizeAction
}
byteArray.selectedBank = bank;
_statusRep.bankForDescription = bank;
if (bank != (uint16_t)-1) {
[self.memoryBankInput setStringValue:[NSString stringWithFormat:@"$%x", byteArray.selectedBank]];
}
[self.memoryBankInput setStringValue:(bank == (uint16_t)-1)? @"" :
[NSString stringWithFormat:@"$%x", byteArray.selectedBank]];
[_hexController reloadData];
for (NSView *view in self.memoryView.subviews) {
@ -2047,7 +2214,7 @@ enum GBWindowResizeAction
NSError *error;
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice: device error: &error];
CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions([[[device formats] lastObject] formatDescription]);
CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions([[device activeFormat] formatDescription]);
if (!input) {
GB_camera_updated(&_gb);
@ -2344,9 +2511,16 @@ enum GBWindowResizeAction
- (void)setFileURL:(NSURL *)fileURL
{
[super setFileURL:fileURL];
self.consoleWindow.title = [NSString stringWithFormat:@"Debug Console %@", [[fileURL path] lastPathComponent]];
self.memoryWindow.title = [NSString stringWithFormat:@"Memory %@", [[fileURL path] lastPathComponent]];
self.vramWindow.title = [NSString stringWithFormat:@"VRAM Viewer %@", [[fileURL path] lastPathComponent]];
if (@available(macOS 11.0, *)) {
self.consoleWindow.subtitle = [self.fileURL.path lastPathComponent];
self.memoryWindow.subtitle = [self.fileURL.path lastPathComponent];
self.vramWindow.subtitle = [self.fileURL.path lastPathComponent];
}
else {
self.consoleWindow.title = [NSString stringWithFormat:@"Debug Console %@", [self.fileURL.path lastPathComponent]];
self.memoryWindow.title = [NSString stringWithFormat:@"Memory %@", [self.fileURL.path lastPathComponent]];
self.vramWindow.title = [NSString stringWithFormat:@"VRAM Viewer %@", [self.fileURL.path lastPathComponent]];
}
}
- (BOOL)splitView:(GBSplitView *)splitView canCollapseSubview:(NSView *)subview;
@ -2388,6 +2562,14 @@ enum GBWindowResizeAction
[self.cheatsWindow makeKeyAndOrderFront:nil];
}
- (IBAction)showCheatSearch:(id)sender
{
if (!_cheatSearchController) {
_cheatSearchController = [GBCheatSearchController controllerWithDocument:self];
}
[_cheatSearchController.window makeKeyAndOrderFront:sender];
}
- (IBAction)toggleCheats:(id)sender
{
GB_set_cheats_enabled(&_gb, !GB_cheats_enabled(&_gb));
@ -2410,6 +2592,8 @@ enum GBWindowResizeAction
}
GB_set_turbo_mode(&_gb, false, false);
GB_set_turbo_mode(&partner->_gb, false, false);
GB_set_turbo_cap(&_gb, [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBTurboCap"]);
GB_set_turbo_cap(&partner->_gb, [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBTurboCap"]);
}
}
@ -2425,6 +2609,7 @@ enum GBWindowResizeAction
GB_set_turbo_mode(&partner->_gb, true, true);
_slave = partner;
partner->_master = self;
GB_set_turbo_cap(&partner->_gb, 0);
_linkOffset = 0;
GB_set_serial_transfer_bit_start_callback(&_gb, _linkCableBitStart);
GB_set_serial_transfer_bit_start_callback(&partner->_gb, _linkCableBitStart);
@ -2773,4 +2958,15 @@ enum GBWindowResizeAction
[self queueDebuggerCommand:sender.alternateTitle];
}
+ (NSArray<NSString *> *)readableTypes
{
NSMutableSet *set = [NSMutableSet setWithArray:[super readableTypes]];
for (NSString *type in @[@"gb", @"gbc", @"isx", @"gbs"]) {
[set addObject:(__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
(__bridge CFStringRef)type,
NULL)];
}
return [set allObjects];
}
@end

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="24093.7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="24093.7"/>
<capability name="System colors introduced in macOS 10.14" minToolsVersion="10.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -15,15 +15,19 @@
<outlet property="consoleInput" destination="l22-S8-uji" id="Heu-am-YgB"/>
<outlet property="consoleOutput" destination="doS-dM-hnl" id="Gn5-ju-Wb0"/>
<outlet property="consoleWindow" destination="21F-Ah-yHX" id="eQ4-ug-LsT"/>
<outlet property="debuggerBackstepButton" destination="onn-R8-3vg" id="gi1-dC-tJj"/>
<outlet property="debuggerContinueButton" destination="G4h-KO-Z3g" id="Dad-5e-XYM"/>
<outlet property="debuggerFinishButton" destination="vtb-n5-Qlz" id="9vv-fJ-gxp"/>
<outlet property="debuggerNextButton" destination="cOi-Rs-9gS" id="Xjx-uM-D0u"/>
<outlet property="cpuCounter" destination="xdx-GC-Tb8" id="oSn-U3-qvg"/>
<outlet property="cpuView" destination="aBf-yU-8M0" id="RIb-Fj-lvt"/>
<outlet property="debugBar" destination="sah-kv-6KJ" id="24d-aM-rs5"/>
<outlet property="debuggerBackstepButton" destination="E87-Uq-f2l" id="PI7-Wu-f0v"/>
<outlet property="debuggerContinueButton" destination="ybQ-jy-NgI" id="fRF-S3-xSh"/>
<outlet property="debuggerFinishButton" destination="jdD-yP-Nr6" id="V7Y-wP-nSS"/>
<outlet property="debuggerNextButton" destination="tTP-Zs-Ohu" id="mfm-Yl-UZA"/>
<outlet property="debuggerScrollView" destination="oTo-zx-o6N" id="EbZ-Le-dZJ"/>
<outlet property="debuggerSideView" destination="JgV-7E-iwp" id="RaA-fw-3i1"/>
<outlet property="debuggerSideViewInput" destination="w0g-eK-jM4" id="GBf-WK-ryI"/>
<outlet property="debuggerSidebarEffectView" destination="4Z2-33-dYY" id="Ja6-bC-rQg"/>
<outlet property="debuggerSplitView" destination="pUc-ZN-vl5" id="0sG-0D-cID"/>
<outlet property="debuggerStepButton" destination="DsN-Ce-QoH" id="Ts4-uK-pvI"/>
<outlet property="debuggerStepButton" destination="fsQ-dD-A8C" id="1Vi-Pi-rsI"/>
<outlet property="debuggerVerticalLine" destination="7bR-gM-1At" id="rfy-7Z-388"/>
<outlet property="feedImageView" destination="Ar0-nN-eop" id="wHa-St-o4G"/>
<outlet property="gridButton" destination="fL6-2S-Rgd" id="jtV-jh-GHC"/>
@ -52,7 +56,7 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" tabbingMode="disallowed" id="xOd-HO-29H" userLabel="Window">
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" tabbingMode="disallowed" id="xOd-HO-29H" userLabel="Window" customClass="GBWindow">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
<rect key="contentRect" x="0.0" y="0.0" width="160" height="144"/>
@ -86,41 +90,41 @@
</connections>
<point key="canvasLocation" x="293" y="347"/>
</window>
<window title="Debug Console" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="21F-Ah-yHX" customClass="NSPanel">
<window title="Debug Console" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="21F-Ah-yHX" customClass="GBPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES" utility="YES" HUD="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenAuxiliary="YES"/>
<rect key="contentRect" x="0.0" y="0.0" width="921" height="400"/>
<rect key="contentRect" x="0.0" y="0.0" width="921" height="480"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
<value key="minSize" type="size" width="921" height="400"/>
<view key="contentView" id="dCP-E5-7Fi" customClass="GBOptionalVisualEffectView">
<rect key="frame" x="0.0" y="0.0" width="921" height="400"/>
<rect key="frame" x="0.0" y="0.0" width="921" height="480"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<box horizontalHuggingPriority="750" boxType="separator" id="7bR-gM-1At">
<rect key="frame" x="590" y="0.0" width="5" height="401"/>
<rect key="frame" x="590" y="0.0" width="5" height="481"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" heightSizable="YES"/>
</box>
<splitView dividerStyle="thin" vertical="YES" id="pUc-ZN-vl5" customClass="GBSplitView">
<rect key="frame" x="0.0" y="0.0" width="921" height="401"/>
<rect key="frame" x="0.0" y="0.0" width="921" height="481"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<customView fixedFrame="YES" id="2rj-7i-kxc">
<rect key="frame" x="0.0" y="0.0" width="591" height="401"/>
<rect key="frame" x="0.0" y="0.0" width="591" height="481"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="oTo-zx-o6N">
<rect key="frame" x="0.0" y="52" width="591" height="349"/>
<rect key="frame" x="0.0" y="52" width="591" height="429"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="EQe-Ad-L7S">
<rect key="frame" x="0.0" y="0.0" width="591" height="349"/>
<rect key="frame" x="0.0" y="0.0" width="591" height="429"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" baseWritingDirection="leftToRight" findStyle="bar" allowsNonContiguousLayout="YES" id="doS-dM-hnl">
<rect key="frame" x="0.0" y="0.0" width="591" height="349"/>
<rect key="frame" x="0.0" y="0.0" width="591" height="429"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.25" colorSpace="custom" customColorSpace="sRGB"/>
<size key="minSize" width="591" height="349"/>
<size key="minSize" width="591" height="429"/>
<size key="maxSize" width="1160" height="10000000"/>
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
@ -134,7 +138,7 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="cwi-6E-rbh">
<rect key="frame" x="575" y="0.0" width="16" height="349"/>
<rect key="frame" x="575" y="0.0" width="16" height="429"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
@ -153,106 +157,112 @@
<action selector="consoleInput:" target="-2" id="ylQ-vw-ARS"/>
</connections>
</textField>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="xJr-K6-B4B">
<rect key="frame" x="0.0" y="49" width="591" height="4"/>
<customView id="sah-kv-6KJ">
<rect key="frame" x="0.0" y="26" width="591" height="26"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="9DF-fj-a2v">
<rect key="frame" x="0.0" y="24" width="591" height="4"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G4h-KO-Z3g" customClass="GBDebuggerButton">
<rect key="frame" x="2" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Interrupt" alternateTitle="interrupt" bezelStyle="rounded" image="InterruptTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="wfO-32-eG5">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<color key="contentTintColor" name="controlAccentColor" catalog="System" colorSpace="catalog"/>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="SjG-90-8dJ"/>
<outlet property="textField" destination="l22-S8-uji" id="NZ8-eJ-Uyd"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cOi-Rs-9gS" customClass="GBDebuggerButton">
<rect key="frame" x="28" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Over" alternateTitle="next" bezelStyle="rounded" image="NextTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="buW-ke-lgF">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="g7E-UM-SHV"/>
<outlet property="textField" destination="l22-S8-uji" id="1uM-AA-yHi"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DsN-Ce-QoH" customClass="GBDebuggerButton">
<rect key="frame" x="54" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Into" alternateTitle="step" bezelStyle="rounded" image="StepTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="ATJ-Vx-zbo">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="QMw-82-HKJ"/>
<outlet property="textField" destination="l22-S8-uji" id="qaF-TF-cwg"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vtb-n5-Qlz" customClass="GBDebuggerButton">
<rect key="frame" x="78" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Out" alternateTitle="finish" bezelStyle="rounded" image="FinishTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="8mF-ii-5Hx">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="krr-9m-Jfz"/>
<outlet property="textField" destination="l22-S8-uji" id="uYK-tU-BnO"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oCa-UH-1mi" customClass="GBDebuggerButton">
<rect key="frame" x="563" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Help" alternateTitle="help" bezelStyle="rounded" image="HelpTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="tvn-kY-8FO">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="PwN-rf-AcB"/>
<outlet property="textField" destination="l22-S8-uji" id="blK-B3-MWI"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="onn-R8-3vg" customClass="GBDebuggerButton">
<rect key="frame" x="102" y="26" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Backwards" alternateTitle="backstep" bezelStyle="rounded" image="BackstepTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="WtK-kD-bf6">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="S9a-jV-Z6g"/>
<outlet property="textField" destination="l22-S8-uji" id="1gw-Lc-QFS"/>
</connections>
</button>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ybQ-jy-NgI" customClass="GBDebuggerButton">
<rect key="frame" x="4" y="0.0" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Interrupt" alternateTitle="interrupt" bezelStyle="rounded" image="InterruptTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="Yd7-kY-21r">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<color key="contentTintColor" name="controlAccentColor" catalog="System" colorSpace="catalog"/>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="8pX-u8-oFG"/>
<outlet property="textField" destination="l22-S8-uji" id="cIZ-tr-dAu"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jdD-yP-Nr6" customClass="GBDebuggerButton">
<rect key="frame" x="80" y="0.0" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Out" alternateTitle="finish" bezelStyle="rounded" image="FinishTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="16t-ix-lOh">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="FXb-hO-cEh"/>
<outlet property="textField" destination="l22-S8-uji" id="IPT-hF-MHv"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tTP-Zs-Ohu" customClass="GBDebuggerButton">
<rect key="frame" x="30" y="0.0" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Over" alternateTitle="next" bezelStyle="rounded" image="NextTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="835-qy-CNq">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="qL6-Mz-v2a"/>
<outlet property="textField" destination="l22-S8-uji" id="MRn-cs-a9T"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="E87-Uq-f2l" customClass="GBDebuggerButton">
<rect key="frame" x="104" y="0.0" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Backward" alternateTitle="backstep" bezelStyle="rounded" image="BackstepTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="yr5-aU-Fli">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="vyO-14-k3A"/>
<outlet property="textField" destination="l22-S8-uji" id="f5e-xA-0En"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fsQ-dD-A8C" customClass="GBDebuggerButton">
<rect key="frame" x="56" y="0.0" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Step Into" alternateTitle="step" bezelStyle="rounded" image="StepTemplate" imagePosition="only" alignment="center" enabled="NO" imageScaling="proportionallyDown" inset="2" id="lau-41-TYH">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="6DD-pu-gwc"/>
<outlet property="textField" destination="l22-S8-uji" id="ILQ-oy-iGc"/>
</connections>
</button>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="8bt-2t-EIG">
<rect key="frame" x="-2" y="23" width="593" height="4"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="eSO-2z-QHX">
<rect key="frame" x="-2" y="-2" width="593" height="4"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0Jt-TO-8CM" customClass="GBDebuggerButton">
<rect key="frame" x="561" y="0.0" width="26" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="bevel" title="Help" alternateTitle="help" bezelStyle="rounded" image="HelpTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="fVh-bT-eYs">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="debuggerButtonPressed:" target="-2" id="hKh-wH-W5U"/>
<outlet property="textField" destination="l22-S8-uji" id="PMA-QA-gwg"/>
</connections>
</button>
</subviews>
</customView>
</subviews>
</customView>
<customView fixedFrame="YES" id="4Z2-33-dYY" customClass="GBOptionalVisualEffectView">
<rect key="frame" x="592" y="0.0" width="329" height="401"/>
<rect key="frame" x="592" y="0.0" width="329" height="481"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" scrollerKnobStyle="dark" translatesAutoresizingMaskIntoConstraints="NO" id="V9U-Ua-F4z">
<rect key="frame" x="0.0" y="354" width="329" height="47"/>
<rect key="frame" x="0.0" y="418" width="329" height="63"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="YHx-TM-zIC">
<rect key="frame" x="0.0" y="0.0" width="329" height="47"/>
<rect key="frame" x="0.0" y="0.0" width="329" height="63"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView drawsBackground="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" allowsCharacterPickerTouchBarItem="NO" allowsUndo="YES" allowsNonContiguousLayout="YES" textCompletion="NO" spellingCorrection="YES" id="w0g-eK-jM4">
<rect key="frame" x="0.0" y="0.0" width="329" height="47"/>
<rect key="frame" x="0.0" y="0.0" width="329" height="63"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="329" height="47"/>
<size key="minSize" width="329" height="63"/>
<size key="maxSize" width="463" height="10000000"/>
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
@ -266,27 +276,27 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="qgN-F8-fdB">
<rect key="frame" x="313" y="0.0" width="16" height="47"/>
<rect key="frame" x="313" y="0.0" width="16" height="63"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="5qI-qZ-nkh">
<rect key="frame" x="0.0" y="352" width="329" height="5"/>
<rect key="frame" x="0.0" y="415" width="329" height="5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
</box>
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vts-CC-ZjQ">
<rect key="frame" x="0.0" y="0.0" width="329" height="354"/>
<rect key="frame" x="0.0" y="78" width="329" height="339"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="Cs9-3x-ATg">
<rect key="frame" x="0.0" y="0.0" width="329" height="354"/>
<rect key="frame" x="0.0" y="0.0" width="329" height="339"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView editable="NO" drawsBackground="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" baseWritingDirection="leftToRight" findStyle="bar" allowsNonContiguousLayout="YES" spellingCorrection="YES" id="JgV-7E-iwp">
<rect key="frame" x="0.0" y="0.0" width="329" height="354"/>
<rect key="frame" x="0.0" y="0.0" width="329" height="339"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" red="0.14901960780000001" green="0.14901960780000001" blue="0.14901960780000001" alpha="1" colorSpace="calibratedRGB"/>
<size key="minSize" width="329" height="354"/>
<size key="minSize" width="329" height="339"/>
<size key="maxSize" width="1160" height="10000000"/>
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
@ -301,10 +311,38 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="4jm-Gm-D2R">
<rect key="frame" x="313" y="0.0" width="16" height="354"/>
<rect key="frame" x="313" y="0.0" width="16" height="339"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="wC1-WG-WRf">
<rect key="frame" x="0.0" y="75" width="329" height="5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</box>
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aBf-yU-8M0" customClass="GBCPUView">
<rect key="frame" x="0.0" y="0.0" width="329" height="77"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<subviews>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="F9b-AT-CdX">
<rect key="frame" x="2" y="59" width="100" height="16"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="CPU Load" id="ai6-8E-Let">
<font key="font" metaFont="smallSystemBold"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xdx-GC-Tb8">
<rect key="frame" x="2" y="2" width="100" height="16"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="left" title="100%" id="set-AM-fVX">
<font key="font" metaFont="smallSystemBold"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</customView>
</subviews>
</customView>
</subviews>
@ -318,9 +356,12 @@
</splitView>
</subviews>
</view>
<connections>
<outlet property="ownerWindow" destination="xOd-HO-29H" id="beo-JZ-Ekb"/>
</connections>
<point key="canvasLocation" x="347.5" y="-29"/>
</window>
<window title="Memory" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" toolbarStyle="expanded" id="mRm-dL-mCj" customClass="NSPanel">
<window title="Memory" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" toolbarStyle="expanded" id="mRm-dL-mCj" customClass="GBPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenAuxiliary="YES"/>
<rect key="contentRect" x="0.0" y="0.0" width="528" height="320"/>
@ -329,20 +370,20 @@
<rect key="frame" x="0.0" y="0.0" width="528" height="320"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</view>
<toolbar key="toolbar" implicitIdentifier="D857E961-E523-4295-83F8-0849316E827C" autosavesConfiguration="NO" allowsUserCustomization="NO" displayMode="iconAndLabel" sizeMode="regular" id="82v-uB-RPi">
<toolbar key="toolbar" implicitIdentifier="D857E961-E523-4295-83F8-0849316E827C" autosavesConfiguration="NO" allowsUserCustomization="NO" showsBaselineSeparator="NO" displayMode="iconAndLabel" sizeMode="regular" id="82v-uB-RPi">
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="WUk-8p-S6B"/>
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="E3z-um-6KG"/>
<toolbarItem implicitItemIdentifier="4F6AAE25-1E9D-4111-9E5B-91F0792E56CD" label="Address Space" paletteLabel="Address Space" id="VTy-lj-K0H">
<nil key="toolTip"/>
<size key="minSize" width="100" height="25"/>
<size key="maxSize" width="130" height="25"/>
<size key="minSize" width="160" height="25"/>
<size key="maxSize" width="160" height="25"/>
<popUpButton key="view" verticalHuggingPriority="750" id="vfJ-vu-gqJ">
<rect key="frame" x="0.0" y="14" width="128" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="bpD-j9-omo">
<rect key="frame" x="0.0" y="14" width="160" height="25"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<popUpButtonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="bpD-j9-omo" customClass="GBToolbarPopUpButtonCell">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<font key="font" metaFont="message"/>
<menu key="menu" id="gTX-6Z-mOH">
<items>
<menuItem title="Entire Space" id="Zp5-J9-dd3"/>
@ -361,31 +402,29 @@
<toolbarItem implicitItemIdentifier="D16C64D2-2F0D-4033-A1EC-A1E699522ECE" label="Bank" paletteLabel="Bank" id="bWC-FW-IYP">
<nil key="toolTip"/>
<size key="minSize" width="64" height="22"/>
<size key="maxSize" width="64" height="22"/>
<textField key="view" verticalHuggingPriority="750" id="rdV-q6-hc6">
<size key="maxSize" width="80" height="22"/>
<textField key="view" focusRingType="none" verticalHuggingPriority="750" id="rdV-q6-hc6">
<rect key="frame" x="0.0" y="14" width="64" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" id="JCn-Y1-eHS">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" placeholderString="Bank" id="JCn-Y1-eHS" customClass="GBToolbarFieldCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="hexUpdateBank:" target="-2" id="Mx9-WI-wgO"/>
</connections>
</textField>
</toolbarItem>
<toolbarItem implicitItemIdentifier="F9723DA8-D79F-43AB-876B-783DD0204AA6" label="Go to" paletteLabel="Go to" id="rLO-D7-zRG">
<toolbarItem implicitItemIdentifier="F9723DA8-D79F-43AB-876B-783DD0204AA6" label="Go To" paletteLabel="Go To" id="rLO-D7-zRG">
<nil key="toolTip"/>
<size key="minSize" width="96" height="22"/>
<size key="maxSize" width="128" height="22"/>
<textField key="view" verticalHuggingPriority="750" id="EJd-jG-hmH">
<rect key="frame" x="0.0" y="14" width="96" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" bezelStyle="round" id="vg5-Nn-abb">
<size key="minSize" width="160" height="22"/>
<size key="maxSize" width="160" height="22"/>
<textField key="view" focusRingType="none" verticalHuggingPriority="750" id="EJd-jG-hmH">
<rect key="frame" x="0.0" y="14" width="160" height="22"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" placeholderString="Address" bezelStyle="round" id="vg5-Nn-abb" customClass="GBToolbarFieldCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="hexGoTo:" target="-2" id="7WG-8C-SK8"/>
@ -400,15 +439,18 @@
<toolbarItem reference="rLO-D7-zRG"/>
</defaultToolbarItems>
</toolbar>
<connections>
<outlet property="ownerWindow" destination="xOd-HO-29H" id="wCE-dT-kGv"/>
</connections>
<point key="canvasLocation" x="-185" y="61"/>
</window>
<menuItem title="Cartridge RAM" id="ylM-ah-PNQ"/>
<window title="VRAM Viewer" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" toolbarStyle="expanded" id="mbr-db-iZh" customClass="NSPanel">
<window title="VRAM Viewer" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" toolbarStyle="expanded" id="mbr-db-iZh" customClass="GBPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenAuxiliary="YES"/>
<rect key="contentRect" x="0.0" y="0.0" width="512" height="432"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
<view key="contentView" id="GYW-dv-Um1">
<view key="contentView" misplaced="YES" id="GYW-dv-Um1">
<rect key="frame" x="0.0" y="0.0" width="512" height="432"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
@ -416,7 +458,7 @@
<rect key="frame" x="0.0" y="406" width="512" height="5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</box>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6vK-IP-PmP">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6vK-IP-PmP">
<rect key="frame" x="-2" y="4" width="516" height="14"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="umk-4r-VNg">
@ -549,7 +591,7 @@
</connections>
</popUpButton>
<popUpButton focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="YIJ-Qc-SIZ">
<rect key="frame" x="135" y="412" width="96" height="17"/>
<rect key="frame" x="135" y="412" width="100" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="roundRect" title="Effective Tilemap" bezelStyle="roundedRect" alignment="left" controlSize="mini" lineBreakMode="truncatingTail" state="on" borderStyle="border" focusRingType="none" imageScaling="proportionallyDown" inset="2" selectedItem="XRF-Vj-3gs" id="3W1-Db-wDn">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -567,7 +609,7 @@
</connections>
</popUpButton>
<popUpButton focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="k4c-Vg-MBu">
<rect key="frame" x="235" y="412" width="96" height="17"/>
<rect key="frame" x="239" y="412" width="100" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="roundRect" title="Effective Tileset" bezelStyle="roundedRect" alignment="left" controlSize="mini" lineBreakMode="truncatingTail" state="on" borderStyle="border" focusRingType="none" imageScaling="proportionallyDown" inset="2" selectedItem="CRe-dX-rzY" id="h53-sb-Odg">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -635,21 +677,19 @@
</tabView>
</subviews>
</view>
<toolbar key="toolbar" implicitIdentifier="7FF8B5E5-F61B-408C-9634-A5D496FE5E70" autosavesConfiguration="NO" allowsUserCustomization="NO" displayMode="iconOnly" sizeMode="regular" id="SVR-To-n7n">
<toolbar key="toolbar" implicitIdentifier="7FF8B5E5-F61B-408C-9634-A5D496FE5E70" autosavesConfiguration="NO" allowsUserCustomization="NO" showsBaselineSeparator="NO" displayMode="iconOnly" sizeMode="regular" id="SVR-To-n7n">
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="hnI-48-dYt"/>
<toolbarItem implicitItemIdentifier="B9D3CF98-8020-4389-9372-F99361440794" label="" paletteLabel="" id="fmK-Jl-Koj">
<toolbarItem implicitItemIdentifier="B9D3CF98-8020-4389-9372-F99361440794" label="" paletteLabel="" sizingBehavior="auto" id="fmK-Jl-Koj">
<nil key="toolTip"/>
<size key="minSize" width="100" height="25"/>
<size key="maxSize" width="268" height="25"/>
<segmentedControl key="view" verticalHuggingPriority="750" id="Aul-vO-dCK">
<rect key="frame" x="0.0" y="14" width="268" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<autoresizingMask key="autoresizingMask"/>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="texturedSquare" trackingMode="selectOne" id="HhR-ky-5NN">
<font key="font" metaFont="system"/>
<segments>
<segment label="Tileset" selected="YES"/>
<segment label="Tilemap" tag="1"/>
<segment label="Tilemap"/>
<segment label="Objects"/>
<segment label="Palettes"/>
</segments>
@ -667,9 +707,12 @@
</defaultToolbarItems>
</toolbar>
<contentBorderThickness minY="24"/>
<connections>
<outlet property="ownerWindow" destination="xOd-HO-29H" id="hkb-AH-4fo"/>
</connections>
<point key="canvasLocation" x="182" y="760"/>
</window>
<window title="Printer Feed" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" hidesOnDeactivate="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="NdE-0B-WCf" customClass="NSPanel">
<window title="Printer" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" hidesOnDeactivate="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="NdE-0B-WCf" customClass="GBPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
<rect key="contentRect" x="0.0" y="0.0" width="320" height="288"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
@ -685,7 +728,7 @@
</imageView>
</subviews>
</view>
<toolbar key="toolbar" implicitIdentifier="1FF86A2B-6637-4EE6-A25A-7298D79AE84E" autosavesConfiguration="NO" allowsUserCustomization="NO" displayMode="iconAndLabel" sizeMode="regular" id="gH3-SH-7il">
<toolbar key="toolbar" implicitIdentifier="1FF86A2B-6637-4EE6-A25A-7298D79AE84E" autosavesConfiguration="NO" allowsUserCustomization="NO" showsBaselineSeparator="NO" displayMode="iconAndLabel" sizeMode="regular" id="gH3-SH-7il">
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="15EB8D49-8C6E-42F2-9F7F-F7D7A0BBDAAF" label="Save" paletteLabel="Save" tag="-1" image="NSFolder" id="CBz-1N-o0Q">
<size key="minSize" width="22" height="22"/>
@ -717,168 +760,30 @@
<toolbarItem reference="L6N-6G-UWl"/>
</defaultToolbarItems>
</toolbar>
<connections>
<outlet property="ownerWindow" destination="xOd-HO-29H" id="8Lk-t1-HNi"/>
</connections>
<point key="canvasLocation" x="-159" y="356"/>
</window>
<window title="Cheats" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="4Yb-Np-JrF" customClass="NSPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<rect key="contentRect" x="0.0" y="0.0" width="692" height="272"/>
<window title="Cheats" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="4Yb-Np-JrF" customClass="GBPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="0.0" y="0.0" width="604" height="400"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
<value key="minSize" type="size" width="604" height="400"/>
<value key="maxSize" type="size" width="604" height="99999"/>
<view key="contentView" id="gBP-5p-BTh">
<rect key="frame" x="0.0" y="0.0" width="692" height="272"/>
<rect key="frame" x="0.0" y="0.0" width="604" height="400"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view id="fWr-0i-K1d" customClass="GBOptionalVisualEffectView">
<rect key="frame" x="0.0" y="0.0" width="294" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="hqi-ob-NW9">
<rect key="frame" x="16" y="174" width="154" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="To value:" id="Ycx-oE-aA4">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Kq8-6F-9GK">
<rect key="frame" x="16" y="142" width="154" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Only if old value was: " bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="LkB-WQ-9Qd">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="updateCheat:" target="v7q-gT-jHT" id="kNc-cj-bmF"/>
</connections>
</button>
<box verticalHuggingPriority="750" boxType="separator" id="D6k-Pe-23u">
<rect key="frame" x="10" y="129" width="274" height="5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</box>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="r5T-ol-Dod">
<rect key="frame" x="16" y="107" width="270" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Import GameShark or GameGenie cheat:" id="0mf-EN-cKc">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X7K-nJ-alF">
<rect key="frame" x="39" y="78" width="233" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" focusRingType="none" placeholderString="Code" drawsBackground="YES" usesSingleLineMode="YES" id="2bz-dT-7Fi">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<action selector="selectText:" target="KHj-uX-Wbk" id="11z-0U-tMA"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KHj-uX-Wbk">
<rect key="frame" x="39" y="47" width="233" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" focusRingType="none" placeholderString="Description" drawsBackground="YES" usesSingleLineMode="YES" id="50d-va-Cen">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="performClick:" target="C3V-Ep-bMj" id="kIN-jl-A8d"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="C6E-oI-hDC">
<rect key="frame" x="20" y="233" width="252" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" focusRingType="none" placeholderString="Description" drawsBackground="YES" usesSingleLineMode="YES" id="2uR-9N-hBb">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<outlet property="delegate" destination="v7q-gT-jHT" id="zyw-h0-hRP"/>
</connections>
</textField>
<button verticalHuggingPriority="750" id="C3V-Ep-bMj">
<rect key="frame" x="203" y="12" width="83" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="roundTextured" title="Import" bezelStyle="texturedRounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="mMP-KW-YNy">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="importCheat:" target="v7q-gT-jHT" id="lkX-N5-wD1"/>
</connections>
</button>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" mirrorLayoutDirectionWhenInternationalizing="never" translatesAutoresizingMaskIntoConstraints="NO" id="qHx-1z-daR">
<rect key="frame" x="176" y="204" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" focusRingType="none" drawsBackground="YES" usesSingleLineMode="YES" id="edq-46-JeP" customClass="GBCheatTextFieldCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<outlet property="delegate" destination="v7q-gT-jHT" id="79v-33-R1X"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" mirrorLayoutDirectionWhenInternationalizing="never" translatesAutoresizingMaskIntoConstraints="NO" id="N3I-PP-X85">
<rect key="frame" x="176" y="174" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" focusRingType="none" drawsBackground="YES" usesSingleLineMode="YES" id="CV2-D9-WsB" customClass="GBCheatTextFieldCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<outlet property="delegate" destination="v7q-gT-jHT" id="P69-nT-oOt"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" mirrorLayoutDirectionWhenInternationalizing="never" translatesAutoresizingMaskIntoConstraints="NO" id="S6O-LB-gSj">
<rect key="frame" x="176" y="144" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" focusRingType="none" drawsBackground="YES" usesSingleLineMode="YES" id="tpM-ys-MEO" customClass="GBCheatTextFieldCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<outlet property="delegate" destination="v7q-gT-jHT" id="6RH-dg-SL7"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="uFo-ly-Veq">
<rect key="frame" x="16" y="204" width="152" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Change byte at address:" id="xwa-TF-eY1">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</view>
<scrollView autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="6rU-Xg-KHc">
<rect key="frame" x="293" y="-1" width="400" height="275"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" heightSizable="YES"/>
<scrollView autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="6rU-Xg-KHc">
<rect key="frame" x="-1" y="143" width="606" height="259"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" id="mzf-yu-RID">
<rect key="frame" x="1" y="1" width="398" height="273"/>
<autoresizingMask key="autoresizingMask"/>
<rect key="frame" x="1" y="1" width="604" height="257"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" headerView="pvX-uJ-qK5" id="tA3-8T-bxb">
<rect key="frame" x="0.0" y="0.0" width="398" height="256"/>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="24" headerView="pvX-uJ-qK5" id="tA3-8T-bxb">
<rect key="frame" x="0.0" y="0.0" width="604" height="240"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -889,13 +794,13 @@
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<buttonCell key="dataCell" type="inline" bezelStyle="inline" image="NSStopProgressFreestandingTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="5xh-hN-jHH">
<buttonCell key="dataCell" type="inline" bezelStyle="inline" image="NSStopProgressFreestandingTemplate" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="5xh-hN-jHH" customClass="GBDeleteButtonCell">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn width="40" minWidth="40" maxWidth="1000" id="9DZ-oW-Scx">
<tableColumn width="52" minWidth="52" maxWidth="1000" id="9DZ-oW-Scx">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Enabled">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
@ -906,24 +811,24 @@
</buttonCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn editable="NO" width="142" minWidth="40" maxWidth="1000" id="4Qa-FQ-QWY">
<tableColumn editable="NO" width="320" minWidth="320" maxWidth="1000" id="4Qa-FQ-QWY">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Description">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Description" id="1hX-Sr-bGz">
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Description" id="1hX-Sr-bGz" customClass="GBCenteredTextCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn editable="NO" width="134" minWidth="40" maxWidth="1000" id="ACq-gU-K36">
<tableColumn editable="NO" width="172" minWidth="172" maxWidth="1000" id="ACq-gU-K36">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Action">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Action" id="8Sq-h9-eV7">
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Action" id="8Sq-h9-eV7" customClass="GBCenteredTextCell">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -939,7 +844,7 @@
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="3Hg-LL-VqH">
<rect key="frame" x="1" y="119" width="223" height="15"/>
<rect key="frame" x="1" y="242" width="604" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="zET-KH-qF4">
@ -947,13 +852,159 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
<tableHeaderView key="headerView" wantsLayer="YES" id="pvX-uJ-qK5">
<rect key="frame" x="0.0" y="0.0" width="398" height="17"/>
<rect key="frame" x="0.0" y="0.0" width="604" height="17"/>
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="TFe-hA-XJc">
<rect key="frame" x="-1" y="0.0" width="308" height="135"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" id="hqi-ob-NW9">
<rect key="frame" x="20" y="52" width="176" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="To value:" id="Ycx-oE-aA4">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Kq8-6F-9GK">
<rect key="frame" x="42" y="22" width="152" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES"/>
<buttonCell key="cell" type="check" title="Only if old value was: " bezelStyle="regularSquare" imagePosition="left" alignment="right" state="on" inset="2" id="LkB-WQ-9Qd">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="updateCheat:" target="v7q-gT-jHT" id="kNc-cj-bmF"/>
</connections>
</button>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="C6E-oI-hDC">
<rect key="frame" x="22" y="113" width="276" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Description" drawsBackground="YES" usesSingleLineMode="YES" id="2uR-9N-hBb">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<outlet property="delegate" destination="v7q-gT-jHT" id="zyw-h0-hRP"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" mirrorLayoutDirectionWhenInternationalizing="never" translatesAutoresizingMaskIntoConstraints="NO" id="qHx-1z-daR">
<rect key="frame" x="202" y="82" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" drawsBackground="YES" usesSingleLineMode="YES" id="edq-46-JeP" customClass="GBCheatTextFieldCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<outlet property="delegate" destination="v7q-gT-jHT" id="79v-33-R1X"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" mirrorLayoutDirectionWhenInternationalizing="never" translatesAutoresizingMaskIntoConstraints="NO" id="N3I-PP-X85">
<rect key="frame" x="202" y="51" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" drawsBackground="YES" usesSingleLineMode="YES" id="CV2-D9-WsB" customClass="GBCheatTextFieldCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<outlet property="delegate" destination="v7q-gT-jHT" id="P69-nT-oOt"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" mirrorLayoutDirectionWhenInternationalizing="never" translatesAutoresizingMaskIntoConstraints="NO" id="S6O-LB-gSj">
<rect key="frame" x="202" y="20" width="96" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" drawsBackground="YES" usesSingleLineMode="YES" id="tpM-ys-MEO" customClass="GBCheatTextFieldCell">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<outlet property="delegate" destination="v7q-gT-jHT" id="6RH-dg-SL7"/>
</connections>
</textField>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" id="uFo-ly-Veq">
<rect key="frame" x="18" y="83" width="178" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Change byte at address:" id="xwa-TF-eY1">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</customView>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="r5T-ol-Dod">
<rect key="frame" x="316" y="116" width="270" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Import GameShark or Game Genie cheat:" id="0mf-EN-cKc">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X7K-nJ-alF">
<rect key="frame" x="351" y="82" width="233" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="Code" drawsBackground="YES" usesSingleLineMode="YES" id="2bz-dT-7Fi">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</textFieldCell>
<connections>
<action selector="selectText:" target="KHj-uX-Wbk" id="11z-0U-tMA"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KHj-uX-Wbk">
<rect key="frame" x="351" y="51" width="233" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="Description" drawsBackground="YES" usesSingleLineMode="YES" id="50d-va-Cen">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="performClick:" target="C3V-Ep-bMj" id="kIN-jl-A8d"/>
</connections>
</textField>
<button verticalHuggingPriority="750" id="C3V-Ep-bMj">
<rect key="frame" x="508" y="13" width="83" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES"/>
<buttonCell key="cell" type="push" title="Import" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="mMP-KW-YNy">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="importCheat:" target="v7q-gT-jHT" id="lkX-N5-wD1"/>
</connections>
</button>
<box horizontalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="P90-u5-8ko">
<rect key="frame" x="302" y="12" width="5" height="123"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
</box>
</subviews>
</view>
<point key="canvasLocation" x="254" y="-463"/>
<connections>
<outlet property="ownerWindow" destination="xOd-HO-29H" id="ZQr-6h-iby"/>
</connections>
<point key="canvasLocation" x="210" y="-399"/>
</window>
<customObject id="v7q-gT-jHT" customClass="GBCheatWindowController">
<connections>
@ -975,7 +1026,7 @@
<image name="HelpTemplate" width="14" height="14"/>
<image name="InterruptTemplate" width="14" height="14"/>
<image name="NSFolder" width="32" height="32"/>
<image name="NSStopProgressFreestandingTemplate" width="15" height="15"/>
<image name="NSStopProgressFreestandingTemplate" width="20" height="20"/>
<image name="NextTemplate" width="14" height="14"/>
<image name="StepTemplate" width="14" height="14"/>
<image name="printer" catalog="system" width="18" height="16"/>

View File

@ -22,5 +22,6 @@
@property (strong) IBOutlet NSButton *updateProgressButton;
@property (strong) IBOutlet NSWindow *updateProgressWindow;
@property (strong) IBOutlet NSProgressIndicator *updateProgressSpinner;
- (void)updateThemesDefault:(bool)overwrite;
@end

View File

@ -8,9 +8,15 @@
#import <JoyKit/JoyKit.h>
#import <WebKit/WebKit.h>
#import <mach-o/dyld.h>
#include <sys/mount.h>
#include <sys/xattr.h>
#define UPDATE_SERVER "https://sameboy.github.io"
@interface NSToolbarItem(private)
- (NSButton *)_view;
@end
static uint32_t color_to_int(NSColor *color)
{
color = [color colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
@ -40,14 +46,26 @@ static uint32_t color_to_int(NSColor *color)
- (void) applicationDidFinishLaunching:(NSNotification *)notification
{
// Refresh icon if launched via a software update
[NSApplication sharedApplication].applicationIconImage = [NSImage imageNamed:@"AppIcon"];
if (@available(macOS 26.0, *)) {
// Severely broken on macOS 26
}
else {
NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile:[[NSBundle mainBundle] bundlePath]];
icon.size = [NSApplication sharedApplication].applicationIconImage.size;
[NSApplication sharedApplication].applicationIconImage = icon;
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
for (unsigned i = 0; i < GBButtonCount; i++) {
for (unsigned i = 0; i < GBKeyboardButtonCount; i++) {
if ([[defaults objectForKey:button_to_preference_name(i, 0)] isKindOfClass:[NSString class]]) {
[defaults removeObjectForKey:button_to_preference_name(i, 0)];
}
}
bool hasSFMono = false;
if (@available(macOS 10.15, *)) {
hasSFMono = [[NSFont monospacedSystemFontOfSize:12 weight:NSFontWeightRegular].displayName containsString:@"SF"];
}
[[NSUserDefaults standardUserDefaults] registerDefaults:@{
@"GBRight": @(kVK_RightArrow),
@"GBLeft": @(kVK_LeftArrow),
@ -83,8 +101,24 @@ static uint32_t color_to_int(NSColor *color)
@"GBJoyConAutoPair": @YES,
@"GBJoyConsDefaultsToHorizontal": @YES,
@"GBEmulatedModel": @(MODEL_AUTO),
@"GBDebuggerFont": hasSFMono? @"SF Mono" : @"Menlo",
@"GBDebuggerFontSize": @12,
@"GBColorPalette": @1,
@"GBTurboCap": @0,
// Default themes
@"GBThemes": @{
@"Canyon": @{
@"BrightnessBias": @0.1227009965823247,
@"Colors": @[@0xff0c1e20, @0xff122b91, @0xff466aa2, @0xfff1efae, @0xfff1efae],
@"DisabledLCDColor": @NO,
@"HueBias": @0.01782661816105247,
@"HueBiasStrength": @1,
@"Manual": @NO,
},
@"Desert": @{
@"BrightnessBias": @0.0,
@"Colors": @[@0xff302f3e, @0xff576674, @0xff839ba4, @0xffb1d0d2, @0xffb7d7d8],
@ -109,6 +143,30 @@ static uint32_t color_to_int(NSColor *color)
@"HueBiasStrength": @0.18424738545816732,
@"Manual": @NO,
},
@"Green Slate": @{
@"BrightnessBias": @0.2210012227296829,
@"Colors": @[@0xff343117, @0xff6a876f, @0xff98b4a1, @0xffc3daca, @0xffc8decf],
@"DisabledLCDColor": @YES,
@"HueBias": @0.1887667975388467,
@"HueBiasStrength": @0.1272283345460892,
@"Manual": @NO,
},
@"Green Tea": @{
@"BrightnessBias": @-0.4946326622596153,
@"Colors": @[@0xff1a1d08, @0xff1d5231, @0xff3b9774, @0xff97e4c6, @0xffa9eed1],
@"DisabledLCDColor": @YES,
@"HueBias": @0.1912955007245464,
@"HueBiasStrength": @0.3621708039314516,
@"Manual": @NO,
},
@"Lavender": @{
@"BrightnessBias": @0.10072476038566,
@"Colors": @[@0xff2b2a3a, @0xff8c507c, @0xffbf82a8, @0xffe9bcce, @0xffeec3d3],
@"DisabledLCDColor": @YES,
@"HueBias": @0.7914529587142169,
@"HueBiasStrength": @0.2498168498277664,
@"Manual": @NO,
},
@"Magic Eggplant": @{
@"BrightnessBias": @0.0,
@"Colors": @[@0xff3c2136, @0xff942e84, @0xffc7699d, @0xfff1e4b0, @0xfff6f9b2],
@ -117,6 +175,22 @@ static uint32_t color_to_int(NSColor *color)
@"HueBiasStrength": @0.65018052788844627,
@"Manual": @NO,
},
@"Mystic Blue": @{
@"BrightnessBias": @-0.3291049897670746,
@"Colors": @[@0xff3b2306, @0xffa27807, @0xffd1b523, @0xfff6ebbe, @0xfffaf1e4],
@"DisabledLCDColor": @YES,
@"HueBias": @0.5282051088288426,
@"HueBiasStrength": @0.7699633836746216,
@"Manual": @NO,
},
@"Pink Pop": @{
@"BrightnessBias": @0.624908447265625,
@"Colors": @[@0xff28140a, @0xff7c42cb, @0xffaa83de, @0xffd1ceeb, @0xffd5d8ec],
@"DisabledLCDColor": @YES,
@"HueBias": @0.9477411056868732,
@"HueBiasStrength": @0.80024421215057373,
@"Manual": @NO,
},
@"Radioactive Pea": @{
@"BrightnessBias": @-0.48079556772908372,
@"Colors": @[@0xff215200, @0xff1f7306, @0xff169e34, @0xff03ceb8, @0xff00d4d1],
@ -125,6 +199,14 @@ static uint32_t color_to_int(NSColor *color)
@"HueBiasStrength": @0.34337649402390436,
@"Manual": @NO,
},
@"Rose": @{
@"BrightnessBias": @0.2727272808551788,
@"Colors": @[@0xff001500, @0xff4e1fae, @0xff865ac4, @0xffb7e6d3, @0xffbdffd4],
@"DisabledLCDColor": @YES,
@"HueBias": @0.9238900924101472,
@"HueBiasStrength": @0.9957716464996338,
@"Manual": @NO,
},
@"Seaweed": @{
@"BrightnessBias": @-0.28532744023904377,
@"Colors": @[@0xff3f0015, @0xff426532, @0xff58a778, @0xff95e0df, @0xffa0e7ee],
@ -169,6 +251,31 @@ static uint32_t color_to_int(NSColor *color)
if ([[NSProcessInfo processInfo].arguments containsObject:@"--update-launch"]) {
[NSApp activateIgnoringOtherApps:true];
}
if (![[[NSUserDefaults standardUserDefaults] stringForKey:@"GBThemesVersion"] isEqualToString:@(GB_VERSION)]) {
[self updateThemesDefault:false];
[[NSUserDefaults standardUserDefaults] setObject:@(GB_VERSION) forKey:@"GBThemesVersion"];
}
}
- (void)updateThemesDefault:(bool)overwrite
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *currentThemes = [defaults dictionaryForKey:@"GBThemes"].mutableCopy;
[defaults removeObjectForKey:@"GBThemes"];
NSMutableDictionary *defaultThemes = [defaults dictionaryForKey:@"GBThemes"].mutableCopy;
if (![[NSUserDefaults standardUserDefaults] stringForKey:@"GBThemesVersion"]) {
// Force update the Pink Pop theme, it was glitchy in 1.0
[currentThemes removeObjectForKey:@"Pink Pop"];
}
if (overwrite) {
[currentThemes addEntriesFromDictionary:defaultThemes];
[defaults setObject:currentThemes forKey:@"GBThemes"];
}
else {
[defaultThemes addEntriesFromDictionary:currentThemes];
[defaults setObject:defaultThemes forKey:@"GBThemes"];
}
}
- (IBAction)toggleDeveloperMode:(id)sender
@ -216,7 +323,10 @@ static uint32_t color_to_int(NSColor *color)
[item.image setSize:NSMakeSize(16, 16)];
[items addObject:item];
}
menu.itemArray = items;
[menu removeAllItems];
for (NSMenuItem *item in items) {
[menu addItem:item];
}
}
- (IBAction) showPreferences: (id) sender
@ -232,9 +342,8 @@ static uint32_t color_to_int(NSColor *color)
#ifndef UPDATE_SUPPORT
[_preferencesWindow.toolbar removeItemAtIndex:4];
#endif
if (@available(macOS 11.0, *)) {
[_preferencesWindow.toolbar insertItemWithItemIdentifier:NSToolbarFlexibleSpaceItemIdentifier atIndex:0];
[_preferencesWindow.toolbar insertItemWithItemIdentifier:NSToolbarFlexibleSpaceItemIdentifier atIndex:_preferencesWindow.toolbar.items.count];
for (unsigned i = _preferencesWindow.toolbar.items.count; i--;) {
[_preferencesWindow.toolbar.items[i] _view].imageScaling = NSImageScaleNone;
}
}
[_preferencesWindow makeKeyAndOrderFront:self];
@ -294,7 +403,12 @@ static uint32_t color_to_int(NSColor *color)
else {
self.updateChanges.preferences.standardFontFamily = @"Lucida Grande";
}
self.updateChanges.preferences.fixedFontFamily = @"Menlo";
if (@available(macOS 10.15, *)) {
self.updateChanges.preferences.fixedFontFamily = [NSFont monospacedSystemFontOfSize:12 weight:NSFontWeightRegular].displayName;
}
else {
self.updateChanges.preferences.fixedFontFamily = @"Menlo";
}
self.updateChanges.drawsBackground = false;
[self.updateChanges.mainFrame loadHTMLString:html baseURL:nil];
});
@ -550,6 +664,14 @@ static uint32_t color_to_int(NSColor *color)
}
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
[[NSFileManager defaultManager] removeItemAtPath:contentsTempPath error:nil];
// Remove the quarantine flag so we don't have to escape translocation
NSString *bundlePath = [NSBundle mainBundle].bundlePath;
removexattr(bundlePath.UTF8String, "com.apple.quarantine", 0);
for (NSString *path in [[NSFileManager defaultManager] enumeratorAtPath:bundlePath]) {
removexattr([bundlePath stringByAppendingPathComponent:path].UTF8String, "com.apple.quarantine", 0);
};
_downloadDirectory = nil;
atexit_b(^{
execl(executablePath.UTF8String, executablePath.UTF8String, "--update-launch", NULL);
@ -669,4 +791,27 @@ static uint32_t color_to_int(NSColor *color)
- (IBAction)nop:(id)sender
{
}
/* This runs before C constructors. If we need to escape translocation, we should
do it ASAP to minimize our launch time. */
+ (void)load
{
if (@available(macOS 10.12, *)) {
/* Detect and escape translocation so we can safely update ourselves */
if ([[[NSBundle mainBundle] bundlePath] containsString:@"/AppTranslocation/"]) {
const char *mountPath = [[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent].UTF8String;
struct statfs *mntbuf;
int mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
for (unsigned i = 0; i < mntsize; i++) {
if (strcmp(mntbuf[i].f_mntonname, mountPath) == 0) {
NSBundle *origBundle = [NSBundle bundleWithPath:@(mntbuf[i].f_mntfromname)];
execl(origBundle.executablePath.UTF8String, origBundle.executablePath.UTF8String, NULL);
break;
}
}
}
}
}
@end

View File

@ -7,20 +7,24 @@ typedef enum {
GBB,
GBSelect,
GBStart,
GBRapidA,
GBRapidB,
GBTurbo,
GBRewind,
GBUnderclock,
GBHotkey1,
GBHotkey2,
GBJoypadButtonCount,
GBButtonCount = GBUnderclock + 1,
GBGameBoyButtonCount = GBStart + 1,
GBTotalButtonCount,
GBKeyboardButtonCount = GBUnderclock + 1,
GBPerPlayerButtonCount = GBRapidB + 1,
} GBButton;
#define GBJoyKitHotkey1 JOYButtonUsageGeneric0 + 0x100
#define GBJoyKitHotkey2 JOYButtonUsageGeneric0 + 0x101
#define GBJoyKitRapidA JOYButtonUsageGeneric0 + 0x102
#define GBJoyKitRapidB JOYButtonUsageGeneric0 + 0x103
extern NSString const *GBButtonNames[GBJoypadButtonCount];
extern NSString const *GBButtonNames[GBTotalButtonCount];
static inline NSString *n2s(uint64_t number)
{

View File

@ -1,4 +1,4 @@
#import <Foundation/Foundation.h>
#import "GBButtons.h"
NSString const *GBButtonNames[] = {@"Right", @"Left", @"Up", @"Down", @"A", @"B", @"Select", @"Start", @"Turbo", @"Rewind", @"Slow-Motion", @"Hotkey 1", @"Hotkey 2"};
NSString const *GBButtonNames[] = {@"Right", @"Left", @"Up", @"Down", @"A", @"B", @"Select", @"Start", @"Rapid A", @"Rapid B", @"Turbo", @"Rewind", @"Slow-Motion", @"Hotkey 1", @"Hotkey 2"};

5
Cocoa/GBCPUView.h Normal file
View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBCPUView : NSView
- (void)addSample:(double)sample;
@end

126
Cocoa/GBCPUView.m Normal file
View File

@ -0,0 +1,126 @@
#import "GBCPUView.h"
#define SAMPLE_COUNT 0x100 // ~4 seconds
@implementation GBCPUView
{
double _samples[SAMPLE_COUNT];
size_t _position;
}
- (void)drawRect:(NSRect)dirtyRect
{
CGRect bounds = self.bounds;
NSSize size = bounds.size;
unsigned factor = [[self.window screen] backingScaleFactor];
NSBitmapImageRep *maskBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:(unsigned)size.width * factor
pixelsHigh:(unsigned)size.height * factor
bitsPerSample:8
samplesPerPixel:2
hasAlpha:true
isPlanar:false
colorSpaceName:NSDeviceWhiteColorSpace
bytesPerRow:size.width * 2 * factor
bitsPerPixel:16];
NSGraphicsContext *mainContext = [NSGraphicsContext currentContext];
NSColor *greenColor, *redColor;
if (@available(macOS 10.10, *)) {
greenColor = [NSColor systemGreenColor];
redColor = [NSColor systemRedColor];
}
else {
greenColor = [NSColor colorWithRed:3.0 / 16 green:0.5 blue:5.0 / 16 alpha:1.0];
redColor = [NSColor colorWithRed:13.0 / 16 green:0.25 blue:0.25 alpha:1.0];
}
NSBitmapImageRep *colorBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:SAMPLE_COUNT
pixelsHigh:1
bitsPerSample:8
samplesPerPixel:3
hasAlpha:false
isPlanar:false
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:SAMPLE_COUNT * 4
bitsPerPixel:32];
unsigned lastFill = 0;
NSBezierPath *line = [NSBezierPath bezierPath];
bool isRed = false;
{
double sample = _samples[_position % SAMPLE_COUNT];
[line moveToPoint:NSMakePoint(0,
(sample * (size.height - 1) + 0.5) * factor)];
isRed = sample == 1;
}
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:colorBitmap]];
for (unsigned i = 1; i < SAMPLE_COUNT; i++) {
double sample = _samples[(i + _position) % SAMPLE_COUNT];
[line lineToPoint:NSMakePoint(size.width * i * factor / (SAMPLE_COUNT - 1),
(sample * (size.height - 1) + 0.5) * factor)];
if (isRed != (sample == 1)) {
// Color changed
[(isRed? redColor : greenColor) setFill];
NSRectFill(CGRectMake(lastFill, 0, i - lastFill, 1));
lastFill = i;
isRed ^= true;
}
}
[(isRed? redColor : greenColor) setFill];
NSRectFill(CGRectMake(lastFill, 0, SAMPLE_COUNT - lastFill, 1));
NSBezierPath *fill = [line copy];
[fill lineToPoint:NSMakePoint(size.width * factor, 0)];
[fill lineToPoint:NSMakePoint(0, 0)];
NSColor *strokeColor = [NSColor whiteColor];
NSColor *fillColor = [strokeColor colorWithAlphaComponent:1 / 3.0];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:maskBitmap]];
[fillColor setFill];
[fill fill];
[strokeColor setStroke];
[line setLineWidth:factor];
[line stroke];
CGContextRef maskContext = CGContextRetain([NSGraphicsContext currentContext].graphicsPort);
[NSGraphicsContext setCurrentContext:mainContext];
CGContextSaveGState(mainContext.graphicsPort);
CGImageRef maskImage = CGBitmapContextCreateImage(maskContext);
CGContextClipToMask(mainContext.graphicsPort, bounds, maskImage);
CGImageRelease(maskImage);
NSImage *colors = [[NSImage alloc] initWithSize:NSMakeSize(SAMPLE_COUNT, 1)];
[colors addRepresentation:colorBitmap];
[colors drawInRect:bounds];
CGContextRestoreGState(mainContext.graphicsPort);
CGContextRelease(maskContext);
[super drawRect:dirtyRect];
}
- (void)addSample:(double)sample
{
_samples[_position++] = sample;
if (_position == SAMPLE_COUNT) {
_position = 0;
}
}
@end

View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBCenteredTextCell : NSTextFieldCell
@end

View File

@ -0,0 +1,29 @@
#import "GBCenteredTextCell.h"
@implementation GBCenteredTextCell
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
double height = round([self.attributedStringValue size].height);
cellFrame.origin.y += (cellFrame.size.height - height) / 2;
cellFrame.size.height = height;
[super drawInteriorWithFrame:cellFrame inView:controlView];
}
- (void)selectWithFrame:(NSRect)rect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)delegate start:(NSInteger)selStart length:(NSInteger)selLength
{
double height = round([self.attributedStringValue size].height);
rect.origin.y += (rect.size.height - height) / 2;
rect.size.height = height;
[super selectWithFrame:rect inView:controlView editor:textObj delegate:delegate start:selStart length:selLength];
}
- (void)editWithFrame:(NSRect)rect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)delegate event:(NSEvent *)event
{
double height = round([self.attributedStringValue size].height);
rect.origin.y += (rect.size.height - height) / 2;
rect.size.height = height;
[super editWithFrame:rect inView:controlView editor:textObj delegate:delegate event:event];
}
@end

View File

@ -0,0 +1,8 @@
#import <AppKit/AppKit.h>
#import "Document.h"
@interface GBCheatSearchController<NSTableViewDelegate, NSTableViewDataSource, NSControlTextEditingDelegate> : NSObject
@property IBOutlet NSWindow *window;
@property IBOutlet NSTableView *tableView;
+ (instancetype)controllerWithDocument:(Document *)document;
@end

View File

@ -0,0 +1,234 @@
#import "GBCheatSearchController.h"
#import "GBWarningPopover.h"
#import "GBCheatWindowController.h"
#import "GBPanel.h"
@interface GBCheatSearchController() <NSTableViewDelegate, NSTableViewDataSource>
@property IBOutlet NSPopUpButton *dataTypeButton;
@property IBOutlet NSPopUpButton *conditionTypeButton;
@property IBOutlet NSTextField *operandField;
@property IBOutlet NSTextField *conditionField;
@property IBOutlet NSTextField *resultsLabel;
@property (strong) IBOutlet NSButton *addCheatButton;
@end
@implementation GBCheatSearchController
{
__weak Document *_document;
size_t _resultCount;
GB_cheat_search_result_t *_results;
GBPanel *_window;
}
+ (instancetype)controllerWithDocument:(Document *)document
{
GBCheatSearchController *ret = [[self alloc] init];
ret->_document = document;
NSArray *objects;
[[NSBundle mainBundle] loadNibNamed:@"CheatSearch" owner:ret topLevelObjects:&objects];
ret->_resultsLabel.stringValue = @"";
ret->_resultsLabel.cell.backgroundStyle = NSBackgroundStyleRaised;
ret->_window.ownerWindow = document.mainWindow;
return ret;
}
- (IBAction)reset:(id)sender
{
_dataTypeButton.enabled = true;
[_document performAtomicBlock:^{
GB_cheat_search_reset(_document.gb);
}];
_resultCount = 0;
if (_results) {
free(_results);
_results = NULL;
}
[_tableView reloadData];
_resultsLabel.stringValue = @"";
}
- (IBAction)search:(id)sender
{
// Dispatch to work around firstResponder oddities
dispatch_async(dispatch_get_main_queue(), ^{
if ([sender isKindOfClass:[NSTextField class]]) {
// Action sent by losing focus rather than pressing enter
if (![sender currentEditor]) return;
}
_dataTypeButton.enabled = false;
[_document performAtomicBlock:^{
__block bool success = false;
NSString *error = [_document captureOutputForBlock:^{
success = GB_cheat_search_filter(_document.gb, _conditionField.stringValue.UTF8String, _dataTypeButton.selectedTag);
}];
if (!success) {
dispatch_async(dispatch_get_main_queue(), ^{
[GBWarningPopover popoverWithContents:error onView:_conditionField];
NSBeep();
});
return;
}
_resultCount = GB_cheat_search_result_count(_document.gb);
_results = malloc(sizeof(*_results) * _resultCount);
GB_cheat_search_get_results(_document.gb, _results);
}];
if (_resultCount == 0) {
_dataTypeButton.enabled = true;
_resultsLabel.stringValue = @"No results.";
}
else {
_resultsLabel.stringValue = [NSString stringWithFormat:@"%@ result%s",
[NSNumberFormatter localizedStringFromNumber:@(_resultCount)
numberStyle:NSNumberFormatterDecimalStyle],
_resultCount > 1? "s" : ""];
}
[_tableView reloadData];
});
}
- (IBAction)conditionChanged:(id)sender
{
unsigned index = [_conditionTypeButton indexOfSelectedItem];
_conditionField.enabled = index == 11;
_operandField.enabled = index >= 1 && index <= 6;
switch ([_conditionTypeButton indexOfSelectedItem]) {
case 0: _conditionField.stringValue = @"1"; break;
case 1: _conditionField.stringValue = [NSString stringWithFormat:@"new == (%@)", _operandField.stringValue]; break;
case 2: _conditionField.stringValue = [NSString stringWithFormat:@"new != (%@)", _operandField.stringValue]; break;
case 3: _conditionField.stringValue = [NSString stringWithFormat:@"new > (%@)", _operandField.stringValue]; break;
case 4: _conditionField.stringValue = [NSString stringWithFormat:@"new >= (%@)", _operandField.stringValue]; break;
case 5: _conditionField.stringValue = [NSString stringWithFormat:@"new < (%@)", _operandField.stringValue]; break;
case 6: _conditionField.stringValue = [NSString stringWithFormat:@"new <= (%@)", _operandField.stringValue]; break;
case 7: _conditionField.stringValue = @"new != old"; break;
case 8: _conditionField.stringValue = @"new == old"; break;
case 9: _conditionField.stringValue = @"new > old"; break;
case 10: _conditionField.stringValue = @"new < old"; break;
}
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return _resultCount;
}
- (uint8_t *)addressForRow:(unsigned)row
{
uint8_t *base;
uint32_t offset;
if (_results[row].addr < 0xc000) {
base = GB_get_direct_access(_document.gb, GB_DIRECT_ACCESS_CART_RAM, NULL, NULL);
offset = (_results[row].addr & 0x1FFF) + _results[row].bank * 0x2000;
}
else if (_results[row].addr < 0xe000) {
base = GB_get_direct_access(_document.gb, GB_DIRECT_ACCESS_RAM, NULL, NULL);
offset = (_results[row].addr & 0xFFF) + _results[row].bank * 0x1000;
}
else {
base = GB_get_direct_access(_document.gb, GB_DIRECT_ACCESS_HRAM, NULL, NULL);
offset = (_results[row].addr & 0x7F);
}
return base + offset;
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
switch ([[tableView tableColumns] indexOfObject:tableColumn]) {
case 0:
return [NSString stringWithFormat:@"$%02x:$%04x", _results[row].bank, _results[row].addr];
case 1:
if (_dataTypeButton.selectedTag & GB_CHEAT_SEARCH_DATA_TYPE_16BIT) {
return [NSString stringWithFormat:@"$%04x", _results[row].value];
}
return [NSString stringWithFormat:@"$%02x", _results[row].value];
default: {
const uint8_t *data = [self addressForRow:row];
GB_cheat_search_data_type_t dataType = _dataTypeButton.selectedTag;
uint16_t value = data[0];
if (!(dataType & GB_CHEAT_SEARCH_DATA_TYPE_16BIT)) {
return [NSString stringWithFormat:@"$%02x", value];
}
value |= data[1] << 8;
if ((dataType & GB_CHEAT_SEARCH_DATA_TYPE_BE_BIT)) {
value = __builtin_bswap16(value);
}
return [NSString stringWithFormat:@"$%04x", value];
}
}
}
- (void)tableView:(NSTableView *)tableView setObjectValue:(NSString *)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
[_document performAtomicBlock:^{
__block bool success = false;
__block uint16_t value;
NSString *error = [_document captureOutputForBlock:^{
success = !GB_debugger_evaluate(_document.gb, object.UTF8String, &value, NULL);
}];
if (!success) {
dispatch_async(dispatch_get_main_queue(), ^{
[GBWarningPopover popoverWithContents:error onView:tableView];
NSBeep();
});
return;
}
uint8_t *dest = [self addressForRow:row];
GB_cheat_search_data_type_t dataType = _dataTypeButton.selectedTag;
if (dataType & GB_CHEAT_SEARCH_DATA_TYPE_BE_BIT) {
value = __builtin_bswap16(value);
}
dest[0] = value;
if (dataType & GB_CHEAT_SEARCH_DATA_TYPE_16BIT) {
dest[1] = value >> 8;
}
dispatch_async(dispatch_get_main_queue(), ^{
[tableView reloadData];
});
}];
}
- (void)controlTextDidChange:(NSNotification *)obj
{
[self conditionChanged:nil];
}
- (IBAction)addCheat:(id)sender
{
GB_cheat_search_result_t *result = _results + _tableView.selectedRow;
uint8_t *data = [self addressForRow:_tableView.selectedRow];
GB_cheat_search_data_type_t dataType = _dataTypeButton.selectedTag;
size_t rowToSelect = 0;
GB_get_cheats(_document.gb, &rowToSelect);
[_document performAtomicBlock:^{
GB_add_cheat(_document.gb,
(dataType & GB_CHEAT_SEARCH_DATA_TYPE_16BIT)? "New Cheat (Part 1)" : "New Cheat",
result->addr, result->bank,
*data,
0, false,
true);
if (dataType & GB_CHEAT_SEARCH_DATA_TYPE_16BIT) {
GB_add_cheat(_document.gb,
(dataType & GB_CHEAT_SEARCH_DATA_TYPE_16BIT)? "New Cheat (Part 2)" : "New Cheat",
result->addr + 1, result->bank,
data[1],
0, false,
true);
}
GB_set_cheats_enabled(_document.gb, true);
}];
[_document.cheatsWindow makeKeyAndOrderFront:nil];
[_document.cheatWindowController.cheatsTable reloadData];
[_document.cheatWindowController.cheatsTable selectRow:rowToSelect byExtendingSelection:false];
[_document.cheatWindowController.cheatsTable.delegate tableViewSelectionDidChange:nil];
}
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
_addCheatButton.enabled = _tableView.numberOfSelectedRows != 0;
}
- (void)dealloc
{
if (_results) free(_results);
}
@end

View File

@ -102,7 +102,7 @@
else {
dispatch_async(dispatch_get_main_queue(), ^{
NSBeep();
[GBWarningPopover popoverWithContents:@"This code is not a valid GameShark or GameGenie code" onView:self.importCodeField];
[GBWarningPopover popoverWithContents:@"This code is not a valid GameShark or Game Genie code" onView:self.importCodeField];
});
}
}];

5
Cocoa/GBColorTextCell.h Normal file
View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBColorTextCell : NSTextFieldCell
@end

19
Cocoa/GBColorTextCell.m Normal file
View File

@ -0,0 +1,19 @@
#import "GBColorTextCell.h"
@implementation GBColorTextCell
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
[self.backgroundColor set];
NSRectFill(cellFrame);
NSBezierPath *path = [NSBezierPath bezierPathWithRect:cellFrame];
path.lineWidth = 2;
[[NSColor colorWithWhite:0 alpha:0.25] setStroke];
[path addClip];
[path stroke];
[self drawInteriorWithFrame:cellFrame inView:controlView];
}
@end

View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBDeleteButtonCell : NSButtonCell
@end

View File

@ -0,0 +1,30 @@
#import "GBDeleteButtonCell.h"
@implementation GBDeleteButtonCell
// Image scaling is broken on some older macOS versions
- (void)drawImage:(NSImage *)image withFrame:(NSRect)frame inView:(NSView *)controlView
{
double size = 13;
unsigned offset = 1;
if (@available(macOS 10.10, *)) {
size = 15;
offset = 0;
}
frame.origin.x += round((frame.size.width - size) / 2) + offset;
frame.origin.y += round((frame.size.height - size) / 2) - offset;
frame.size.width = frame.size.height = size;
[super drawImage:image withFrame:frame inView:controlView];
}
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
[self drawImage:self.image withFrame:cellFrame inView:controlView];
}
-(void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView
{
}
@end

5
Cocoa/GBDisabledButton.h Normal file
View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBDisabledButton : NSButton
@end

8
Cocoa/GBDisabledButton.m Normal file
View File

@ -0,0 +1,8 @@
#import "GBDisabledButton.h"
@implementation GBDisabledButton
- (void)mouseDown:(NSEvent *)event
{
}
@end

View File

@ -136,7 +136,7 @@
if (!_gb) {
return [NSString stringWithFormat:@"$%llX", offset];
}
return @(GB_debugger_describe_address(_gb, offset + _baseAddress, _bankForDescription, false, isRangeEnd));
return @(GB_debugger_describe_address(_gb, offset + _baseAddress, offset < 0x4000? -1 :_bankForDescription, false, isRangeEnd));
}

View File

@ -46,17 +46,29 @@
-(void)drawKnob:(NSRect)knobRect
{
[super drawKnob:knobRect];
NSRect peekRect = knobRect;
peekRect.size.width /= 2;
peekRect.size.height = peekRect.size.width;
peekRect.origin.x += peekRect.size.width / 2;
peekRect.origin.y += peekRect.size.height / 2;
NSBezierPath *path = nil;
if (@available(macos 26.0, *)) {
NSRect peekRect = knobRect;
peekRect.size.height /= 2;
peekRect.size.width -= peekRect.size.height;
peekRect.origin.x += peekRect.size.height / 2;
peekRect.origin.y += peekRect.size.height / 2;
path = [NSBezierPath bezierPathWithRoundedRect:peekRect xRadius:peekRect.size.height / 2 yRadius:peekRect.size.height / 2];
}
else {
NSRect peekRect = knobRect;
peekRect.size.width /= 2;
peekRect.size.height = peekRect.size.width;
peekRect.origin.x += peekRect.size.width / 2;
peekRect.origin.y += peekRect.size.height / 2;
path = [NSBezierPath bezierPathWithOvalInRect:peekRect];
}
NSColor *color = self.colorValue;
if (!self.enabled) {
color = [color colorWithAlphaComponent:0.5];
}
[color setFill];
NSBezierPath *path = [NSBezierPath bezierPathWithOvalInRect:peekRect];
[path fill];
[[NSColor colorWithWhite:0 alpha:0.25] setStroke];
[path setLineWidth:0.5];

View File

@ -44,7 +44,8 @@
}
if (parent.displayScrollRect) {
NSBezierPath *path = [NSBezierPath bezierPathWithRect:CGRectInfinite];
// CGRectInfinite in NSBezierPath is broken in newer macOS versions
NSBezierPath *path = [NSBezierPath bezierPathWithRect:CGRectMake(-0x4000, -0x4000, 0x8000, 0x8000)];
for (unsigned x = 0; x < 2; x++) {
for (unsigned y = 0; y < 2; y++) {
NSRect rect = parent.scrollRect;

View File

@ -16,7 +16,7 @@
static GBJoyConManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc] _init];
manager = [[super allocWithZone:nil] _init];
});
return manager;
}
@ -32,6 +32,16 @@
return ret;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
return [self sharedInstance];
}
+ (instancetype)alloc
{
return [self sharedInstance];
}
- (instancetype)init
{
return [self.class sharedInstance];

View File

@ -57,6 +57,9 @@
uint8_t length = document.oamCount;
bool cgb = GB_is_cgb(document.gb);
uint8_t height = document.oamHeight;
NSFont *font = [document debuggerFontOfSize:11];
NSFont *boldFont = [[NSFontManager sharedFontManager] convertFont:font toHaveTrait:NSBoldFontMask];
for (unsigned i = 0; i < 40; i++) {
GBObjectViewItem *item = _items[i];
if (i >= length) {
@ -64,6 +67,13 @@
}
else {
item.view.hidden = false;
item.oamAddress.font = boldFont;
item.position.font = font;
item.attributes.font = font;
item.tile.font = font;
item.tileAddress.font = font;
item.oamAddress.stringValue = [NSString stringWithFormat:@"$%04X", info[i].oam_addr];
item.position.stringValue = [NSString stringWithFormat:@"(%d, %d)",
((signed)(unsigned)info[i].x) - 8,

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>

View File

@ -29,11 +29,12 @@
- (instancetype)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat *)format
{
__unsafe_unretained GBOpenGLView *weakSelf = self;
self = [super initWithFrame:frameRect pixelFormat:format];
[self observeStandardDefaultsKey:@"GBFilter" withBlock:^(id newValue) {
weakSelf.shader = nil;
[weakSelf setNeedsDisplay:true];
}];
return [super initWithFrame:frameRect pixelFormat:format];
return self;
}
@end

View File

@ -14,5 +14,7 @@
@property (weak) IBOutlet NSSlider *hueStrengthSlider;
@property (weak) IBOutlet NSTableView *themesList;
@property (weak) IBOutlet NSMenu *menu;
@property (weak) IBOutlet NSSegmentedControl *segmentControl;
@property IBOutlet NSMenu *segmentMenu;
+ (const GB_palette_t *)userPalette;
@end

View File

@ -1,5 +1,6 @@
#import "GBPaletteEditorController.h"
#import "GBHueSliderCell.h"
#import "GBApp.h"
#import <Core/gb.h>
#define MAGIC 'SBPL'
@ -199,11 +200,17 @@ static double blend(double from, double to, double position)
if (theme && themes[theme]) {
unsigned index = [[themes.allKeys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] indexOfObject:theme];
[_themesList selectRowIndexes:[NSIndexSet indexSetWithIndex:index] byExtendingSelection:false];
[_themesList scrollRowToVisible:index];
}
else {
[_themesList selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:false];
[_themesList scrollRowToVisible:0];
}
[self tableViewSelectionDidChange:nil];
if (@available(macOS 10.10, *)) {
_themesList.enclosingScrollView.contentView.automaticallyAdjustsContentInsets = false;
_themesList.enclosingScrollView.contentView.contentInsets = NSEdgeInsetsMake(0, 0, 10, 0);
}
}
- (IBAction)addTheme:(id)sender
@ -360,19 +367,48 @@ static double blend(double from, double to, double position)
}
[defaults setObject:newName forKey:@"GBCurrentTheme"];
[self savePalette:sender];
[self.themesList reloadData];
[self awakeFromNib];
}
}
- (IBAction)segmentAction:(NSSegmentedControl *)sender
{
switch (sender.selectedSegment) {
case 0: [self addTheme:sender]; return;
case 1: [self deleteTheme:sender]; return;
case 3: {
NSSize buttonSize = _segmentControl.bounds.size;
[_segmentMenu popUpMenuPositioningItem:_segmentMenu.itemArray.lastObject
atLocation:NSMakePoint(buttonSize.width,
0)
inView:sender];
return;
}
}
}
- (IBAction)restoreDefaultPalettes:(id)sender
{
[(GBApp *)NSApp updateThemesDefault:true];
[self awakeFromNib];
}
- (IBAction)done:(NSButton *)sender
{
[sender.window.sheetParent endSheet:sender.window];
}
- (instancetype)init
+ (instancetype)alloc
{
static id singleton = nil;
if (singleton) return singleton;
return (singleton = [super init]);
return (singleton = [super allocWithZone:nil]);
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
return [self alloc];
}
@end

View File

@ -43,6 +43,7 @@
GB_gameboy_t *gb = document.gb;
uint8_t *bg = GB_get_direct_access(gb, GB_DIRECT_ACCESS_BGP, NULL, NULL);
uint8_t *obj = GB_get_direct_access(gb, GB_DIRECT_ACCESS_OBP, NULL, NULL);
NSFont *font = [document debuggerFontOfSize:13];
for (unsigned i = 0; i < 4 * 8 * 2; i++) {
uint8_t index = i % (4 * 8);
@ -58,6 +59,7 @@
field.stringValue = [NSString stringWithFormat:@"$%04X", color];
field.textColor = r * 3 + g * 4 + b * 2 > 120? [NSColor blackColor] : [NSColor whiteColor];
field.toolTip = [NSString stringWithFormat:@"Red: %d, Green: %d, Blue: %d", r, g, b];
field.font = font;
field.backgroundColor = [NSColor colorWithRed:(nativeColor & 0xFF) / 255.0
green:((nativeColor >> 8) & 0xFF) / 255.0
blue:((nativeColor >> 16) & 0xFF) / 255.0

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="24093.7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="24093.7"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -22,44 +22,44 @@
<rect key="frame" x="0.0" y="0.0" width="512" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ypt-t4-Mf3">
<rect key="frame" x="131" y="0.0" width="96" height="24"/>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ypt-t4-Mf3">
<rect key="frame" x="131" y="0.0" width="95" height="24"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="center" title="$7FFF" drawsBackground="YES" id="sKu-Uy-2LG">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="center" title="$7FFF" drawsBackground="YES" id="sKu-Uy-2LG" customClass="GBColorTextCell">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KkX-Z8-Sqi">
<rect key="frame" x="226" y="0.0" width="96" height="24"/>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KkX-Z8-Sqi">
<rect key="frame" x="226" y="0.0" width="95" height="24"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="center" title="$7FFF" drawsBackground="YES" id="9LH-TF-W1L">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="center" title="$7FFF" drawsBackground="YES" id="9LH-TF-W1L" customClass="GBColorTextCell">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jDk-Ej-4yI">
<rect key="frame" x="321" y="0.0" width="96" height="24"/>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jDk-Ej-4yI">
<rect key="frame" x="321" y="0.0" width="95" height="24"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="center" title="$7FFF" drawsBackground="YES" id="arE-i5-zCC">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="center" title="$7FFF" drawsBackground="YES" id="arE-i5-zCC" customClass="GBColorTextCell">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7PI-YE-fTk">
<rect key="frame" x="416" y="0.0" width="96" height="24"/>
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7PI-YE-fTk">
<rect key="frame" x="416" y="0.0" width="95" height="24"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="center" title="$7FFF" drawsBackground="YES" id="ZbU-nE-FsE">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="center" title="$7FFF" drawsBackground="YES" id="ZbU-nE-FsE" customClass="GBColorTextCell">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NOK-yI-LKh">
<rect key="frame" x="4" y="0.0" width="121" height="20"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NOK-yI-LKh">
<rect key="frame" x="8" y="0.0" width="121" height="20"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Background 0" id="qM4-cY-SDE">
<font key="font" usesAppearanceFont="YES"/>

5
Cocoa/GBPanel.h Normal file
View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBPanel : NSPanel
@property (weak) IBOutlet NSWindow *ownerWindow;
@end

11
Cocoa/GBPanel.m Normal file
View File

@ -0,0 +1,11 @@
#import "GBPanel.h"
@implementation GBPanel
- (void)becomeKeyWindow
{
if ([_ownerWindow canBecomeMainWindow]) {
[_ownerWindow makeMainWindow];
}
[super becomeKeyWindow];
}
@end

View File

@ -1,6 +1,7 @@
#import <Cocoa/Cocoa.h>
#import <JoyKit/JoyKit.h>
#import "GBPaletteEditorController.h"
#import "GBTitledPopUpButton.h"
@interface GBPreferencesWindow : NSWindow <NSTableViewDelegate, NSTableViewDataSource, JOYListener>
@property IBOutlet NSTableView *controlsTableView;
@ -18,4 +19,10 @@
@property IBOutlet NSPopUpButton *colorPalettePopupButton;
@property IBOutlet NSPopUpButton *hotkey1PopupButton;
@property IBOutlet NSPopUpButton *hotkey2PopupButton;
@property IBOutlet NSButton *turboCapButton;
@property IBOutlet NSSlider *turboCapSlider;
@property IBOutlet NSTextField *turboCapLabel;
@property IBOutlet GBTitledPopUpButton *fontPopupButton;
@property IBOutlet NSStepper *fontSizeStepper;
@end

View File

@ -20,7 +20,7 @@
- (NSWindowToolbarStyle)toolbarStyle
{
return NSWindowToolbarStyleExpanded;
return NSWindowToolbarStylePreference;
}
- (void)close
@ -40,16 +40,16 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
if (self.playerListButton.selectedTag == 0) {
return GBButtonCount;
return GBKeyboardButtonCount;
}
return GBGameBoyButtonCount;
return GBPerPlayerButtonCount;
}
- (unsigned) usesForKey:(unsigned) key
{
unsigned ret = 0;
for (unsigned player = 4; player--;) {
for (unsigned button = player == 0? GBButtonCount:GBGameBoyButtonCount; button--;) {
for (unsigned button = player == 0? GBKeyboardButtonCount:GBPerPlayerButtonCount; button--;) {
NSNumber *other = [[NSUserDefaults standardUserDefaults] valueForKey:button_to_preference_name(button, player)];
if (other && [other unsignedIntValue] == key) {
ret++;
@ -205,7 +205,7 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
if (joystick_configuration_state == GBUnderclock) {
[self.configureJoypadButton setTitle:@"Press Button for Slo-Mo"]; // Full name is too long :<
}
else if (joystick_configuration_state < GBJoypadButtonCount) {
else if (joystick_configuration_state < GBTotalButtonCount) {
[self.configureJoypadButton setTitle:[NSString stringWithFormat:@"Press Button for %@", GBButtonNames[joystick_configuration_state]]];
}
else {
@ -227,7 +227,7 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
if (!button.isPressed) return;
if (joystick_configuration_state == -1) return;
if (joystick_configuration_state == GBJoypadButtonCount) return;
if (joystick_configuration_state == GBTotalButtonCount) return;
if (!joystick_being_configured) {
joystick_being_configured = controller.uniqueID;
}
@ -266,6 +266,8 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
[GBB] = JOYButtonUsageB,
[GBSelect] = JOYButtonUsageSelect,
[GBStart] = JOYButtonUsageStart,
[GBRapidA] = GBJoyKitRapidA,
[GBRapidB] = GBJoyKitRapidB,
[GBTurbo] = JOYButtonUsageL1,
[GBRewind] = JOYButtonUsageL2,
[GBUnderclock] = JOYButtonUsageR1,
@ -337,6 +339,70 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
else {
[_colorPalettePopupButton selectItemWithTitle:[[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"] ?: @""];
}
_fontSizeStepper.intValue = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBDebuggerFontSize"];
[self updateFonts];
double cap = [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBTurboCap"];
if (cap) {
_turboCapSlider.intValue = round(cap * 100);
_turboCapButton.state = NSOnState;
}
[self turboCapToggled:_turboCapButton];
}
- (IBAction)fontSizeChanged:(id)sender
{
NSString *selectedFont = [[NSUserDefaults standardUserDefaults] stringForKey:@"GBDebuggerFont"];
[[NSUserDefaults standardUserDefaults] setInteger:[sender intValue] forKey:@"GBDebuggerFontSize"];
[_fontPopupButton setDisplayTitle:[NSString stringWithFormat:@"%@ %upt", selectedFont, (unsigned)[[NSUserDefaults standardUserDefaults] integerForKey:@"GBDebuggerFontSize"]]];
}
- (IBAction)fontChanged:(id)sender
{
NSString *selectedFont = _fontPopupButton.selectedItem.title;
[[NSUserDefaults standardUserDefaults] setObject:selectedFont forKey:@"GBDebuggerFont"];
[_fontPopupButton setDisplayTitle:[NSString stringWithFormat:@"%@ %upt", selectedFont, (unsigned)[[NSUserDefaults standardUserDefaults] integerForKey:@"GBDebuggerFontSize"]]];
}
- (void)updateFonts
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSFontManager *fontManager = [NSFontManager sharedFontManager];
NSArray *allFamilies = [fontManager availableFontFamilies];
NSMutableSet *families = [NSMutableSet set];
for (NSString *family in allFamilies) {
if ([fontManager fontNamed:family hasTraits:NSFixedPitchFontMask]) {
[families addObject:family];
}
}
bool hasSFMono = false;
if (@available(macOS 10.15, *)) {
hasSFMono = [[NSFont monospacedSystemFontOfSize:12 weight:NSFontWeightRegular].displayName containsString:@"SF"];
}
if (hasSFMono) {
[families addObject:@"SF Mono"];
}
NSArray *sortedFamilies = [[families allObjects] sortedArrayUsingSelector:@selector(compare:)];
dispatch_async(dispatch_get_main_queue(), ^{
if (![families containsObject:[[NSUserDefaults standardUserDefaults] stringForKey:@"GBDebuggerFont"]]) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"GBDebuggerFont"];
}
[_fontPopupButton.menu removeAllItems];
for (NSString *family in sortedFamilies) {
[_fontPopupButton addItemWithTitle:family];
}
NSString *selectedFont = [[NSUserDefaults standardUserDefaults] stringForKey:@"GBDebuggerFont"];
[_fontPopupButton selectItemWithTitle:selectedFont];
[_fontPopupButton setDisplayTitle:[NSString stringWithFormat:@"%@ %upt", selectedFont, (unsigned)[[NSUserDefaults standardUserDefaults] integerForKey:@"GBDebuggerFontSize"]]];
});
});
}
- (void)dealloc
@ -461,7 +527,7 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
[GB_COLOR_CORRECTION_MODERN_BALANCED] = @"Emulates a modern display. Blue contrast is moderately enhanced at the cost of slight hue inaccuracy.",
[GB_COLOR_CORRECTION_MODERN_BOOST_CONTRAST] = @"Like Modern Balanced, but further boosts the contrast of greens and magentas that is lacking on the original hardware.",
[GB_COLOR_CORRECTION_REDUCE_CONTRAST] = @"Slightly reduce the contrast to better represent the tint and contrast of the original display.",
[GB_COLOR_CORRECTION_LOW_CONTRAST] = @"Harshly reduce the contrast to accurately represent the tint and low constrast of the original display.",
[GB_COLOR_CORRECTION_LOW_CONTRAST] = @"Harshly reduce the contrast to accurately represent the tint and low contrast of the original display.",
[GB_COLOR_CORRECTION_MODERN_ACCURATE] = @"Emulates a modern display. Colors have their hues and brightness corrected.",
}) [self.colorCorrectionPopupButton.selectedItem.tag]
title:self.colorCorrectionPopupButton.selectedItem.title
@ -496,4 +562,35 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
[GBJoyConManager sharedInstance].arrangementMode = false;
}
- (IBAction)turboCapToggled:(NSButton *)sender
{
if (sender.state) {
_turboCapSlider.enabled = true;
[self turboCapChanged:_turboCapSlider];
if (@available(macOS 10.10, *)) {
_turboCapLabel.textColor = [NSColor labelColor];
}
else {
_turboCapLabel.textColor = [NSColor blackColor];
}
}
else {
_turboCapSlider.enabled = false;
_turboCapLabel.enabled = false;
[[NSUserDefaults standardUserDefaults] setDouble:0 forKey:@"GBTurboCap"];
if (@available(macOS 10.10, *)) {
_turboCapLabel.textColor = [NSColor disabledControlTextColor];
}
else {
_turboCapLabel.textColor = [NSColor colorWithWhite:0 alpha:0.25];
}
}
}
- (IBAction)turboCapChanged:(NSSlider *)sender
{
_turboCapLabel.stringValue = [NSString stringWithFormat:@"%d%%", sender.intValue];
[[NSUserDefaults standardUserDefaults] setDouble:sender.doubleValue / 100.0 forKey:@"GBTurboCap"];
}
@end

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="24093.7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="24093.7"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -25,7 +25,7 @@
<rect key="frame" x="0.0" y="0.0" width="332" height="221"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="H3v-X3-48q">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" id="H3v-X3-48q">
<rect key="frame" x="18" y="192" width="296" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="Title" id="BwZ-Zj-sP6">
@ -34,7 +34,7 @@
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="gaD-ZH-Beh">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" id="gaD-ZH-Beh">
<rect key="frame" x="18" y="166" width="296" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="Author" id="IgT-r1-T38">
@ -59,7 +59,7 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" borderStyle="border" focusRingType="none" imageScaling="proportionallyDown" inset="2" id="YJh-dI-A5D">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<font key="font" metaFont="message"/>
<menu key="menu" id="Knp-Ok-Pb4"/>
</popUpButtonCell>
<connections>
@ -67,7 +67,7 @@
</connections>
</popUpButton>
<segmentedControl verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SRS-M5-VVL">
<rect key="frame" x="247" y="129" width="68" height="24"/>
<rect key="frame" x="247" y="128" width="68" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<segmentedCell key="cell" borderStyle="border" alignment="left" style="rounded" trackingMode="momentary" id="cmq-I8-cFL">
<font key="font" metaFont="system"/>
@ -94,7 +94,7 @@
</customView>
</subviews>
</customView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="2dl-dH-E3J">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" id="2dl-dH-E3J">
<rect key="frame" x="18" y="5" width="296" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" alignment="center" title="Copyright" id="nM9-oF-OV9">

View File

@ -11,23 +11,23 @@
@implementation GBTerminalTextFieldCell
{
GBTerminalTextView *field_editor;
GBTerminalTextView *_fieldEditor;
}
- (NSTextView *)fieldEditorForView:(NSTextField *)controlView
{
if (field_editor) {
field_editor.gb = self.gb;
return field_editor;
if (_fieldEditor) {
_fieldEditor.gb = self.gb;
return _fieldEditor;
}
field_editor = [[GBTerminalTextView alloc] init];
[field_editor setFieldEditor:true];
field_editor.gb = self.gb;
field_editor->_field = (NSTextField *)controlView;
_fieldEditor = [[GBTerminalTextView alloc] init];
[_fieldEditor setFieldEditor:true];
_fieldEditor.gb = self.gb;
_fieldEditor->_field = (NSTextField *)controlView;
((NSTextFieldCell *)controlView.cell).textInset =
field_editor.textContainerInset =
NSMakeSize(0, 2);
return field_editor;
_fieldEditor.textContainerInset =
NSMakeSize(7, 2);
return _fieldEditor;
}
@end
@ -45,7 +45,7 @@
{
self = [super init];
if (!self) {
return NULL;
return nil;
}
lines = [[NSMutableOrderedSet alloc] init];
return self;

View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBTitledPopUpButton : NSPopUpButton
@property NSString *displayTitle;
@end

View File

@ -0,0 +1,22 @@
#import "GBTitledPopUpButton.h"
@implementation GBTitledPopUpButton
- (void)setDisplayTitle:(NSString *)displayTitle
{
if (!displayTitle) {
((NSPopUpButtonCell *)self.cell).usesItemFromMenu = true;
((NSPopUpButtonCell *)self.cell).menuItem = nil;
return;
}
((NSPopUpButtonCell *)self.cell).usesItemFromMenu = false;
((NSPopUpButtonCell *)self.cell).menuItem = [[NSMenuItem alloc] initWithTitle:displayTitle action:nil keyEquivalent:@""];
}
- (NSString *)displayTitle
{
return ((NSPopUpButtonCell *)self.cell).menuItem.title;
}
@end

View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBToolbarFieldCell : NSSearchFieldCell
@end

View File

@ -0,0 +1,40 @@
#import "GBToolbarFieldCell.h"
#import <objc/runtime.h>
@interface NSTextFieldCell()
- (void)textDidChange:(id)sender;
@end
@implementation GBToolbarFieldCell
- (void)textDidChange:(id)sender
{
IMP imp = [NSTextFieldCell instanceMethodForSelector:_cmd];
method_setImplementation(class_getInstanceMethod([GBToolbarFieldCell class], _cmd), imp);
((void(*)(id, SEL, id))imp)(self, _cmd, sender);
}
- (void)endEditing:(NSText *)textObj
{
IMP imp = [NSTextFieldCell instanceMethodForSelector:_cmd];
method_setImplementation(class_getInstanceMethod([GBToolbarFieldCell class], _cmd), imp);
((void(*)(id, SEL, id))imp)(self, _cmd, textObj);
}
- (void)resetSearchButtonCell
{
}
- (void)resetCancelButtonCell
{
}
// We only need this hack on Solarium, avoid regressions
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
if (@available(macOS 26.0, *)) {
return [super allocWithZone:zone];
}
return (id)[NSTextFieldCell allocWithZone:zone];
}
@end

View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBToolbarPopUpButtonCell : NSPopUpButtonCell
@end

View File

@ -0,0 +1,17 @@
#import "GBToolbarPopUpButtonCell.h"
@implementation GBToolbarPopUpButtonCell
-(void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
[super drawInteriorWithFrame:CGRectInset(cellFrame, 5, 0) inView:controlView];
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
if (@available(macOS 26.0, *)) {
return [super allocWithZone:zone];
}
return (id)[NSPopUpButtonCell allocWithZone:zone];
}
@end

View File

@ -119,6 +119,9 @@ static const uint8_t workboy_vk_to_key[] = {
bool _mouseControlEnabled;
NSMutableDictionary<NSNumber *, JOYController *> *_controllerMapping;
unsigned _lastPlayerCount;
bool _rapidA[4], _rapidB[4];
uint8_t _rapidACount[4], _rapidBCount[4];
}
+ (instancetype)alloc
@ -145,6 +148,9 @@ static const uint8_t workboy_vk_to_key[] = {
[self observeStandardDefaultsKey:@"GBAspectRatioUnkept" withBlock:^(id newValue) {
[weakSelf setFrame:weakSelf.superview.frame];
}];
[self observeStandardDefaultsKey:@"GBForceIntegerScale" withBlock:^(id newValue) {
[weakSelf setFrame:weakSelf.superview.frame];
}];
[self observeStandardDefaultsKey:@"JoyKitDefaultControllers" withBlock:^(id newValue) {
[weakSelf reassignControllers];
}];
@ -279,7 +285,9 @@ static const uint8_t workboy_vk_to_key[] = {
- (void)setFrame:(NSRect)frame
{
frame = self.superview.frame;
NSView *superview = self.superview;
if (GB_unlikely(!superview)) return;
frame = superview.frame;
if (_gb && ![[NSUserDefaults standardUserDefaults] boolForKey:@"GBAspectRatioUnkept"]) {
double ratio = frame.size.width / frame.size.height;
double width = GB_get_screen_width(_gb);
@ -297,6 +305,19 @@ static const uint8_t workboy_vk_to_key[] = {
frame.origin.x = 0;
}
}
if (_gb && [[NSUserDefaults standardUserDefaults] boolForKey:@"GBForceIntegerScale"]) {
double factor = self.window.backingScaleFactor;
double width = GB_get_screen_width(_gb) / factor;
double height = GB_get_screen_height(_gb) / factor;
double new_width = floor(frame.size.width / width) * width;
double new_height = floor(frame.size.height / height) * height;
frame.origin.x += floor((frame.size.width - new_width) / 2);
frame.origin.y += floor((frame.size.height - new_height) / 2);
frame.size.width = new_width;
frame.size.height = new_height;
}
[super setFrame:frame];
}
@ -343,6 +364,17 @@ static const uint8_t workboy_vk_to_key[] = {
(analogClockMultiplierValid && analogClockMultiplier < 1)) {
[self.osdView displayText:@"Slow motion…"];
}
for (unsigned i = GB_get_player_count(_gb); i--;) {
if (_rapidA[i]) {
_rapidACount[i]++;
GB_set_key_state_for_player(_gb, GB_KEY_A, i, !(_rapidACount[i] & 2));
}
if (_rapidB[i]) {
_rapidBCount[i]++;
GB_set_key_state_for_player(_gb, GB_KEY_B, i, !(_rapidBCount[i] & 2));
}
}
[super flip];
}
@ -370,7 +402,7 @@ static const uint8_t workboy_vk_to_key[] = {
player_count = 2;
}
for (unsigned player = 0; player < player_count; player++) {
for (GBButton button = 0; button < GBButtonCount; button++) {
for (GBButton button = 0; button < GBKeyboardButtonCount; button++) {
NSNumber *key = [defaults valueForKey:button_to_preference_name(button, player)];
if (!key) continue;
@ -401,17 +433,38 @@ static const uint8_t workboy_vk_to_key[] = {
analogClockMultiplierValid = false;
break;
case GBRapidA:
_rapidA[player] = true;
_rapidACount[player] = 0;
GB_set_key_state_for_player(_gb, GB_KEY_A, player, true);
break;
case GBRapidB:
_rapidB[player] = true;
_rapidBCount[player] = 0;
GB_set_key_state_for_player(_gb, GB_KEY_B, player, true);
break;
default:
if (self.document.partner) {
if (player == 0) {
GB_set_key_state_for_player(_gb, (GB_key_t)button, 0, true);
if ((GB_key_t)button <= GB_KEY_DOWN) {
GB_set_use_faux_analog_inputs(_gb, 0, false);
}
}
else {
GB_set_key_state_for_player(self.document.partner.gb, (GB_key_t)button, 0, true);
if ((GB_key_t)button <= GB_KEY_DOWN) {
GB_set_use_faux_analog_inputs(self.document.partner.gb, 0, false);
}
}
}
else {
GB_set_key_state_for_player(_gb, (GB_key_t)button, player, true);
if ((GB_key_t)button <= GB_KEY_DOWN) {
GB_set_use_faux_analog_inputs(_gb, player, false);
}
}
break;
}
@ -444,7 +497,7 @@ static const uint8_t workboy_vk_to_key[] = {
player_count = 2;
}
for (unsigned player = 0; player < player_count; player++) {
for (GBButton button = 0; button < GBButtonCount; button++) {
for (GBButton button = 0; button < GBKeyboardButtonCount; button++) {
NSNumber *key = [defaults valueForKey:button_to_preference_name(button, player)];
if (!key) continue;
@ -470,6 +523,16 @@ static const uint8_t workboy_vk_to_key[] = {
underclockKeyDown = false;
analogClockMultiplierValid = false;
break;
case GBRapidA:
_rapidA[player] = false;
GB_set_key_state_for_player(_gb, GB_KEY_A, player, false);
break;
case GBRapidB:
_rapidB[player] = false;
GB_set_key_state_for_player(_gb, GB_KEY_B, player, false);
break;
default:
if (self.document.partner) {
@ -545,12 +608,63 @@ static const uint8_t workboy_vk_to_key[] = {
}
}
- (bool)controller:(JOYController *)controller applicableForPlayer:(unsigned)player effectivePlayer:(unsigned *)effectivePlayer effectiveGB:(GB_gameboy_t **)effectiveGB
{
NSDictionary<NSNumber *, JOYController *> *controllerMapping = [self controllerMapping];
JOYController *preferredJoypad = controllerMapping[@(player)];
if (preferredJoypad && preferredJoypad != controller) return false; // The player has a different assigned controller
if (!preferredJoypad && self.playerCount != 1) return false; // The player has no assigned controller in multiplayer mode, prevent controller inputs
dispatch_async(dispatch_get_main_queue(), ^{
[controller setPlayerLEDs:[controller LEDMaskForPlayer:player]];
});
*effectiveGB = _gb;
*effectivePlayer = player;
if (player && self.document.partner) {
*effectiveGB = self.document.partner.gb;
*effectivePlayer = 0;
if (controller != self.document.partner.view->lastController) {
[self setRumble:0];
self.document.partner.view->lastController = controller;
}
}
else {
if (controller != lastController) {
[self setRumble:0];
lastController = controller;
}
}
return true;
}
- (void)controller:(JOYController *)controller movedAxes2D:(JOYAxes2D *)axes
{
if (!_gb) return;
if ([self shouldControllerUseJoystickForMotion:controller]) {
if (!self.mouseControlsActive) {
GB_set_accelerometer_values(_gb, -axes.value.x, -axes.value.y);
/* Always handle only the most dominant 2D input. */
for (JOYAxes2D *otherAxes in controller.axes2D) {
if (otherAxes == axes) continue;
if (otherAxes.distance > axes.distance) {
return;
}
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([self shouldControllerUseJoystickForMotion:controller] && !self.mouseControlsActive) {
GB_set_accelerometer_values(_gb, -axes.value.x, -axes.value.y);
}
else if ([defaults boolForKey:@"GBFauxAnalogInputs"]) {
unsigned playerCount = self.playerCount;
for (unsigned player = 0; player < playerCount; player++) {
unsigned effectivePlayer;
GB_gameboy_t *effectiveGB;
if (![self controller:controller applicableForPlayer:player effectivePlayer:&effectivePlayer effectiveGB:&effectiveGB]) continue;
GB_set_use_faux_analog_inputs(effectiveGB, effectivePlayer, true);
NSPoint position = axes.value;
GB_set_faux_analog_inputs(effectiveGB, effectivePlayer, position.x, position.y);
}
}
}
@ -614,18 +728,17 @@ static const uint8_t workboy_vk_to_key[] = {
IOPMAssertionDeclareUserActivity(CFSTR(""), kIOPMUserActiveLocal, &assertionID);
NSDictionary<NSNumber *, JOYController *> *controllerMapping = [self controllerMapping];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
bool fauxAnalog = [defaults boolForKey:@"GBFauxAnalogInputs"];
for (unsigned player = 0; player < playerCount; player++) {
JOYController *preferredJoypad = controllerMapping[@(player)];
if (preferredJoypad && preferredJoypad != controller) continue; // The player has a different assigned controller
if (!preferredJoypad && playerCount != 1) continue; // The player has no assigned controller in multiplayer mode, prevent controller inputs
unsigned effectivePlayer;
GB_gameboy_t *effectiveGB;
if (![self controller:controller applicableForPlayer:player effectivePlayer:&effectivePlayer effectiveGB:&effectiveGB]) continue;
dispatch_async(dispatch_get_main_queue(), ^{
[controller setPlayerLEDs:[controller LEDMaskForPlayer:player]];
});
NSDictionary *mapping = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"JoyKitInstanceMapping"][controller.uniqueID];
NSDictionary *mapping = [defaults dictionaryForKey:@"JoyKitInstanceMapping"][controller.uniqueID];
if (!mapping) {
mapping = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"JoyKitNameMapping"][controller.deviceName];
mapping = [defaults dictionaryForKey:@"JoyKitNameMapping"][controller.deviceName];
}
JOYButtonUsage usage = ((JOYButtonUsage)[mapping[n2s(button.uniqueID)] unsignedIntValue]) ?: button.usage;
@ -633,25 +746,18 @@ static const uint8_t workboy_vk_to_key[] = {
usage = GB_inline_const(JOYButtonUsage[], {JOYButtonUsageY, JOYButtonUsageA, JOYButtonUsageB, JOYButtonUsageX})[(usage - JOYButtonUsageGeneric0) & 3];
}
GB_gameboy_t *effectiveGB = _gb;
unsigned effectivePlayer = player;
if (player && self.document.partner) {
effectiveGB = self.document.partner.gb;
effectivePlayer = 0;
if (controller != self.document.partner.view->lastController) {
[self setRumble:0];
self.document.partner.view->lastController = controller;
if (usage >= JOYButtonUsageDPadLeft && usage <= JOYButtonUsageDPadDown) {
if (fauxAnalog && button.type == JOYButtonTypeAxes2DEmulated) {
// This isn't a real button, it's an emulated Axes2D. We want to handle it as an Axes2D instead
continue;
}
}
else {
if (controller != lastController) {
[self setRumble:0];
lastController = controller;
else {
// User used a digital direction input, revert to non-analog inputs
GB_set_use_faux_analog_inputs(effectiveGB, effectivePlayer, false);
}
}
switch (usage) {
switch ((unsigned)usage) {
case JOYButtonUsageNone: break;
case JOYButtonUsageA: GB_set_key_state_for_player(effectiveGB, GB_KEY_A, effectivePlayer, button.isPressed); break;
@ -696,7 +802,16 @@ static const uint8_t workboy_vk_to_key[] = {
case JOYButtonUsageDPadUp: GB_set_key_state_for_player(effectiveGB, GB_KEY_UP, effectivePlayer, button.isPressed); break;
case JOYButtonUsageDPadDown: GB_set_key_state_for_player(effectiveGB, GB_KEY_DOWN, effectivePlayer, button.isPressed); break;
default:
case GBJoyKitRapidA:
_rapidA[effectivePlayer] = button.isPressed;
_rapidACount[effectivePlayer] = 0;
GB_set_key_state_for_player(_gb, GB_KEY_A, effectivePlayer, button.isPressed);
break;
case GBJoyKitRapidB:
_rapidB[effectivePlayer] = button.isPressed;
_rapidBCount[effectivePlayer] = 0;
GB_set_key_state_for_player(_gb, GB_KEY_B, effectivePlayer, button.isPressed);
break;
}
}

5
Cocoa/GBWindow.h Normal file
View File

@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBWindow : NSWindow
@end

22
Cocoa/GBWindow.m Normal file
View File

@ -0,0 +1,22 @@
#import "GBWindow.h"
@interface NSWindow(private)
- (void)_zoomFill:(id)sender;
@end
/*
For some reason, Apple replaced the alt + zoom button behavior to be "fill" rather than zoom.
I don't like that. It prevents SameBoy's integer scaling from working. Let's restore it.
*/
@implementation GBWindow
- (void)_zoomFill:(id)sender
{
if (sender == [self standardWindowButton:NSWindowZoomButton] &&
((self.currentEvent.modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask) == NSEventModifierFlagOption)) {
[self zoom:sender];
return;
}
[super _zoomFill:sender];
}
@end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@ -22,7 +22,8 @@
<key>LSItemContentTypes</key>
<array>
<string>com.github.liji32.sameboy.gb</string>
<string>public.gbrom</string>
<string>public.gbrom</string>
<string>com.retroarch.gb</string>
</array>
<key>LSTypeIsPackage</key>
<integer>0</integer>
@ -43,6 +44,7 @@
<key>LSItemContentTypes</key>
<array>
<string>com.github.liji32.sameboy.gbc</string>
<string>com.retroarch.gbc</string>
</array>
<key>LSTypeIsPackage</key>
<integer>0</integer>
@ -111,7 +113,9 @@
<key>CFBundleExecutable</key>
<string>SameBoy</string>
<key>CFBundleIconFile</key>
<string>AppIcon.icns</string>
<string>AppIcon</string>
<key>CFBundleIconName</key>
<string>AppIcon</string>
<key>CFBundleIdentifier</key>
<string>com.github.liji32.sameboy</string>
<key>LSApplicationCategoryType</key>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 461 B

View File

@ -4,10 +4,10 @@
@interface NSKeyboardShortcut : NSObject <NSCopying>
+ (id)shortcutWithPreferencesEncoding:(NSString *)encoding;
+ (id)shortcutWithKeyEquivalent:(NSString *)key_equivalent modifierMask:(unsigned long long)mask;
- (id)initWithKeyEquivalent:(NSString *)key_equivalent modifierMask:(unsigned long long)mask;
+ (id)shortcutWithKeyEquivalent:(NSString *)key_equivalent modifierMask:(NSUInteger)mask;
- (id)initWithKeyEquivalent:(NSString *)key_equivalent modifierMask:(NSUInteger)mask;
@property(readonly) unsigned long long modifierMask;
@property(readonly) NSUInteger modifierMask;
@property(readonly) NSString *keyEquivalent;
@property(readonly) NSString *preferencesEncoding;
@property(readonly) NSString *localizedModifierMaskDisplayName;

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="24093.9" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="24093.9"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@ -82,7 +82,7 @@
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
</connections>
</menuItem>
<menuItem title="Hot Swap Cartridge…" keyEquivalent="o" id="Rik-p8-QCf">
<menuItem title="Hot Swap Cartridge…" secondaryImage="arrow.down.left.arrow.up.right" catalog="system" keyEquivalent="o" id="Rik-p8-QCf">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="cartSwap:" target="-1" id="iXS-Ol-IS0"/>
@ -102,7 +102,7 @@
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
<menuItem title="New Cartridge Instance…" keyEquivalent="n" id="Vld-be-NZu">
<menuItem title="New Cartridge Instance…" secondaryImage="plus.square.on.square" catalog="system" keyEquivalent="n" id="Vld-be-NZu">
<connections>
<action selector="newCartridgeInstance:" target="-1" id="GJc-xU-ZEr"/>
</connections>
@ -158,7 +158,7 @@
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="Aru-vr-frG"/>
<menuItem title="Find" id="efg-jw-GVP">
<menuItem title="Find" secondaryImage="text.page.badge.magnifyingglass" catalog="system" id="efg-jw-GVP">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Find" id="4R6-IU-Jq6">
<items>
@ -197,29 +197,73 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Emulation" id="HyV-fh-RgO">
<items>
<menuItem title="Reset" keyEquivalent="r" id="p0i-Lt-sTg">
<menuItem title="Reset" secondaryImage="arrow.trianglehead.2.counterclockwise.rotate.90" catalog="system" keyEquivalent="r" id="p0i-Lt-sTg">
<connections>
<action selector="reset:" target="-1" id="DKW-Bd-h3v"/>
</connections>
</menuItem>
<menuItem title="Quick Reset" tag="-1" alternate="YES" keyEquivalent="r" id="uPG-01-49E">
<menuItem title="Quick Reset" secondaryImage="arrow.trianglehead.2.counterclockwise.rotate.90" catalog="system" tag="-1" alternate="YES" keyEquivalent="r" id="uPG-01-49E">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="reset:" target="-1" id="VV1-VP-L7g"/>
</connections>
</menuItem>
<menuItem title="Reload ROM" alternate="YES" keyEquivalent="R" id="eQP-Fb-nkz">
<menuItem title="Reload ROM" secondaryImage="arrow.trianglehead.2.counterclockwise.rotate.90" catalog="system" alternate="YES" keyEquivalent="R" id="eQP-Fb-nkz">
<connections>
<action selector="reloadROM:" target="-1" id="BpN-8V-Csg"/>
</connections>
</menuItem>
<menuItem title="Pause" keyEquivalent="p" id="4K4-hw-R7Q">
<menuItem title="Pause" secondaryImage="pause" catalog="system" keyEquivalent="p" id="4K4-hw-R7Q">
<connections>
<action selector="togglePause:" target="-1" id="osW-wt-QAa"/>
</connections>
</menuItem>
<menuItem title="Emulated Model" id="Cip-1S-4Zp">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Emulated Model" id="MtH-V4-vUi">
<items>
<menuItem title="Pick Automatically" tag="6" id="GXg-yH-3dl">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="ao2-FI-kk1"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="Nyl-zW-Uez"/>
<menuItem title="Game Boy" tag="1" id="g7C-LA-VAr">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="rxG-cz-s1S"/>
</connections>
</menuItem>
<menuItem title="Game Boy Pocket/Light" tag="5" id="1bM-CT-hoW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="U7l-BM-kB1"/>
</connections>
</menuItem>
<menuItem title="Super Game Boy" tag="4" id="vc7-yy-ARW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="E4M-QG-ua9"/>
</connections>
</menuItem>
<menuItem title="Game Boy Color" tag="2" id="hdG-Bl-8nJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="xAz-cr-0u2"/>
</connections>
</menuItem>
<menuItem title="Game Boy Advance" tag="3" id="7jw-B1-tf5">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="xQk-4e-kd7"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="QIS-av-Byy"/>
<menuItem title="Save State" id="Hdz-ut-okE">
<menuItem title="Save State" secondaryImage="square.and.arrow.down" catalog="system" id="Hdz-ut-okE">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Save State" id="Mxx-u1-M9D">
<items>
@ -276,7 +320,7 @@
</items>
</menu>
</menuItem>
<menuItem title="Load State" id="EXD-SL-cz4">
<menuItem title="Load State" secondaryImage="square.and.arrow.up" catalog="system" id="EXD-SL-cz4">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Load State" id="l9D-Ej-sh2">
<items>
@ -344,7 +388,7 @@
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="5GS-tt-E0a"/>
<menuItem title="Save Screenshot" keyEquivalent="s" id="0J3-yf-iXs">
<menuItem title="Save Screenshot" secondaryImage="photo" catalog="system" keyEquivalent="s" id="0J3-yf-iXs">
<connections>
<action selector="saveScreenshot:" target="-1" id="gJd-ml-J8p"/>
</connections>
@ -360,44 +404,13 @@
<action selector="copyScreenshot:" target="-1" id="XJC-EB-HNl"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="zk7-gf-LXN"/>
<menuItem title="Game Boy" tag="1" id="g7C-LA-VAr">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="rxG-cz-s1S"/>
</connections>
</menuItem>
<menuItem title="Game Boy Pocket/Light" tag="5" id="1bM-CT-hoW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="U7l-BM-kB1"/>
</connections>
</menuItem>
<menuItem title="Super Game Boy" tag="4" id="vc7-yy-ARW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="E4M-QG-ua9"/>
</connections>
</menuItem>
<menuItem title="Game Boy Color" tag="2" id="hdG-Bl-8nJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="xAz-cr-0u2"/>
</connections>
</menuItem>
<menuItem title="Game Boy Advance" tag="3" id="7jw-B1-tf5">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="xQk-4e-kd7"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="DPb-Sh-5tg"/>
<menuItem title="Start Audio Recording…" keyEquivalent="A" id="1UK-8n-QPP">
<menuItem title="Start Audio Recording…" secondaryImage="record.circle" catalog="system" keyEquivalent="A" id="1UK-8n-QPP">
<connections>
<action selector="toggleAudioRecording:" target="-1" id="YE5-mi-Yzd"/>
</connections>
</menuItem>
<menuItem title="Mute Sound" keyEquivalent="m" id="zo0-Rh-wTu">
<menuItem title="Mute Sound" secondaryImage="speaker.slash" catalog="system" keyEquivalent="m" id="zo0-Rh-wTu">
<connections>
<action selector="mute:" target="-1" id="eK3-ea-ExJ"/>
</connections>
@ -414,18 +427,24 @@
<action selector="toggleCheats:" target="-1" id="gsw-UY-fhu"/>
</connections>
</menuItem>
<menuItem title="Show Cheats" id="LZV-QK-YXi">
<menuItem title="Show Cheats" id="Nf8-F1-YyD">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showCheats:" target="-1" id="tfr-qM-q8X"/>
<action selector="showCheats:" target="-1" id="stn-Ei-aFE"/>
</connections>
</menuItem>
<menuItem title="Search Cheats" secondaryImage="text.page.badge.magnifyingglass" catalog="system" id="LZV-QK-YXi">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showCheatSearch:" target="-1" id="eI1-x0-ykn"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Connectivity" id="IcW-ZC-4wb">
<menuItem title="Connect" id="IcW-ZC-4wb">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Connectivity" id="BDM-Cv-BOm">
<menu key="submenu" title="Connect" id="BDM-Cv-BOm">
<items>
<menuItem title="None" id="SiH-Q4-OBY">
<modifierMask key="keyEquivalentModifierMask"/>
@ -433,7 +452,7 @@
<action selector="disconnectAllAccessories:" target="-1" id="5hY-9U-nRn"/>
</connections>
</menuItem>
<menuItem title="Game Link Cable &amp; Infrared" id="V4S-Fo-xJK">
<menuItem title="Game Link Cable &amp; Infrared" secondaryImage="cable.connector.horizontal" catalog="system" id="V4S-Fo-xJK">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Game Link Cable &amp; Infrared" id="6sJ-Wz-QLj">
<connections>
@ -444,13 +463,13 @@
<action selector="nop:" target="-3" id="Bpa-0C-lkN"/>
</connections>
</menuItem>
<menuItem title="Game Boy Printer" id="zHR-Ha-pOR">
<menuItem title="Game Boy Printer" secondaryImage="printer" catalog="system" id="zHR-Ha-pOR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="connectPrinter:" target="-1" id="tl1-CL-tAw"/>
</connections>
</menuItem>
<menuItem title="Workboy" id="lo9-CX-BJj">
<menuItem title="Workboy" secondaryImage="keyboard" catalog="system" id="lo9-CX-BJj">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="connectWorkboy:" target="-1" id="6vS-bq-wAX"/>
@ -463,14 +482,14 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Develop" id="UVb-cc-at0">
<items>
<menuItem title="Developer Mode" id="Qx6-Tt-zZR">
<menuItem title="Developer Mode" secondaryImage="wrench.and.screwdriver" catalog="system" id="Qx6-Tt-zZR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleDeveloperMode:" target="-3" id="PIc-o3-bzb"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="66c-T0-8pW"/>
<menuItem title="Show Console" id="Wse-UY-Y9l">
<menuItem title="Show Console" secondaryImage="apple.terminal" catalog="system" id="Wse-UY-Y9l">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showConsoleWindow:" target="-1" id="mFf-4i-jLG"/>
@ -482,14 +501,14 @@
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="3If-Yf-U7B"/>
<menuItem title="Break Debugger" keyEquivalent="c" id="uBD-GY-Doi">
<menuItem title="Break Debugger" secondaryImage="pause" catalog="system" keyEquivalent="c" id="uBD-GY-Doi">
<modifierMask key="keyEquivalentModifierMask" control="YES"/>
<connections>
<action selector="interrupt:" target="-1" id="ZmB-wG-fTs"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="M6n-8G-LZS"/>
<menuItem title="Audio Channels" id="Cib-LN-Y4o">
<menuItem title="Audio Channels" secondaryImage="speaker.wave.3" catalog="system" id="Cib-LN-Y4o">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Audio Channels" id="l22-4p-yTK">
<items>
@ -521,13 +540,13 @@
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="v5c-ri-BoZ"/>
<menuItem title="Show Background and Window" state="on" id="yfD-Qd-zoz">
<menuItem title="Show Background and Window" state="on" secondaryImage="mountain.2" catalog="system" id="yfD-Qd-zoz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleDisplayBackground:" target="-1" id="p5b-1n-SPR"/>
</connections>
</menuItem>
<menuItem title="Show Objects" state="on" id="OWx-a0-vQk">
<menuItem title="Show Objects" state="on" secondaryImage="cube" catalog="system" id="OWx-a0-vQk">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleDisplayObjects:" target="-1" id="8ie-ey-739"/>
@ -601,4 +620,24 @@
<point key="canvasLocation" x="140" y="260"/>
</menu>
</objects>
<resources>
<image name="apple.terminal" catalog="system" width="18" height="14"/>
<image name="arrow.down.left.arrow.up.right" catalog="system" width="18" height="17"/>
<image name="arrow.trianglehead.2.counterclockwise.rotate.90" catalog="system" width="16" height="15"/>
<image name="cable.connector.horizontal" catalog="system" width="19" height="7"/>
<image name="cube" catalog="system" width="16" height="17"/>
<image name="keyboard" catalog="system" width="19" height="13"/>
<image name="mountain.2" catalog="system" width="25" height="14"/>
<image name="pause" catalog="system" width="9" height="13"/>
<image name="photo" catalog="system" width="18" height="14"/>
<image name="plus.square.on.square" catalog="system" width="17" height="16"/>
<image name="printer" catalog="system" width="18" height="16"/>
<image name="record.circle" catalog="system" width="15" height="15"/>
<image name="speaker.slash" catalog="system" width="14" height="16"/>
<image name="speaker.wave.3" catalog="system" width="22" height="15"/>
<image name="square.and.arrow.down" catalog="system" width="15" height="17"/>
<image name="square.and.arrow.up" catalog="system" width="15" height="18"/>
<image name="text.page.badge.magnifyingglass" catalog="system" width="15" height="18"/>
<image name="wrench.and.screwdriver" catalog="system" width="19" height="18"/>
</resources>
</document>

View File

@ -3,8 +3,8 @@
#import <objc/runtime.h>
@interface NSTextFieldCell ()
- (CGRect)_textLayerDrawingRectForCellFrame:(CGRect)rect;
@property NSSize textInset;
- (bool)_isEditingInView:(NSView *)view;
@end
@implementation NSTextFieldCell (Inset)
@ -19,21 +19,59 @@
return [objc_getAssociatedObject(self, _cmd) sizeValue];
}
- (CGRect)_textLayerDrawingRectForCellFrameHook:(CGRect)rect
- (void)drawWithFrameHook:(NSRect)cellFrame inView:(NSView *)controlView
{
CGRect ret = [self _textLayerDrawingRectForCellFrameHook:rect];
NSSize inset = self.textInset;
ret.origin.x += inset.width;
ret.origin.y += inset.height;
ret.size.width -= inset.width;
ret.size.height -= inset.height;
return ret;
if (self.drawsBackground) {
[self.backgroundColor setFill];
if ([self _isEditingInView:controlView]) {
NSRectFill(cellFrame);
}
else {
NSRectFill(NSMakeRect(cellFrame.origin.x, cellFrame.origin.y,
cellFrame.size.width, inset.height));
NSRectFill(NSMakeRect(cellFrame.origin.x, cellFrame.origin.y + cellFrame.size.height - inset.height,
cellFrame.size.width, inset.height));
NSRectFill(NSMakeRect(cellFrame.origin.x, cellFrame.origin.y + inset.height,
inset.width, cellFrame.size.height - inset.height * 2));
NSRectFill(NSMakeRect(cellFrame.origin.x + cellFrame.size.width - inset.width, cellFrame.origin.y + inset.height,
inset.width, cellFrame.size.height - inset.height * 2));
}
}
cellFrame.origin.x += inset.width;
cellFrame.origin.y += inset.height;
cellFrame.size.width -= inset.width * 2;
cellFrame.size.height -= inset.height * 2;
[self drawWithFrameHook:cellFrame inView:controlView];
}
+ (void)load
{
method_exchangeImplementations(class_getInstanceMethod(self, @selector(_textLayerDrawingRectForCellFrame:)),
class_getInstanceMethod(self, @selector(_textLayerDrawingRectForCellFrameHook:)));
method_exchangeImplementations(class_getInstanceMethod(self, @selector(drawWithFrame:inView:)),
class_getInstanceMethod(self, @selector(drawWithFrameHook:inView:)));
}
@end
@implementation NSTextField (Inset)
- (bool)wantsUpdateLayerHook
{
CGSize inset = ((NSTextFieldCell *)self.cell).textInset;
if (inset.width || inset.height) return false;
return [self wantsUpdateLayerHook];
}
+ (void)load
{
Method method = class_getInstanceMethod(self, @selector(wantsUpdateLayer));
if (class_addMethod(self, @selector(wantsUpdateLayer), method_getImplementation(method), method_getTypeEncoding(method))) {
method = class_getInstanceMethod(self, @selector(wantsUpdateLayer));
}
method_exchangeImplementations(method,
class_getInstanceMethod(self, @selector(wantsUpdateLayerHook)));
}
@end

View File

@ -6,7 +6,7 @@ static id nop(id self, SEL _cmd)
return nil;
}
static double blah(id self, SEL _cmd)
static double minSize(id self, SEL _cmd)
{
return 80.0;
}
@ -18,7 +18,7 @@ static double blah(id self, SEL _cmd)
// Prevent collapsing toolbar items into menu items, they don't work in that form
method_setImplementation(class_getInstanceMethod(self, @selector(menuFormRepresentation)), (IMP)nop);
// Prevent over-agressive collapsing of the Printer Feed menu
method_setImplementation(class_getInstanceMethod(NSClassFromString(@"NSToolbarTitleView"), @selector(minSize)), (IMP)blah);
method_setImplementation(class_getInstanceMethod(NSClassFromString(@"NSToolbarTitleView"), @selector(minSize)), (IMP)minSize);
}
@end

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11762"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -13,7 +13,7 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="oUc-bq-d5t">
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" id="oUc-bq-d5t">
<rect key="frame" x="0.0" y="0.0" width="66" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" alignment="left" title="Test" id="xyx-iy-kse">

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.device.camera</key>
<true/>
</dict>
</plist>

168
Cocoa/SolariumFixer.m Normal file
View File

@ -0,0 +1,168 @@
#import <Cocoa/Cocoa.h>
#import <objc/runtime.h>
// Comment out to debug
#define NSLog(...)
// Solarium has weird proportions, we need to fix them.
@implementation NSControl (SolariumFixer)
- (void)awakeFromNib
{
if (@available(macOS 26.0, *)) {
if ([self.superview isKindOfClass:objc_getClass("NSToolbarItemViewer")]) return;
if ([self isKindOfClass:[NSStepper class]]) {
NSLog(@"Stepper needs adjustment: %s in window %@", sel_getName(self.action), self.window.title);
CGRect frame = self.frame;
frame.origin.y += 1;
self.frame = frame;
return;
}
if (self.controlSize != NSControlSizeRegular) return;
if ([self isKindOfClass:[NSPopUpButton class]] ) {
NSLog(@"Popup button needs adjustment: %@ in window %@", ((NSButton *)self).title, self.window.title);
CGRect frame = self.frame;
if (frame.size.height != 25) {
NSLog(@"%@ in window %@ has the wrong height!", ((NSButton *)self).title, self.window.title);
return;
}
frame.size.width -= 2 + 5; // Remove 5 from the right and 2 from the left
frame.origin.x += 2;
frame.origin.y += 2;
self.frame = frame;
}
else if ([self isKindOfClass:[NSSegmentedControl class]] ) {
NSLog(@"Segmented button needs adjustment: %s in window %@", sel_getName(self.action), self.window.title);
CGRect frame = self.frame;
if (frame.size.height != 25) {
NSLog(@"%s in window %@ has the wrong height!", sel_getName(self.action), self.window.title);
return;
}
frame.origin.x += 8;
frame.origin.y += 1;
self.frame = frame;
}
else if ([self isKindOfClass:[NSTextField class]]) {
NSTextField *field = (id)self;
if (![field isBezeled]) return;
NSLog(@"Text field needs adjustment: %@ in window %@", ((NSTextField *)self).placeholderString, self.window.title);
CGRect frame = self.frame;
if (frame.size.height == 21) {
frame.size.height = 24;
}
else {
NSLog(@"%@ in window %@ has the wrong height!", ((NSTextField *)self).placeholderString, self.window.title);
return;
}
frame.size.width -= 1 + 1; // Remove 1 from the right and 1 from the left
frame.origin.x += 1;
frame.origin.y -= 1;
self.frame = frame;
}
else if ([self isKindOfClass:[NSButton class]]) {
NSLog(@"Button: %@ in window %@", @(sel_getName(self.action)), self.window.title);
NSButton *button = (id)self;
if (!button.isBordered) return;
if (button.bezelStyle == NSBezelStylePush) {
NSLog(@"Button needs adjustment: %@ in window %@", @(sel_getName(self.action)), self.window.title);
CGRect frame = self.frame;
frame.size.width -= 7 + 7; // Remove 7 from the right and 7 from the left
frame.origin.x += 7;
frame.origin.y += 5;
if (frame.size.height == 32) {
frame.size.height = 25;
}
else {
NSLog(@"%@ in window %@ has the wrong height!", @(sel_getName(self.action)), self.window.title);
} self.frame = frame;
}
else if (button.bezelStyle == NSBezelStyleRegularSquare) {
CGRect frame = self.frame;
if (frame.size.height != 18) return;
NSLog(@"Check/Radio needs adjustment: %@ in window %@", ((NSButton *)self).title, self.window.title);
frame.size.width -= 2;
frame.origin.x += 2;
frame.origin.y += 1;
frame.size.height = 16;
self.frame = frame;
}
else if (button.bezelStyle == NSBezelStyleHelpButton) {
CGRect frame = self.frame;
NSLog(@"Help button needs adjustment: %@ in window %@", ((NSButton *)self).title, self.window.title);
frame.origin.y += 2;
self.frame = frame;
}
}
else if ([self isKindOfClass:[NSSlider class]]) {
NSLog(@"Slider needs adjustment: %s in window %@", sel_getName(self.action), self.window.title);
CGRect frame = self.frame;
frame.origin.y += 3;
self.frame = frame;
}
}
}
@end
@implementation NSToolbarItem (SolariumFixer)
static CGSize minSizeHook(id self, SEL _cmd)
{
return CGSizeMake(8, 0);
}
- (void)awakeFromNib
{
if (@available(macOS 26.0, *)) {
NSLog(@"Toolbar item %@ has view %@", self.label, self.view);
if ([self.view isKindOfClass:[NSTextField class]]) {
NSLog(@"Handling (Text field)");
self.bordered = true;
NSSize maxSize = self.maxSize;
maxSize.height = 36;
self.maxSize = maxSize;
NSSize minSize = self.minSize;
minSize.height = 36;
self.minSize = minSize;
((NSTextField *)self.view).backgroundColor = [NSColor clearColor];
((NSTextField *)self.view).bezeled = false;
((NSTextField *)self.view).bordered = true;
// Work around even more AppKit bugs
self.toolbar.displayMode++;
self.toolbar.displayMode--;
}
else if ([self.view isKindOfClass:[NSPopUpButton class]]) {
NSLog(@"Handling (Pop up button)");
self.bordered = true;
NSSize maxSize = self.maxSize;
maxSize.height = 28;
self.maxSize = maxSize;
NSSize minSize = self.minSize;
minSize.height = 28;
self.minSize = minSize;
}
}
else if (@available(macOS 11.0, *)) { // While at it, make macOS 11-15 a bit more consistent
if ([self.view isKindOfClass:[NSTextField class]]) {
((NSTextField *)self.view).bezelStyle = NSTextFieldRoundedBezel;
}
}
}
+ (void)load
{
if (@available(macOS 26.0, *)) {
method_setImplementation(class_getInstanceMethod(objc_getClass("NSToolbarFlexibleSpaceItem"), @selector(minSize)),
(void *)minSizeHook);
}
}
@end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 527 B

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 884 B

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -21,7 +21,6 @@
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Update Available" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
@ -97,7 +96,6 @@ DQ
<point key="canvasLocation" x="217" y="267"/>
</window>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="2Gy-QG-FoA">
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="283" y="305" width="512" height="61"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="jjT-Z5-15Q">
@ -125,7 +123,7 @@ Gw
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wIm-GX-c6B">
<rect key="frame" x="58" y="15" width="359" height="24"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Downloading update..." id="qmF-X1-v5B">
<textFieldCell key="cell" lineBreakMode="clipping" title="Downloading update" id="qmF-X1-v5B">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 B

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 569 B

Some files were not shown because too many files have changed in this diff Show More