1071 Commits
Author SHA1 Message Date
Craig b51612a74c Merge pull request #63 from sunlollyking/serialization-quirks
libretro: report that states are incomplete
2026-11-06 15:23:20 +00:00
Chris 2963db9c62 libretro: report that states are incomplete
Loading a state reinitializes the system. A frontend that loads one
every frame from power-on, as run-ahead does, keeps the game from ever
booting and shows a black screen.

Report RETRO_SERIALIZATION_QUIRK_INCOMPLETE so frontends don't rely on
states for run-ahead or netplay.
2026-10-16 19:00:14 +01:00
Craig 05439f9612 Merge pull request #61 from Renkoto/master
libretro: fix build on BSD systems
2026-09-19 21:36:56 +01:00
LibretroAdmin 260f523441 Merge pull request #62 from cscd98/wiiu 2026-09-04 14:25:28 +02:00
Craig Carnell 97252e4b84 libretro: replace mwup with __wiiu__ 2026-09-04 13:11:01 +01:00
💜Sumimi~💜 0915cdfa46 libretro: fix build on BSD systems 2026-09-02 14:42:31 -05:00
Craig Carnell 6d19eef583 libretro: build fixes since update 2026-08-12 19:32:08 +01:00
Craig Carnell 41b3757beb Merge upstream bsnes/master 2026-08-12 15:36:05 +01:00
Morilli 7d5aa1e656 fix horizontal offset in high-resolution offset-by-tile mode 2026-05-23 16:51:31 +10:00
Tim Allen cb6ce0c537 MSYS2 doesn't have a "mingw-w64-gcc" package, and also needs "make". 2026-03-19 18:47:05 +11:00
Tim Allen 91cc8b8ef4 Document build instructions.
Fixes #60, #379
2026-03-19 18:47:05 +11:00
Akiteru b7304334e6 CX4 cache and bus access timing fixes
- Step 1+WS on both reads for cache, not just one
- Remove extra cycle on bus reads/writes
2026-02-16 20:13:15 +11:00
Akiteru bd4a425b87 CX4 program cache behaviour improvements
- When triggering a cache preload by writing to $7f48, update the pb register with the prepared program page
- When preloading a page, ignore all runtime checks and reload the page immediately
2026-02-16 20:13:15 +11:00
bh247484 ae5cc6010b Add MacOS build artifacts to out gitignore 2026-01-09 15:10:12 +11:00
Tim Allen 385b34933d Remove GTK+2 support.
Although it had HIRO_GTK==3 sections, hiro/gtk/monitor.cpp was actually using
deprecated GTK+2 APIs on GTK3, and the GTK3 code was broken and wouldn't
compile.
2025-09-03 19:31:42 +10:00
John Chadwick 22a2e0a165 Add FreeBSD build to GitHub Actions 2025-09-02 18:13:34 +10:00
John ChadwickandStefan Schlosser 9716212d70 hiro/qt: HexEdit: Match scroll logic with ares
I didn't realize that some of the Qt deprecations were already fixed in
ares. In this case, the change was handled a bit differently, always
considering the y component of scrolling even when the scroll operation
is mostly horizontal. This should work just fine, so we may as well just
adopt that behavior, especially since bsnes doesn't even currently use a
HexEdit.

Backported from ares from:
https://github.com/ares-emulator/ares/commit/ffe97222a1aabd325c301e07ba40042ea58ff081

Co-authored-by: Stefan Schlosser <[email protected]>
2025-09-02 18:09:42 +10:00
John ChadwickandNear 27fdd39e5c hiro/qt: Fix missing overrides
There are a handful of spots in hiro/qt where methods override Qt
virtual methods, but they are not declared as such.

These are backported from ares from:
https://github.com/ares-emulator/ares/commit/960d8a8dcb7b550332a8fc40955b0fd11a9322b3

Co-authored-by: Near <[email protected]>
2025-09-02 18:09:42 +10:00
John Chadwickandinvertego b3ce74253e hiro/qt: Explicitly use nall string in call to Font::size
This is back-ported from ares:
https://github.com/ares-emulator/ares/commit/0d131bf4d83422e60f6ca40ba1cdf3a5dac51db3

Co-authored-by: invertego <[email protected]>
2025-09-02 18:09:42 +10:00
John ChadwickandNear 64a433a644 hiro/qt: Fix incorrect argument to nall::image::scale
The `linear` parameter to `image::scale` is a boolean, not an
enumeration.

This is a back port from ares:
https://github.com/ares-emulator/ares/commit/960d8a8dcb7b550332a8fc40955b0fd11a9322b3

Also, remove the blob of commented code. This was removed in ares v117.

Co-authored-by: Near <[email protected]>
2025-09-02 18:09:42 +10:00
d3a3280f90 hiro/qt: Silence missing override warning in Clang for moc code
With Qt 6 maybe it is possible to finally start cleaning that issue up
in the first place, but for now it's probably better for bsnes and ares
to align closer.

This is backported from the following ares commits:
https://github.com/ares-emulator/ares/commit/0d131bf4d83422e60f6ca40ba1cdf3a5dac51db3
https://github.com/ares-emulator/ares/commit/960d8a8dcb7b550332a8fc40955b0fd11a9322b3

Co-authored-by: Near <[email protected]>
Co-authored-by: invertego <[email protected]>
2025-09-02 18:09:42 +10:00
John ChadwickandStefan Schlosser 924fa315dc hiro/qt: Unify Monitor implementation with ares
Some of the work I'd done was duplicating existing work. Let's unify to
get the best of both works.

This mostly comes from:
https://github.com/ares-emulator/ares/commit/ffe97222a1aabd325c301e07ba40042ea58ff081

Co-authored-by: Stefan Schlosser <[email protected]>
2025-09-02 18:09:42 +10:00
John ChadwickandStefan Schlosser 50ac621430 hiro/qt: Better fix for QFontMetrics::width deprecation
The desired size was probably the boundingRect width and not the advance
width, so the fix from bsdcode is better than mine.

This is backported from ares:
https://github.com/ares-emulator/ares/commit/ffe97222a1aabd325c301e07ba40042ea58ff081

Co-authored-by: Stefan Schlosser <[email protected]>
2025-09-02 18:09:42 +10:00
b424c4b2f7 hiro/qt: Fixes in Application::initialize
- Call XInitThreads at initialization
- Remove spaces from screensaver window name
- Restore LC_NUMERIC after Qt clobbers it

This is sourced from ares v116r07, and:
https://github.com/ares-emulator/ares/commit/6cd447056282b9e810227cbbd841f979567b3b7e

Co-authored-by: Near <[email protected]>
Co-authored-by: Dragorn421 <[email protected]>
2025-09-02 18:09:42 +10:00
John ChadwickandNear ad259a55c0 hiro/qt: Silence xdg-screensaver output
Co-authored-by: Near <[email protected]>
2025-09-02 18:09:42 +10:00
John Chadwickandinvertego f83bc75270 hiro/qt: Add #if guards to X11 code
This is a backport from ares:
https://github.com/ares-emulator/ares/commit/b85395fe7b8445247d8a67ed90fda0235f22f1f1

Co-authored-by: invertego <[email protected]>
2025-09-02 18:09:42 +10:00
John Chadwick ec8aed3f3b hiro/qt: Add support for compiling with Qt 6 2025-09-02 18:02:58 +10:00
Tim Allen b7678f5261 hiro/gtk: Remove pendingEvents here too.
Now that pApplication::pendingEvents() has been removed from hiro/core, it
should be removed from the GTK+ backend too.
2025-09-02 01:13:17 +10:00
John Chadwick 08e6de3186 hiro/qt: Remove pendingEvents, add timeout to processEvents
Qt 6 no longer allows us to poll for the status of the event loop.
However, Qt 6 does still have a processEvents function, and the version
with the timeout actually spins the event loop and returns as early as
there are no more events in it. That's basically what we want to do. We
could run this with a really huge timeout, but that would just make it
more likely that hiro freezes up, so instead let's mirror hiro/gtk3 and
use a 50ms timeout.
2025-09-02 01:13:17 +10:00
John Chadwick aec384b4b0 hiro/core: Remove Application::pendingEvents
This does not seem to be used anywhere in bsnes, higan or ares. It's not
really possible to implement with Qt 6, which has stop exposing this
detail of the event loop. It turns out this is actually OK, since we
don't *really* need it anyway, and in the case of hiro/qt, the
replacement should be more robust anyways.
2025-09-02 01:13:17 +10:00
John Chadwick 253075bfd8 hiro/qt: Use QScreen for Monitor
Qt 5 introduces QScreen, which can be used to implement most of the
functionality needed by Monitor, although some of it probably won't make
sense when using Wayland.
2025-09-02 01:01:04 +10:00
John Chadwick 88de1f11f1 hiro/qt: Fix deprecated QWheelEvent->{delta,orientation}() usage
The orientation() and delta() methods of QWheelEvent were deprecated in
Qt 5.0 in favor of angleDelta(), which expresses higher-fidelity data
for devices like trackpads. In order to keep the behavior 100%
identical, the code used to calculate the orientation() and delta()
values in Qt 5.15 is inlined instead. That logic can be seen here:

https://github.com/qt/qtbase/blob/v5.15.17-lts-lgpl/src/gui/kernel/qevent.cpp#L876-L884

Following this logic, we also break the tie for orientation in favor of
vertical scrolling.

Since there is no actual HexEdit usage in bsnes, I tested it by putting
a dummy HexEdit widget inside the bsnes Presentation window. Scrolling
seemed to work as expected.
2025-09-02 00:52:37 +10:00
John Chadwick a4f0b478ea hiro/qt: QPalette::Background -> QPalette::Window 2025-09-02 00:36:36 +10:00
John Chadwick a6db3d6013 hiro/qt: QLayout::setMargin -> QLayout::setContentsMargins
setMargin has been obsolete since Qt 4.3!
2025-09-02 00:36:36 +10:00
John Chadwick fb09f52093 hiro/qt: QFontMetrics::width -> QFontMetrics::horizontalAdvance
QFontMetrics::width was deprecated in Qt 5.11 in favor of Qt
QFontMetrics::horizontalAdvance. Because QFontMetrics::horizontalAdvance
was introduced in Qt 5.11, it poses the most risk of breaking an
existing user of almost any of the deprecation changes, but Qt 5.11 is
fairly old by now (2018) and has been EOL for a while, so I still opted
to just move to the new function rather than use a version guard.
2025-09-02 00:36:36 +10:00
John Chadwick 58694a2935 hiro/qt: Update deprecated MidButton enumeration
This enum was deprecated in Qt 4.8 and removed in Qt 6.0.
2025-09-02 00:36:36 +10:00
John Chadwick f05dd784fd Use QScreen for Desktop::{size,workspace}
Qt 5.0 adds the QScreen API, which exposes enough information that
Desktop::{size,workspace} no longer needs to fall back to Win32/Xlib. I
manually tested that this seems to give the same exact answers as the
Xlib path (though it technically goes a different route for
Desktop::size.)
2025-08-31 01:48:26 +10:00
John Chadwick 8011051eea Remove Qt 4 support.
Qt 4.8 LTS was released on December 15th, 2011. It hit its official
end-of-life on December 31st, 2015. It has been dead for nearly 10
years. Qt 4 is now so old, that it has been removed from Debian long
enough that "qt4" doesn't show up in *any* of the indexed package suites
in Debian's online package search service.

With that in mind, I think we can safely say nobody is using this,
nobody will miss this, and it is beyond time to get rid of it (and
probably add Qt 6 support some day.)
2025-08-31 01:31:10 +10:00
Tim Allen 2e2440fe74 Update bsnes' SameBoy integration for the new version.
Hat tip to @alice-mkh for figuring out how to update bsnes' integration.
2025-08-31 00:58:11 +10:00
Tim Allen 85ca044ba5 Bump SameBoy version in the About dialog. 2025-08-31 00:31:27 +10:00
Tim Allen 052980f63f Update SameBoy subtree to v1.0.2. 2025-08-31 00:29:18 +10:00
Alice Mikhaylenko b8dcfcd59d system: Use strict serialization method for ICD
Backport of https://gitlab.com/jgemu/bsnes/-/commit/7d8dbd723c5803eba817f455761c6f724406c73c

Otherwise SGB savestates sometimes corrupted, see https://gitlab.com/jgemu/bsnes/-/issues/7
2025-08-31 00:20:26 +10: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
Tim Allen ddc3dc2d47 Make the About dialog link to a website that exists.
The registration for bsnes.dev has lapsed a long time ago, the GitHub repo is
effectively the website now.

Fixes #354
2025-07-13 16:48:43 +10: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 KokkonenandEldred Habert 7f110c4415 Add notes to SDL_Quit atexit call
Co-authored-by: Eldred Habert <[email protected]>
2024-06-15 20:33:26 +03:00
Lior Halphon b5cd06a41e Update version to 0.16.6 2024-06-13 22:47:39 +03:00
Lior Halphon d55426afa0 Fix a bug where haptics randomly stop working 2024-06-13 22:46:56 +03:00
Lior Halphon d1b4af5e76 Catch exceptions when parsing HH JSONs, just in case 2024-06-12 13:48:09 +03:00
Lior Halphon eebdbbfd5b Properly fix the camera threading bugs 2024-06-12 13:35:35 +03:00
Lior Halphon 60ff8577bb Allow user-provided boot ROMs in iOS 2024-06-11 17:48:59 +03:00
Lior Halphon a3128d89c0 Support for a distinct CGB-E boot ROM, internal support for an distinct AGB-0 boot ROM 2024-06-09 22:49:49 +03:00
Lior Halphon 2018f0ee01 Improved dpad controls 2024-06-09 18:28:10 +03:00
Lior Halphon 76c93254ed Disable screen dimming while emulation is running 2024-06-09 18:10:01 +03:00
Lior Halphon e578843745 Merge branch 'master' of github.com:LIJI32/SameBoy 2024-06-09 17:58:34 +03:00
Lior Halphon 8600f96fa2 Fix a race condition with camera emulation 2024-06-09 17:58:28 +03:00
Lior Halphon cb7cc44b7b Merge pull request #635 from ISSOtm/rgblink-x
Use `rgblink -x` instead of `dd`
2024-06-09 17:47:12 +03:00
ISSOtm 2c5455e35d Use rgblink -x instead of dd
This saves a few build steps and intermediate files
2024-06-09 16:36:13 +02:00
Lior Halphon 0b77662504 Fix compatibility issues when linking against Sonoma's SDK. Fixes #633 2024-06-09 15:27:28 +03:00
Lior Halphon b2d1086e2e Make the console window not always on top 2024-06-08 20:34:26 +03:00
Lior Halphon 93cc19b3b9 Homebrew Hub integration in iOS 2024-06-08 18:55:33 +03:00
Lior Halphon 0bc0618a6a Add an option to view the Library in Files 2024-06-04 00:30:34 +03:00
Lior Halphon 322f3c7013 More accurate emulation of the previous quirk 2024-06-03 22:04:17 +03:00
Lior Halphon 5be5bc4709 Emulate a new APU glitch, tweak another. Fixes #617 (Telefang sample audio being broken on CGB-D and CGB-E) 2024-06-03 00:19: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
Lior Halphon b1fec62564 Fix a potential crash upon pausing in iOS and macOS 2024-05-31 20:41:00 +03:00
Lior Halphon 2bf8feb299 Fix a bug causing newly imported ROMs to sometime incorrectly prefer SGB over CGB 2024-05-27 23:06:16 +03:00
Lior Halphon e5e9cf145a Fix temporary audio distortions affecting some Macs and iOS devices 2024-05-27 23:02:54 +03:00
Lior Halphon 5408fe8dd2 Update version to 0.16.5 2024-05-25 21:28:38 +03:00
Lior Halphon eba7e2dde9 Typo fix 2024-05-25 21:23:59 +03:00
Lior Halphon 1d613adac2 Windows being Windows 2024-05-25 21:18:24 +03:00
Lior Halphon ebf4d1d0ee Do not autohide debugger windows, give them all the ROM filename in the title. Closes #620 2024-05-25 20:56:20 +03:00
Lior Halphon 6c613d3b0c Update info.plist from the App Store version 2024-05-25 18:20:16 +03:00
Lior Halphon 302eaf6eca Migrate changes from the App Store version 2024-05-25 18:15:14 +03:00
Lior Halphon 7758713f86 Fix filtered screenshots being saved as 32-bit per channel 2024-04-29 15:51:30 +03:00
Lior Halphon 19cf8d26b1 Force absolute boot ROM paths in libretro's build bot 2024-04-18 22:26:47 +03:00
Lior Halphon c9700dfb29 Relicense the iOS frontend, following the recent events 2024-04-16 21:35:51 +03:00
Lior Halphon 44a35e57f6 Avoid GCC false positives 2024-04-14 00:22:14 +03:00
Lior Halphon 038a2c5892 Merge pull request #608 from roydmerkel/windows-build-fix
Fixed windows cmd build (LIB overrides msvc-clang/clang-cl libpath.)
2024-04-13 21:29:14 +03:00
Roy Merkel 2ea0932726 Fixed windows cmd build (LIB overrides msvc-clang/clang-cl libpath.) 2024-04-13 09:24:19 -07:00
Lior Halphon 5d06f45c0f Merge pull request #607 from Morilli/fix-compiler-warning
Fix potential compiler warning on questionable code path
2024-04-13 13:52:10 +03:00
Morilli c5b3e47925 Fix potential compiler warning on questionable code path 2024-04-13 02:53:52 +02:00
Lior Halphon bd31258725 Fix building SameBoot with the lastest RGBDS master, fixes #606 2024-04-13 00:23:18 +03:00
Lior Halphon b40ba73533 Update version to 0.16.3 2024-04-12 19:57:27 +03:00
Lior Halphon fe917efad5 Add an installer for the iOS Deb release to allow compatibility with rootless jailbreaks 2024-04-12 19:25:58 +03:00
Lior Halphon 3fe9de88a2 Sign reregister at build time 2024-04-12 13:57:21 +03:00
Lior Halphon 86cf0c4d84 Sign the sideloaded iOS app to make sure TrollStore uses the correct entitlements 2024-04-12 13:47:01 +03:00
Lior Halphon b63ddc6e3d Add audio activation settings to iOS 2024-04-12 13:46:29 +03:00
Lior Halphon 4a42dc073b Fix turbo mode not working on iOS if dynamic speed is not enabled 2024-04-12 13:41:59 +03:00
Lior Halphon a791f7e621 Add an option to enable single-touch A+B combo in iOS, closes #587 2024-04-06 15:16:41 +03:00
Lior Halphon 3f799f21ff Make the SGB boot ROMs closer in timing to the original ones, fixed #602 2024-04-05 18:44:49 +03:00
Lior Halphon a80a19b418 Fix warning 2024-04-05 14:54:05 +03:00
Lior Halphon 2b37404447 It did trigger GCC 2024-04-05 14:46:12 +03:00
Lior Halphon 514e27d975 Enable a few warnings, hopefully they won't trigger GCC 2024-04-05 14:39:23 +03:00
Lior Halphon a39445e63b Merge pull request #600 from CasualPokePlayer/new_folder_dialog
Add support for the newer Vista style select folder dialog
2024-04-05 13:47:17 +03:00
CasualPokePlayer 3caf6183bc Add support for the newer Vista style select folder dialog 2024-04-04 15:15:27 -07:00
Lior Halphon 0f6299edfc Merge pull request #592 from orbea/tester
sanity_tests.sh: avoid bash brace expansion
2024-03-31 20:11:31 +03:00
Lior Halphon 0b0abce956 Merge pull request #598 from max-m/GBViewController-patch-1
Remove duplicate observer for the `GBInterferenceVolume` setting
2024-03-31 14:18:34 +03:00
Lior Halphon 60d77a6931 Merge pull request #599 from max-m/Shader-WebGL-compat
Make shaders compatible with GLES 3.0
2024-03-31 14:17:49 +03:00
Lior Halphon 7ed8fb1de9 Merge pull request #603 from YayIguess/master
Fix message always being logged when running ticks command
2024-03-31 14:04:28 +03:00
Braiden Gent 66ec48e0eb Don't tell user tick count has been reset if they've kept the value
"Tick count reset." is currently logged even if the user supplied the 'keep' argument.
2024-03-22 03:47:33 -07:00
Maximilian Mader 00dce71eab Make shaders compatible with GLES 3.0
GLES, at least as used in WebGL 2, does not like mixing integers and floats,
for example:
> ERROR: 1:8: '*' : wrong operand types - no operation '*' exists that takes a left-hand operand of type 'mediump 2-component vector of float' and a right operand of type 'const int' (or there is no acceptable conversion)

This patch converts those integer constants into floats.
With this patch the shaders (apart from the master shader) can be used in WebGL contexts too.
2024-03-11 16:40:23 +01:00
Maximilian Mader d7523d27e8 Remove duplicate observer for the GBInterferenceVolume setting 2024-03-11 16:05:00 +01:00
Lior Halphon e7792c16b2 Prevent filtered screenshots from using 64-bit color depth, as it causes some apps to misinterpret color space information 2024-03-09 21:04:54 +02:00
Lior Halphon 5e2b6e7e9e Fix rounding errors in the LCD and CRT shaders, closes #595 2024-03-09 18:07:04 +02:00
Lior Halphon a125da6a98 Fix ISX support, oops 2024-03-09 16:37:17 +02:00
Lior Halphon 8739da61c0 Avoid strict aliasing violations. Closes #593 2024-03-09 15:41:07 +02:00
Lior Halphon efc93d0422 Avoid realpath, no available on macOS 12.x 2024-03-09 13:37:50 +02:00
Lior Halphon 17c962e500 Update libretro build 2024-03-09 13:19:31 +02:00
Lior Halphon 2d29ece3b8 Various libretro buildbot fixes 2024-03-09 03:22:40 +02:00
Lior Halphon 6eedee78db Better path handling in libretro's Makefile 2024-03-09 02:20:53 +02:00
Lior Halphon 8aa19fe092 Update libretro's Makefile to support more targets
(cherry picked from commit 17f0ff2cf7)
2024-03-08 23:53:44 +02:00
Lior Halphon 17f0ff2cf7 Update libretro's Makefile to support more targets 2024-03-08 23:52:30 +02:00
Libretro Updater c382f7ea5a Update libretro branch to v0.16.2 2024-03-08 21:44:06 +00:00
Lior Halphon df59294c38 Fix Android libretro buildbot builds 2024-03-08 23:39:30 +02:00
Lior Halphon 6d6982abee The path should be relative to the libretro folder 2024-03-08 19:43:51 +02:00
Lior Halphon cd2275c129 Build the version-correct boot ROMs rather than the latest, add libretro GitLab CI 2024-03-08 19:07:18 +02:00
Lior Halphon 7113c5484b I still don't understand git 2024-03-08 18:54:05 +02:00
Lior Halphon 633ea9df90 I don't understand git 2024-03-08 18:51:27 +02:00
Lior Halphon ba45911734 Push the branch as well 2024-03-08 18:39:20 +02:00
Lior Halphon de0046d7d6 Fetch tags 2024-03-08 18:27:34 +02:00
Lior Halphon b583f62e7b It works on my machine :( 2024-03-08 18:24:32 +02:00
Lior Halphon 950c0d5524 Chmod the script 2024-03-08 18:20:02 +02:00
Lior Halphon 06bc4cd0bf Make the libretro branch only use stable releases, tag libretro releases 2024-03-08 18:17:29 +02:00
Lior Halphon 3ef8fab7c4 Fix typo 2024-03-08 18:17:29 +02:00
Lior Halphon 153cdb2e11 Fix the States view header in iOS 16 and newer 2024-03-08 18:17:29 +02:00
Lior Halphon 5e4a1f6db7 Adjust the handling of >4MB ISX files 2024-03-08 18:17:29 +02:00
Lior Halphon 8c9c97b74f ISX does not support symbols with a bank >FF 2024-03-08 18:17:29 +02:00
Lior Halphon 42474a0859 Slightly simplify boot ROM stripping 2024-03-08 18:17:29 +02:00
Lior Halphon a3a751b1b6 Remove empty Obj-C extensions 2024-03-08 18:17:29 +02:00
Lior Halphon 6d7dad9ce5 Correct the license in the Cocoa and iOS frontends 2024-03-08 18:17:29 +02:00
orbea e3b240147a sanity_tests.sh: avoid bash brace expansion 2024-03-03 07:30:26 -08:00
Lior Halphon 6edc35804c Merge pull request #591 from orbea/missing-prototypes
pb12: silence -Wmissing-prototypes warnings
2024-02-29 11:02:24 +02:00
orbea 8017a4a044 pb12: silence -Wmissing-prototypes warnings 2024-02-28 19:12:00 -08:00
Lior Halphon e79f2c1764 Add a menu item to reload the ROM without resetting 2024-01-21 13:46:51 +02:00
Lior Halphon 9c13590f30 Allow hot-swapping a ROM into itself, fixes #512 2024-01-21 13:45:52 +02:00
Lior Halphon 0c81f36269 Disable function outlining 2024-01-16 23:23:53 +02:00
Lior Halphon 27b5935b8d Update version to 0.16.2 2024-01-13 22:18:15 +02:00
Lior Halphon 8d063391a4 Support for certain bootlag games with malformed headers, fixes #585 2024-01-13 18:06:22 +02:00
Lior Halphon 9f53fcc30b Proper fix to Metal flickering 2024-01-13 18:05:27 +02:00
Lior Halphon 4cf3b3c948 Accurate emulation of frame parity 2024-01-13 15:50:07 +02:00
Lior Halphon a9c01d35fc Fix a bug where the Metal renderer would sometimes flicker in the Cocoa/iOS frontends 2024-01-13 15:49:37 +02:00
Lior Halphon 686a506e17 Fix the Quick Look generator for macOS Sonoma, fixes #581 2024-01-11 23:55:01 +02:00
Lior Halphon 5fb6d55c67 Fix the update dialog font, which was broken on both older and newer versions of macOS 2024-01-06 21:49:48 +02:00
Lior Halphon 226825bda4 Fix menu layout in bordered/SGB mode, in the SDL port 2024-01-06 18:45:18 +02:00
Lior Halphon 927b7493e5 Fix menu redrawing mode in the SDL frontend in bordered/SGB mode, fixes #576 2024-01-06 17:46:12 +02:00
Lior Halphon e9c2c866eb Replace XAudio 2.7 and 2.9 with the redistrib version of XAudio 2.9 2024-01-06 17:41:24 +02:00
Lior Halphon 97e8df29c5 Don't prompt for an xcode-select reset every build 2024-01-05 22:50:23 +02:00
Lior Halphon f725e70e84 Merge pull request #579 from Nyanport/master
Fix bugs in Makefile for newer operating systems
2024-01-03 20:08:48 +02:00
Max Parry 4569114cab Update Makefile (as per LIJI32) 2024-01-03 14:19:23 +11:00
Max Parry d51dcaca19 Update Makefile 2023-12-31 20:04:40 +11:00
Max Parry 10eb15bb90 Add files via upload 2023-12-31 19:55:28 +11:00
Lior Halphon 91f2a82f19 Merge pull request #577 from orbea/c++
gb.h: add include guards for C++ projects
2023-12-29 17:09:05 +01:00
orbea 8cf319e941 gb.h: add include guards for C++ projects
This is helpful for C++ projects like bsnes that wish to include gb.h
without needing to set extern "C" themselves.
2023-12-28 09:59:37 -08:00
Lior Halphon e666ec09db Update version to 0.16.1 2023-12-23 20:42:47 +02:00
Lior Halphon c9fb3b3ec6 Fix XAudio2.7 hanging on device disconnection 2023-12-23 20:42:21 +02:00
Lior Halphon e89df2df43 Automatically disable VSync on displays lower than 60Hz 2023-12-23 16:34:40 +02:00
Lior Halphon b516f9a3ee Drop ownership information from DEB TARs 2023-12-22 15:13:45 +02:00
Lior Halphon 2e38cec98b Verify the entitlements match the plist, fixes #551 2023-12-21 23:45:07 +02:00
Lior Halphon 8ed46a6a58 Allow SameBoy Cocoa to coexist with VBA 2023-12-20 23:54:49 +02:00
Lior Halphon 27d42146ba Fix compatibility with Catalina and older versions of macOS, improve printer UI 2023-12-18 22:41:15 +02:00
Lior Halphon 00e1c925a4 Prevent GB_workboy_is_enabled incorrectly returning true, prevent GB_workboy_set_key from affecting other accessories if Workboy isn't connected 2023-12-18 21:48:09 +02:00
Lior Halphon 9619500445 Use a more compatible TAR format for iOS debs 2023-12-16 23:22:34 +02:00
Lior Halphon 9cc70c085f Update version to 0.16 2023-12-16 20:26:57 +02:00
Lior Halphon 746204e57c Silence zip 2023-12-16 20:03:04 +02:00
Lior Halphon 3fd09ffcde Update README for Windows builds 2023-12-16 19:55:41 +02:00
Lior Halphon 6e923645d3 The previous change should only affect channel 3 2023-12-15 20:52:24 +02:00
Lior Halphon c7c2d08dc5 More accurate audio mixing in AGB mode, fixes #555 2023-12-15 20:38:19 +02:00
Lior Halphon fcf31be735 Fix SDL controllers not automatically reconnecting. Fixes #563 2023-12-15 15:24:09 +02:00
Lior Halphon d8905f57bf iOS alarm support 2023-12-15 14:28:19 +02:00
Lior Halphon 8b2f683c20 Todo confirmed 2023-12-14 22:08:55 +02:00
Lior Halphon 404e153744 Use Expat rather than X11, as X11 has one extra clause. Fixes #574 2023-12-14 21:54:46 +02:00
Lior Halphon 9f56f5fee0 Switch the Windows build to x86-64 2023-12-12 00:26:13 +02:00
Lior Halphon 977d941f48 Using Base.lproj prevents the VRAM toolbar from appearing in Sonoma for some reason. Fixes #567. 2023-12-10 23:52:51 +02:00
Lior Halphon 34c9d4c791 Correctly emulate the vram_rd_eol test ROMs (except in odd mode) 2023-12-10 22:40:47 +02:00
Lior Halphon 40ded1114f Correct timing TODO 2023-12-10 14:56:41 +02:00
Lior Halphon fbd1d06f1c Confirmed SCX on double speed mode 2023-12-10 14:48:15 +02:00
Lior Halphon 1c0f65177f Fix HDMA5 not being correctly updated in memory when disabling hblank HDMA 2023-12-09 15:54:57 +02:00
Lior Halphon b51aac4bf5 Modernize some RGBASM syntax to silence most deprecation warnings in the upcoming 0.7 RGBDS release 2023-12-09 15:04:27 +02:00
Lior Halphon 68ba89cf43 Fix unquoted realpath, fixes #572 2023-12-07 01:02:01 +02:00
Lior Halphon 8642715a6d Merge pull request #573 from Rangi42/rgbds
Allow rgbds to build SameBoy's BootROMs for testing
2023-12-06 23:09:52 +02:00
Rangi42 6d3a65759e Allow rgbds to build SameBoy's BootROMs for testing
rgbds needs to use a local copy of its executables for testing,
passed as an `RGBDS=../../` prefix for the path to them all.

This commit enables that, so rgbds can do
    test_downstream LIJI32/SameBoy bootroms
in its run-tests.sh script.
2023-12-06 12:12:15 -05:00
Lior Halphon eba273d89c Menu items and shortcut to resize the window in the Cocoa frontend 2023-12-04 00:34:48 +02:00
Lior Halphon bce413821d Merge pull request #569 from SnowyMouse/gbenum-fix
Fix GB_ENUM on C++
2023-11-26 19:39:23 +02:00
Lior Halphon 1c8a14ff1c Improved controller assignment in the Cocoa port, affects #532 2023-11-26 17:32:33 +02:00
Lior Halphon 5823bf9d70 Merge branch 'master' of github.com:LIJI32/SameBoy 2023-11-25 21:24:56 +02:00
Lior Halphon ecbdb9e95e Emulate several more pre-CGB-D channel 1 glitches 2023-11-25 21:24:46 +02:00
Lior Halphon 35a91768b4 iPad support was missing from the iOS plist file 2023-11-25 21:22:01 +02:00
Lior Halphon a795514bc4 Refer to SameBoy's license as the X11 License 2023-11-25 21:21:34 +02:00
Snowy 8657d3e4b6 Fix GB_ENUM on C++
The else branch results in an error from defining a type in a cast.
2023-10-28 14:20:31 +02:00
Lior Halphon aff42affc0 Merge pull request #570 from max-m/fix-cheats
Fix memory corruption on removal / update of cheats with the same address hash
2023-10-22 21:01:54 +03:00
Maximilian Mader 0ece951173 Fix memory corruption on removal of multiple cheats with the same address hash 2023-10-22 18:39:14 +02:00
Hitomi Nakayama d267d83cec Added warning for SDL init failure 2023-10-12 17:57:33 -07:00
Lior Halphon e59bc436bd CGB-C NR10 conflict improvements 2023-09-25 23:35:26 +03:00
Lior Halphon 340d4e0630 WIP: Fix APU regressions (CGB-D/E only so far) 2023-09-09 23:54:01 +03:00
Lior Halphon 3ab6150508 Fixed weird printer related crashes on open, seems like an Apple regression? 2023-09-03 16:46:00 +03:00
Lior Halphon 5192e3a07b Merge branch 'master' of github.com:LIJI32/SameBoy 2023-09-03 15:54:42 +03:00
Lior Halphon d662407df0 Accurate emulation of NR10 write glitches 2023-09-03 15:54:37 +03:00
Lior Halphon 4f69e4e86c Merge pull request #561 from vailkyte/tes
Force parsing order
2023-09-02 13:38:08 +03:00
vailkyte 816cdf2c62 Force parsing order 2023-09-01 22:19:06 -05:00
Lior Halphon 7542de74e7 Merge pull request #560 from rizinorg/oob-read
Fix oob reads in debugger command parsing
2023-08-19 17:05:02 +03:00
Florian Märkl 6b6800445f Fix oob reads in debugger command parsing
The length of only one of the operand strings was checked before the
memcmp in these cases, causing out-of-bounds reads when the other was
shorter.
This could be seen by compiling with ASAN and for example executing any
command longer than 2 characters.
2023-08-19 15:03:27 +02:00
Lior Halphon 240d8d1ffa Silence warning 2023-08-12 13:40:16 +03:00
Lior Halphon 3bad68f2ab Add backstep to the Cocoa button bar 2023-08-12 13:35:32 +03:00
Lior Halphon 3168e0e1fa Fixed potential deadlocks 2023-08-12 13:34:57 +03:00
Lior Halphon 7e6f1f866e Merge pull request #558 from arthurgiroux/bugfix/hexfiend-compilation-mac
Removed unused local variable "lineIndex" that was generating a warning.
2023-08-06 17:52:17 +03:00
Arthur Giroux 10955abe6c Removed unused local variable "lineIndex" that was generating a warning. 2023-08-06 16:47:07 +02:00
Lior Halphon 3389f50884 Merge pull request #557 from arkie/master
Add SIGUSR1 to reload to the SDL frontend
2023-08-04 23:27:53 +03:00
Jon c709ea0d98 SIGHUP -> SIGUSR1 2023-08-04 13:53:58 -04:00
Lior Halphon 12ad85355c Build the iOS frontend without the debugger 2023-08-04 20:02:42 +03:00
Lior Halphon a9ce9f538f Experimental backstepping support 2023-08-04 19:54:14 +03:00
Lior Halphon 0b54eea084 Change the internal macro to use hidden, which guarantees a standard ABI 2023-08-04 19:53:52 +03:00
Jon e40e254add Add SIGHUP to reload to the SDL frontend 2023-08-02 11:35:01 -04:00
Lior Halphon fb3db82d42 The Cocoa memory viewer new symbolicates the selection 2023-07-30 20:11:35 +03:00
Lior Halphon ac45888a37 The memory viewer's "Go to" field can now switch banks and address spaces 2023-07-30 14:25:41 +03:00
Lior Halphon aedb3e2332 Fix GB_debugger_evaluate not correctly returning the bank 2023-07-30 14:21:41 +03:00
Lior Halphon 048da6e6d1 Fixed a bug where accurate RTC emulation halted while SameBoy wasn't running 2023-07-29 22:27:50 +03:00
Lior Halphon 4ab256d896 Correct read emulation of the BANK register while still in the boot ROM 2023-07-29 16:08:26 +03:00
Lior Halphon 10d996330c Inclusive ranges 2023-07-29 16:05:28 +03:00
Lior Halphon 29becc2870 Treat local and non-local symbols differently 2023-07-29 14:51:31 +03:00
Lior Halphon d209628369 Fixed a bug where breakpoint and watchpoints would sometime stop working 2023-07-29 13:45:26 +03:00
Lior Halphon 323b6fafa8 Ranged breakpoints and watchpoints 2023-07-29 01:00:36 +03:00
Lior Halphon f2466fd770 Deprecated the IO_ symbols, rename rWAV_START and rWAV_END 2023-07-29 01:00:23 +03:00
Lior Halphon dd1330d707 Breakpoints and watchpoints are now identified by a unique id rather than an address 2023-07-28 19:07:56 +03:00
Lior Halphon 61f3c8d7f3 Fixed an edge case where jump-to breakpoints did not work as expected/took the slow path 2023-07-28 00:49:31 +03:00
Lior Halphon 54f45f2fd3 Fix a bug where jump-to breakpoint disassembled the wrong address under certain scenarios 2023-07-28 00:47:15 +03:00
Lior Halphon 636349d5f2 Not going to use Constraints, Apple. Getting toolbar items to behave is hard enough as is 2023-07-23 22:03:42 +03:00
Lior Halphon a5903ca5bc Do the same for the CRT shader 2023-07-23 14:20:09 +03:00
Lior Halphon df1b89bf61 Update constants in the LCD shader that weren't updated after shaders switched to using linear RGB 2023-07-23 14:14:30 +03:00
Lior Halphon d93c1e501c Remove outdated comments, PPU timings and and the STAT interrupt are no longer based on these sources 2023-07-08 00:55:59 +03:00
Lior Halphon 8cb4085218 Fix Xbox Wireless Controller support, closes #527 2023-07-08 00:55:16 +03:00
Lior Halphon 803abd9925 Halt and Stop trigger the OAM bug 2023-07-04 23:25:53 +03:00
Lior Halphon 49ec02b3b3 Replace cycle_oam_bug_pc with a generic call to cycle_oam_bug 2023-07-04 01:07:01 +03:00
Lior Halphon e9be438d91 Turns out jr triggers the OAM bug, thanks Sono! 2023-07-04 00:21:57 +03:00
Lior Halphon 1b50856dcf More of the same 2023-06-21 21:49:23 +03:00
Lior Halphon 207851bc56 Merge branch 'master' of github.com:LIJI32/SameBoy 2023-06-21 21:47:45 +03:00
Lior Halphon 57b50cab63 Work around bad Clang and GCC optimizations of inline compile-time consts (They can't be static before C23, which isn't supported by Clang) 2023-06-21 21:47:30 +03:00
Lior Halphon 16294baa05 Merge pull request #549 from nununoisy/master
Library access to raw APU channel volumes
2023-06-20 20:58:35 +03:00
Noah Sweilem 074d152a4e Formatting fixes 2023-06-20 10:28:18 -07:00
Noah Sweilem dad9e4b704 Formatting fixes 2023-06-20 10:28:01 -07:00
Noah Sweilem 9148b26bd8 Move edge_triggered variables into gb->apu_output 2023-06-20 10:25:25 -07:00
Noah Sweilem 4213524286 Fix swapped wave channel volume 2023-06-16 19:04:12 -07:00
Noah Sweilem ae855d470d Use different sample index for square channel edge trigger depending on duty cycle 2023-06-11 16:23:26 -07:00
Noah Sweilem ec9536eede Try a modified edge trigger detection for pulse and wave channels 2023-06-11 15:44:28 -07:00
Noah Sweilem 7bdf8dbe47 Add initial edge trigger detection method
- GB_get_channel_edge_triggered()
2023-06-11 15:27:31 -07:00
Noah Sweilem 5c7b1f01a3 Add som APU query methods for libsameboy
- GB_get_channel_volume()
- GB_get_channel_amplitude()
- GB_get_channel_period()
- GB_get_apu_wave_table()
2023-06-10 14:23:15 -07:00
Lior Halphon 951d0b07f0 Give sliders the same treatment 2023-06-10 13:35:21 +03:00
Lior Halphon de9fc76a2c Make most preferences controls codeless 2023-06-10 01:10:06 +03:00
Lior Halphon d61e5f248d Drop the direct use of NSNotificationCenter for most preferences 2023-06-09 17:42:31 +03:00
Lior Halphon daf713132b ivar naming in Document.m 2023-06-09 16:28:58 +03:00
Lior Halphon fef175dcc6 Use #pragma once for include guards, use #import exclusively on Obj-C files 2023-06-09 14:44:57 +03:00
Lior Halphon bed26daf73 Allow disabling SameBoy features when compiling as a library. Probably introduces some speed improvements to the Libretro core, as well as bsnes and BizHawk 2023-06-03 22:37:42 +03:00
Lior Halphon d62132be38 These should be in defs.h 2023-06-03 21:54:01 +03:00
Lior Halphon ee9b6c1444 Maybe this will fix it 2023-06-03 14:58:19 +03:00
Lior Halphon 406189b79e I don't know yaml 2023-06-03 14:54:24 +03:00
Lior Halphon 6eb42ab283 Also upload lib/ and include/ 2023-06-03 14:49:32 +03:00
Lior Halphon be171cfe66 Add a library target, complete with headers that strip implementation details out. 2023-06-03 14:39:21 +03:00
Lior Halphon 4254dcdb2c Fix incorrect initial value of register IE when playing GBS files. Fixes #544 2023-05-12 17:57:20 +03:00
Lior Halphon b8d6bb7fd2 Automatic detection of -Oz support 2023-05-11 01:42:46 +03:00
Lior Halphon c234111024 GCC doesn't support Oz, only Os 2023-05-11 00:31:59 +03:00
Lior Halphon 996ebaafa3 Use Oz for the frontend files, reduce some aggressive loop unrolling 2023-05-11 00:08:54 +03:00
Lior Halphon 96e337edac Automatic key mappings for wired Switch controllers 2023-05-10 20:55:13 +03:00
Lior Halphon 40b7e25126 Accurate emulation of SVBK, fixes audio in Flyeyes (unlicensed game) 2023-05-10 00:55:04 +03:00
Lior Halphon 06621d1dfe Fix GB_debugger_break on builds without the debugger 2023-05-10 00:54:34 +03:00
Lior Halphon 3e3ac23432 More likely/unlikely fun 2023-04-25 13:35:25 +03:00
Lior Halphon c6e187a80b Enable fast math 2023-04-25 13:08:34 +03:00
Lior Halphon 32a419ad2e Do not inline the slow path of frequently called functions 2023-04-25 13:08:19 +03:00
Lior Halphon 237e127b36 Add a comment 2023-04-11 12:37:13 +03:00
Lior Halphon 4421dedbb9 One last attempt 2023-04-11 12:33:10 +03:00
Lior Halphon 479c16e698 Try a better hint 2023-04-11 12:30:05 +03:00
Lior Halphon aaba172c02 This might hint GCC 9 and make it suck less 2023-04-11 12:23:50 +03:00
Lior Halphon 5b37d3c402 Add a debugger reset command, with a frontend-handled reload option. Closes #537 2023-04-11 12:02:32 +03:00
Lior Halphon 9a5aa6b5c8 Replace Ubuntu 18.04 with 20.04 (while keeping ubuntu-latest) 2023-04-11 11:14:53 +03:00
Lior Halphon a6de76eb2b Specify the deployment target when compiling NIB files, fixes #531 2023-04-09 21:23:07 +03:00
Lior Halphon 47ce95afb5 Fixed typo that caused the libretro core to crash during link mode. Fixes #534 2023-04-06 10:30:04 +03:00
Lior Halphon 147341a1d4 Add model/revision selection CLI option to the SDL frontend, closes #533 2023-04-05 18:22:28 +03:00
Lior Halphon 7ac920d2be Double speed STAT conflicts 2023-03-05 00:32:24 +02:00
Lior Halphon 502f64e6d7 Remove some old TODOs 2023-03-04 20:34:41 +02:00
Lior Halphon e48eb3515d More double speed write conflict updates 2023-02-28 01:00:57 +02:00
Lior Halphon cc4baa1d28 LCDC write conflict emulation in double speed mode 2023-02-25 17:28:48 +02:00
Lior Halphon 1c8397e8f3 Prevent the console window from remaining open and orphaned in rare edge conditions 2023-02-24 19:13:11 +02:00
Lior Halphon f145f05f15 Timing adjustments to object line address calculation 2023-02-19 00:32:16 +02:00
Lior Halphon 29e920697a Object aborts are DMG only, commit 34cf0f5 accidentally made them happen on CGB 2023-02-18 22:31:29 +02:00
Lior Halphon 22afa576c2 Fix incorrect timing adjustment on LCDC object abort 2023-02-18 20:42:23 +02:00
Lior Halphon 42ce9c410b Dynamic rewind/forward speed in iOS 2023-02-12 18:25:33 +02:00
Lior Halphon ef8f3aff66 A bit more correct 2023-02-11 21:56:03 +02:00
Lior Halphon 8dd5e6d9b8 Improved emulation of joypad switching delay 2023-02-11 20:21:24 +02:00
Lior Halphon 59ecd4b9bc Explicitly set register A to 0 in the DMG, SGB, MGB, and SGB2 bootroms 2023-02-11 19:31:19 +02:00
Lior Halphon 947687ac0d Use standard function 2023-02-09 20:56:08 +02:00
Lior Halphon 3f033e1e53 Merge branch 'master' of github.com:LIJI32/SameBoy 2023-02-09 20:50:07 +02:00
Lior Halphon 175af178bd Fix imported cheats not appearing on Cocoa 2023-02-09 20:50:02 +02:00
Lior Halphon 4f8b081f82 SDL cheats 2023-02-09 20:49:01 +02:00
Lior Halphon f79f18704d Improved cheats API, fixed incorrect GameShark imports 2023-02-09 19:49:40 +02:00
Lior Halphon 38a130714f Make the SDL menus left aligned 2023-02-09 19:49:07 +02:00
Lior Halphon 801e61a4e7 Merge pull request #525 from deltabeard/master
Fix MGB bootrom padding larger than 256 bytes
2023-02-07 14:49:21 +02:00
Mahyar Koshkouei 91c75141a8 Fix MGB bootrom padding larger than 256 bytes
mgb_boot.bin was incorrectly being padded to a CGB-size bootrom.

Signed-off-by: Mahyar Koshkouei <[email protected]>
2023-02-07 12:40:55 +00:00
Lior Halphon e1be593a65 Expose and use the built-in accessory type enum 2023-02-05 22:59:26 +02:00
Lior Halphon c0d6c3d6bb Merge branch 'thread_safety' 2023-02-05 21:36:03 +02:00
Lior Halphon ed01c569d4 Correct layout on iPhone 12 and 13 Mini 2023-02-05 21:35:52 +02:00
Lior Halphon 30e2a7b7e4 Add thread safety assertions in debug 2023-02-05 19:51:11 +02:00
Lior Halphon a040b1b395 Fixing a wrong default 2023-02-05 12:58:50 +02:00
Lior Halphon c8b3b080a8 Remove debugging code 2023-02-04 12:49:46 +02:00
Lior Halphon 830f2ddc38 Break save state compatibility. Windows save states should now work with non-Windows save states again. 2023-02-04 02:13:01 +02:00
Lior Halphon 2b6cf0c8f1 Correctly set the B register on Nintendo-licensed games running with the built-in CGB and AGB boot ROMs 2023-02-02 23:46:23 +02:00
Lior Halphon 93aa93e42c I forgot ISX support 2023-02-02 00:21:47 +02:00
Lior Halphon 65a646f050 Expose an API to reset the rewind buffer, explicitly reset on ROM changes 2023-02-02 00:18:01 +02:00
Lior Halphon 4c8f364ad7 Force the rewind buffer to reset after the save state size changes 2023-02-02 00:06:22 +02:00
Lior Halphon c36c7126f8 Hack to not break save state compatibility 2023-02-01 23:47:25 +02:00
Lior Halphon 7f3b3879a0 Fix ROM size rounding when loading from buffer, make size rounding a function 2023-02-01 22:07:16 +02:00
Lior Halphon 1757e1b128 Allow rewinding a state load on iOS 2023-02-01 21:59:26 +02:00
Lior Halphon d5ff93af3b Emulate GB printer timer, letting one emulate the mini game in Hello Kitty Pocket Camera. Closes #290 2023-01-30 22:42:03 +02:00
Lior Halphon c06e320b95 Fix the camera using the wrong aspect ratio on some Macs. Fix a bug that caused artifacts on the right and bottom edges of the camera image. 2023-01-29 23:19:26 +02:00
Lior Halphon b032b89457 Banked breakpoints should not affect the boot ROM 2023-01-29 12:41:32 +02:00
Lior Halphon 9972ce999d Don't apply the about screen inset on button-less iPads 2023-01-29 01:45:17 +02:00
Lior Halphon 8755e505d5 y u so picky about spaces markdown 2023-01-29 00:22:56 +02:00
Lior Halphon 2e1f4445e9 Ehh how did that happen 2023-01-29 00:10:25 +02:00
Lior Halphon 8edbbbdf49 No need to run the sanity test on the auto-generated libretro branch commits 2023-01-29 00:06:41 +02:00
Lior Halphon 0cf095dd21 AudioUnits is required to link against some macOS SDKs? 2023-01-29 00:03:46 +02:00
Lior Halphon 0cf3aec939 Allow building against iOS ≥15 SDKs 2023-01-28 23:34:11 +02:00
Lior Halphon bbf6b66251 Update readme and the GitHub action 2023-01-28 23:23:39 +02:00
Lior Halphon 5ec10d3c9a Fix the about screen 2023-01-28 23:15:05 +02:00
Lior Halphon ed39e6258d Allow packaging both as an IPA and as a DEB package for jailbreak 2023-01-28 22:21:24 +02:00
Lior Halphon fabc3901b8 Fix iOS dep generation 2023-01-27 19:04:54 +02:00
Lior Halphon ff12bd2bec iPad icons 2023-01-27 19:01:37 +02:00
Lior Halphon df248736c8 Better rewind speed (use a different amount of rewind pops rather than clock multiplier) 2023-01-27 18:00:21 +02:00
Lior Halphon 6829ebf44a File icons 2023-01-27 16:42:31 +02:00
Lior Halphon e1075b1bdc Turbo and rewind speed controls 2023-01-27 14:55:51 +02:00
Lior Halphon b2bbd9cfdc Camera emulation 2023-01-27 14:41:12 +02:00
Lior Halphon 8b1b5b9348 Motion controls 2023-01-26 00:00:10 +02:00
Lior Halphon 8557a2c1ec Swipe controls for rewind, turbo and quick save/load 2023-01-25 22:57:03 +02:00
Lior Halphon e7cce8fdde Fix the theme resetting to Twilight 2023-01-24 22:56:37 +02:00
Lior Halphon defd8d4f69 Swipe controls option, improve dpad angle thresholds 2023-01-24 22:45:51 +02:00
Lior Halphon 413212f993 Stylistic changes 2023-01-23 00:36:41 +02:00
Lior Halphon f7ad805559 Save states 2023-01-22 22:10:55 +02:00
Lior Halphon 8ea5e8d74d More ROM management features 2023-01-21 22:51:30 +02:00
Lior Halphon 6ddc3b0f0a Settings screen 2023-01-21 19:41:38 +02:00
Lior Halphon e582e38abc This shouldn't have been the default 2023-01-21 15:11:22 +02:00
Lior Halphon 1cc131227c Fix mathematical error in temperature_tint 2023-01-21 01:25:51 +02:00
Lior Halphon 31c53e8e05 Show unloaded ROM hint 2023-01-20 12:47:37 +02:00
Lior Halphon e0b77d3821 Can't permanently disable the Home Bar, so the Safe Area must be followed :( 2023-01-20 12:47:29 +02:00
Lior Halphon 2530370f90 Fix opening in place 2023-01-19 21:07:28 +02:00
Lior Halphon 1fde385cd7 Visual improvements 2023-01-19 01:19:30 +02:00
Lior Halphon d32bff58a4 Basic ROM management functionality 2023-01-19 00:47:35 +02:00
Lior Halphon 21f21f6bc7 Allow importing ROMs and Files app interaction 2023-01-18 23:08:17 +02:00
Lior Halphon 322ead9b93 Use the non-recursive methods 2023-01-18 20:31:39 +02:00
Lior Halphon 3b1fc41064 Add about screen 2023-01-17 00:07:10 +02:00
Lior Halphon 00367a79b4 Add screenshots to the ROM library (A similar functionality will be given to the state manager) 2023-01-15 23:00:06 +02:00
Lior Halphon 181a236fce Fix rumble 2023-01-15 22:07:28 +02:00
Lior Halphon 6673427c54 Add model selection 2023-01-15 21:51:27 +02:00
Lior Halphon 0549dc702c Add an API to get the model from the state file 2023-01-15 19:15:45 +02:00
Lior Halphon a838c31d02 Add a menu 2023-01-15 18:37:25 +02:00
Lior Halphon 7f0ad795ec Recrush all graphics 2023-01-15 17:53:18 +02:00
Lior Halphon e04aeebc0a Automatic save/restore 2023-01-15 01:43:34 +02:00
Lior Halphon 1c1d6bec78 Buttons now appear pressed when interacted with 2023-01-14 23:57:58 +02:00
Lior Halphon d0f17cfaed Fix portrait support 2023-01-14 23:46:51 +02:00
Lior Halphon 76500ebf15 Vibration support on legacy devices 2023-01-14 21:15:25 +02:00
Lior Halphon ffc80b2c0d Adjustments to support the 2016 iPhone SE and iPod Touch 2023-01-14 20:09:47 +02:00
Lior Halphon e0af961ad3 CoreHaptics support for rumble and button feedback 2023-01-14 18:28:08 +02:00
Lior Halphon 3e75016fe0 Implement controls 2023-01-14 15:02:34 +02:00
Lior Halphon 7624688e3b Bare bones ROM loading functionality (requires modification of the app container to add ROMs) 2023-01-14 01:25:36 +02:00
Lior Halphon be765a3e7e Initial emulation support 2023-01-13 23:30:28 +02:00
Lior Halphon 4c5d896630 Porting GBViewMetal 2023-01-13 21:57:57 +02:00
Lior Halphon 093998389c "Port" GBAudioClient 2023-01-13 17:24:28 +02:00
Lior Halphon 0441967332 Automatic layout generation 2023-01-13 16:48:44 +02:00
Lior Halphon d9bf739f52 Remove auto-generated comments 2023-01-12 23:19:24 +02:00
Lior Halphon 7ed8169d30 Basic buildability 2023-01-11 17:49:10 +02:00
Lior Halphon aa8b7b0c03 Improved emulation of envelope locking, fixes #522 2023-01-10 01:19:07 +02:00
Lior Halphon d90ecec085 Oops 2023-01-07 15:30:29 +02:00
Lior Halphon f5092c00de Reopening a modified ROM (via Open, Open Recent, command-line or Finder) will reload the ROM. Closes #497 2023-01-07 13:31:51 +02:00
Lior Halphon 88e64fadda More accurate and customizable timings 2023-01-06 19:06:22 +02:00
Lior Halphon c92a2c2131 Writes affect the data bus too 2023-01-06 18:46:58 +02:00
Lior Halphon 7a390414ff Improved accuracy of open bus behavior, merged with the HDMA open bus logic (it's the same bus) 2023-01-06 12:51:36 +02:00
Lior Halphon 0e6803aaa9 Add comment 2023-01-02 00:53:51 +02:00
Lior Halphon bd6843444f Emulate cart open bus behavior. Fixes #516 2023-01-01 22:59:16 +02:00
Lior Halphon 29d6960075 Merge pull request #521 from max-m/actions-checkout-v3
[CI] Update to actions/checkout@v3
2022-12-31 22:13:28 +02:00
Maximilian Mader 37785f779f [CI] Update to actions/checkout@v3
See https://github.com/actions/checkout/issues/1047
2022-12-30 23:04:41 +01:00
Lior Halphon 0989ee2763 Automatic libretro boot ROM rebuild 2022-12-30 19:45:33 +02:00
Lior Halphon 288bd84d19 Make libretro's build respect BOOTROMS_DIR 2022-12-30 18:04:57 +02:00
Lior Halphon 1247d00cbb Minor cosmetic change 2022-12-30 17:32:36 +02:00
Lior Halphon 9e5d3e449b Fix the Step icon on non-Retina displays 2022-11-23 19:47:53 +02:00
Lior Halphon bbe425e695 Update version to 0.15.8 2022-11-06 13:53:18 +02:00
Lior Halphon f1e912b64f Map the B button to back on SDL menus 2022-11-06 13:52:30 +02:00
Lior Halphon 31340d2a90 Fix debugger buttons appearing glitched on newer versions of macOS, fixes #509 2022-11-06 13:52:02 +02:00
Lior Halphon 1a85abfd2a Update version to 0.15.7 2022-10-31 23:09:36 +02:00
Lior Halphon b6e38bfa5f Microsoft and their underscore bullshit again 2022-10-31 23:04:35 +02:00
Lior Halphon e1fa28bd54 Adjust Joy-Con terminology 2022-10-31 22:49:17 +02:00
Lior Halphon 052e2429e0 Minor optimization 2022-10-31 21:17:32 +02:00
Lior Halphon cfee59918e Add Joy-Con orientation change support, motion controls 2022-10-31 21:11:00 +02:00
Lior Halphon 2776c8ad36 Add Joy-Con pairing interface 2022-10-30 14:42:54 +02:00
Lior Halphon 5ef668251c Rearrange the controls settings 2022-10-29 14:46:01 +03:00
Lior Halphon a43c293629 UI cleanup 2022-10-29 00:13:54 +03:00
Lior Halphon 354f68a861 Fix uniqueIDs not being unique in combined controllers 2022-10-28 20:15:24 +03:00
Lior Halphon 6547137389 Add an API to combine controllers 2022-10-28 14:49:54 +03:00
Lior Halphon 36f084f474 Explicitly enable vibration for Switch controllers, fixes rumble for Joy-Cons 2022-10-28 13:32:06 +03:00
Lior Halphon a450ab2a8e Basic JoyCon support, no rumble, no grouping 2022-10-28 01:02:54 +03:00
Lior Halphon eeb15c74f9 Fix visual glitches with the debugger split divider 2022-10-24 01:07:16 +03:00
Lior Halphon 0d1f686d68 Farewell, manual line breaks 2022-10-22 18:20:05 +03:00
Lior Halphon 87a2b0c842 Give ticks an optional "keep" argument 2022-10-22 17:37:25 +03:00
Lior Halphon 6536754944 Rename method to prevent overriding an Apple internal method on newer macOS versions. Be less strict about the inclusion of $. 2022-10-21 23:53:53 +03:00
Lior Halphon 36149dfa9f Don't crash on invalid GameShark/Genie codes 2022-10-19 22:54:54 +03:00
Lior Halphon 4649cdd290 Fix a bug that made the cheats window send debugger commands 2022-10-19 22:48:54 +03:00
Lior Halphon 5d5ff1702e Add quick reset API (Closes #506) 2022-10-17 18:52:02 +03:00
Lior Halphon 9b202c670e Was technically implementation defined 2022-10-17 14:34:55 +03:00
Lior Halphon 4180348567 Fix issues where finish and next did not behave as expected 2022-10-17 14:27:11 +03:00
Lior Halphon eef8b8448c That wasn't dead code, just another glitch. Fixes m3_wx_4_change_sprites 2022-10-16 23:57:19 +03:00
Lior Halphon ac9e36bc1a Fix assertion regression, fix window pixel insertion glitch regression, remove dead code. Closes #504 2022-10-16 18:19:43 +03:00
Lior Halphon e49527eff8 Shifter and fetcher information in the debugger 2022-10-16 16:04:30 +03:00
Lior Halphon 1720638017 Add margins to buttons 2022-10-15 21:31:38 +03:00
Lior Halphon ec6612d445 Fix DMA restart regression 2022-10-15 21:31:13 +03:00
Lior Halphon 90b3e1ff38 Add launchservices category to Cocoa. Closes #505 2022-10-15 14:36:36 +03:00
Lior Halphon b3d9404055 Merge pull request #502 from orbea/strict-prototypes
Fix -Werror=strict-prototypes
2022-10-10 23:43:24 +03:00
orbea cbb7e018b8 Fix -Werror=strict-prototypes
This will be required for upcoming gcc and clang versions.

Reference: https://archives.gentoo.org/gentoo-dev/message/dd9f2d3082b8b6f8dfbccb0639e6e240
2022-10-10 13:36:16 -07:00
Lior Halphon 832c7463bc Add comment to pb12 2022-10-04 15:06:39 +03:00
Lior Halphon 51510b53fd Update GitHub Actions to use RGBDS 0.6.0 2022-10-04 14:59:01 +03:00
Lior Halphon c0966ceeba Update SameBoot to support RGBDS 0.6.x, RGBDS 0.4.x support dropped. Closes #500, #501 2022-10-04 14:21:54 +03:00
Lior Halphon 55507274d6 Fix build 2022-10-01 16:14:36 +03:00
Lior Halphon 36cf778232 Update the Cocoa debugger interface with buttons, add an interrupt command 2022-10-01 16:07:06 +03:00
Lior Halphon ecaa92f853 Switch SameBoy from paused to debugger-paused on console input 2022-09-28 20:11:17 +03:00
Lior Halphon cb33119114 Update version to 0.15.6 2022-09-18 13:30:45 +03:00
Lior Halphon 98e986b48b Oopsie 2022-09-18 13:30:36 +03:00
Lior Halphon e545413a42 Save before swapping 2022-09-17 13:58:45 +03:00
Lior Halphon 51aa09517d SDL cart swap 2022-09-17 13:57:38 +03:00
Lior Halphon 93eb32c40f Group all options into a menu 2022-09-17 13:33:17 +03:00
Lior Halphon abaf471350 Cart hot-swapping (Cocoa) 2022-09-17 13:17:03 +03:00
Lior Halphon ea40a7be05 Fix DMA regression, fixes #495 2022-09-16 12:20:59 +03:00
Lior Halphon 0ebfdb840a Channel toggling in SDL 2022-09-16 12:20:23 +03:00
Lior Halphon 14c4548325 Allow muting audio channels (Missing: SDL) 2022-09-11 15:53:07 +03:00
Lior Halphon c9a22ddfd1 Missing colon 2022-09-11 15:43:30 +03:00
Lior Halphon 7917984376 Comments 2022-09-11 15:31:05 +03:00
Lior Halphon c580c44ad3 Constant replacements 2022-09-10 14:55:19 +03:00
Lior Halphon 4f78e4b109 Guide users to use the 'help' command in the debugger, fix apu command line breaks 2022-09-09 15:59:03 +03:00
Lior Halphon 8d2e01c4b6 Fix memory viewer Go To being broken 2022-09-09 15:52:19 +03:00
Lior Halphon 9208f82d09 Add new models and revisions to libretro 2022-09-09 14:21:14 +03:00
Lior Halphon 2f00211321 Force the timing info to update on model switch. Fixes #493 2022-09-09 00:15:49 +03:00
Lior Halphon b380f71886 Fix broken graphics 2022-09-03 14:42:48 +03:00
Lior Halphon c368c77d28 Use names for LCDC bits 2022-08-28 20:31:50 +03:00
Lior Halphon 5194a41d99 Slight improvements to symbol hash performance 2022-08-28 16:48:20 +03:00
Lior Halphon 7efd26c548 Allow building with older SDL versions 2022-08-24 23:59:38 +03:00
Lior Halphon 70332621cb Update version to 0.15.5 2022-08-24 23:17:20 +03:00
Lior Halphon e7de1fccab Support for MBC RAM was broken 2022-08-23 23:35:00 +03:00
Lior Halphon 9fcac76a03 New memory management APIs 2022-08-20 21:45:14 +03:00
Lior Halphon 58750424c7 Fully reset the MBC, for correct ROM switching. Fixes #489 2022-08-20 13:09:08 +03:00
Lior Halphon 2c7343a6ad Automatically update the copyright year 2022-08-14 19:10:00 +03:00
Lior Halphon 6ecc2f15b5 Link to debugger help and sponsor pages 2022-08-14 18:44:40 +03:00
Lior Halphon 9bf7e0b4df More accurate sample repeat glitch, fixes #483 2022-08-14 17:43:28 +03:00
Lior Halphon 95773b9538 Make things const 2022-08-14 01:54:28 +03:00
Lior Halphon 52ab200544 Accurately emulate CGB first frame behavior. Fixes #432, fixes #482 2022-08-09 00:54:31 +03:00
Lior Halphon f0959d4e70 Fix threading issue causing crashes and deadlocks 2022-08-04 01:15:25 +03:00
Lior Halphon 779ffe3e1b Fix desaturation 2022-08-03 01:06:34 +03:00
Lior Halphon ab07f955e4 Update version to 0.15.4 2022-07-31 13:30:28 +03:00
Lior Halphon ae1d3ddf6c Work around a Wayland bug – wait for mouse up before creating a new window #470 2022-07-31 13:30:21 +03:00
Lior Halphon a005ebe417 Merge branch 'master' of https://github.com/LIJI32/SameBoy 2022-07-31 13:29:26 +03:00
Lior Halphon 1bdd58d051 Auto-skip D-Pad configuration if hats are used, closes #480 2022-07-31 01:17:04 +03:00
Lior Halphon 7b5846fbaf Build break 2022-07-31 01:16:03 +03:00
Lior Halphon d6adbe0c7f No clue why force redrawing the parent wasn't enough 2022-07-31 00:53:38 +03:00
Lior Halphon 9383acda34 Optimize performAtomicBlock 2022-07-31 00:41:27 +03:00
Lior Halphon 44618f75c4 Optimize the memory viewer, GB_INTERNAL no longer required 2022-07-31 00:32:40 +03:00
Lior Halphon 352f8d54f8 Add popover descriptions to the color correction and high-pass filter options 2022-07-30 14:31:21 +03:00
Lior Halphon 3f7bcb9af2 Rename several color correction modes, add a new accurate mode 2022-07-30 13:32:40 +03:00
Lior Halphon 0894c1dcda Avoid rounding errors in color correction, minor optimization 2022-07-29 20:31:27 +03:00
Lior Halphon 86a05e2591 Fix updater crash, closes #469 2022-07-29 20:00:05 +03:00
Lior Halphon 84a193a918 Fix shader artifacts, revise AAScale4x 2022-07-29 17:08:51 +03:00
Lior Halphon f3915a6494 Create FUNDING.yml 2022-07-29 15:31:53 +03:00
Lior Halphon 859ff79527 Fix sanity test 2022-07-25 23:10:30 +03:00
Lior Halphon 1414e68a76 Update version to 0.15.3 2022-07-25 22:56:34 +03:00
Lior Halphon 99ac632d3a Fix creat on Windows 2022-07-25 22:56:26 +03:00
Lior Halphon f6de7b3fbd This is wrong 2022-07-25 22:43:56 +03:00
Lior Halphon 12655cb50c Fix Windows build 2022-07-25 22:21:44 +03:00
Lior Halphon f47e143e75 Update the boot ROM color to match SameBoy's logo slightly better 2022-07-25 19:56:44 +03:00
Lior Halphon e0436e33d4 Use gamma correct (and nearly gamma correct) color mixing 2022-07-25 19:55:31 +03:00
Lior Halphon 43e1e85179 Style 2022-07-25 19:11:41 +03:00
Lior Halphon ae14fcfbd7 Fix allow background controllers not working correctly on start up 2022-07-25 19:08:55 +03:00
Lior Halphon c5362023c8 Fix false positives when detecting unwritable save paths 2022-07-25 00:26:42 +03:00
Lior Halphon bcfe36897c Color correction improvements 2022-07-24 23:57:29 +03:00
Lior Halphon dd435ae5f0 Fixed potential race condition in the Cocoa memory viewer 2022-07-24 17:41:34 +03:00
Lior Halphon 53dd19ec35 Update version to 0.15.2 2022-07-24 14:54:31 +03:00
Lior Halphon 10df4d7a13 Missing static 2022-07-24 14:54:14 +03:00
Lior Halphon 45bd5342e7 GBP support in SDL 2022-07-24 14:51:22 +03:00
Lior Halphon 0c2772942e Oops 2022-07-24 14:49:58 +03:00
Lior Halphon dbd33684e8 Missed some switches 2022-07-24 14:34:32 +03:00
Lior Halphon 4db047c7d1 Make GBP selectable in Cocoa 2022-07-24 14:28:31 +03:00
Lior Halphon 6f9da353bd Add GBP model to the core (disables bouncing) 2022-07-24 14:22:49 +03:00
Lior Halphon 03f4f03661 Rename function 2022-07-24 13:56:33 +03:00
Lior Halphon 5cd65f845d Warn when progress can't be saved 2022-07-24 13:23:50 +03:00
Lior Halphon 4b03cc05c1 Optimization to joypad code 2022-07-24 13:16:19 +03:00
Lior Halphon 0f31c7a1ba Lag minimization bounce optimization 2022-07-24 02:35:46 +03:00
Lior Halphon a524cc3105 Emulate key bouncing 2022-07-23 23:49:11 +03:00
Lior Halphon 33ba353c3a Emulate the JOYP mode switching delay on the DMG 2022-07-23 19:29:23 +03:00
Lior Halphon 0e1d6545e9 Various improvements and fixes 2022-07-23 14:38:55 +03:00
Lior Halphon 04afa64597 Can't be NULL 2022-07-23 14:24:28 +03:00
Lior Halphon 8e125b31f6 macOS compatibility, stability 2022-07-23 14:21:31 +03:00
Lior Halphon 2a29570f17 Merge remote-tracking branch 'origin/master' into openal 2022-07-23 13:41:35 +03:00
Lior Halphon dd24801507 Merge pull request #476 from CasualPokePlayer/camera_improvements
Various GB Camera improvements
2022-07-23 13:24:50 +03:00
Lior Halphon 6a8743e13a Fix Cocoa being broken outside of a debug environment 2022-07-23 13:24:10 +03:00
Lior Halphon 93c611e9bc Values must be added to the end of a GB_SECTION for save state compatibility 2022-07-23 13:12:48 +03:00
CasualPokePlayer bb8f973fb4 Implement GB Camera timing (when no webcam is connected), misc camera accuracy improvements, use GB_random instead of rand for noise_seed 2022-07-22 20:15:00 -07:00
Lior Halphon f5f79f88ab Insert the pixel at the correct position 2022-07-23 01:52:33 +03:00
Lior Halphon f75f170448 Proper fix for WX=0 in the window pixel insertion glitch 2022-07-22 19:51:38 +03:00
Lior Halphon 029b7492b6 Fix WX=0 regression 2022-07-22 19:51:20 +03:00
Lior Halphon 537d0e1b25 Fix for WX=1-6 2022-07-22 18:55:48 +03:00
Lior Halphon ee407f07f3 Better describe softbreak 2022-07-22 13:51:56 +03:00
Lior Halphon 1fedb81ab7 Emulate window pixel insertion glitch, fixes Star Trek - 25th Anniversary, closes #278 2022-07-22 00:27:21 +03:00
Lior Halphon 3a86b868fe Add the same feature to Cocoa. Closes #474 2022-07-21 21:27:10 +03:00
Lior Halphon 349114097b Add joypad hotkeys to SDL 2022-07-19 23:55:34 +03:00
Lior Halphon 08549c1395 Typo 2022-07-19 02:19:31 +03:00
Lior Halphon 541dbc5db3 One last try 2022-07-19 01:52:38 +03:00
Maximilian Mader de10338962 Change _audio_get_queue_length() accoring to a856566b
This also reduces the internal audio buffer size down to 5 ms,
similar to the SDL backend at 96 kHz.
2022-07-18 22:24:00 +02:00
Lior Halphon 110deee6f8 Oops 2022-07-18 23:22:23 +03:00
Maximilian Mader 43210876be Use pkg-config to check if OpenAL is available
If `pkg-config` is available, the OpenAL driver will be compiled
unless OpenAL dev headers cannot be found or `ENABLE_OPENAL=0` is set.

If `pkg-config` is unavailable `ENABLE_OPENAL=1` can be set to force
the use of OpenAL. In this case users must make sure that they have
OpenAL dev headers installed to compile successfully.
2022-07-18 22:16:34 +02:00
Maximilian Mader 8760cc5517 Mark check_al_error() as static 2022-07-18 22:16:34 +02:00
Maximilian Mader 91a2b459f9 Initialize the SDL audio system in the driver 2022-07-18 22:16:32 +02:00
Maximilian Mader d48037beec Remove __FILE__ usage in the OpenAL driver 2022-07-18 22:15:35 +02:00
Maximilian Mader 8fa02e0ea2 Make sure that audio resumes playing after clearing the queue 2022-07-18 22:15:35 +02:00
Maximilian Mader 7a24073f6d Make sure that AL_BUFFERS_PROCESSED returns a valid value in _audio_deinit() 2022-07-18 22:15:35 +02:00
Maximilian Mader 64db300f24 Add an optional OpenAL audio driver for the SDL frontend
To compile the OpenAL driver specify `ENABLE_OPENAL=1` when
invoking `make`.
2022-07-18 22:15:35 +02:00
Lior Halphon 09cbf6a13f Fix GCC C++ warning? #464 2022-07-18 22:19:10 +03:00
Lior Halphon a856566b54 Fixed GB_audio_get_queue_length to actually be the length rather than size, fixed XAudio2.7 audio overflow crash, changed the maximum lag limit to 1/8s rather than 1/4s. Closes #473 2022-07-18 21:56:47 +03:00
Lior Halphon d31f34cab4 Allow the user-configured keys to be used in the SDL menu 2022-07-17 20:30:09 +03:00
Lior Halphon 96b5306ff3 Make the scrollbar draggable in SDL 2022-07-17 19:57:29 +03:00
Lior Halphon cbf1a5481f Allow the SDL port to use custom palettes imported from Cocoa 2022-07-17 15:48:41 +03:00
Lior Halphon 9a966a5581 SDL GUI follows the DMG palette 2022-07-17 01:19:43 +03:00
Lior Halphon 500e767247 And the same feature in Cocoa as well. Closes #472 2022-07-16 18:54:16 +03:00
Lior Halphon f9401300b5 SDL – Add setting to allow background joypad control 2022-07-16 18:23:08 +03:00
Lior Halphon 56deb4b92e Update version to 0.15.1 2022-07-08 20:10:11 +03:00
Lior Halphon eceb2e4830 Fix SDL/tester release builds on ARM64 Macs, strip and codesign Quick Look 2022-07-08 20:08:28 +03:00
Lior Halphon 0dbfaef4cf Query the system sample rate on Windows and use it, rather than hardcode 96KHz 2022-07-08 19:51:10 +03:00
Lior Halphon 88f5b22bf6 Allow setting a non-default audio driver, fixes #466 2022-07-08 17:51:42 +03:00
Lior Halphon d9b8e829a5 Fix crash on Windows 8.x 2022-07-08 14:17:28 +03:00
Lior Halphon 856a2b0ebe Makefile fixes, explicitly codesign the app bundle for releases 2022-07-04 00:13:05 +03:00
Lior Halphon 004c20d8e2 Handle GateKeeper and write permissions in the auto updater 2022-07-03 22:23:35 +03:00
Lior Halphon 3c4bfd2a1b Update version to 0.15 2022-07-02 22:41:17 +03:00
Lior Halphon faccdd3e9b Correct the Windows audio dialog rate, add a default file name 2022-07-02 22:41:07 +03:00
Lior Halphon e466c3c5b1 Ehh oops 2022-07-02 22:40:37 +03:00
Lior Halphon 7071032288 Improved MMM01 emulation, fixes #447 2022-07-02 21:03:26 +03:00
Lior Halphon 887a8104f5 Refresh icon if launched via a software update 2022-07-02 21:00:40 +03:00
Lior Halphon a773297b3a Add CGB revision selection to the SDL frontend 2022-07-02 18:11:55 +03:00
Lior Halphon 63a858d767 Fix GBS player's appearance on Big Sur and newer 2022-07-01 22:46:03 +03:00
Lior Halphon 1065a40d8f Add rX as symbol aliases to IO_X 2022-07-01 17:40:47 +03:00
Lior Halphon f2429e1c25 Fix IB oopsies 2022-07-01 16:24:54 +03:00
Lior Halphon 96d127e160 Remove the SLD command, reorder debugger commands 2022-07-01 16:14:52 +03:00
Lior Halphon 1b38e8c932 Prevent audio chuckling when an instance is debug-stopped 2022-06-25 20:09:23 +03:00
Lior Halphon 52a4c09855 More accurate PPU/OAM-DMA conflicts, artifacts in "It Came from Planet Zilog" should match hardware now 2022-06-25 20:08:59 +03:00
Lior Halphon 6a24598266 Grammar 2022-06-25 15:55:42 +03:00
Lior Halphon aaf9a76b67 The vblank callback now reports the vblank type 2022-06-25 01:59:51 +03:00
Lior Halphon 58df8144ec Fix audio artifacts in the SGB jingle 2022-06-25 01:44:50 +03:00
Lior Halphon 16913f925b Oops 2022-06-24 14:24:24 +03:00
Lior Halphon 9a765820cc Runtime audio driver fallback 2022-06-24 14:18:53 +03:00
Lior Halphon fd6b734fd0 Add XAudio2.7 as an compile-time audio driver for vanilla Windows 7 2022-06-24 14:18:30 +03:00
Lior Halphon 9ae2c9fd54 Replace SDL2 audio with XAudio2 on Windows 2022-06-23 01:13:59 +03:00
Lior Halphon 8f8b7f6b33 Minor adjustment to 32x32@2x 2022-06-18 23:10:48 +03:00
Lior Halphon ec4c1948f5 New macOS icon (again) 2022-06-18 22:36:08 +03:00
Lior Halphon 22f8ab6509 Last fix was wrong, this is correct 2022-06-17 18:17:29 +03:00
Lior Halphon 517f455486 Theorized HDMA behavior proven wrong 2022-06-17 15:58:37 +03:00
Lior Halphon 9b5dc9eca7 Refine TILE_SEL glitch, fixes #445 2022-06-12 21:43:04 +03:00
Lior Halphon b932f6699e Fix libretro build 2022-06-12 21:42:26 +03:00
Lior Halphon 20e9b1c655 Merge branch 'master' of https://github.com/LIJI32/SameBoy 2022-06-12 21:29:03 +03:00
Lior Halphon 3fbeb61c09 Fix MMM01 RAM size detection (Closes #446) 2022-06-12 21:28:58 +03:00
Lior Halphon ab4fa3a478 Merge pull request #457 from radimerry/libretro-core-options
[Libretro] Sync core options
2022-06-12 21:07:56 +03:00
Lior Halphon 4d90504688 HuC-1 mode is not a thing, fixes Robopon Japanese prototype 2022-06-11 20:57:02 +03:00
Lior Halphon d41c188cfd More accurate Camera MBC emulation 2022-06-11 14:44:06 +03:00
Lior Halphon 24796acccf MBC7 mouse control in SDL 2022-06-10 23:51:06 +03:00
Lior Halphon 979d32faed Group keyboard and joypad controls into a submenu 2022-06-10 14:55:13 +03:00
Lior Halphon 197a475fab SDL Joypad controls for MBC7 games 2022-06-10 14:37:28 +03:00
radimerry 426d3d3a37 [Libretro] Sync core options 2022-06-10 04:12:15 +00:00
Lior Halphon 4f91b19a94 Added MBC7 BESS support, documented BESS TPP1 2022-06-05 14:09:33 +03:00
Lior Halphon abf6e5632c Disable pkg-config on macOS 2022-05-23 22:16:06 +03:00
Lior Halphon eb60dbce0d There you go, kouhai. Closes #455 2022-05-23 22:13:59 +03:00
Lior Halphon 12891c641b Merge pull request #453 from remind-me-later/master
fix rlc_r zero flag
2022-05-21 22:15:32 +03:00
Lior Halphon 6bd7b96ed5 Include some default editable color themes 2022-05-21 21:27:02 +03:00
Lior Halphon 95f5eeb40b Add audio recording to SDL 2022-05-21 18:18:34 +03:00
Ricardo Maurizio Paul c79e67b8cc fix rlc_r zero flag 2022-05-21 14:45:16 +02:00
Lior Halphon cdfcc4ca2d Audio recording in the Cocoa frontend 2022-05-21 14:33:03 +03:00
Lior Halphon 6055092249 Add audio recording APIs 2022-05-21 02:06:10 +03:00
Lior Halphon 5cc845d715 Fix scrolling not updating in the VRAM viewer 2022-05-19 23:43:31 +03:00
Lior Halphon 706135113c Fix AGB APU regression 2022-05-19 20:59:48 +03:00
Lior Halphon 8c86cff486 Fix MBC5's initial state 2022-05-14 01:33:45 +03:00
Lior Halphon bb836662dd More accurate emulation of Hblank skip, emulation of Mode 2 skip 2022-05-14 01:14:41 +03:00
Lior Halphon 87fdf91e0c Better debugger output for scrolling adjustment 2022-05-13 00:58:21 +03:00
Lior Halphon f866284b49 Fix the 16x16 cartridge icon 2022-05-11 03:35:17 +03:00
Lior Halphon 4521bb4767 Fixed and accurate emulation of object at x=0 timings 2022-05-11 02:15:56 +03:00
Lior Halphon a68f749c3a Initial emulation of "SCX banging" to prolong mode 3 2022-05-09 17:15:54 +03:00
Lior Halphon cb73e0b91a Oops, I broke the window 2022-05-09 00:43:49 +03:00
Lior Halphon 6337e3e43a Remove unused 2022-05-07 20:24:28 +03:00
Lior Halphon ac29b4391e Refactor FIFOs 2022-05-07 19:27:25 +03:00
Lior Halphon 69a5ed3396 Fix several potential regressions 2022-05-04 19:30:29 +03:00
Lior Halphon 36e2896ec7 Fix a regression while emulating object size change during fetch 2022-05-04 00:23:55 +03:00
Lior Halphon bef1529bb2 Merge pull request #443 from OFFTKP/issue-442
Fix random segmentation fault (fixes #442 fixes #425)
2022-04-29 01:11:30 +03:00
Lior Halphon 851d44869f No reason for this to be a do...while 2022-04-29 01:11:11 +03:00
Lior Halphon 18126994ff Downgrade hardware.inc (rgbds is old in Ubuntu's repos, used by GitHub Actions), move definitions to hardware.inc's bottom 2022-04-18 20:03:51 +03:00
Lior Halphon 51cf4c638c Merge pull request #450 from remind-me-later/bootrom_reg_names
use friendly names for HW registers instead of magic numbers
2022-04-18 19:47:09 +03:00
Ricardo Maurizio Paul de21e8d628 use friendly names for HW registers instead of magic numbers 2022-04-18 18:09:16 +02:00
Lior Halphon bfdab8f246 Merge branch 'master' of https://github.com/LIJI32/SameBoy 2022-04-18 01:36:32 +03:00
Lior Halphon b2edcc9543 Improve serial accuracy 2022-04-17 23:41:05 +03:00
Lior Halphon 2a034d4ebe Merge pull request #444 from realnc/fix-audio-perf
Libretro: Batch upload audio to frontend after video upload
2022-04-15 00:57:12 +03:00
Lior Halphon 339de0db96 Merge pull request #449 from sredna/comdlg_optim
Improve Windows open dialog handling
2022-04-15 00:55:28 +03:00
Anders 9c271a637d Improve Windows open dialog handling
- Correctly handle OleUninitialize
- Don't leak LPITEMIDLIST if SHGetPathFromIDListW fails
- Use correct nMaxFile size
- Use string alloc helper function
- Hide read-only checkbox
2022-04-14 19:43:45 +02:00
Lior Halphon 019f262531 Fix RetroAchievements support (Closes #448) 2022-04-10 11:24:42 +03:00
Nikos Chantziaras 9e8f918b27 Libretro: Batch upload audio to frontend after video upload
Uploading audio at the end of retro_run() with
retro_audio_sample_batch_t instead of using retro_audio_sample_t to
submit samples as they are generated has peformance benefits when using
low audio latency settings. Frontends that implement audio sync and DRC
(like RetroArch) will block for a long time when submitting audio. This
can cause video frame presentation to be delayed too long. Low audio
latency settings make it worse, as DRC and audio sync is performed more
often, creating a bottleneck.

Simply accumulating all generated audio samples and uploading them at
the end with retro_audio_sample_batch_t improves things condiderably.
2022-04-02 08:51:39 +03:00
Lior Halphon b31bd58642 Consistent wording 2022-04-02 00:57:22 +03:00
offtkp dc16104cfd fixes #442 2022-03-25 02:19:46 +02:00
Lior Halphon 79945c8c18 XIB fixes for Mavericks 2022-03-19 01:25:08 +02:00
Lior Halphon 9c7bed97d5 I hope this actually works 2022-03-15 00:37:05 +02:00
Lior Halphon 86a1977034 Visual updates for Big Sur and newer 2022-03-13 01:14:29 +02:00
Lior Halphon 9fe965bcc2 Fix skipped square tick when writing to NR13/23, fixes Telefang start screen audio on CGB-D and E 2022-03-12 15:38:05 +02:00
Lior Halphon b5e271386a Add an optional argument to the APU command 2022-03-12 15:08:15 +02:00
Lior Halphon ef15c9b160 More square zombie step quirks 2022-03-12 14:32:16 +02:00
Lior Halphon d713ba85c7 Fix selected GBA model 2022-03-12 00:50:19 +02:00
Lior Halphon ab109da683 Fix several square channel zombie stepping quirks 2022-03-12 00:49:43 +02:00
Lior Halphon 5e119548e9 GDMA during mode 3 writes to both banks, list AGB_E as a future model 2022-03-09 00:32:50 +02:00
Lior Halphon 0925b06555 Add support for Mani carts 2022-03-06 15:54:29 +02:00
Lior Halphon 965e623637 Fix several BESS compatibility issues 2022-03-06 15:53:33 +02:00
Lior Halphon 7350843cca Fix incorrect INFO block on MMM01 BESS states 2022-03-05 23:05:00 +02:00
Lior Halphon c78a003712 MMM01 support 2022-03-05 21:20:42 +02:00
Lior Halphon a621803e82 More compact memory usage for symbol maps, removes the 0x200 bank limit 2022-02-28 23:30:31 +02:00
Lior Halphon 777013e998 Fix the 16x16 icon 2022-02-26 13:07:09 +02:00
Lior Halphon 2c635c7a87 Add Cartridge Instances – allow multiple saves without multiple ROM copies 2022-02-26 01:47:47 +02:00
Lior Halphon 641f26e13e Fix serial close behavior 2022-02-25 14:29:21 +02:00
Lior Halphon 8073e3d39e Visual refresh, update copyright year, crush PNGs 2022-02-24 00:38:27 +02:00
Lior Halphon 4d74719d56 One day I'll just report that bug to Clang 2022-02-23 20:40:10 +02:00
Lior Halphon f52152b2c9 Fix the Preserve Waveforms setting 2022-02-23 20:34:50 +02:00
Lior Halphon 586459bb74 Make it hex editing more reasonable while the core is running 2022-02-20 19:05:49 +02:00
Lior Halphon 7c8b9cf05a Less hacky, less buggy 2022-02-20 18:59:38 +02:00
Lior Halphon a48f251039 New and faster palette viewer 2022-02-20 14:23:49 +02:00
Lior Halphon 9a2e8e1acf Speed things even more by cachine 2022-02-20 03:18:29 +02:00
Lior Halphon f02bb2f0e6 New and faster OAM viewer 2022-02-20 01:59:42 +02:00
Lior Halphon 3c6a46830d Make GBImageView not slow 2022-02-19 22:13:07 +02:00
Lior Halphon 4c6bc91ded Add missing register 2022-02-14 22:59:05 +02:00
Lior Halphon a4209b47d0 Be consistent with hex casing 2022-02-13 16:58:44 +02:00
Lior Halphon efe31cefc9 More accurate DMA write conflicts 2022-02-13 12:56:16 +02:00
Lior Halphon c730ba767b Not sure where I've got that 0 from 2022-02-07 00:21:45 +02:00
Lior Halphon f8a105e8d0 Stop whining GCC 2022-02-06 14:42:53 +02:00
Lior Halphon 97c758ba75 More accurate internal bus behavior 2022-02-06 13:02:15 +02:00
Lior Halphon 4e27558ac2 Mode 2 OAM open bus behavior 2022-02-05 18:50:33 +02:00
Lior Halphon 850e7bb78c Fixed obscured object indication in the OAM viewer API 2022-02-05 17:44:10 +02:00
Lior Halphon b5eea012cc STAT reads 0 during mode 2 if DMA is active 2022-02-05 17:43:48 +02:00
Lior Halphon 6a8db89ae5 Emulate PPU OAM reads while both DMA and GDMA are active 2022-02-05 14:52:09 +02:00
Lior Halphon 1c6ecc2e14 GDMA/DMA Timing fix 2022-02-05 14:08:56 +02:00
Lior Halphon e7236deb11 Fixes to OAM viewer 2022-02-05 13:54:30 +02:00
Lior Halphon ba5416ee5b Correct comment 2022-02-04 19:07:47 +02:00
Lior Halphon 320aff1d1e DMA doesn't block GDMA 2022-02-04 13:58:44 +02:00
Lior Halphon 864f0927be Timing confirmed and improved 2022-02-04 13:55:06 +02:00
Lior Halphon 7c5704621a Don't batch during stop mode 2022-02-03 22:34:14 +02:00
Lior Halphon 37ca174f37 OAM DMA/GDMA conflicts 2022-02-03 21:00:37 +02:00
Anders cead58471d Don't determine if there is a real console with AllocConsole 2022-02-02 22:22:31 +01:00
Lior Halphon 76b881c2e1 More accurate HDMA during halt 2022-02-02 23:01:38 +02:00
Lior Halphon 967fdadd7c More accurate IR modeling, fixes Gen 2 Pokémon mystery gifts 2022-02-01 23:23:24 +02:00
Lior Halphon 1a41957b3c LCDOff behavior, basic halt/stop behavior 2022-01-31 01:02:31 +02:00
Lior Halphon ad1f019893 Actually fix overflow behavior 2022-01-30 23:11:29 +02:00
Lior Halphon 941afee3ba Fix overflow behavior 2022-01-30 21:33:33 +02:00
Lior Halphon dbb14d7040 Minor edge case for HDMA instant start 2022-01-30 20:52:34 +02:00
Lior Halphon 44ee6dc73f HDMA timing 2022-01-30 20:09:58 +02:00
Lior Halphon a7f7530eed Preparation for future AGB-0 and B support 2022-01-30 18:11:35 +02:00
Lior Halphon 4bebd2bc33 Correct comment 2022-01-30 17:33:33 +02:00
Lior Halphon 3a2d028efa GDMA/PPU conflicts 2022-01-30 14:38:58 +02:00
Lior Halphon 9e3ad31df1 Fix HDMA usage in SameBoot 2022-01-29 02:12:27 +02:00
Lior Halphon 26656de44f Improvements to GDMA 2022-01-28 23:56:26 +02:00
Lior Halphon 81e2ec08e0 Oops 2022-01-23 22:07:15 +02:00
Lior Halphon aa5a279116 Halt during DMA with objects 2022-01-23 21:05:29 +02:00
Lior Halphon 0ab7bf7749 VRAM conflicts during halt/stop on a CGB 2022-01-22 22:52:34 +02:00
Lior Halphon 196aaaa7ed Conflicts don't happen in the first 6 T-cycles 2022-01-22 16:56:32 +02:00
Lior Halphon 8676a7c7bc Typo 2022-01-22 16:36:22 +02:00
Lior Halphon f810a2cd60 Merge branch 'master' of https://github.com/LIJI32/SameBoy 2022-01-22 01:11:53 +02:00
Lior Halphon 582a5588ba Undo is stopped only 2022-01-22 01:11:50 +02:00
Lior Halphon 56b14c67aa Fixed AGB audio regression 2022-01-22 01:11:23 +02:00
Lior Halphon 95153af1d6 Merge pull request #431 from max-m/sdl-fix-palette-load
[SDL] Fix loading of the configured DMG palette
2022-01-20 20:43:40 +02:00
Maximilian Mader 13e0b90b47 [SDL] Fix loading of the configured DMG palette
There are four options for the DMG color palette:
- Greyscale
- Lime (Game Boy)
- Olive (Pocket)
- Teal (Light)

When loading the configuration from the `prefs.bin`
the configured `dmg_palette` gets normalized by applying
`mod 3` to it, limiting the possible values to [ 0, 1, 2 ],
thus selecting the “Teal” color palette will be saved as such,
but the next time the config gets loaded it gets reset to Greyscale.
2022-01-20 19:15:08 +01:00
Lior Halphon ee03b1e433 Initial halt/stop during DMA support 2022-01-19 01:24:40 +02:00
Lior Halphon cce36f1754 DMA debugger command 2022-01-18 23:42:22 +02:00
Lior Halphon e903333c7e Add TODO 2022-01-17 22:56:13 +02:00
Lior Halphon ab75858c86 DMA/PPU VRAM conflicts on the CGB/AGB 2022-01-17 22:07:24 +02:00
Lior Halphon b45761146f VRAM DMA during mode 3 2022-01-16 13:50:59 +02:00
Lior Halphon 3133687e68 Potential logic bug fixes 2022-01-16 00:50:08 +02:00
Lior Halphon dbe9035c55 Merge branch 'master' of https://github.com/LIJI32/SameBoy 2022-01-16 00:16:12 +02:00
Lior Halphon 5088bd0959 Redundant OR 2022-01-16 00:16:06 +02:00
Lior Halphon e922b3fc4a Merge pull request #430 from orbea/pedantic
sgb.h: Silence -Wgnu-anonymous-struct and -Wnested-anon-type warnings
2022-01-15 01:29:49 +02:00
orbea 7c9ab0fd46 sgb.h: Use GB_INTERNAL to hide internal struct data
Silences warnings in downstream projects that use a different language standard
when including gb.h.

sgb.h:14:9: warning: anonymous structs are a GNU extension [-Wgnu-anonymous-struct]
        struct {
        ^
sgb.h:14:9: warning: anonymous types declared in an anonymous union are an extension [-Wnested-anon-types]
        struct {
        ^
2022-01-14 15:26:15 -08:00
Lior Halphon eaeeb49612 Minor stylistic changes 2022-01-14 22:26:23 +02:00
Lior Halphon b92dd51101 Merge pull request #429 from orbea/pedantic
Silence more -pedantic warnings
2022-01-14 22:23:30 +02:00
orbea adfc329cdf gb.h: Silence -Wembedded-directive warning with -pedantic
gb.h:731:2: warning: embedding a directive within macro arguments has undefined behavior [-Wembedded-directive]
\#define GB_REWIND_FRAMES_PER_KEY 255
 ^
2022-01-14 11:40:55 -08:00
orbea 5cf71b406e gb.h: Silence -Wembedded-directive warnings with -pedantic
gb.h:400:2: warning: embedding a directive within macro arguments has undefined behavior [-Wembedded-directive]
\#ifdef GB_BIG_ENDIAN
 ^
gb.h:410:2: warning: embedding a directive within macro arguments has undefined behavior [-Wembedded-directive]
\#endif
 ^
2022-01-14 11:40:55 -08:00
Lior Halphon d92148b461 Merge branch 'master' of https://github.com/LIJI32/SameBoy 2022-01-14 17:09:49 +02:00
Lior Halphon ffa53eda20 DMA during mode 3 emulation 2022-01-14 17:09:39 +02:00
Lior Halphon 4ce8e77796 More accurate OAM access timings 2022-01-14 15:07:50 +02:00
Lior Halphon 20cbc896a1 Merge pull request #428 from orbea/pedantic
gb.h: Silence -pedantic warnings
2022-01-14 13:39:48 +02:00
orbea fefb81ab65 gb.h: Silence -pedantic warnings
Silences warnings such as the following when including gb.h as a dependency.

gb.h:385:6: warning: extra ';' inside a struct [-Wextra-semi]
    );
     ^
2022-01-13 20:12:58 -08:00
Lior Halphon ec012cf9f8 is_dma_restarting hack no longer needed 2022-01-12 14:12:55 +02:00
Lior Halphon c4a14ac4db Simplify DMA code, fix DMA read timing 2022-01-12 00:26:18 +02:00
Lior Halphon b1187919d3 Fixed a bug with the joy_accessed API 2022-01-09 16:43:32 +02:00
Lior Halphon 2c71ca789f Fixed a regression caused by a recent optimization 2022-01-09 15:36:01 +02:00
Lior Halphon 8df572f92e Comment fix 2022-01-09 15:30:33 +02:00
Lior Halphon b7f03dea8d Add CGB-A support 2022-01-05 21:55:46 +02:00
Lior Halphon ab1d4cd26e More DMA write conflicts 2022-01-05 21:40:10 +02:00
Lior Halphon 5e7bb0f891 DMA write conflict revision differences 2022-01-04 19:59:46 +02:00
Lior Halphon 79ec22b28e Clang hates this 2022-01-03 17:55:00 +02:00
Lior Halphon 5c17c0ec3b unreachable fun 2022-01-03 17:17:35 +02:00
Lior Halphon cd16431699 OMA DMA improvements (WIP) 2022-01-03 16:51:45 +02:00
Lior Halphon 81e45b00b9 Minor Cocoa bug fixes 2022-01-03 16:51:24 +02:00
Lior Halphon c7298ae5a6 Fix a silly underflow 2022-01-03 16:51:05 +02:00
Lior Halphon 8e675295a8 Enable LTO in Windows builds, fix missing MGB boot in SDL 2021-12-31 00:40:34 +02:00
Lior Halphon bc073e3d09 Expose PC 2021-12-30 23:53:24 +02:00
Lior Halphon 52c5610528 Cocoa audio driver goes brrrr 2021-12-29 17:21:06 +02:00
Lior Halphon 38eafeb0cf Never deadlock ever again thanks 2021-12-29 17:03:44 +02:00
Lior Halphon 97652b7460 Cocoa audio bugfix 2021-12-29 16:53:28 +02:00
Lior Halphon 59c315a5dd Minor free optimization 2021-12-29 16:33:04 +02:00
Lior Halphon b72c2ea225 DMG palette getter 2021-12-29 13:08:46 +02:00
Lior Halphon 769aac93c0 Lazy APU, extra ~17% speed up 2021-12-29 00:48:44 +02:00
Lior Halphon db50462710 More accurate fix 2021-12-26 23:24:08 +02:00
Lior Halphon 59dfb1a85a It's not verified because it's wrong 2021-12-26 21:57:40 +02:00
Lior Halphon 6ffe924637 This is probably better but still wrong 2021-12-26 21:43:54 +02:00
Lior Halphon d178ece909 Disabled an incorrectly emulated portion of the TILE_SET glitch 2021-12-26 19:57:18 +02:00
Lior Halphon 6e7ba7589c Fixed blurred unfiltered screenshots 2021-12-26 18:38:08 +02:00
Lior Halphon 66f7babe86 Cache the clock rate 2021-12-26 15:50:24 +02:00
Lior Halphon c53d99dbc4 Abolished slow double use 2021-12-26 15:20:46 +02:00
Lior Halphon c5f6be1e64 Several likely/unlikely optimization, saving on a memset 2021-12-26 02:38:54 +02:00
Lior Halphon 69de3f0fae Implement a PPU fast path, up to 34% performance boost 2021-12-26 01:47:59 +02:00
Lior Halphon f3277ab8d3 Sorry C++ users 2021-12-20 18:59:51 +02:00
Lior Halphon e9906e44cd Sure, why not 2021-12-19 21:46:22 +02:00
Lior Halphon f866441481 Improved emulation of channel 3 wave RAM read glitch 2021-12-19 19:27:40 +02:00
Lior Halphon e9629407a5 Fix potential alignment issues 2021-12-19 00:54:29 +02:00
Lior Halphon cdc3321c36 Add an API to allow illegal inputs 2021-12-19 00:28:24 +02:00
Lior Halphon eaccd792ed Fixes to safe reads, closes #422 2021-12-18 14:56:33 +02:00
Lior Halphon 5127cb0022 Direct access to registers (#422) 2021-12-18 14:51:14 +02:00
Lior Halphon c63ddbe771 Lag frame detection API (#422) 2021-12-18 01:25:06 +02:00
Lior Halphon c3d9141b7c Replace the term sprite with object for consistency 2021-12-17 21:16:23 +02:00
Lior Halphon c1ae129ed4 Allow hiding background/object "layers" (#422) 2021-12-17 21:12:26 +02:00
Lior Halphon f78fac12c2 Fixed several issues involving LY change timing, as well as an LYC issue in models prior to CGB-D 2021-12-14 20:27:38 +02:00
Lior Halphon 7e5e672988 RTC speed multiplier, for TAS syncing (#422) 2021-12-11 02:51:21 +02:00
Lior Halphon a30247cf16 LCD line callback (for #422) 2021-12-10 19:49:52 +02:00
Lior Halphon 7508ddb0cf Execute callback (for #422) 2021-12-10 19:42:47 +02:00
Lior Halphon e087bd5218 The GBS visualizer should use custom color palettes 2021-12-10 02:06:12 +02:00
Lior Halphon 9e57201b08 Accurate IF clear timing 2021-12-05 16:18:54 +02:00
Lior Halphon 25e3414974 Redesigned vblank callback scheduling scheme, should be more regular and less prune to various sorts of frontend DOS 2021-12-04 15:04:46 +02:00
Lior Halphon 4b3c77bfa5 oops 2021-12-02 11:54:26 +02:00
Lior Halphon 8660e20eeb New inputs API 2021-12-02 11:23:44 +02:00
Lior Halphon b770bbea2e Fix save state issue that caused vblank callbacks timings to differ 2021-12-02 11:21:12 +02:00
Lior Halphon 486f8a2c10 Merge pull request #420 from SnowyMouse/cgb_mode
Add GB_is_cgb_in_cgb_mode
2021-11-26 14:10:35 +02:00
Lior Halphon 06b744259b Add memory write callback, optimize memory access with likely/unlikely 2021-11-26 14:09:41 +02:00
Lior Halphon bdbe02b043 Add a safe memory read API 2021-11-26 13:54:28 +02:00
Lior Halphon 33090a5cc0 Fix an oops from the last commit 2021-11-26 13:38:52 +02:00
Snowy d0a9d2f72a Add GB_is_cgb_in_cgb_mode 2021-11-25 17:16:11 -06:00
Lior Halphon f1e5e04198 ...even when timekeeping is disabled 2021-11-25 21:46:51 +02:00
Lior Halphon d0d39015ee Let update_input_hint_callback get called during turbo 2021-11-25 21:17:49 +02:00
Lior Halphon f08f16346e Fix #293 2021-11-24 23:13:52 +02:00
Lior Halphon d94c8b9125 Switch Pro Controller motion controls 2021-11-22 23:29:10 +02:00
Lior Halphon d15eaf4134 Mouse controls for MBC7 2021-11-14 21:43:31 +02:00
Lior Halphon ae930472f0 Units info 2021-11-14 13:18:58 +02:00
Lior Halphon 7a78649e21 Implement motion controls in JoyKit, implement accel/gyro in DualSense and DualShock 4, implement motion controls in Cocoa 2021-11-13 19:23:45 +02:00
Lior Halphon 06ce30d3a8 Map joysticks to motion controls 2021-11-12 18:10:03 +02:00
Lior Halphon c6f39bc60b Initial MBC7 support 2021-11-12 17:44:51 +02:00
Lior Halphon 02f55d12d3 Maybe one day GCC will stop being shit at handling __attribute__s 2021-11-07 14:13:52 +02:00
Lior Halphon 1650820edb Clean up endian-related code 2021-11-07 13:57:43 +02:00
Lior Halphon 18e7a3f4fa Cleanup, better symbol handling, improves LTO 2021-11-07 13:39:18 +02:00
Lior Halphon fbf1bb7f98 Save state compatibility breaking cleanup 2021-11-07 12:56:46 +02:00
Lior Halphon 5565c2540b Register name and info update 2021-11-06 13:34:34 +02:00
Lior Halphon 4a7afb246d Fix some oopsies 2021-11-05 21:45:54 +02:00
Lior Halphon 178860e715 Custom palette and editor 2021-11-05 19:07:27 +02:00
Lior Halphon f237b1e9b9 CGB-0 support 2021-11-04 00:35:44 +02:00
Lior Halphon 6cd13be624 Add CGB-B support 2021-10-30 20:58:57 +03:00
Lior Halphon b54365fc40 Merge branch 'v0.14.x' 2021-10-30 18:40:27 +03:00
Lior Halphon 72b6d6c532 Merge branch 'master' of https://github.com/LIJI32/SameBoy 2021-10-30 18:31:47 +03:00
Lior Halphon fd8c9bba5d Detect missing ANSI support on Windows 2021-10-30 16:03:33 +03:00
Lior Halphon 1f7b20251b Improved sanitation for save states for better security and stability 2021-10-30 16:03:13 +03:00
Lior Halphon 93ef8d7db8 Merge pull request #411 from SnowyMouse/sprite_h
Fix partially offscreen sprites not being returned in GB_get_oam_info
2021-10-27 01:44:26 +03:00
Lior Halphon 739a9eb2bf Use a monospaced font in the palette viewer 2021-10-27 01:43:36 +03:00
Lior Halphon e6c4ceaf5a Add CGB-D support 2021-10-27 01:40:28 +03:00
Snowy 2ec573c84a Change y to a signed value 2021-10-24 11:15:28 -05:00
Lior Halphon 5b9746084d Writes to SVBK should work before the boot ROM is disabled 2021-10-23 23:51:48 +03:00
Lior Halphon 18007f0e53 MGB support 2021-10-23 23:28:54 +03:00
593 changed files with 37291 additions and 9533 deletions

No files matched your search

-23
View File
@@ -1,23 +0,0 @@
freebsd-x86_64-binaries_task:
freebsd_instance:
image_family: freebsd-12-2
setup_script:
- pkg install --yes gmake gdb gcc8 pkgconf sdl2 openal-soft gtk3 gtksourceview3 libXv zip
compile_script:
- gmake -C bsnes local=false
package_script:
- mkdir bsnes-nightly
- mkdir bsnes-nightly/Database
- mkdir bsnes-nightly/Firmware
- cp -a bsnes/out/bsnes bsnes-nightly/bsnes
- cp -a bsnes/Database/* bsnes-nightly/Database
- cp -a shaders bsnes-nightly/Shaders
- cp -a GPLv3.txt bsnes-nightly
- cp -a extras/* bsnes-nightly
- zip -r bsnes-nightly.zip bsnes-nightly
bsnes-nightly_artifacts:
path: "bsnes-nightly.zip"
+20 -1
View File
@@ -34,6 +34,24 @@ jobs:
name: bsnes-${{ matrix.os.name }}
path: bsnes/out/bsnes*
build-freebsd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: vmactions/freebsd-vm@v1
with:
release: "14.3"
usesh: true
prepare: |
pkg install --yes gmake gdb gcc14 pkgconf sdl2 openal-soft gtk3 gtksourceview3 libXv zip
run: |
gmake -j4 -C bsnes local=false
- name: Upload
uses: actions/upload-artifact@v4
with:
name: bsnes-freebsd
path: bsnes/out/bsnes*
release:
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
# Prevent multiple conflicting release jobs from running at once.
@@ -41,6 +59,7 @@ jobs:
runs-on: ubuntu-latest
needs:
- build
- build-freebsd
steps:
- uses: actions/checkout@v4
with:
@@ -68,7 +87,7 @@ jobs:
chmod +x ${bindir}/${program}-macos/${program}.app/Contents/MacOS/${program}
done
for os in ubuntu windows macos
for os in ubuntu windows macos freebsd
do
mkdir "${os}"
cd "${os}"
+1 -1
View File
@@ -233,7 +233,7 @@ else ifeq ($(platform), wiiu)
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
ENDIANNESS_DEFINES += -DGEKKO -DWIIU -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float -DMSB_FIRST
ENDIANNESS_DEFINES += -DGEKKO -DWIIU -DHW_RVL -D__wiiu__ -mcpu=750 -meabi -mhard-float -DMSB_FIRST
FLAGS += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int
EXTRA_INCLUDES := -I$(DEVKITPRO)/libogc/include
+1 -1
View File
@@ -34,7 +34,7 @@ namespace Emulator {
static const string Version = "115";
static const string Copyright = "bsnes team";
static const string License = "GPLv3 or later";
static const string Website = "https://bsnes.dev";
static const string Website = "https://github.com/bsnes-emu/bsnes/";
//incremented only when serialization format changes
static const string SerializerVersion = "115.1";
+1
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
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: LIJI32
+16 -3
View File
@@ -1,10 +1,10 @@
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.4.0.zip > rgbds.zip
curl -L https://github.com/rednex/rgbds/archive/v0.6.0.zip > rgbds.zip
unzip rgbds.zip
cd rgbds-*
make -sj
@@ -12,9 +12,22 @@ case `echo $1 | cut -d '-' -f 1` in
cd ..
rm -rf *
)
(
cd `mktemp -d`
curl -L https://github.com/BR903/cppp/archive/refs/heads/master.zip > cppp.zip
unzip cppp.zip
cd cppp-*
make -sj
sudo make install
cd ..
rm -rf *
)
;;
macos)
brew install rgbds sdl2
brew install rgbds sdl2 cppp
;;
*)
echo "Unsupported OS"
+5 -3
View File
@@ -1,3 +1,5 @@
#!/bin/sh
set -e
./build/bin/tester/sameboy_tester --jobs 5 \
@@ -7,7 +9,7 @@ set -e
--dmg --length 45 .github/actions/dmg_sound-2.gb \
--dmg --length 20 .github/actions/oam_bug-2.gb
mv .github/actions/dmg{,-mode}-acid2.bmp
mv .github/actions/dmg-acid2.bmp .github/actions/dmg-mode-acid2.bmp
./build/bin/tester/sameboy_tester \
--dmg --length 10 .github/actions/dmg-acid2.gb
@@ -16,10 +18,10 @@ set +e
FAILED_TESTS=`
shasum .github/actions/*.bmp | grep -E -v \(\
5283564df0cf5bb78a7a90aff026c1a4692fd39e\ \ .github/actions/cgb-acid2.bmp\|\
64c3fd9a5fe9aee40fe15f3371029c0d2f20f5bc\ \ .github/actions/cgb-acid2.bmp\|\
dbcc438dcea13b5d1b80c5cd06bda2592cc5d9e0\ \ .github/actions/cgb_sound.bmp\|\
0caadf9634e40247ae9c15ff71992e8f77bbf89e\ \ .github/actions/dmg-acid2.bmp\|\
a732077f98f43d9231453b1764d9f797a836924d\ \ .github/actions/dmg-mode-acid2.bmp\|\
fbdb5e342bfdd2edda3ea5601d35d0ca60d18034\ \ .github/actions/dmg-mode-acid2.bmp\|\
c9e944b7e01078bdeba1819bc2fa9372b111f52d\ \ .github/actions/dmg_sound-2.bmp\|\
f0172cc91867d3343fbd113a2bb98100074be0de\ \ .github/actions/oam_bug-2.bmp\
\)`
+30
View File
@@ -0,0 +1,30 @@
set -ex
git fetch --tags
LATEST=$(git tag --sort=-creatordate | grep "^v" | grep -v libretro | head -n 1)
if [ $(git tag -l "$LATEST"-libretro) ]; then
echo "The libretro branch is already up-to-date"
exit 0
fi
git config --global --add --bool push.autoSetupRemote true
git config --global user.name 'Libretro Updater'
git config --global user.email '<>'
cp libretro/gitlab-ci.yml .gitlab-ci.yml
echo "Switching to tag $LATEST"
git branch --delete libretro || true
git checkout tags/$LATEST -b libretro
echo "Building boot ROMs..."
make -j bootroms
echo "Updating branch"
mv build/bin/BootROMs BootROMs/prebuilt
git add BootROMs/prebuilt/* .gitlab-ci.yml
git commit -m "Update libretro branch to $LATEST"
git tag "$LATEST"-libretro
git push --force
git push --tags
+28
View File
@@ -0,0 +1,28 @@
name: "libretro branch update"
on:
push:
branches:
- master
jobs:
libretro-prebuilt-update:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
name: Checkout
with:
repository: LIJI32/SameBoy
token: ${{ secrets.WEBSITETOKEN }}
submodules: false
- name: Install Deps
shell: bash
run: |
./.github/actions/install_deps.sh ${{ matrix.os }}
- name: Build Boot ROMs and Push
run: |
./.github/actions/update_libretro.sh
+15 -7
View File
@@ -1,36 +1,44 @@
name: "Bulidability and Sanity"
on: push
on:
push:
branches:
- master
- '*'
- '!libretro'
jobs:
sanity:
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, ubuntu-18.04]
os: [macos-latest, ubuntu-latest, ubuntu-22.04]
cc: [gcc, clang]
include:
- os: macos-latest
cc: clang
extra_target: cocoa
extra_targets: cocoa ios-ipa ios-deb
exclude:
- os: macos-latest
cc: gcc
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install deps
shell: bash
run: |
./.github/actions/install_deps.sh ${{ matrix.os }}
- name: Build
run: |
${{ matrix.cc }} -v; (make -j sdl tester libretro ${{ matrix.extra_target }} CONF=release CC=${{ matrix.cc }} || (echo "==== Build Failed ==="; make sdl tester libretro ${{ matrix.extra_target }} CONF=release CC=${{ matrix.cc }}))
${{ matrix.cc }} -v; (make -j all CONF=release CC=${{ matrix.cc }} || (echo "==== Build Failed ==="; make all CONF=release CC=${{ matrix.cc }}))
- name: Sanity tests
shell: bash
run: |
./.github/actions/sanity_tests.sh
- name: Upload binaries
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v4
with:
name: sameboy-canary-${{ matrix.os }}-${{ matrix.cc }}
path: build/bin
path: |
build/bin
build/lib
build/include
@@ -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
@@ -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])) {
@@ -35,30 +35,43 @@ static OSStatus render(
// kAudioUnitSubType_DefaultOutput on Mac OS X)
AudioComponentDescription defaultOutputDescription;
defaultOutputDescription.componentType = kAudioUnitType_Output;
#if TARGET_OS_IPHONE
defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO;
#else
defaultOutputDescription.componentSubType = kAudioUnitSubType_DefaultOutput;
#endif
defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
defaultOutputDescription.componentFlags = 0;
defaultOutputDescription.componentFlagsMask = 0;
// Get the default playback output unit
AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription);
NSAssert(defaultOutput, @"Can't find default output");
if (!defaultOutput) {
NSLog(@"Can't find default output");
return nil;
}
// Create a new unit based on this that we'll use for output
OSErr err = AudioComponentInstanceNew(defaultOutput, &audioUnit);
NSAssert1(audioUnit, @"Error creating unit: %hd", err);
if (!audioUnit) {
NSLog(@"Error creating unit: %hd", err);
return nil;
}
// Set our tone rendering function on the unit
AURenderCallbackStruct input;
input.inputProc = (void*)render;
input.inputProcRefCon = (__bridge void * _Nullable)(self);
input.inputProcRefCon = (__bridge void *)(self);
err = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&input,
sizeof(input));
NSAssert1(err == noErr, @"Error setting callback: %hd", err);
if (err) {
NSLog(@"Error setting callback: %hd", err);
return nil;
}
AudioStreamBasicDescription streamFormat;
streamFormat.mSampleRate = rate;
@@ -76,9 +89,16 @@ static OSStatus render(
0,
&streamFormat,
sizeof(AudioStreamBasicDescription));
NSAssert1(err == noErr, @"Error setting stream format: %hd", err);
if (err) {
NSLog(@"Error setting stream format: %hd", err);
return nil;
}
err = AudioUnitInitialize(audioUnit);
NSAssert1(err == noErr, @"Error initializing unit: %hd", err);
if (err) {
NSLog(@"Error initializing unit: %hd", err);
return nil;
}
self.renderBlock = block;
_rate = rate;
@@ -89,7 +109,10 @@ static OSStatus render(
-(void) start
{
OSErr err = AudioOutputUnitStart(audioUnit);
NSAssert1(err == noErr, @"Error starting unit: %hd", err);
if (err) {
NSLog(@"Error starting unit: %hd", err);
return;
}
_playing = true;
}
+36
View File
@@ -0,0 +1,36 @@
#import <TargetConditionals.h>
#if TARGET_OS_IPHONE
#define NSView UIView
#import <UIKit/UIKit.h>
#else
#import <Cocoa/Cocoa.h>
#endif
#import <Core/gb.h>
typedef enum {
GB_FRAME_BLENDING_MODE_DISABLED,
GB_FRAME_BLENDING_MODE_SIMPLE,
GB_FRAME_BLENDING_MODE_ACCURATE,
GB_FRAME_BLENDING_MODE_ACCURATE_EVEN = GB_FRAME_BLENDING_MODE_ACCURATE,
GB_FRAME_BLENDING_MODE_ACCURATE_ODD,
} GB_frame_blending_mode_t;
@interface GBViewBase : NSView
{
@public
GB_gameboy_t *_gb;
}
@property (nonatomic) GB_gameboy_t *gb;
@property (nonatomic) GB_frame_blending_mode_t frameBlendingMode;
@property (nonatomic, strong) NSView *internalView;
- (void) flip;
- (uint32_t *) pixels;
- (void)screenSizeChanged;
- (void) createInternalView;
- (uint32_t *)currentBuffer;
- (uint32_t *)previousBuffer;
- (instancetype)mirroredView;
@end
+121
View File
@@ -0,0 +1,121 @@
#import "GBViewBase.h"
@implementation GBViewBase
{
uint32_t *_imageBuffers[3];
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]);
size_t buffer_size = sizeof(_imageBuffers[0][0]) * GB_get_screen_width(_gb) * GB_get_screen_height(_gb);
_imageBuffers[0] = calloc(1, buffer_size);
_imageBuffers[1] = calloc(1, buffer_size);
_imageBuffers[2] = calloc(1, buffer_size);
}
- (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;
}
- (void) createInternalView
{
assert(false && "createInternalView must not be inherited");
}
- (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];
}
- (void) setFrameBlendingMode:(GB_frame_blending_mode_t)frameBlendingMode
{
_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;
}
return _oddFrame ? GB_FRAME_BLENDING_MODE_ACCURATE_ODD : GB_FRAME_BLENDING_MODE_ACCURATE_EVEN;
}
return _frameBlendingMode;
}
- (void)dealloc
{
if (_parent) return;
free(_imageBuffers[0]);
free(_imageBuffers[1]);
free(_imageBuffers[2]);
}
#if !TARGET_OS_IPHONE
- (void)setNeedsDisplay
{
[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
+11
View File
@@ -0,0 +1,11 @@
#import <TargetConditionals.h>
#import <MetalKit/MetalKit.h>
#if TARGET_OS_IPHONE
#import "../iOS/GBView.h"
#else
#import "../Cocoa/GBView.h"
#endif
@interface GBViewMetal : GBView<MTKViewDelegate>
+ (bool) isSupported;
@end
@@ -1,7 +1,9 @@
#import <CoreImage/CoreImage.h>
#import "GBViewMetal.h"
#pragma clang diagnostic ignored "-Wpartial-availability"
#if !TARGET_OS_IPHONE
#import "../Cocoa/NSObject+DefaultsObserver.h"
#endif
static const vector_float2 rect[] =
{
@@ -13,27 +15,33 @@ static const vector_float2 rect[] =
@implementation GBViewMetal
{
id<MTLDevice> device;
id<MTLTexture> texture, previous_texture;
id<MTLBuffer> vertices;
id<MTLRenderPipelineState> pipeline_state;
id<MTLCommandQueue> command_queue;
id<MTLBuffer> frame_blending_mode_buffer;
id<MTLBuffer> output_resolution_buffer;
vector_float2 output_resolution;
id<MTLDevice> _device;
id<MTLTexture> _texture, _previousTexture;
id<MTLBuffer> _vertices;
id<MTLRenderPipelineState> _pipelineState;
id<MTLCommandQueue> _commandQueue;
id<MTLBuffer> _frameBlendingModeBuffer;
id<MTLBuffer> _outputResolutionBuffer;
vector_float2 _outputResolution;
id<MTLCommandBuffer> _commandBuffer;
bool _waitedForFrame;
_Atomic unsigned _pendingFrames;
}
+ (bool)isSupported
{
#if TARGET_OS_IPHONE
return true;
#else
if (MTLCopyAllDevices) {
return [MTLCopyAllDevices() count];
}
return false;
#endif
}
- (void) allocateTextures
{
if (!device) return;
if (!_device) return;
MTLTextureDescriptor *texture_descriptor = [[MTLTextureDescriptor alloc] init];
@@ -42,39 +50,44 @@ static const vector_float2 rect[] =
texture_descriptor.width = GB_get_screen_width(self.gb);
texture_descriptor.height = GB_get_screen_height(self.gb);
texture = [device newTextureWithDescriptor:texture_descriptor];
previous_texture = [device newTextureWithDescriptor:texture_descriptor];
_texture = [_device newTextureWithDescriptor:texture_descriptor];
_previousTexture = [_device newTextureWithDescriptor:texture_descriptor];
}
- (void)createInternalView
{
MTKView *view = [[MTKView alloc] initWithFrame:self.frame device:(device = MTLCreateSystemDefaultDevice())];
MTKView *view = [[MTKView alloc] initWithFrame:self.frame device:(_device = MTLCreateSystemDefaultDevice())];
view.delegate = self;
self.internalView = view;
view.paused = true;
view.enableSetNeedsDisplay = true;
view.framebufferOnly = false;
vertices = [device newBufferWithBytes:rect
_vertices = [_device newBufferWithBytes:rect
length:sizeof(rect)
options:MTLResourceStorageModeShared];
static const GB_frame_blending_mode_t default_blending_mode = GB_FRAME_BLENDING_MODE_DISABLED;
frame_blending_mode_buffer = [device newBufferWithBytes:&default_blending_mode
_frameBlendingModeBuffer = [_device newBufferWithBytes:&default_blending_mode
length:sizeof(default_blending_mode)
options:MTLResourceStorageModeShared];
output_resolution_buffer = [device newBufferWithBytes:&output_resolution
length:sizeof(output_resolution)
_outputResolutionBuffer = [_device newBufferWithBytes:&_outputResolution
length:sizeof(_outputResolution)
options:MTLResourceStorageModeShared];
output_resolution = (simd_float2){view.drawableSize.width, view.drawableSize.height};
_outputResolution = (simd_float2){view.drawableSize.width, view.drawableSize.height};
/* TODO: NSObject+DefaultsObserver can replace the less flexible `addDefaultObserver` in iOS */
#if TARGET_OS_IPHONE
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadShader) name:@"GBFilterChanged" object:nil];
[self loadShader];
#else
[self observeStandardDefaultsKey:@"GBFilter" selector:@selector(loadShader)];
#endif
}
- (void) loadShader
- (void)loadShader
{
NSError *error = nil;
NSString *shader_source = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MasterShader"
@@ -95,7 +108,7 @@ static const vector_float2 rect[] =
MTLCompileOptions *options = [[MTLCompileOptions alloc] init];
options.fastMathEnabled = true;
id<MTLLibrary> library = [device newLibraryWithSource:shader_source
id<MTLLibrary> library = [_device newLibraryWithSource:shader_source
options:options
error:&error];
if (error) {
@@ -115,19 +128,19 @@ static const vector_float2 rect[] =
pipeline_state_descriptor.colorAttachments[0].pixelFormat = ((MTKView *)self.internalView).colorPixelFormat;
error = nil;
pipeline_state = [device newRenderPipelineStateWithDescriptor:pipeline_state_descriptor
_pipelineState = [_device newRenderPipelineStateWithDescriptor:pipeline_state_descriptor
error:&error];
if (error) {
NSLog(@"Failed to created pipeline state, error %@", error);
return;
}
command_queue = [device newCommandQueue];
_commandQueue = [_device newCommandQueue];
}
- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size
{
output_resolution = (vector_float2){size.width, size.height};
_outputResolution = (vector_float2){size.width, size.height};
dispatch_async(dispatch_get_main_queue(), ^{
[(MTKView *)self.internalView draw];
});
@@ -135,90 +148,110 @@ static const vector_float2 rect[] =
- (void)drawInMTKView:(MTKView *)view
{
#if !TARGET_OS_IPHONE
if (!(view.window.occlusionState & NSWindowOcclusionStateVisible)) return;
#endif
if (!self.gb) return;
if (texture.width != GB_get_screen_width(self.gb) ||
texture.height != GB_get_screen_height(self.gb)) {
if (_texture.width != GB_get_screen_width(self.gb) ||
_texture.height != GB_get_screen_height(self.gb)) {
[self allocateTextures];
}
MTLRegion region = {
{0, 0, 0}, // MTLOrigin
{texture.width, texture.height, 1} // MTLSize
{_texture.width, _texture.height, 1} // MTLSize
};
/* Don't start rendering if the previous frame hasn't finished yet. Either wait, or skip the frame */
if (_commandBuffer && _commandBuffer.status != MTLCommandBufferStatusCompleted) {
if (_waitedForFrame) return;
[_commandBuffer waitUntilCompleted];
_waitedForFrame = true;
}
else {
_waitedForFrame = false;
}
[texture replaceRegion:region
GB_frame_blending_mode_t mode = [self frameBlendingMode];
[_texture replaceRegion:region
mipmapLevel:0
withBytes:[self currentBuffer]
bytesPerRow:texture.width * 4];
if ([self frameBlendingMode]) {
[previous_texture replaceRegion:region
bytesPerRow:_texture.width * 4];
if (mode) {
[_previousTexture replaceRegion:region
mipmapLevel:0
withBytes:[self previousBuffer]
bytesPerRow:texture.width * 4];
bytesPerRow:_texture.width * 4];
}
MTLRenderPassDescriptor *render_pass_descriptor = view.currentRenderPassDescriptor;
id<MTLCommandBuffer> command_buffer = [command_queue commandBuffer];
if (render_pass_descriptor != nil) {
*(GB_frame_blending_mode_t *)[frame_blending_mode_buffer contents] = [self frameBlendingMode];
*(vector_float2 *)[output_resolution_buffer contents] = output_resolution;
id<MTLRenderCommandEncoder> render_encoder =
[command_buffer renderCommandEncoderWithDescriptor:render_pass_descriptor];
[render_encoder setViewport:(MTLViewport){0.0, 0.0,
output_resolution.x,
output_resolution.y,
MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
_commandBuffer = [_commandQueue commandBuffer];
if (renderPassDescriptor) {
*(GB_frame_blending_mode_t *)[_frameBlendingModeBuffer contents] = mode;
*(vector_float2 *)[_outputResolutionBuffer contents] = _outputResolution;
id<MTLRenderCommandEncoder> renderEncoder =
[_commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
[renderEncoder setViewport:(MTLViewport){0.0, 0.0,
_outputResolution.x,
_outputResolution.y,
-1.0, 1.0}];
[render_encoder setRenderPipelineState:pipeline_state];
[renderEncoder setRenderPipelineState:_pipelineState];
[render_encoder setVertexBuffer:vertices
[renderEncoder setVertexBuffer:_vertices
offset:0
atIndex:0];
[render_encoder setFragmentBuffer:frame_blending_mode_buffer
[renderEncoder setFragmentBuffer:_frameBlendingModeBuffer
offset:0
atIndex:0];
[render_encoder setFragmentBuffer:output_resolution_buffer
[renderEncoder setFragmentBuffer:_outputResolutionBuffer
offset:0
atIndex:1];
[render_encoder setFragmentTexture:texture
[renderEncoder setFragmentTexture:_texture
atIndex:0];
[render_encoder setFragmentTexture:previous_texture
[renderEncoder setFragmentTexture:_previousTexture
atIndex:1];
[render_encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip
vertexStart:0
vertexCount:4];
[render_encoder endEncoding];
[renderEncoder endEncoding];
[command_buffer presentDrawable:view.currentDrawable];
[_commandBuffer presentDrawable:view.currentDrawable];
}
[command_buffer commit];
[_commandBuffer commit];
}
- (void)flip
{
[super flip];
if (_pendingFrames == 2) return;
_pendingFrames++;
dispatch_async(dispatch_get_main_queue(), ^{
[(MTKView *)self.internalView setNeedsDisplay:true];
[(MTKView *)self.internalView draw];
_pendingFrames--;
});
}
#if !TARGET_OS_IPHONE
- (NSImage *)renderToImage
{
CIImage *ciImage = [CIImage imageWithMTLTexture:[[(MTKView *)self.internalView currentDrawable] texture]
options:@{
kCIImageColorSpace: (__bridge_transfer id)CGColorSpaceCreateDeviceRGB()
kCIImageColorSpace: (__bridge_transfer id)CGColorSpaceCreateDeviceRGB(),
kCIImageProperties: [NSNull null]
}];
ciImage = [ciImage imageByApplyingTransform:CGAffineTransformTranslate(CGAffineTransformMakeScale(1, -1),
0, ciImage.extent.size.height)];
@@ -228,5 +261,6 @@ static const vector_float2 rect[] =
CGImageRelease(cgImage);
return ret;
}
#endif
@end
+47 -5
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).
@@ -89,7 +89,7 @@ The values of memory-mapped registers should be written 'as-is' to memory as if
* Unused register bits have Don't-Care values which should be ignored
* If the model is CGB or newer, the value of KEY0 (FF4C) must be valid as it determines DMG mode
* Bit 2 determines DMG mode. A value of 0x04 usually denotes DMG mode, while a value of `0x80` usually denotes CGB mode.
* Sprite priority is derived from KEY0 (FF4C) instead of OPRI (FF6C) because OPRI can be modified after booting, but only the value of OPRI during boot ROM execution takes effect
* Object priority is derived from KEY0 (FF4C) instead of OPRI (FF6C) because OPRI can be modified after booting, but only the value of OPRI during boot ROM execution takes effect
* If a register doesn't exist on the emulated model (For example, KEY0 (FF4C) on a DMG), its value should be ignored.
* BANK (FF50) should be 0 if the boot ROM is still mapped, and 1 otherwise, and must be valid.
* Implementations should not start a serial transfer when writing the value of SB
@@ -176,6 +176,48 @@ The length of this block is 0x11 bytes long and it follows the following structu
| 0x0E | Scheduled alarm time days (16-bit) |
| 0x10 | Alarm enabled flag (8-bits, either 0 or 1) |
#### TPP1 block
The TPP1 block uses the `'TPP1'` identifier, and is an optional block that is used while emulating a TPP1 cartridge to store RTC information. This block can be omitted if the ROM header does not specify the inclusion of a RTC.
The length of this block is 0x11 bytes long and it follows the following structure:
| Offset | Content |
|--------|-------------------------------------------------------|
| 0x00 | UNIX timestamp at the time of the save state (64-bit) |
| 0x08 | The current RTC data (4 bytes) |
| 0x0C | The latched RTC data (4 bytes) |
| 0x10 | The value of the MR4 register (8-bits) |
#### MBC7 block
The MBC7 block uses the `'MBC7'` identifier, and is an optional block that is used while emulating an MBC7 cartridge to store the EEPROM communication state and motion control state.
The length of this block is 0xA bytes long and it follows the following structure:
| Offset | Content |
|--------|-------------------------------------------------------|
| 0x00 | Flags (8-bits) |
| 0x01 | Argument bits left (8-bits) |
| 0x02 | Current EEPROM command (16-bits) |
| 0x04 | Pending bits to read (16-bits) |
| 0x06 | Latched gyro X value (16-bits) |
| 0x08 | Latched gyro Y value (16-bits) |
The meaning of the individual bits in flags are:
* Bit 0: Latch ready; set after writing `0x55` to `0xAX0X` and reset after writing `0xAA` to `0xAX1X`
* Bit 1: EEPROM DO line
* Bit 2: EEPROM DI line
* Bit 3: EEPROM CLK line
* Bit 4: EEPROM CS line
* Bit 5: EEPROM write enable; set after an `EWEN` command, reset after an `EWDS` command
* Bits 6-7: Unused.
The current EEPROM command field has bits pushed to its LSB first, padded with zeros. For example, if the ROM clocked a single `1` bit, this field should contain `0b1`; if the ROM later clocks a `0` bit, this field should contain `0b10`.
If the currently transmitted command has an argument, the "Argument bits left" field should contain the number argument bits remaining. Otherwise, it should contain 0.
The "Pending bits to read" field contains the pending bits waiting to be shifted into the DO signal, MSB first, padded with ones.
#### SGB block
The SGB block uses the `'SGB '` identifier, and is an optional block that is only used while emulating an SGB or SGB2 *and* SGB commands enabled. Implementations must not save this block on other models or when SGB commands are disabled, and should assume SGB commands are disabled if this block is missing.
@@ -214,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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 479 B

After

Width:  |  Height:  |  Size: 477 B

+2 -2
View File
@@ -1,2 +1,2 @@
AGB EQU 1
include "cgb_boot.asm"
DEF AGB = 1
include "cgb_boot.asm"
+2
View File
@@ -0,0 +1,2 @@
DEF CGB0 = 1
include "cgb_boot.asm"
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -1,2 +1,2 @@
FAST EQU 1
include "cgb_boot.asm"
DEF FAST = 1
include "cgb_boot.asm"
+71 -52
View File
@@ -1,12 +1,15 @@
; SameBoy DMG bootstrap ROM
; Todo: use friendly names for HW registers instead of magic numbers
SECTION "BootCode", ROM0[$0]
include "sameboot.inc"
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
ldi [hl], a
@@ -14,24 +17,25 @@ Start:
jr z, .clearVRAMLoop
; Init Audio
ld a, $80
ldh [$26], a
ldh [$11], a
ld a, $f3
ldh [$12], a
ldh [$25], a
ld a, AUDENA_ON
ldh [rNR52], a
assert AUDENA_ON == AUDLEN_DUTY_50
ldh [rNR11], 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 [$24], a
ldh [rNR50], a ; Volume $7, left and right
; Init BG palette
ld a, $54
ldh [$47], a
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
@@ -40,88 +44,92 @@ 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 [$ff42], a
; Turn on LCD
ld a, $91
ldh [$40], a
ldh [rSCY], a
ld d, (-119) & $FF
; Turn on LCD
ld a, LCDCF_ON | LCDCF_BLK01 | LCDCF_BGON
ldh [rLCDC], a
ld d, LOW(-119)
ld c, 15
.animate
call WaitFrame
ld a, d
sra a
sra a
ldh [$ff42], a
ldh [rSCY], a
ld a, d
add c
ld d, a
ld a, c
cp 8
jr nz, .noPaletteChange
ld a, $A8
ldh [$47], a
ld a, %10_10_10_00
ldh [rBGP], a
.noPaletteChange
dec c
jr nz, .animate
ld a, $fc
ldh [$47], a
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
ld hl, $01B0
IF DEF(MGB)
lb hl, BOOTUP_A_MGB, %10110000
ELSE
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
@@ -148,7 +156,7 @@ DoubleBitsAndWriteRow:
WaitFrame:
push hl
ld hl, $FF0F
ld hl, rIF
res 0, [hl]
.wait
bit 0, [hl]
@@ -163,15 +171,26 @@ WaitBFrames:
ret
PlaySound:
ldh [$13], a
ld a, $87
ldh [$14], a
ldh [rNR13], a
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 [$50], a
ldh [rBANK], a ; unmap boot ROM
+1113
View File
File diff suppressed because it is too large. Load diff
+2
View File
@@ -0,0 +1,2 @@
DEF MGB = 1
include "dmg_boot.asm"
+4 -4
View File
@@ -5,7 +5,7 @@
#include <unistd.h>
#include <assert.h>
void opts(uint8_t byte, uint8_t *options)
static void opts(uint8_t byte, uint8_t *options)
{
*(options++) = byte | ((byte << 1) & 0xff);
*(options++) = byte & (byte << 1);
@@ -13,7 +13,7 @@ void opts(uint8_t byte, uint8_t *options)
*(options++) = byte & (byte >> 1);
}
void write_all(int fd, const void *buf, size_t count) {
static void write_all(int fd, const void *buf, size_t count) {
while (count) {
ssize_t written = write(fd, buf, count);
if (written < 0) {
@@ -25,7 +25,7 @@ void write_all(int fd, const void *buf, size_t count) {
}
}
int main()
int main(void)
{
static uint8_t source[0x4000];
size_t size = read(STDIN_FILENO, &source, sizeof(source));
@@ -87,7 +87,7 @@ int main()
prev[1] = byte;
if (bits >= 8) {
uint8_t outctl = control >> (bits - 8);
assert(outctl != 1);
assert(outctl != 1); // 1 is reserved as the end byte
write_all(STDOUT_FILENO, &outctl, 1);
write_all(STDOUT_FILENO, literals, literals_size);
bits -= 8;
+40
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
+2 -2
View File
@@ -1,2 +1,2 @@
SGB2 EQU 1
include "sgb_boot.asm"
DEF SGB2 = 1
include "sgb_boot.asm"
+97 -75
View File
@@ -1,12 +1,15 @@
; SameBoy SGB bootstrap ROM
; Todo: use friendly names for HW registers instead of magic numbers
SECTION "BootCode", ROM0[$0]
include "sameboot.inc"
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
ldi [hl], a
@@ -14,24 +17,25 @@ Start:
jr z, .clearVRAMLoop
; Init Audio
ld a, $80
ldh [$26], a
ldh [$11], a
ld a, $f3
ldh [$12], a
ldh [$25], a
ld a, AUDENA_ON
ldh [rNR52], a
assert AUDENA_ON == AUDLEN_DUTY_50
ldh [rNR11], 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 [$24], a
ldh [rNR50], a ; Volume $7, left and right
; Init BG palette to white
ld a, $0
ldh [$47], a
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
@@ -40,111 +44,124 @@ 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
ldh [$40], a
ld a, LCDCF_ON | LCDCF_BLK01 | LCDCF_BGON
ldh [rLCDC], a
ld a, $F1 ; Packet magic, increases by 2 for every packet
ldh [hCommand], a
ld hl, NintendoLogo ; Header start
ld a, $f1 ; Packet magic, increases by 2 for every packet
ldh [$80], a
ld hl, $104 ; 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, [$80]
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
ldh [rIE], a
xor a
.waitLoop
ldh [rIF], a
halt
nop
dec e
jr nz, .waitLoop
ldh [rIE], a
; Update command
ldh a, [$80]
ldh a, [hCommand]
add 2
ldh [$80], 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
ldh [$47], a
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
@@ -168,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
@@ -195,19 +212,24 @@ DoubleBitsAndWriteRow:
inc hl
ret
WaitFrame:
push hl
ld hl, $FF0F
res 0, [hl]
.wait
bit 0, [hl]
jr z, .wait
pop hl
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 [$50], a
ldh [rBANK], a
SECTION "HRAM", HRAM[_HRAM]
hCommand:
ds 1
+1 -1
View File
@@ -24,7 +24,7 @@ SameBoy's main target compiler is Clang, but GCC is also supported when targetin
### Third Party Libraries and Tools
Avoid adding new required dependencies; run-time and compile-time dependencies alike. Most importantly, avoid linking against GPL licensed libraries (LGPL libraries are fine), so SameBoy can retain its MIT license.
Avoid adding new required dependencies; run-time and compile-time dependencies alike. Most importantly, avoid linking against GPL licensed libraries (LGPL libraries are fine), so SameBoy can retain its Expat license.
### Spacing, Indentation and Formatting
-449
View File
@@ -1,449 +0,0 @@
#import "AppDelegate.h"
#include "GBButtons.h"
#include "GBView.h"
#include <Core/gb.h>
#import <Carbon/Carbon.h>
#import <JoyKit/JoyKit.h>
#import <WebKit/WebKit.h>
#define UPDATE_SERVER "https://sameboy.github.io"
static uint32_t color_to_int(NSColor *color)
{
color = [color colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
return (((unsigned)(color.redComponent * 0xFF)) << 16) |
(((unsigned)(color.greenComponent * 0xFF)) << 8) |
((unsigned)(color.blueComponent * 0xFF));
}
@implementation AppDelegate
{
NSWindow *preferences_window;
NSArray<NSView *> *preferences_tabs;
NSString *_lastVersion;
NSString *_updateURL;
NSURLSessionDownloadTask *_updateTask;
enum {
UPDATE_DOWNLOADING,
UPDATE_EXTRACTING,
UPDATE_WAIT_INSTALL,
UPDATE_INSTALLING,
UPDATE_FAILED,
} _updateState;
NSString *_downloadDirectory;
}
- (void) applicationDidFinishLaunching:(NSNotification *)notification
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
for (unsigned i = 0; i < GBButtonCount; i++) {
if ([[defaults objectForKey:button_to_preference_name(i, 0)] isKindOfClass:[NSString class]]) {
[defaults removeObjectForKey:button_to_preference_name(i, 0)];
}
}
[[NSUserDefaults standardUserDefaults] registerDefaults:@{
@"GBRight": @(kVK_RightArrow),
@"GBLeft": @(kVK_LeftArrow),
@"GBUp": @(kVK_UpArrow),
@"GBDown": @(kVK_DownArrow),
@"GBA": @(kVK_ANSI_X),
@"GBB": @(kVK_ANSI_Z),
@"GBSelect": @(kVK_Delete),
@"GBStart": @(kVK_Return),
@"GBTurbo": @(kVK_Space),
@"GBRewind": @(kVK_Tab),
@"GBSlow-Motion": @(kVK_Shift),
@"GBFilter": @"NearestNeighbor",
@"GBColorCorrection": @(GB_COLOR_CORRECTION_EMULATE_HARDWARE),
@"GBHighpassFilter": @(GB_HIGHPASS_REMOVE_DC_OFFSET),
@"GBRewindLength": @(10),
@"GBFrameBlendingMode": @([defaults boolForKey:@"DisableFrameBlending"]? GB_FRAME_BLENDING_MODE_DISABLED : GB_FRAME_BLENDING_MODE_ACCURATE),
@"GBDMGModel": @(GB_MODEL_DMG_B),
@"GBCGBModel": @(GB_MODEL_CGB_E),
@"GBSGBModel": @(GB_MODEL_SGB2),
@"GBRumbleMode": @(GB_RUMBLE_CARTRIDGE_ONLY),
@"GBVolume": @(1.0),
}];
[JOYController startOnRunLoop:[NSRunLoop currentRunLoop] withOptions:@{
JOYAxes2DEmulateButtonsKey: @YES,
JOYHatsEmulateButtonsKey: @YES,
}];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBNotificationsUsed"]) {
[NSUserNotificationCenter defaultUserNotificationCenter].delegate = self;
}
[self askAutoUpdates];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBAutoUpdatesEnabled"]) {
[self checkForUpdates];
}
if ([[NSProcessInfo processInfo].arguments containsObject:@"--update-launch"]) {
[NSApp activateIgnoringOtherApps:true];
}
}
- (IBAction)toggleDeveloperMode:(id)sender
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:![defaults boolForKey:@"DeveloperMode"] forKey:@"DeveloperMode"];
}
- (IBAction)switchPreferencesTab:(id)sender
{
for (NSView *view in preferences_tabs) {
[view removeFromSuperview];
}
NSView *tab = preferences_tabs[[sender tag]];
NSRect old = [_preferencesWindow frame];
NSRect new = [_preferencesWindow frameRectForContentRect:tab.frame];
new.origin.x = old.origin.x;
new.origin.y = old.origin.y + (old.size.height - new.size.height);
[_preferencesWindow setFrame:new display:true animate:_preferencesWindow.visible];
[_preferencesWindow.contentView addSubview:tab];
}
- (BOOL)validateMenuItem:(NSMenuItem *)anItem
{
if ([anItem action] == @selector(toggleDeveloperMode:)) {
[(NSMenuItem *)anItem setState:[[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]];
}
if (anItem == self.linkCableMenuItem) {
return [[NSDocumentController sharedDocumentController] documents].count > 1;
}
return true;
}
- (void)menuNeedsUpdate:(NSMenu *)menu
{
NSMutableArray *items = [NSMutableArray array];
NSDocument *currentDocument = [[NSDocumentController sharedDocumentController] currentDocument];
for (NSDocument *document in [[NSDocumentController sharedDocumentController] documents]) {
if (document == currentDocument) continue;
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:document.displayName action:@selector(connectLinkCable:) keyEquivalent:@""];
item.representedObject = document;
item.image = [[NSWorkspace sharedWorkspace] iconForFile:document.fileURL.path];
[item.image setSize:NSMakeSize(16, 16)];
[items addObject:item];
}
menu.itemArray = items;
}
- (IBAction) showPreferences: (id) sender
{
NSArray *objects;
if (!_preferencesWindow) {
[[NSBundle mainBundle] loadNibNamed:@"Preferences" owner:self topLevelObjects:&objects];
NSToolbarItem *first_toolbar_item = [_preferencesWindow.toolbar.items firstObject];
_preferencesWindow.toolbar.selectedItemIdentifier = [first_toolbar_item itemIdentifier];
preferences_tabs = @[self.emulationTab, self.graphicsTab, self.audioTab, self.controlsTab, self.updatesTab];
[self switchPreferencesTab:first_toolbar_item];
[_preferencesWindow center];
#ifndef UPDATE_SUPPORT
[_preferencesWindow.toolbar removeItemAtIndex:4];
#endif
}
[_preferencesWindow makeKeyAndOrderFront:self];
}
- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender
{
[self askAutoUpdates];
/* Bring an existing panel to the foreground */
for (NSWindow *window in [[NSApplication sharedApplication] windows]) {
if ([window isKindOfClass:[NSOpenPanel class]]) {
[(NSOpenPanel *)window makeKeyAndOrderFront:nil];
return true;
}
}
[[NSDocumentController sharedDocumentController] openDocument:self];
return true;
}
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
[[NSDocumentController sharedDocumentController] openDocumentWithContentsOfFile:notification.identifier display:true];
}
- (void)updateFound
{
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@UPDATE_SERVER "/raw_changes"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSColor *linkColor = [NSColor colorWithRed:0.125 green:0.325 blue:1.0 alpha:1.0];
if (@available(macOS 10.10, *)) {
linkColor = [NSColor linkColor];
}
NSString *changes = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSRange cutoffRange = [changes rangeOfString:@"<!--(" GB_VERSION ")-->"];
if (cutoffRange.location != NSNotFound) {
changes = [changes substringToIndex:cutoffRange.location];
}
NSString *html = [NSString stringWithFormat:@"<!DOCTYPE html><html><head><title></title>"
"<style>html {background-color:transparent; color: #%06x; line-height:1.5} a:link, a:visited{color:#%06x; text-decoration:none}</style>"
"</head><body>%@</body></html>",
color_to_int([NSColor textColor]),
color_to_int(linkColor),
changes];
if ([(NSHTTPURLResponse *)response statusCode] == 200) {
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *objects;
[[NSBundle mainBundle] loadNibNamed:@"UpdateWindow" owner:self topLevelObjects:&objects];
self.updateChanges.preferences.standardFontFamily = [NSFont systemFontOfSize:0].familyName;
self.updateChanges.preferences.fixedFontFamily = @"Menlo";
self.updateChanges.drawsBackground = false;
[self.updateChanges.mainFrame loadHTMLString:html baseURL:nil];
});
}
}] resume];
}
- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems
{
// Disable reload context menu
if ([defaultMenuItems count] <= 2) {
return nil;
}
return defaultMenuItems;
}
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sender.mainFrame.frameView.documentView.enclosingScrollView.drawsBackground = true;
sender.mainFrame.frameView.documentView.enclosingScrollView.backgroundColor = [NSColor textBackgroundColor];
sender.policyDelegate = self;
[self.updateWindow center];
[self.updateWindow makeKeyAndOrderFront:nil];
});
}
- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener
{
[listener ignore];
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
}
- (void)checkForUpdates
{
#ifdef UPDATE_SUPPORT
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@UPDATE_SERVER "/latest_version"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.updatesSpinner stopAnimation:nil];
[self.updatesButton setEnabled:true];
});
if ([(NSHTTPURLResponse *)response statusCode] == 200) {
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray <NSString *> *components = [string componentsSeparatedByString:@"|"];
if (components.count != 2) return;
_lastVersion = components[0];
_updateURL = components[1];
if (![@GB_VERSION isEqualToString:_lastVersion] &&
![[[NSUserDefaults standardUserDefaults] stringForKey:@"GBSkippedVersion"] isEqualToString:_lastVersion]) {
[self updateFound];
}
}
}] resume];
#endif
}
- (IBAction)userCheckForUpdates:(id)sender
{
if (self.updateWindow) {
[self.updateWindow makeKeyAndOrderFront:sender];
}
else {
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"GBSkippedVersion"];
[self checkForUpdates];
[sender setEnabled:false];
[self.updatesSpinner startAnimation:sender];
}
}
- (void)askAutoUpdates
{
#ifdef UPDATE_SUPPORT
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"GBAskedAutoUpdates"]) {
NSAlert *alert = [[NSAlert alloc] init];
alert.messageText = @"Should SameBoy check for updates when launched?";
alert.informativeText = @"SameBoy is frequently updated with new features, accuracy improvements, and bug fixes. This setting can always be changed in the preferences window.";
[alert addButtonWithTitle:@"Check on Launch"];
[alert addButtonWithTitle:@"Don't Check on Launch"];
[[NSUserDefaults standardUserDefaults] setBool:[alert runModal] == NSAlertFirstButtonReturn forKey:@"GBAutoUpdatesEnabled"];
[[NSUserDefaults standardUserDefaults] setBool:true forKey:@"GBAskedAutoUpdates"];
}
#endif
}
- (IBAction)skipVersion:(id)sender
{
[[NSUserDefaults standardUserDefaults] setObject:_lastVersion forKey:@"GBSkippedVersion"];
[self.updateWindow performClose:sender];
}
- (IBAction)installUpdate:(id)sender
{
[self.updateProgressSpinner startAnimation:nil];
self.updateProgressButton.title = @"Cancel";
self.updateProgressButton.enabled = true;
self.updateProgressLabel.stringValue = @"Downloading update...";
_updateState = UPDATE_DOWNLOADING;
_updateTask = [[NSURLSession sharedSession] downloadTaskWithURL: [NSURL URLWithString:_updateURL] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
_updateTask = nil;
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Extracting update...";
_updateState = UPDATE_EXTRACTING;
});
_downloadDirectory = [[[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory
inDomain:NSUserDomainMask
appropriateForURL:[[NSBundle mainBundle] bundleURL]
create:true
error:nil] path];
NSTask *unzipTask;
if (!_downloadDirectory) {
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Failed to extract update.";
_updateState = UPDATE_FAILED;
self.updateProgressButton.title = @"Close";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
}
unzipTask = [[NSTask alloc] init];
unzipTask.launchPath = @"/usr/bin/unzip";
unzipTask.arguments = @[location.path, @"-d", _downloadDirectory];
[unzipTask launch];
[unzipTask waitUntilExit];
if (unzipTask.terminationStatus != 0 || unzipTask.terminationReason != NSTaskTerminationReasonExit) {
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Failed to extract update.";
_updateState = UPDATE_FAILED;
self.updateProgressButton.title = @"Close";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
return;
}
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Update ready, save your game progress and click Install.";
_updateState = UPDATE_WAIT_INSTALL;
self.updateProgressButton.title = @"Install";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
}];
[_updateTask resume];
self.updateProgressWindow.preventsApplicationTerminationWhenModal = false;
[self.updateWindow beginSheet:self.updateProgressWindow completionHandler:^(NSModalResponse returnCode) {
[self.updateWindow close];
}];
}
- (void)performUpgrade
{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Instaling update...";
_updateState = UPDATE_INSTALLING;
self.updateProgressButton.enabled = false;
[self.updateProgressSpinner startAnimation:nil];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *executablePath = [[NSBundle mainBundle] executablePath];
NSString *contentsPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Contents"];
NSString *contentsTempPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"TempContents"];
NSString *updateContentsPath = [_downloadDirectory stringByAppendingPathComponent:@"SameBoy.app/Contents"];
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:contentsPath toPath:contentsTempPath error:&error];
if (error) {
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
_downloadDirectory = nil;
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Failed to install update.";
_updateState = UPDATE_FAILED;
self.updateProgressButton.title = @"Close";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
return;
}
[[NSFileManager defaultManager] moveItemAtPath:updateContentsPath toPath:contentsPath error:&error];
if (error) {
[[NSFileManager defaultManager] moveItemAtPath:contentsTempPath toPath:contentsPath error:nil];
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
_downloadDirectory = nil;
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Failed to install update.";
_updateState = UPDATE_FAILED;
self.updateProgressButton.title = @"Close";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
return;
}
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
[[NSFileManager defaultManager] removeItemAtPath:contentsTempPath error:nil];
_downloadDirectory = nil;
atexit_b(^{
execl(executablePath.UTF8String, executablePath.UTF8String, "--update-launch", NULL);
});
dispatch_async(dispatch_get_main_queue(), ^{
[NSApp terminate:nil];
});
});
}
- (IBAction)updateAction:(id)sender
{
switch (_updateState) {
case UPDATE_DOWNLOADING:
[_updateTask cancelByProducingResumeData:nil];
_updateTask = nil;
[self.updateProgressWindow close];
break;
case UPDATE_WAIT_INSTALL:
[self performUpgrade];
break;
case UPDATE_EXTRACTING:
case UPDATE_INSTALLING:
break;
case UPDATE_FAILED:
[self.updateProgressWindow close];
break;
}
}
- (void)dealloc
{
if (_downloadDirectory) {
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
}
}
- (IBAction)nop:(id)sender
{
}
@end
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,51 @@
<?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">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="Document">
<connections>
<outlet property="audioFormatButton" destination="knX-AW-zt5" id="fKt-eI-H0y"/>
<outlet property="audioRecordingAccessoryView" destination="c22-O7-iKe" id="XD8-Gi-qOC"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="c22-O7-iKe">
<rect key="frame" x="0.0" y="0.0" width="354" height="36"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Atq-RE-328">
<rect key="frame" x="18" y="10" width="56" height="16"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Format:" id="dso-NS-JlD">
<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="knX-AW-zt5">
<rect key="frame" x="81" y="4" width="256" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Apple AIFF" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="proportionallyDown" inset="2" selectedItem="M3Z-UN-VKZ" id="tLM-Di-Dy3">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<menu key="menu" id="gqn-SL-AA5">
<items>
<menuItem title="Apple AIFF" state="on" tag="1" id="M3Z-UN-VKZ"/>
<menuItem title="RIFF WAVE" tag="2" id="zA0-Np-4XD"/>
<menuItem title="Raw PCM (Stereo 96KHz, 16-bit LE)" id="r9J-4k-XH5"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="audioFormatChanged:" target="-2" id="I1k-d9-afp"/>
</connections>
</popUpButton>
</subviews>
<point key="canvasLocation" x="75" y="19"/>
</customView>
</objects>
</document>
Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

-4
View File
@@ -1,6 +1,4 @@
#import <Cocoa/Cocoa.h>
#ifndef BigSurToolbar_h
#define BigSurToolbar_h
/* Backport the toolbarStyle property to allow compilation with older SDKs*/
#ifndef __MAC_10_16
@@ -26,5 +24,3 @@ typedef NS_ENUM(NSInteger, NSWindowToolbarStyle) {
@end
#endif
#endif
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.
+253
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.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 849 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

+91 -54
View File
@@ -1,61 +1,98 @@
#import <Cocoa/Cocoa.h>
#include "GBView.h"
#include "GBImageView.h"
#include "GBSplitView.h"
#include "GBVisualizerView.h"
#include "GBOSDView.h"
#import "GBView.h"
#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;
@interface Document : NSDocument <NSWindowDelegate, GBImageViewDelegate, NSTableViewDataSource, NSTableViewDelegate, NSSplitViewDelegate>
@property (nonatomic, readonly) GB_gameboy_t *gb;
@property (nonatomic, strong) IBOutlet GBView *view;
@property (nonatomic, strong) IBOutlet NSTextView *consoleOutput;
@property (nonatomic, strong) IBOutlet NSPanel *consoleWindow;
@property (nonatomic, strong) IBOutlet NSTextField *consoleInput;
@property (nonatomic, strong) IBOutlet NSWindow *mainWindow;
@property (nonatomic, strong) IBOutlet NSView *memoryView;
@property (nonatomic, strong) IBOutlet NSPanel *memoryWindow;
@property (nonatomic, readonly) GB_gameboy_t *gameboy;
@property (nonatomic, strong) IBOutlet NSTextField *memoryBankInput;
@property (nonatomic, strong) IBOutlet NSToolbarItem *memoryBankItem;
@property (nonatomic, strong) IBOutlet GBImageView *tilesetImageView;
@property (nonatomic, strong) IBOutlet NSPopUpButton *tilesetPaletteButton;
@property (nonatomic, strong) IBOutlet GBImageView *tilemapImageView;
@property (nonatomic, strong) IBOutlet NSPopUpButton *tilemapPaletteButton;
@property (nonatomic, strong) IBOutlet NSPopUpButton *tilemapMapButton;
@property (nonatomic, strong) IBOutlet NSPopUpButton *TilemapSetButton;
@property (nonatomic, strong) IBOutlet NSButton *gridButton;
@property (nonatomic, strong) IBOutlet NSTabView *vramTabView;
@property (nonatomic, strong) IBOutlet NSPanel *vramWindow;
@property (nonatomic, strong) IBOutlet NSTextField *vramStatusLabel;
@property (nonatomic, strong) IBOutlet NSTableView *paletteTableView;
@property (nonatomic, strong) IBOutlet NSTableView *spritesTableView;
@property (nonatomic, strong) IBOutlet NSPanel *printerFeedWindow;
@property (nonatomic, strong) IBOutlet NSImageView *feedImageView;
@property (nonatomic, strong) IBOutlet NSTextView *debuggerSideViewInput;
@property (nonatomic, strong) IBOutlet NSTextView *debuggerSideView;
@property (nonatomic, strong) IBOutlet GBSplitView *debuggerSplitView;
@property (nonatomic, strong) IBOutlet NSBox *debuggerVerticalLine;
@property (nonatomic, strong) IBOutlet NSPanel *cheatsWindow;
@property (nonatomic, strong) IBOutlet GBCheatWindowController *cheatWindowController;
@property (nonatomic, readonly) Document *partner;
@property (nonatomic, readonly) bool isSlave;
@property (strong) IBOutlet NSView *gbsPlayerView;
@property (strong) IBOutlet NSTextField *gbsTitle;
@property (strong) IBOutlet NSTextField *gbsAuthor;
@property (strong) IBOutlet NSTextField *gbsCopyright;
@property (strong) IBOutlet NSPopUpButton *gbsTracks;
@property (strong) IBOutlet NSButton *gbsPlayPauseButton;
@property (strong) IBOutlet NSButton *gbsRewindButton;
@property (strong) IBOutlet NSSegmentedControl *gbsNextPrevButton;
@property (strong) IBOutlet GBVisualizerView *gbsVisualizer;
@property (strong) IBOutlet GBOSDView *osdView;
@interface Document : NSDocument <NSWindowDelegate, GBImageViewDelegate, NSSplitViewDelegate>
@property (readonly) GB_gameboy_t *gb;
@property IBOutlet GBView *view;
@property IBOutlet NSTextView *consoleOutput;
@property IBOutlet NSPanel *consoleWindow;
@property IBOutlet NSTextField *consoleInput;
@property IBOutlet NSWindow *mainWindow;
@property IBOutlet NSView *memoryView;
@property IBOutlet NSPanel *memoryWindow;
@property (readonly) GB_gameboy_t *gameboy;
@property IBOutlet NSTextField *memoryBankInput;
@property IBOutlet NSToolbarItem *memoryBankItem;
@property IBOutlet NSPopUpButton *memorySpaceButton;
@property IBOutlet GBImageView *tilesetImageView;
@property IBOutlet NSPopUpButton *tilesetPaletteButton;
@property IBOutlet GBImageView *tilemapImageView;
@property IBOutlet NSPopUpButton *tilemapPaletteButton;
@property IBOutlet NSPopUpButton *tilemapMapButton;
@property IBOutlet NSPopUpButton *TilemapSetButton;
@property IBOutlet NSButton *gridButton;
@property IBOutlet NSTabView *vramTabView;
@property IBOutlet NSPanel *vramWindow;
@property IBOutlet NSTextField *vramStatusLabel;
@property IBOutlet GBPaletteView *paletteView;
@property IBOutlet GBObjectView *objectView;
@property IBOutlet NSPanel *printerFeedWindow;
@property IBOutlet NSProgressIndicator *printerSpinner;
@property IBOutlet NSImageView *feedImageView;
@property IBOutlet NSTextView *debuggerSideViewInput;
@property IBOutlet NSTextView *debuggerSideView;
@property IBOutlet GBSplitView *debuggerSplitView;
@property IBOutlet NSBox *debuggerVerticalLine;
@property IBOutlet NSPanel *cheatsWindow;
@property IBOutlet GBCheatWindowController *cheatWindowController;
@property (readonly) Document *partner;
@property (readonly) bool isSlave;
@property IBOutlet NSView *gbsPlayerView;
@property IBOutlet NSTextField *gbsTitle;
@property IBOutlet NSTextField *gbsAuthor;
@property IBOutlet NSTextField *gbsCopyright;
@property IBOutlet NSPopUpButton *gbsTracks;
@property IBOutlet NSButton *gbsPlayPauseButton;
@property IBOutlet NSButton *gbsRewindButton;
@property IBOutlet NSSegmentedControl *gbsNextPrevButton;
@property IBOutlet GBVisualizerView *gbsVisualizer;
@property IBOutlet GBOSDView *osdView;
@property (readonly) GB_oam_info_t *oamInfo;
@property uint8_t oamCount;
@property uint8_t oamHeight;
@property IBOutlet NSView *audioRecordingAccessoryView;
@property IBOutlet NSPopUpButton *audioFormatButton;
@property IBOutlet NSVisualEffectView *debuggerSidebarEffectView API_AVAILABLE(macos(10.10));
-(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;
@property IBOutlet GBDebuggerButton *debuggerContinueButton;
@property IBOutlet GBDebuggerButton *debuggerNextButton;
@property IBOutlet GBDebuggerButton *debuggerStepButton;
@property IBOutlet GBDebuggerButton *debuggerFinishButton;
@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;
- (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
+1566 -909
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

@@ -1,7 +1,8 @@
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
#import <JoyKit/JoyKit.h>
@interface AppDelegate : NSObject <NSApplicationDelegate, NSUserNotificationCenterDelegate, NSMenuDelegate, WebUIDelegate, WebPolicyDelegate, WebFrameLoadDelegate>
@interface GBApp : NSApplication <NSApplicationDelegate, NSUserNotificationCenterDelegate, NSMenuDelegate, WebUIDelegate, WebPolicyDelegate, WebFrameLoadDelegate, JOYListener>
@property (nonatomic, strong) IBOutlet NSWindow *preferencesWindow;
@property (nonatomic, strong) IBOutlet NSView *graphicsTab;
@@ -21,5 +22,6 @@
@property (strong) IBOutlet NSButton *updateProgressButton;
@property (strong) IBOutlet NSWindow *updateProgressWindow;
@property (strong) IBOutlet NSProgressIndicator *updateProgressSpinner;
- (void)updateThemesDefault:(bool)overwrite;
@end
+817
View File
@@ -0,0 +1,817 @@
#import "GBApp.h"
#import "GBButtons.h"
#import "GBView.h"
#import "Document.h"
#import "GBJoyConManager.h"
#import <Core/gb.h>
#import <Carbon/Carbon.h>
#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]];
return (((unsigned)(color.redComponent * 0xFF)) << 16) |
(((unsigned)(color.greenComponent * 0xFF)) << 8) |
((unsigned)(color.blueComponent * 0xFF));
}
@implementation GBApp
{
NSArray<NSView *> *_preferencesTabs;
NSString *_lastVersion;
NSString *_updateURL;
NSURLSessionDownloadTask *_updateTask;
enum {
UPDATE_DOWNLOADING,
UPDATE_EXTRACTING,
UPDATE_WAIT_INSTALL,
UPDATE_INSTALLING,
UPDATE_FAILED,
} _updateState;
NSString *_downloadDirectory;
AuthorizationRef _auth;
bool _simulatingMenuEvent;
}
- (void) applicationDidFinishLaunching:(NSNotification *)notification
{
// Refresh icon if launched via a software update
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 < 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),
@"GBUp": @(kVK_UpArrow),
@"GBDown": @(kVK_DownArrow),
@"GBA": @(kVK_ANSI_X),
@"GBB": @(kVK_ANSI_Z),
@"GBSelect": @(kVK_Delete),
@"GBStart": @(kVK_Return),
@"GBTurbo": @(kVK_Space),
@"GBRewind": @(kVK_Tab),
@"GBSlow-Motion": @(kVK_Shift),
@"GBFilter": @"NearestNeighbor",
@"GBColorCorrection": @(GB_COLOR_CORRECTION_MODERN_BALANCED),
@"GBHighpassFilter": @(GB_HIGHPASS_ACCURATE),
@"GBRewindLength": @(120),
@"GBFrameBlendingMode": @([defaults boolForKey:@"DisableFrameBlending"]? GB_FRAME_BLENDING_MODE_DISABLED : GB_FRAME_BLENDING_MODE_ACCURATE),
@"GBDMGModel": @(GB_MODEL_DMG_B),
@"GBCGBModel": @(GB_MODEL_CGB_E),
@"GBAGBModel": @(GB_MODEL_AGB_A),
@"GBSGBModel": @(GB_MODEL_SGB2),
@"GBRumbleMode": @(GB_RUMBLE_CARTRIDGE_ONLY),
@"GBVolume": @(1.0),
@"GBMBC7JoystickOverride": @NO,
@"GBMBC7AllowMouse": @YES,
@"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],
@"DisabledLCDColor": @YES,
@"HueBias": @0.10087773904382469,
@"HueBiasStrength": @0.062142056772908363,
@"Manual": @NO,
},
@"Evening": @{
@"BrightnessBias": @-0.10168700106441975,
@"Colors": @[@0xff362601, @0xff695518, @0xff899853, @0xffa6e4ae, @0xffa9eebb],
@"DisabledLCDColor": @YES,
@"HueBias": @0.60027079191058874,
@"HueBiasStrength": @0.33816297305747867,
@"Manual": @NO,
},
@"Fog": @{
@"BrightnessBias": @0.0,
@"Colors": @[@0xff373c34, @0xff737256, @0xff9da386, @0xffc3d2bf, @0xffc7d8c6],
@"DisabledLCDColor": @YES,
@"HueBias": @0.55750435756972117,
@"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],
@"DisabledLCDColor": @YES,
@"HueBias": @0.87717878486055778,
@"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],
@"DisabledLCDColor": @YES,
@"HueBias": @0.3795131972111554,
@"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],
@"DisabledLCDColor": @YES,
@"HueBias": @0.2694067480079681,
@"HueBiasStrength": @0.51565612549800799,
@"Manual": @NO,
},
@"Twilight": @{
@"BrightnessBias": @-0.091789093625498031,
@"Colors": @[@0xff3f0015, @0xff461286, @0xff6254bd, @0xff97d3e9, @0xffa0e7ee],
@"DisabledLCDColor": @YES,
@"HueBias": @0.0,
@"HueBiasStrength": @0.49710532868525897,
@"Manual": @NO,
},
},
@"NSToolbarItemForcesStandardSize": @YES, // Forces Monterey to resepect toolbar item sizes
@"NSToolbarItemWarnOnMinMaxSize": @NO, // Not going to use Constraints, Apple
}];
[JOYController startOnRunLoop:[NSRunLoop currentRunLoop] withOptions:@{
JOYAxes2DEmulateButtonsKey: @YES,
JOYHatsEmulateButtonsKey: @YES,
}];
[GBJoyConManager sharedInstance]; // Starts handling Joy-Cons
[JOYController registerListener:self];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBNotificationsUsed"]) {
[NSUserNotificationCenter defaultUserNotificationCenter].delegate = self;
}
[self askAutoUpdates];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBAutoUpdatesEnabled"]) {
[self checkForUpdates];
}
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
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:![defaults boolForKey:@"DeveloperMode"] forKey:@"DeveloperMode"];
}
- (IBAction)switchPreferencesTab:(id)sender
{
for (NSView *view in _preferencesTabs) {
[view removeFromSuperview];
}
NSView *tab = _preferencesTabs[[sender tag]];
NSRect old = [_preferencesWindow frame];
NSRect new = [_preferencesWindow frameRectForContentRect:tab.frame];
new.origin.x = old.origin.x;
new.origin.y = old.origin.y + (old.size.height - new.size.height);
[_preferencesWindow setFrame:new display:true animate:_preferencesWindow.visible];
[_preferencesWindow.contentView addSubview:tab];
}
- (BOOL)validateMenuItem:(NSMenuItem *)anItem
{
if ([anItem action] == @selector(toggleDeveloperMode:)) {
[(NSMenuItem *)anItem setState:[[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]];
}
if (anItem == self.linkCableMenuItem) {
return [[NSDocumentController sharedDocumentController] documents].count > 1;
}
return true;
}
- (void)menuNeedsUpdate:(NSMenu *)menu
{
NSMutableArray *items = [NSMutableArray array];
NSDocument *currentDocument = [[NSDocumentController sharedDocumentController] currentDocument];
for (NSDocument *document in [[NSDocumentController sharedDocumentController] documents]) {
if (document == currentDocument) continue;
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:document.displayName action:@selector(connectLinkCable:) keyEquivalent:@""];
item.representedObject = document;
item.image = [[NSWorkspace sharedWorkspace] iconForFile:document.fileURL.path];
[item.image setSize:NSMakeSize(16, 16)];
[items addObject:item];
}
[menu removeAllItems];
for (NSMenuItem *item in items) {
[menu addItem:item];
}
}
- (IBAction) showPreferences: (id) sender
{
NSArray *objects;
if (!_preferencesWindow) {
[[NSBundle mainBundle] loadNibNamed:@"Preferences" owner:self topLevelObjects:&objects];
NSToolbarItem *first_toolbar_item = [_preferencesWindow.toolbar.items firstObject];
_preferencesWindow.toolbar.selectedItemIdentifier = [first_toolbar_item itemIdentifier];
_preferencesTabs = @[self.emulationTab, self.graphicsTab, self.audioTab, self.controlsTab, self.updatesTab];
[self switchPreferencesTab:first_toolbar_item];
[_preferencesWindow center];
#ifndef UPDATE_SUPPORT
[_preferencesWindow.toolbar removeItemAtIndex:4];
#endif
for (unsigned i = _preferencesWindow.toolbar.items.count; i--;) {
[_preferencesWindow.toolbar.items[i] _view].imageScaling = NSImageScaleNone;
}
}
[_preferencesWindow makeKeyAndOrderFront:self];
}
- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender
{
[self askAutoUpdates];
/* Bring an existing panel to the foreground */
for (NSWindow *window in [[NSApplication sharedApplication] windows]) {
if ([window isKindOfClass:[NSOpenPanel class]]) {
[(NSOpenPanel *)window makeKeyAndOrderFront:nil];
return true;
}
}
[[NSDocumentController sharedDocumentController] openDocument:self];
return true;
}
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
[[NSDocumentController sharedDocumentController] openDocumentWithContentsOfFile:notification.identifier display:true];
}
- (void)updateFound
{
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@UPDATE_SERVER "/raw_changes"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSColor *linkColor = [NSColor colorWithRed:0.125 green:0.325 blue:1.0 alpha:1.0];
if (@available(macOS 10.10, *)) {
linkColor = [NSColor linkColor];
}
NSString *changes = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSRange cutoffRange = [changes rangeOfString:@"<!--(" GB_VERSION ")-->"];
if (cutoffRange.location != NSNotFound) {
changes = [changes substringToIndex:cutoffRange.location];
}
NSString *html = [NSString stringWithFormat:@"<!DOCTYPE html><html><head><title></title>"
"<style>html {background-color:transparent; color: #%06x; line-height:1.5} a:link, a:visited{color:#%06x; text-decoration:none}</style>"
"</head><body>%@</body></html>",
color_to_int([NSColor textColor]),
color_to_int(linkColor),
changes];
if ([(NSHTTPURLResponse *)response statusCode] == 200) {
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *objects;
[[NSBundle mainBundle] loadNibNamed:@"UpdateWindow" owner:self topLevelObjects:&objects];
if (@available(macOS 10.11, *)) {
self.updateChanges.preferences.standardFontFamily = @"-apple-system";
}
else if (@available(macOS 10.10, *)) {
self.updateChanges.preferences.standardFontFamily = @"Helvetica Neue";
}
else {
self.updateChanges.preferences.standardFontFamily = @"Lucida Grande";
}
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];
});
}
}] resume];
}
- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems
{
// Disable reload context menu
if ([defaultMenuItems count] <= 2) {
return nil;
}
return defaultMenuItems;
}
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sender.mainFrame.frameView.documentView.enclosingScrollView.drawsBackground = true;
sender.mainFrame.frameView.documentView.enclosingScrollView.backgroundColor = [NSColor textBackgroundColor];
sender.policyDelegate = self;
[self.updateWindow center];
[self.updateWindow makeKeyAndOrderFront:nil];
});
}
- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener
{
[listener ignore];
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
}
- (void)checkForUpdates
{
#ifdef UPDATE_SUPPORT
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@UPDATE_SERVER "/latest_version"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.updatesSpinner stopAnimation:nil];
[self.updatesButton setEnabled:true];
});
if ([(NSHTTPURLResponse *)response statusCode] == 200) {
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray <NSString *> *components = [string componentsSeparatedByString:@"|"];
if (components.count != 2) return;
_lastVersion = components[0];
_updateURL = components[1];
if (![@GB_VERSION isEqualToString:_lastVersion] &&
![[[NSUserDefaults standardUserDefaults] stringForKey:@"GBSkippedVersion"] isEqualToString:_lastVersion]) {
[self updateFound];
}
}
}] resume];
#endif
}
- (IBAction)userCheckForUpdates:(id)sender
{
if (self.updateWindow) {
[self.updateWindow makeKeyAndOrderFront:sender];
}
else {
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"GBSkippedVersion"];
[self checkForUpdates];
[sender setEnabled:false];
[self.updatesSpinner startAnimation:sender];
}
}
- (void)askAutoUpdates
{
#ifdef UPDATE_SUPPORT
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"GBAskedAutoUpdates"]) {
NSAlert *alert = [[NSAlert alloc] init];
alert.messageText = @"Should SameBoy check for updates when launched?";
alert.informativeText = @"SameBoy is frequently updated with new features, accuracy improvements, and bug fixes. This setting can always be changed in the preferences window.";
[alert addButtonWithTitle:@"Check on Launch"];
[alert addButtonWithTitle:@"Don't Check on Launch"];
[[NSUserDefaults standardUserDefaults] setBool:[alert runModal] == NSAlertFirstButtonReturn forKey:@"GBAutoUpdatesEnabled"];
[[NSUserDefaults standardUserDefaults] setBool:true forKey:@"GBAskedAutoUpdates"];
}
#endif
}
- (IBAction)skipVersion:(id)sender
{
[[NSUserDefaults standardUserDefaults] setObject:_lastVersion forKey:@"GBSkippedVersion"];
[self.updateWindow performClose:sender];
}
- (bool)executePath:(NSString *)path withArguments:(NSArray <NSString *> *)arguments
{
if (!_auth) {
NSTask *task = [[NSTask alloc] init];
task.launchPath = path;
task.arguments = arguments;
[task launch];
[task waitUntilExit];
return task.terminationStatus == 0 && task.terminationReason == NSTaskTerminationReasonExit;
}
char *argv[arguments.count + 1];
argv[arguments.count] = NULL;
for (unsigned i = 0; i < arguments.count; i++) {
argv[i] = (char *)arguments[i].UTF8String;
}
return AuthorizationExecuteWithPrivileges(_auth, path.UTF8String, kAuthorizationFlagDefaults, argv, NULL) == errAuthorizationSuccess;
}
- (void)deauthorize
{
if (_auth) {
AuthorizationFree(_auth, kAuthorizationFlagDefaults);
_auth = nil;
}
}
- (IBAction)installUpdate:(id)sender
{
bool needsAuthorization = false;
if ([self executePath:@"/usr/sbin/spctl" withArguments:@[@"--status"]]) { // Succeeds when GateKeeper is on
// GateKeeper is on, we need to --add ourselves as root, else we might get a GateKeeper crash
needsAuthorization = true;
}
else if (access(_dyld_get_image_name(0), W_OK)) {
// We don't have write access, so we need authorization to update as root
needsAuthorization = true;
}
if (needsAuthorization && !_auth) {
AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagPreAuthorize | kAuthorizationFlagInteractionAllowed, &_auth);
// Make sure we can modify the bundle
if (![self executePath:@"/usr/sbin/chown" withArguments:@[@"-R", [NSString stringWithFormat:@"%d:%d", getuid(), getgid()], [NSBundle mainBundle].bundlePath]]) {
[self deauthorize];
return;
}
}
[self.updateProgressSpinner startAnimation:nil];
self.updateProgressButton.title = @"Cancel";
self.updateProgressButton.enabled = true;
self.updateProgressLabel.stringValue = @"Downloading update…";
_updateState = UPDATE_DOWNLOADING;
_updateTask = [[NSURLSession sharedSession] downloadTaskWithURL: [NSURL URLWithString:_updateURL] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
_updateTask = nil;
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Extracting update…";
_updateState = UPDATE_EXTRACTING;
});
_downloadDirectory = [[[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory
inDomain:NSUserDomainMask
appropriateForURL:[[NSBundle mainBundle] bundleURL]
create:true
error:nil] path];
if (!_downloadDirectory) {
[self deauthorize];
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Failed to extract update.";
_updateState = UPDATE_FAILED;
self.updateProgressButton.title = @"Close";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
return;
}
NSTask *unzipTask;
unzipTask = [[NSTask alloc] init];
unzipTask.launchPath = @"/usr/bin/unzip";
unzipTask.arguments = @[location.path, @"-d", _downloadDirectory];
[unzipTask launch];
[unzipTask waitUntilExit];
if (unzipTask.terminationStatus != 0 || unzipTask.terminationReason != NSTaskTerminationReasonExit) {
[self deauthorize];
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Failed to extract update.";
_updateState = UPDATE_FAILED;
self.updateProgressButton.title = @"Close";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
return;
}
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Update ready, save your game progress and click Install.";
_updateState = UPDATE_WAIT_INSTALL;
self.updateProgressButton.title = @"Install";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
}];
[_updateTask resume];
self.updateProgressWindow.preventsApplicationTerminationWhenModal = false;
[self.updateWindow beginSheet:self.updateProgressWindow completionHandler:^(NSModalResponse returnCode) {
[self.updateWindow close];
}];
}
- (void)performUpgrade
{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Instaling update…";
_updateState = UPDATE_INSTALLING;
self.updateProgressButton.enabled = false;
[self.updateProgressSpinner startAnimation:nil];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *executablePath = [[NSBundle mainBundle] executablePath];
NSString *contentsPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Contents"];
NSString *contentsTempPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"TempContents"];
NSString *updateContentsPath = [_downloadDirectory stringByAppendingPathComponent:@"SameBoy.app/Contents"];
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:contentsPath toPath:contentsTempPath error:&error];
if (error) {
[self deauthorize];
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
_downloadDirectory = nil;
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Failed to install update.";
_updateState = UPDATE_FAILED;
self.updateProgressButton.title = @"Close";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
return;
}
[[NSFileManager defaultManager] moveItemAtPath:updateContentsPath toPath:contentsPath error:&error];
if (error) {
[self deauthorize];
[[NSFileManager defaultManager] moveItemAtPath:contentsTempPath toPath:contentsPath error:nil];
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
_downloadDirectory = nil;
dispatch_sync(dispatch_get_main_queue(), ^{
self.updateProgressButton.enabled = false;
self.updateProgressLabel.stringValue = @"Failed to install update.";
_updateState = UPDATE_FAILED;
self.updateProgressButton.title = @"Close";
self.updateProgressButton.enabled = true;
[self.updateProgressSpinner stopAnimation:nil];
});
return;
}
[[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);
});
dispatch_async(dispatch_get_main_queue(), ^{
[NSApp terminate:nil];
});
});
}
- (IBAction)updateAction:(id)sender
{
switch (_updateState) {
case UPDATE_DOWNLOADING:
[_updateTask cancelByProducingResumeData:nil];
_updateTask = nil;
[self.updateProgressWindow close];
break;
case UPDATE_WAIT_INSTALL:
[self performUpgrade];
break;
case UPDATE_EXTRACTING:
case UPDATE_INSTALLING:
break;
case UPDATE_FAILED:
[self.updateProgressWindow close];
break;
}
}
- (void)orderFrontAboutPanel:(id)sender
{
// NSAboutPanelOptionApplicationIcon is not available prior to 10.13, but the key is still there and working.
[[NSApplication sharedApplication] orderFrontStandardAboutPanelWithOptions:@{
@"ApplicationIcon": [NSImage imageNamed:@"Icon"]
}];
}
- (void)controller:(JOYController *)controller buttonChangedState:(JOYButton *)button
{
if (!button.isPressed) return;
NSDictionary *mapping = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"JoyKitInstanceMapping"][controller.uniqueID];
if (!mapping) {
mapping = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"JoyKitNameMapping"][controller.deviceName];
}
JOYButtonUsage usage = ((JOYButtonUsage)[mapping[n2s(button.uniqueID)] unsignedIntValue]) ?: -1;
if (!mapping && usage >= JOYButtonUsageGeneric0) {
usage = GB_inline_const(JOYButtonUsage[], {JOYButtonUsageY, JOYButtonUsageA, JOYButtonUsageB, JOYButtonUsageX})[(usage - JOYButtonUsageGeneric0) & 3];
}
if (usage == GBJoyKitHotkey1 || usage == GBJoyKitHotkey2) {
if (_preferencesWindow && self.keyWindow == _preferencesWindow) {
return;
}
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"GBAllowBackgroundControllers"] && !self.keyWindow) {
return;
}
NSString *keyEquivalent = [[NSUserDefaults standardUserDefaults] stringForKey:usage == GBJoyKitHotkey1? @"GBJoypadHotkey1" : @"GBJoypadHotkey2"];
NSEventModifierFlags flags = NSEventModifierFlagCommand;
if ([keyEquivalent hasPrefix:@"^"]) {
flags |= NSEventModifierFlagShift;
[keyEquivalent substringFromIndex:1];
}
_simulatingMenuEvent = true;
[[NSApplication sharedApplication] sendEvent:[NSEvent keyEventWithType:NSEventTypeKeyDown
location:(NSPoint){0,}
modifierFlags:flags
timestamp:0
windowNumber:0
context:NULL
characters:keyEquivalent
charactersIgnoringModifiers:keyEquivalent
isARepeat:false
keyCode:0]];
_simulatingMenuEvent = false;
}
}
- (NSWindow *)keyWindow
{
NSWindow *ret = [super keyWindow];
if (!ret && _simulatingMenuEvent) {
ret = [(Document *)self.orderedDocuments.firstObject mainWindow];
}
return ret;
}
- (NSWindow *)mainWindow
{
NSWindow *ret = [super mainWindow];
if (!ret && _simulatingMenuEvent) {
ret = [(Document *)self.orderedDocuments.firstObject mainWindow];
}
return ret;
}
- (IBAction)openDebuggerHelp:(id)sender
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://sameboy.github.io/debugger/"]];
}
- (IBAction)openSponsor:(id)sender
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://github.com/sponsors/LIJI32"]];
}
- (void)dealloc
{
if (_downloadDirectory) {
[[NSFileManager defaultManager] removeItemAtPath:_downloadDirectory error:nil];
}
}
- (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
+14 -9
View File
@@ -1,7 +1,4 @@
#ifndef GBButtons_h
#define GBButtons_h
typedef enum : NSUInteger {
typedef enum {
GBRight,
GBLeft,
GBUp,
@@ -10,14 +7,24 @@ typedef enum : NSUInteger {
GBB,
GBSelect,
GBStart,
GBRapidA,
GBRapidB,
GBTurbo,
GBRewind,
GBUnderclock,
GBButtonCount,
GBGameBoyButtonCount = GBStart + 1,
GBHotkey1,
GBHotkey2,
GBTotalButtonCount,
GBKeyboardButtonCount = GBUnderclock + 1,
GBPerPlayerButtonCount = GBRapidB + 1,
} GBButton;
extern NSString const *GBButtonNames[GBButtonCount];
#define GBJoyKitHotkey1 JOYButtonUsageGeneric0 + 0x100
#define GBJoyKitHotkey2 JOYButtonUsageGeneric0 + 0x101
#define GBJoyKitRapidA JOYButtonUsageGeneric0 + 0x102
#define GBJoyKitRapidB JOYButtonUsageGeneric0 + 0x103
extern NSString const *GBButtonNames[GBTotalButtonCount];
static inline NSString *n2s(uint64_t number)
{
@@ -31,5 +38,3 @@ static inline NSString *button_to_preference_name(GBButton button, unsigned play
}
return [NSString stringWithFormat:@"GB%@", GBButtonNames[button]];
}
#endif
+1 -1
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"};
NSString const *GBButtonNames[] = {@"Right", @"Left", @"Up", @"Down", @"A", @"B", @"Select", @"Start", @"Rapid A", @"Rapid B", @"Turbo", @"Rewind", @"Slow-Motion", @"Hotkey 1", @"Hotkey 2"};
+5
View File
@@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBCPUView : NSView
- (void)addSample:(double)sample;
@end
+126
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
+5
View File
@@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBCenteredTextCell : NSTextFieldCell
@end
+29
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
+8
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
+234
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
+8 -6
View File
@@ -6,7 +6,7 @@
@implementation GBCheatTextView
- (bool)_insertText:(NSString *)string replacementRange:(NSRange)range
- (bool)_internalInsertText:(NSString *)string replacementRange:(NSRange)range
{
if (range.location == NSNotFound) {
range = self.selectedRange;
@@ -60,19 +60,19 @@
return true;
}
if (([string isEqualToString:@"$"] || [string isEqualToString:@":"]) && range.length == 0 && range.location == 0) {
if ([self _insertText:@"$00:" replacementRange:range]) {
if ([self _internalInsertText:@"$00:" replacementRange:range]) {
self.selectedRange = NSMakeRange(1, 2);
return true;
}
}
if ([string isEqualToString:@":"] && range.length + range.location == self.string.length) {
if ([self _insertText:@":$0" replacementRange:range]) {
if ([self _internalInsertText:@":$0" replacementRange:range]) {
self.selectedRange = NSMakeRange(self.string.length - 2, 2);
return true;
}
}
if ([string isEqualToString:@"$"]) {
if ([self _insertText:@"$0" replacementRange:range]) {
if ([self _internalInsertText:@"$0" replacementRange:range]) {
self.selectedRange = NSMakeRange(range.location + 1, 1);
return true;
}
@@ -88,8 +88,10 @@
- (void)insertText:(id)string replacementRange:(NSRange)replacementRange
{
if (![self _insertText:string replacementRange:replacementRange]) {
NSBeep();
if (![self _internalInsertText:string replacementRange:replacementRange]) {
if (![self _internalInsertText:[@"$" stringByAppendingString:string] replacementRange:replacementRange]) {
NSBeep();
}
}
}
+12 -8
View File
@@ -42,7 +42,7 @@
return nil;
}
- (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
size_t cheatCount;
GB_gameboy_t *gb = self.document.gameboy;
@@ -58,7 +58,7 @@
return @NO;
case 2:
return @"Add Cheat...";
return @"Add Cheat…";
case 3:
return @"";
@@ -92,14 +92,18 @@
self.importCodeField.stringValue.UTF8String,
self.importDescriptionField.stringValue.UTF8String,
true)) {
self.importCodeField.stringValue = @"";
self.importDescriptionField.stringValue = @"";
[self.cheatsTable reloadData];
[self tableViewSelectionDidChange:nil];
dispatch_async(dispatch_get_main_queue(), ^{
self.importCodeField.stringValue = @"";
self.importDescriptionField.stringValue = @"";
[self.cheatsTable reloadData];
[self tableViewSelectionDidChange:nil];
});
}
else {
NSBeep();
[GBWarningPopover popoverWithContents:@"This code is not a valid GameShark or GameGenie code" onView:self.importCodeField];
dispatch_async(dispatch_get_main_queue(), ^{
NSBeep();
[GBWarningPopover popoverWithContents:@"This code is not a valid GameShark or Game Genie code" onView:self.importCodeField];
});
}
}];
}
-5
View File
@@ -1,5 +0,0 @@
#import <Cocoa/Cocoa.h>
@interface GBColorCell : NSTextFieldCell
@end
-49
View File
@@ -1,49 +0,0 @@
#import "GBColorCell.h"
static inline double scale_channel(uint8_t x)
{
x &= 0x1f;
return x / 31.0;
}
@implementation GBColorCell
{
NSInteger _integerValue;
}
- (void)setObjectValue:(id)objectValue
{
_integerValue = [objectValue integerValue];
uint8_t r = _integerValue & 0x1F,
g = (_integerValue >> 5) & 0x1F,
b = (_integerValue >> 10) & 0x1F;
super.objectValue = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"$%04x", (uint16_t)(_integerValue & 0x7FFF)] attributes:@{
NSForegroundColorAttributeName: r * 3 + g * 4 + b * 2 > 120? [NSColor blackColor] : [NSColor whiteColor],
NSFontAttributeName: [NSFont userFixedPitchFontOfSize:12]
}];
}
- (NSInteger)integerValue
{
return _integerValue;
}
- (int)intValue
{
return (int)_integerValue;
}
- (NSColor *) backgroundColor
{
/* Todo: color correction */
uint16_t color = self.integerValue;
return [NSColor colorWithRed:scale_channel(color) green:scale_channel(color >> 5) blue:scale_channel(color >> 10) alpha:1.0];
}
- (BOOL)drawsBackground
{
return true;
}
@end
+5
View File
@@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBColorTextCell : NSTextFieldCell
@end
+19
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
+7
View File
@@ -0,0 +1,7 @@
#import <Cocoa/Cocoa.h>
@class GBDocument;
@interface GBDebuggerButton : NSButton
@property (weak) IBOutlet NSTextField *textField;
@end
+49
View File
@@ -0,0 +1,49 @@
#import "GBDebuggerButton.h"
@implementation GBDebuggerButton
{
NSTrackingArea *_trackingArea;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
self.toolTip = self.title;
self.imagePosition = NSImageOnly; // Newer versions of AppKit refuse to respect the value from the nib file
return self;
}
- (void)mouseEntered:(NSEvent *)event
{
if (@available(macOS 10.10, *)) {
NSDictionary *attributes = @{
NSForegroundColorAttributeName: [NSColor colorWithWhite:1.0 alpha:0.5],
NSFontAttributeName: self.textField.font
};
self.textField.placeholderAttributedString =
[[NSAttributedString alloc] initWithString:self.alternateTitle attributes:attributes];
}
}
- (void)mouseExited:(NSEvent *)event
{
if (@available(macOS 10.10, *)) {
if ([self.textField.placeholderAttributedString.string isEqualToString:self.alternateTitle]) {
self.textField.placeholderAttributedString = nil;
}
}
}
- (void)updateTrackingAreas
{
[super updateTrackingAreas];
if (_trackingArea) {
[self removeTrackingArea:_trackingArea];
}
_trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds]
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways
owner:self
userInfo:nil];
[self addTrackingArea:_trackingArea];
}
@end
+5
View File
@@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBDeleteButtonCell : NSButtonCell
@end
+30
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
View File
@@ -0,0 +1,5 @@
#import <Cocoa/Cocoa.h>
@interface GBDisabledButton : NSButton
@end
+8
View File
@@ -0,0 +1,8 @@
#import "GBDisabledButton.h"
@implementation GBDisabledButton
- (void)mouseDown:(NSEvent *)event
{
}
@end
+1 -1
View File
@@ -163,7 +163,7 @@ void main(void) {\n\
/* OpenGL is black magic. Closing one view causes others to be completely black unless we reload their shaders */
/* We're probably not freeing thing in the right place. */
[[NSNotificationCenter defaultCenter] postNotificationName:@"GBFilterChanged" object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"GBFilterChanged$DefaultsObserver" object:nil];
}
+ (GLuint)shaderWithContents:(NSString*)contents type:(GLenum)type
@@ -0,0 +1,10 @@
#import <Core/gb.h>
#import <HexFiend/HFRepresenter.h>
@interface GBHexStatusBarRepresenter : HFRepresenter
@property GB_gameboy_t *gb;
@property (nonatomic) bool useDecimalLength;
@property (nonatomic) uint16_t bankForDescription;
@property (nonatomic) uint16_t baseAddress;
@end
+220
View File
@@ -0,0 +1,220 @@
#import "GBHexStatusBarRepresenter.h"
#import <HexFiend/HFFunctions.h>
@interface GBHexStatusBarView : NSView
{
NSCell *_cell;
NSSize _cellSize;
GBHexStatusBarRepresenter *_representer;
NSDictionary *_cellAttributes;
bool _registeredForAppNotifications;
}
- (void)setRepresenter:(GBHexStatusBarRepresenter *)rep;
- (void)setString:(NSString *)string;
@end
@implementation GBHexStatusBarView
- (void)_sharedInitStatusBarView
{
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment:NSCenterTextAlignment];
style.lineBreakMode = NSLineBreakByTruncatingTail;
_cellAttributes = @{
NSForegroundColorAttributeName: [NSColor windowFrameTextColor],
NSFontAttributeName: [NSFont labelFontOfSize:[NSFont smallSystemFontSize]],
NSParagraphStyleAttributeName: style,
};
_cell = [[NSCell alloc] initTextCell:@""];
[_cell setAlignment:NSCenterTextAlignment];
[_cell setBackgroundStyle:NSBackgroundStyleRaised];
}
- (instancetype)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
[self _sharedInitStatusBarView];
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
[self _sharedInitStatusBarView];
return self;
}
- (BOOL)isFlipped
{
return true;
}
- (void)setRepresenter:(GBHexStatusBarRepresenter *)rep
{
_representer = rep;
}
- (void)setString:(NSString *)string
{
[_cell setAttributedStringValue:[[NSAttributedString alloc] initWithString:string attributes:_cellAttributes]];
_cellSize = [_cell cellSize];
[self setNeedsDisplay:true];
}
- (void)drawRect:(NSRect)clip
{
NSRect bounds = [self bounds];
NSRect cellRect = NSMakeRect(NSMinX(bounds), HFCeil(NSMidY(bounds) - _cellSize.height / 2), NSWidth(bounds), _cellSize.height);
[_cell drawWithFrame:cellRect inView:self];
}
- (void)setFrame:(NSRect)frame
{
[super setFrame:frame];
[self.window setContentBorderThickness:frame.origin.y + frame.size.height forEdge:NSMinYEdge];
}
- (void)mouseDown:(NSEvent *)event
{
_representer.useDecimalLength ^= true;
}
- (void)windowDidChangeKeyStatus:(NSNotification *)note
{
[self setNeedsDisplay:true];
}
- (void)viewDidMoveToWindow
{
HFRegisterViewForWindowAppearanceChanges(self, @selector(windowDidChangeKeyStatus:), !_registeredForAppNotifications);
_registeredForAppNotifications = true;
[self.window setContentBorderThickness:self.frame.origin.y + self.frame.size.height forEdge:NSMinYEdge];
[super viewDidMoveToWindow];
}
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
{
HFUnregisterViewForWindowAppearanceChanges(self, NO);
[super viewWillMoveToWindow:newWindow];
}
- (void)dealloc
{
HFUnregisterViewForWindowAppearanceChanges(self, _registeredForAppNotifications);
}
@end
@implementation GBHexStatusBarRepresenter
- (instancetype)init
{
self = [super init];
return self;
}
- (NSView *)createView {
GBHexStatusBarView *view = [[GBHexStatusBarView alloc] initWithFrame:NSMakeRect(0, 0, 100, 18)];
[view setRepresenter:self];
[view setAutoresizingMask:NSViewWidthSizable];
return view;
}
- (NSString *)describeLength:(unsigned long long)length
{
if (self.useDecimalLength) {
return [NSString stringWithFormat:@"%llu byte%s", length, length == 1 ? "" : "s"];
}
return [NSString stringWithFormat:@"$%llX byte%s", length, length == 1 ? "" : "s"];
}
- (NSString *)describeOffset:(unsigned long long)offset isRangeEnd:(bool)isRangeEnd
{
if (!_gb) {
return [NSString stringWithFormat:@"$%llX", offset];
}
return @(GB_debugger_describe_address(_gb, offset + _baseAddress, offset < 0x4000? -1 :_bankForDescription, false, isRangeEnd));
}
- (NSString *)stringForEmptySelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length
{
return [self describeOffset:offset isRangeEnd:false];
}
- (NSString *)stringForSingleByteSelectionAtOffset:(unsigned long long)offset length:(unsigned long long)length
{
return [NSString stringWithFormat:@"Byte %@ selected", [self describeOffset:offset isRangeEnd:false]];
}
- (NSString *)stringForSingleRangeSelection:(HFRange)range length:(unsigned long long)length
{
return [NSString stringWithFormat:@"Range %@ to %@ selected (%@)",
[self describeOffset:range.location isRangeEnd:false],
[self describeOffset:range.location + range.length isRangeEnd:true],
[self describeLength:range.length]];
}
- (void)updateString
{
NSString *string = nil;
HFController *controller = [self controller];
if (controller) {
unsigned long long length = [controller contentsLength];
NSArray *ranges = [controller selectedContentsRanges];
NSUInteger rangeCount = [ranges count];
if (rangeCount == 1) {
HFRange range = [ranges[0] HFRange];
if (range.length == 0) {
string = [self stringForEmptySelectionAtOffset:range.location length:length];
}
else if (range.length == 1) {
string = [self stringForSingleByteSelectionAtOffset:range.location length:length];
}
else {
string = [self stringForSingleRangeSelection:range length:length];
}
}
else {
string = @"Multiple ranges selected";
}
}
if (! string) string = @"";
[[self view] setString:string];
}
- (void)setUseDecimalLength:(bool)useDecimalLength
{
_useDecimalLength = useDecimalLength;
[self updateString];
}
- (void)setBaseAddress:(uint16_t)baseAddress
{
_baseAddress = baseAddress;
[self updateString];
}
- (void) setBankForDescription:(uint16_t)bankForDescription
{
_bankForDescription = bankForDescription;
[self updateString];
}
- (void)controllerDidChange:(HFControllerPropertyBits)bits
{
if (bits & (HFControllerContentLength | HFControllerSelectedRanges)) {
[self updateString];
}
}
+ (NSPoint)defaultLayoutPosition
{
return NSMakePoint(0, -1);
}
@end
+9
View File
@@ -0,0 +1,9 @@
#import <Cocoa/Cocoa.h>
@interface NSSlider (GBHueSlider)
-(NSColor *)colorValue;
@end
@interface GBHueSliderCell : NSSliderCell
-(NSColor *)colorValue;
@end
+125
View File
@@ -0,0 +1,125 @@
#import "GBHueSliderCell.h"
@interface NSSliderCell(privateAPI)
- (double)_normalizedDoubleValue;
@end
@implementation GBHueSliderCell
{
bool _drawingTrack;
}
-(NSColor *)colorValue
{
double hue = self.doubleValue / 360.0;
double r = 0, g = 0, b =0 ;
double t = fmod(hue * 6, 1);
switch ((int)(hue * 6) % 6) {
case 0:
r = 1;
g = t;
break;
case 1:
r = 1 - t;
g = 1;
break;
case 2:
g = 1;
b = t;
break;
case 3:
g = 1 - t;
b = 1;
break;
case 4:
b = 1;
r = t;
break;
case 5:
b = 1 - t;
r = 1;
break;
}
return [NSColor colorWithRed:r green:g blue:b alpha:1.0];
}
-(void)drawKnob:(NSRect)knobRect
{
[super drawKnob:knobRect];
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];
[path fill];
[[NSColor colorWithWhite:0 alpha:0.25] setStroke];
[path setLineWidth:0.5];
[path stroke];
}
-(double)_normalizedDoubleValue
{
if (_drawingTrack) return 0;
return [super _normalizedDoubleValue];
}
-(void)drawBarInside:(NSRect)rect flipped:(BOOL)flipped
{
if (!self.enabled) {
[super drawBarInside:rect flipped:flipped];
return;
}
_drawingTrack = true;
[super drawBarInside:rect flipped:flipped];
_drawingTrack = false;
NSGradient *gradient = [[NSGradient alloc] initWithColors:@[
[NSColor redColor],
[NSColor yellowColor],
[NSColor greenColor],
[NSColor cyanColor],
[NSColor blueColor],
[NSColor magentaColor],
[NSColor redColor],
]];
rect.origin.y += rect.size.height / 2 - 0.5;
rect.size.height = 1;
rect.size.width -= 2;
rect.origin.x += 1;
[[NSColor redColor] set];
NSRectFill(rect);
rect.size.width -= self.knobThickness + 2;
rect.origin.x += self.knobThickness / 2 - 1;
[gradient drawInRect:rect angle:0];
}
@end
@implementation NSSlider (GBHueSlider)
- (NSColor *)colorValue
{
return ((GBHueSliderCell *)self.cell).colorValue;
}
@end
-5
View File
@@ -1,5 +0,0 @@
#import <Cocoa/Cocoa.h>
@interface GBImageCell : NSImageCell
@end
-10
View File
@@ -1,10 +0,0 @@
#import "GBImageCell.h"
@implementation GBImageCell
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
[super drawWithFrame:cellFrame inView:controlView];
}
@end
+62 -22
View File
@@ -10,18 +10,18 @@
}
@end
@implementation GBImageView
{
NSTrackingArea *trackingArea;
}
@interface GBGridView : NSView
@end
@implementation GBGridView
- (void)drawRect:(NSRect)dirtyRect
{
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
[super drawRect:dirtyRect];
CGFloat y_ratio = self.frame.size.height / self.image.size.height;
CGFloat x_ratio = self.frame.size.width / self.image.size.width;
for (GBImageViewGridConfiguration *conf in self.verticalGrids) {
GBImageView *parent = (GBImageView *)self.superview;
CGFloat y_ratio = parent.frame.size.height / parent.image.size.height;
CGFloat x_ratio = parent.frame.size.width / parent.image.size.width;
for (GBImageViewGridConfiguration *conf in parent.verticalGrids) {
[conf.color set];
for (CGFloat y = conf.size * y_ratio; y < self.frame.size.height; y += conf.size * y_ratio) {
NSBezierPath *line = [NSBezierPath bezierPath];
@@ -32,7 +32,7 @@
}
}
for (GBImageViewGridConfiguration *conf in self.horizontalGrids) {
for (GBImageViewGridConfiguration *conf in parent.horizontalGrids) {
[conf.color set];
for (CGFloat x = conf.size * x_ratio; x < self.frame.size.width; x += conf.size * x_ratio) {
NSBezierPath *line = [NSBezierPath bezierPath];
@@ -43,11 +43,12 @@
}
}
if (self.displayScrollRect) {
NSBezierPath *path = [NSBezierPath bezierPathWithRect:CGRectInfinite];
if (parent.displayScrollRect) {
// 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 = self.scrollRect;
NSRect rect = parent.scrollRect;
rect.origin.x *= x_ratio;
rect.origin.y *= y_ratio;
rect.size.width *= x_ratio;
@@ -56,7 +57,7 @@
rect.origin.x -= self.frame.size.width * x;
rect.origin.y += self.frame.size.height * y;
NSBezierPath *subpath = [NSBezierPath bezierPathWithRect:rect];
[path appendBezierPath:subpath];
@@ -72,36 +73,62 @@
[path stroke];
}
}
@end
@implementation GBImageView
{
NSTrackingArea *_trackingArea;
GBGridView *_gridView;
NSRect _scrollRect;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
self.wantsLayer = true;
_gridView = [[GBGridView alloc] initWithFrame:self.bounds];
_gridView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[self addSubview:_gridView];
return self;
}
-(void)viewWillDraw
{
[super viewWillDraw];
for (CALayer *layer in self.layer.sublayers) {
layer.magnificationFilter = kCAFilterNearest;
}
}
- (void)setHorizontalGrids:(NSArray *)horizontalGrids
{
self->_horizontalGrids = horizontalGrids;
[self setNeedsDisplay];
[_gridView setNeedsDisplay:true];
}
- (void)setVerticalGrids:(NSArray *)verticalGrids
{
self->_verticalGrids = verticalGrids;
[self setNeedsDisplay];
[_gridView setNeedsDisplay:true];
}
- (void)setDisplayScrollRect:(bool)displayScrollRect
{
self->_displayScrollRect = displayScrollRect;
[self setNeedsDisplay];
[_gridView setNeedsDisplay:true];
}
- (void)updateTrackingAreas
{
if (trackingArea != nil) {
[self removeTrackingArea:trackingArea];
if (_trackingArea != nil) {
[self removeTrackingArea:_trackingArea];
}
trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds]
_trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds]
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingMouseMoved
owner:self
userInfo:nil];
[self addTrackingArea:trackingArea];
[self addTrackingArea:_trackingArea];
}
- (void)mouseExited:(NSEvent *)theEvent
@@ -124,4 +151,17 @@
}
}
- (void)setScrollRect:(NSRect)scrollRect
{
if (memcmp(&scrollRect, &_scrollRect, sizeof(scrollRect)) != 0) {
_scrollRect = scrollRect;
[_gridView setNeedsDisplay:true];
}
}
- (NSRect)scrollRect
{
return _scrollRect;
}
@end
+12
View File
@@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <JoyKit/JoyKit.h>
@interface GBJoyConManager : NSObject<JOYListener, NSTableViewDataSource, NSTableViewDelegate>
+ (instancetype)sharedInstance;
- (IBAction)autopair:(id)sender;
@property (nonatomic) bool arrangementMode;
@property (weak) IBOutlet NSTableView *tableView;
@end
+313
View File
@@ -0,0 +1,313 @@
#import "GBJoyConManager.h"
#import "GBTintedImageCell.h"
#import <objc/runtime.h>
@implementation GBJoyConManager
{
GBTintedImageCell *_tintedImageCell;
NSImageCell *_imageCell;
NSMutableDictionary<NSString *, NSString *> *_pairings;
NSMutableDictionary<NSString *, NSNumber *> *_gripSettings;
bool _unpairing;
}
+ (instancetype)sharedInstance
{
static GBJoyConManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[super allocWithZone:nil] _init];
});
return manager;
}
- (NSArray <JOYController *> *)joycons
{
NSMutableArray *ret = [[JOYController allControllers] mutableCopy];
for (JOYController *controller in [JOYController allControllers]) {
if (controller.joyconType == JOYJoyConTypeNone) {
[ret removeObject:controller];
}
}
return ret;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
return [self sharedInstance];
}
+ (instancetype)alloc
{
return [self sharedInstance];
}
- (instancetype)init
{
return [self.class sharedInstance];
}
- (instancetype) _init
{
self = [super init];
_imageCell = [[NSImageCell alloc] init];
_tintedImageCell = [[GBTintedImageCell alloc] init];
if (@available(macOS 10.14, *)) {
_tintedImageCell.tint = [NSColor controlAccentColor];
}
else {
_tintedImageCell.tint = [NSColor selectedMenuItemColor];
}
_pairings = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"GBJoyConPairings"] ?: @{} mutableCopy];
_gripSettings = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"GBJoyConGrips"] ?: @{} mutableCopy];
// Sanity check the pairings
for (NSString *key in _pairings) {
if (![_pairings[_pairings[key]] isEqualToString:key]) {
[_pairings removeAllObjects];
break;
}
}
[JOYController registerListener:self];
for (JOYController *controller in [JOYController allControllers]) {
[self controllerConnected:controller];
}
return self;
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return self.joycons.count;
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
if (row >= [self numberOfRowsInTableView:tableView]) return nil;
unsigned columnIndex = [[tableView tableColumns] indexOfObject:tableColumn];
JOYController *controller = self.joycons[row];
switch (columnIndex) {
case 0: {
switch (controller.joyconType) {
case JOYJoyConTypeNone:
return nil;
case JOYJoyConTypeLeft:
return [NSImage imageNamed:[NSString stringWithFormat:@"%sJoyConLeftTemplate", controller.usesHorizontalJoyConGrip? "Horizontal" :""]];
case JOYJoyConTypeRight:
return [NSImage imageNamed:[NSString stringWithFormat:@"%sJoyConRightTemplate", controller.usesHorizontalJoyConGrip? "Horizontal" :""]];
case JOYJoyConTypeDual:
return [NSImage imageNamed:@"JoyConDualTemplate"];
}
}
case 1: {
NSMutableAttributedString *ret = [[NSMutableAttributedString alloc] initWithString:controller.deviceName
attributes:@{NSFontAttributeName:
[NSFont systemFontOfSize:[NSFont systemFontSize]]}];
[ret appendAttributedString:[[NSAttributedString alloc] initWithString:[@"\n" stringByAppendingString:controller.uniqueID]
attributes:@{NSFontAttributeName:
[NSFont systemFontOfSize:[NSFont smallSystemFontSize]],
NSForegroundColorAttributeName:[NSColor disabledControlTextColor]}]];
return ret;
}
case 2:
return @([(_gripSettings[controller.uniqueID] ?: @(-1)) unsignedIntValue] + 1);
}
return nil;
}
- (void)updateGripForController:(JOYController *)controller
{
NSNumber *grip = _gripSettings[controller.uniqueID];
if (!grip) {
controller.usesHorizontalJoyConGrip = [[NSUserDefaults standardUserDefaults] boolForKey:@"GBJoyConsDefaultsToHorizontal"];
return;
}
controller.usesHorizontalJoyConGrip = [grip unsignedIntValue] == 1;
}
- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
unsigned columnIndex = [[tableView tableColumns] indexOfObject:tableColumn];
if (columnIndex != 2) return;
if (row >= [self numberOfRowsInTableView:tableView]) return;
JOYController *controller = self.joycons[row];
if (controller.joyconType == JOYJoyConTypeDual) {
return;
}
switch ([object unsignedIntValue]) {
case 0:
[_gripSettings removeObjectForKey:controller.uniqueID];
break;
case 1:
_gripSettings[controller.uniqueID] = @(0);
break;
case 2:
_gripSettings[controller.uniqueID] = @(1);
break;
}
[[NSUserDefaults standardUserDefaults] setObject:_gripSettings forKey:@"GBJoyConGrips"];
[self updateGripForController:controller];
}
- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
if (row >= [self numberOfRowsInTableView:tableView]) return [[NSCell alloc] init];
unsigned columnIndex = [[tableView tableColumns] indexOfObject:tableColumn];
if (columnIndex == 2) {
JOYCombinedController *controller = (JOYCombinedController *)self.joycons[row];
if (controller.joyconType == JOYJoyConTypeDual) {
NSButtonCell *cell = [[NSButtonCell alloc] initTextCell:@"Separate Joy-Cons"];
cell.bezelStyle = NSBezelStyleRounded;
cell.action = @selector(invoke);
id block = ^(void) {
dispatch_async(dispatch_get_main_queue(), ^{
for (JOYController *child in controller.children) {
[_pairings removeObjectForKey:child.uniqueID];
}
[[NSUserDefaults standardUserDefaults] setObject:_pairings forKey:@"GBJoyConPairings"];
_unpairing = true;
[controller breakApart];
_unpairing = false;
});
};
// To retain the block
objc_setAssociatedObject(cell, @selector(breakApart), block, OBJC_ASSOCIATION_RETAIN);
cell.target = block;
return cell;
}
}
if (columnIndex == 0) {
JOYController *controller = self.joycons[row];
for (JOYButton *button in controller.buttons) {
if (button.isPressed) {
return _tintedImageCell;
}
}
return _imageCell;
}
return nil;
}
- (void)controllerConnected:(JOYController *)controller
{
[self updateGripForController:controller];
for (JOYController *partner in [JOYController allControllers]) {
if ([partner.uniqueID isEqualToString:_pairings[controller.uniqueID]]) {
[self pairJoyCon:controller withJoyCon:partner];
break;
}
}
if (controller.joyconType == JOYJoyConTypeLeft || controller.joyconType == JOYJoyConTypeRight) {
[self autopair:nil];
}
if (_arrangementMode) {
[self.tableView reloadData];
}
}
- (IBAction)autopair:(id)sender
{
if (_unpairing) return;
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"GBJoyConAutoPair"]) return;
NSArray<JOYController *> *controllers = [[JOYController allControllers] copy];
for (JOYController *first in controllers) {
if (_pairings[first.uniqueID]) continue; // Has an established partner
if (first.joyconType != JOYJoyConTypeLeft) continue;
for (JOYController *second in controllers) {
if (_pairings[second.uniqueID]) continue; // Has an established partner
if (second.joyconType != JOYJoyConTypeRight) continue;
[self pairJoyCon:first withJoyCon:second];
break;
}
}
if (_arrangementMode) {
[self.tableView reloadData];
}
}
- (void)controllerDisconnected:(JOYController *)controller
{
if (_arrangementMode) {
[self.tableView reloadData];
}
}
- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
unsigned columnIndex = [[tableView tableColumns] indexOfObject:tableColumn];
return columnIndex == 2;
}
- (JOYCombinedController *)pairJoyCon:(JOYController *)first withJoyCon:(JOYController *)second
{
if (first.joyconType != JOYJoyConTypeLeft && first.joyconType != JOYJoyConTypeRight) return nil; // Not a Joy-Con
if (second.joyconType != JOYJoyConTypeLeft && second.joyconType != JOYJoyConTypeRight) return nil; // Not a Joy-Con
if (first.joyconType == second.joyconType) return nil; // Not a sensible pair
_pairings[first.uniqueID] = second.uniqueID;
_pairings[second.uniqueID] = first.uniqueID;
first.usesHorizontalJoyConGrip = false;
second.usesHorizontalJoyConGrip = false;
[[NSUserDefaults standardUserDefaults] setObject:_pairings forKey:@"GBJoyConPairings"];
return [[JOYCombinedController alloc] initWithChildren:@[first, second]];
}
- (void)controller:(JOYController *)controller buttonChangedState:(JOYButton *)button
{
if (!_arrangementMode) return;
if (controller.joyconType == JOYJoyConTypeNone) return;
[self.tableView setNeedsDisplay:true];
if (controller.joyconType != JOYJoyConTypeLeft && controller.joyconType != JOYJoyConTypeRight) return;
if (button.usage != JOYButtonUsageL1 && button.usage != JOYButtonUsageR1) return;
// L or R were pressed on a single Joy-Con, try and pair available Joy-Cons
JOYController *left = nil;
JOYController *right = nil;
for (JOYController *controller in [JOYController allControllers]) {
if (!left && controller.joyconType == JOYJoyConTypeLeft) {
for (JOYButton *button in controller.buttons) {
if (button.usage == JOYButtonUsageL1 && button.isPressed) {
left = controller;
break;
}
}
}
if (!right && controller.joyconType == JOYJoyConTypeRight) {
for (JOYButton *button in controller.buttons) {
if (button.usage == JOYButtonUsageR1 && button.isPressed) {
right = controller;
break;
}
}
}
if (left && right) {
[self pairJoyCon:left withJoyCon:right];
return;
}
}
}
- (IBAction)toggleHorizontalDefault:(NSButton *)sender
{
for (JOYController *controller in self.joycons) {
[self updateGripForController:controller];
}
if (_arrangementMode) {
[self.tableView reloadData];
}
}
- (void)setArrangementMode:(bool)arrangementMode
{
_arrangementMode = arrangementMode;
if (arrangementMode) {
[self.tableView reloadData];
}
}
@end
+187 -108
View File
@@ -1,4 +1,3 @@
#define GB_INTERNAL // Todo: Some memory accesses are being done using the struct directly
#import "GBMemoryByteArray.h"
#import "GBCompleteByteSlice.h"
@@ -32,69 +31,110 @@
}
}
- (uint16_t)base
{
switch (_mode) {
case GBMemoryEntireSpace: return 0;
case GBMemoryROM: return 0;
case GBMemoryVRAM: return 0x8000;
case GBMemoryExternalRAM: return 0xA000;
case GBMemoryRAM: return 0xC000;
}
}
- (void)copyBytes:(unsigned char *)dst range:(HFRange)range
{
__block uint16_t addr = (uint16_t) range.location;
__block unsigned long long length = range.length;
if (_mode == GBMemoryEntireSpace) {
while (length) {
*(dst++) = [_document readMemory:addr++];
length--;
}
// Do everything in 0x1000 chunks, never cross a 0x1000 boundary
if ((range.location & 0xF000) != ((range.location + range.length) & 0xF000)) {
size_t partial = 0x1000 - (range.location & 0xFFF);
[self copyBytes:dst + partial range:HFRangeMake(range.location + partial, range.length - partial)];
range.length = partial;
}
else {
[_document performAtomicBlock:^{
unsigned char *_dst = dst;
uint16_t bank_backup = 0;
GB_gameboy_t *gb = _document.gameboy;
switch (_mode) {
case GBMemoryROM:
bank_backup = gb->mbc_rom_bank;
gb->mbc_rom_bank = self.selectedBank;
break;
case GBMemoryVRAM:
bank_backup = gb->cgb_vram_bank;
if (GB_is_cgb(gb)) {
gb->cgb_vram_bank = self.selectedBank;
range.location += self.base;
GB_gameboy_t *gb = _document.gameboy;
switch (range.location >> 12) {
case 0x0:
case 0x1:
case 0x2:
case 0x3: {
uint16_t bank;
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_ROM0, NULL, &bank);
memcpy(dst, data + bank * 0x4000 + range.location, range.length);
break;
}
case 0x4:
case 0x5:
case 0x6:
case 0x7: {
uint16_t bank;
size_t size;
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_ROM, &size, &bank);
if (_mode != GBMemoryEntireSpace) {
bank = self.selectedBank & (size / 0x4000 - 1);
}
memcpy(dst, data + bank * 0x4000 + range.location - 0x4000, range.length);
break;
}
case 0x8:
case 0x9: {
uint16_t bank;
size_t size;
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_VRAM, &size, &bank);
if (_mode != GBMemoryEntireSpace) {
bank = self.selectedBank & (size / 0x2000 - 1);
}
memcpy(dst, data + bank * 0x2000 + range.location - 0x8000, range.length);
break;
}
case 0xA:
case 0xB: {
// Some carts are special, use memory read directly in full mem mode
if (_mode == GBMemoryEntireSpace) {
case 0xF:
slow_path:
[_document performAtomicBlock:^{
for (unsigned i = 0; i < range.length; i++) {
dst[i] = GB_safe_read_memory(gb, range.location + i);
}
addr += 0x8000;
break;
case GBMemoryExternalRAM:
bank_backup = gb->mbc_ram_bank;
gb->mbc_ram_bank = self.selectedBank;
addr += 0xA000;
break;
case GBMemoryRAM:
bank_backup = gb->cgb_ram_bank;
if (GB_is_cgb(gb)) {
gb->cgb_ram_bank = self.selectedBank;
}
addr += 0xC000;
break;
default:
assert(false);
}];
break;
}
while (length) {
*(_dst++) = [_document readMemory:addr++];
length--;
else {
uint16_t bank;
size_t size;
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_CART_RAM, &size, &bank);
bank = self.selectedBank & (size / 0x2000 - 1);
if (size == 0) {
memset(dst, 0xFF, range.length);
}
else if (range.location + range.length - 0xA000 > size) {
goto slow_path;
}
else {
memcpy(dst, data + bank * 0x2000 + range.location - 0xA000, range.length);
}
break;
}
switch (_mode) {
case GBMemoryROM:
gb->mbc_rom_bank = bank_backup;
break;
case GBMemoryVRAM:
gb->cgb_vram_bank = bank_backup;
break;
case GBMemoryExternalRAM:
gb->mbc_ram_bank = bank_backup;
break;
case GBMemoryRAM:
gb->cgb_ram_bank = bank_backup;
break;
default:
assert(false);
}
case 0xC:
case 0xE: {
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_RAM, NULL, NULL);
memcpy(dst, data + (range.location & 0xFFF), range.length);
break;
}
case 0xD: {
uint16_t bank;
size_t size;
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_RAM, &size, &bank);
if (_mode != GBMemoryEntireSpace) {
bank = self.selectedBank & (size / 0x1000 - 1);
}
}];
memcpy(dst, data + bank * 0x1000 + range.location - 0xD000, range.length);
break;
}
}
}
@@ -113,65 +153,104 @@
return ret;
}
- (void)insertByteSlice:(HFByteSlice *)slice inRange:(HFRange)lrange
- (void)insertByteSlice:(HFByteSlice *)slice inRange:(HFRange)range
{
if (slice.length != lrange.length) return; /* Insertion is not allowed, only overwriting. */
[_document performAtomicBlock:^{
uint16_t addr = (uint16_t) lrange.location;
uint16_t bank_backup = 0;
GB_gameboy_t *gb = _document.gameboy;
switch (_mode) {
case GBMemoryROM:
bank_backup = gb->mbc_rom_bank;
gb->mbc_rom_bank = self.selectedBank;
if (slice.length != range.length) return; /* Insertion is not allowed, only overwriting. */
// Do everything in 0x1000 chunks, never cross a 0x1000 boundary
if ((range.location & 0xF000) != ((range.location + range.length) & 0xF000)) {
size_t partial = 0x1000 - (range.location & 0xFFF);
if (slice.length - partial) {
[self insertByteSlice:[slice subsliceWithRange:HFRangeMake(partial, slice.length - partial)]
inRange:HFRangeMake(range.location + partial, range.length - partial)];
}
range.length = partial;
}
range.location += self.base;
GB_gameboy_t *gb = _document.gameboy;
switch (range.location >> 12) {
case 0x0:
case 0x1:
case 0x2:
case 0x3:
case 0x4:
case 0x5:
case 0x6:
case 0x7: {
return; // ROM not writeable
}
case 0x8:
case 0x9: {
uint16_t bank;
size_t size;
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_VRAM, &size, &bank);
if (_mode != GBMemoryEntireSpace) {
bank = self.selectedBank & (size / 0x2000 - 1);
}
uint8_t sliceData[range.length];
[slice copyBytes:sliceData range:HFRangeMake(0, range.length)];
memcpy(data + bank * 0x2000 + range.location - 0x8000, sliceData, range.length);
break;
}
case 0xA:
case 0xB: {
// Some carts are special, use memory write directly in full mem mode
if (_mode == GBMemoryEntireSpace) {
case 0xF:
slow_path:
[_document performAtomicBlock:^{
uint8_t sliceData[range.length];
[slice copyBytes:sliceData range:HFRangeMake(0, range.length)];
for (unsigned i = 0; i < range.length; i++) {
GB_write_memory(gb, range.location + i, sliceData[i]);
}
}];
break;
case GBMemoryVRAM:
bank_backup = gb->cgb_vram_bank;
if (GB_is_cgb(gb)) {
gb->cgb_vram_bank = self.selectedBank;
}
else {
uint16_t bank;
size_t size;
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_CART_RAM, &size, &bank);
bank = self.selectedBank & (size / 0x2000 - 1);
if (size == 0) {
// Nothing to write to
}
addr += 0x8000;
break;
case GBMemoryExternalRAM:
bank_backup = gb->mbc_ram_bank;
gb->mbc_ram_bank = self.selectedBank;
addr += 0xA000;
break;
case GBMemoryRAM:
bank_backup = gb->cgb_ram_bank;
if (GB_is_cgb(gb)) {
gb->cgb_ram_bank = self.selectedBank;
else if (range.location + range.length - 0xA000 > size) {
goto slow_path;
}
else {
uint8_t sliceData[range.length];
[slice copyBytes:sliceData range:HFRangeMake(0, range.length)];
memcpy(data + bank * 0x2000 + range.location - 0xA000, sliceData, range.length);
}
addr += 0xC000;
break;
default:
break;
}
}
uint8_t values[lrange.length];
[slice copyBytes:values range:HFRangeMake(0, lrange.length)];
uint8_t *src = values;
unsigned long long length = lrange.length;
while (length) {
[_document writeMemory:addr++ value:*(src++)];
length--;
case 0xC:
case 0xE: {
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_RAM, NULL, NULL);
uint8_t sliceData[range.length];
[slice copyBytes:sliceData range:HFRangeMake(0, range.length)];
memcpy(data + (range.location & 0xFFF), sliceData, range.length);
break;
}
switch (_mode) {
case GBMemoryROM:
gb->mbc_rom_bank = bank_backup;
break;
case GBMemoryVRAM:
gb->cgb_vram_bank = bank_backup;
break;
case GBMemoryExternalRAM:
gb->mbc_ram_bank = bank_backup;
break;
case GBMemoryRAM:
gb->cgb_ram_bank = bank_backup;
break;
default:
break;
case 0xD: {
uint16_t bank;
size_t size;
uint8_t *data = GB_get_direct_access(gb, GB_DIRECT_ACCESS_RAM, &size, &bank);
if (_mode != GBMemoryEntireSpace) {
bank = self.selectedBank & (size / 0x1000 - 1);
}
uint8_t sliceData[range.length];
[slice copyBytes:sliceData range:HFRangeMake(0, range.length)];
memcpy(data + bank * 0x1000 + range.location - 0xD000, sliceData, range.length);
break;
}
}];
}
}
@end
+6
View File
@@ -0,0 +1,6 @@
#import <Cocoa/Cocoa.h>
#import "Document.h"
@interface GBObjectView : NSView
- (void)reloadData:(Document *)document;
@end
+134
View File
@@ -0,0 +1,134 @@
#import "GBObjectView.h"
@interface GBObjectViewItem : NSObject
@property IBOutlet NSView *view;
@property IBOutlet NSImageView *image;
@property IBOutlet NSTextField *oamAddress;
@property IBOutlet NSTextField *position;
@property IBOutlet NSTextField *attributes;
@property IBOutlet NSTextField *tile;
@property IBOutlet NSTextField *tileAddress;
@property IBOutlet NSImageView *warningIcon;
@property IBOutlet NSBox *verticalLine;
@end
@implementation GBObjectViewItem
{
@public
uint32_t _lastImageData[128];
uint8_t _lastHeight;
}
@end
@implementation GBObjectView
{
NSMutableArray<GBObjectViewItem *> *_items;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
_items = [NSMutableArray array];
CGFloat height = self.frame.size.height;
for (unsigned i = 0; i < 40; i++) {
GBObjectViewItem *item = [[GBObjectViewItem alloc] init];
[_items addObject:item];
[[NSBundle mainBundle] loadNibNamed:@"GBObjectViewItem" owner:item topLevelObjects:nil];
item.view.hidden = true;
[self addSubview:item.view];
[item.view setFrameOrigin:NSMakePoint((i % 4) * 120, height - (i / 4 * 68) - 68)];
item.oamAddress.toolTip = @"OAM address";
item.position.toolTip = @"Position";
item.attributes.toolTip = @"Attributes";
item.tile.toolTip = @"Tile index";
item.tileAddress.toolTip = @"Tile address";
item.warningIcon.toolTip = @"Dropped: too many objects in line";
if ((i % 4) == 3) {
[item.verticalLine removeFromSuperview];
}
item.view.autoresizingMask = NSViewMaxXMargin | NSViewMinYMargin;
}
return self;
}
- (void)reloadData:(Document *)document
{
GB_oam_info_t *info = document.oamInfo;
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) {
item.view.hidden = true;
}
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,
((signed)(unsigned)info[i].y) - 16];
item.tile.stringValue = [NSString stringWithFormat:@"$%02X", info[i].tile];
item.tileAddress.stringValue = [NSString stringWithFormat:@"$%04X", 0x8000 + info[i].tile * 0x10];
item.warningIcon.hidden = !info[i].obscured_by_line_limit;
if (cgb) {
item.attributes.stringValue = [NSString stringWithFormat:@"%c%c%c%d%d",
info[i].flags & 0x80? 'P' : '-',
info[i].flags & 0x40? 'Y' : '-',
info[i].flags & 0x20? 'X' : '-',
info[i].flags & 0x08? 1 : 0,
info[i].flags & 0x07];
}
else {
item.attributes.stringValue = [NSString stringWithFormat:@"%c%c%c%d",
info[i].flags & 0x80? 'P' : '-',
info[i].flags & 0x40? 'Y' : '-',
info[i].flags & 0x20? 'X' : '-',
info[i].flags & 0x10? 1 : 0];
}
size_t imageSize = 8 * 4 * height;
if (height == item->_lastHeight && memcmp(item->_lastImageData, info[i].image, imageSize) == 0) {
continue;
}
memcpy(item->_lastImageData, info[i].image, imageSize);
item->_lastHeight = height;
item.image.image = [Document imageFromData:[NSData dataWithBytesNoCopy:info[i].image
length:64 * 4 * 2
freeWhenDone:false]
width:8
height:height
scale:32.0 / height];
}
}
NSRect frame = self.frame;
CGFloat newHeight = MAX(68 * ((length + 3) / 4), self.superview.frame.size.height);
frame.origin.y -= newHeight - frame.size.height;
frame.size.height = newHeight;
self.frame = frame;
}
- (void)drawRect:(NSRect)dirtyRect
{
if (@available(macOS 10.14, *)) {
[[NSColor alternatingContentBackgroundColors].lastObject setFill];
}
else {
[[NSColor colorWithDeviceWhite:0.96 alpha:1] setFill];
}
NSRect frame = self.frame;
for (unsigned i = 1; i <= 5; i++) {
NSRectFill(NSMakeRect(0, frame.size.height - i * 68 * 2, frame.size.width, 68));
}
}
@end
+94
View File
@@ -0,0 +1,94 @@
<?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">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="GBObjectViewItem">
<connections>
<outlet property="attributes" destination="AVH-lh-aVu" id="F5l-vc-9YB"/>
<outlet property="image" destination="GWF-Vk-eLx" id="cQa-lM-SqU"/>
<outlet property="oamAddress" destination="HiB-x7-HCb" id="LLX-HU-t00"/>
<outlet property="position" destination="bxJ-ig-rox" id="woq-X2-lCK"/>
<outlet property="tile" destination="Kco-1J-bKc" id="C8u-jH-bCh"/>
<outlet property="tileAddress" destination="ptE-vl-9HD" id="9K3-Oq-1vs"/>
<outlet property="verticalLine" destination="Q91-eq-oeo" id="6kc-qh-cFx"/>
<outlet property="view" destination="c22-O7-iKe" id="50f-xf-9Gg"/>
<outlet property="warningIcon" destination="dQV-cO-218" id="Rxi-Wq-Upl"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="c22-O7-iKe">
<rect key="frame" x="0.0" y="0.0" width="120" height="68"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Kco-1J-bKc">
<rect key="frame" x="44" y="4" width="58" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" selectable="YES" alignment="left" title="$32" id="Aps-81-wR7">
<font key="font" size="11" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ptE-vl-9HD">
<rect key="frame" x="0.0" y="4" width="44" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" selectable="YES" alignment="center" title="$8320" id="t2G-E2-vt5">
<font key="font" size="11" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bxJ-ig-rox">
<rect key="frame" x="44" y="36" width="76" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" selectable="YES" title="(32,16)" id="oac-yZ-h47">
<font key="font" size="11" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="AVH-lh-aVu">
<rect key="frame" x="44" y="20" width="76" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" selectable="YES" title="---04" id="tJX-6t-5Kx">
<font key="font" size="11" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HiB-x7-HCb">
<rect key="frame" x="44" y="52" width="76" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" selectable="YES" alignment="left" title="$FE32" id="ysm-jq-PKy">
<font key="font" size="11" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" id="GWF-Vk-eLx" customClass="GBImageView">
<rect key="frame" x="2" y="24" width="40" height="40"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" id="AJz-KH-eeo"/>
</imageView>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dQV-cO-218">
<rect key="frame" x="100" y="4" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSCaution" id="TQB-Vp-9Jm"/>
</imageView>
<box horizontalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="Q91-eq-oeo">
<rect key="frame" x="116" y="4" width="5" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</box>
</subviews>
<point key="canvasLocation" x="132" y="149"/>
</customView>
</objects>
<resources>
<image name="NSCaution" width="32" height="32"/>
</resources>
</document>
+9 -8
View File
@@ -1,6 +1,7 @@
#import "GBOpenGLView.h"
#import "GBView.h"
#include <OpenGL/gl.h>
#import "NSObject+DefaultsObserver.h"
#import <OpenGL/gl.h>
@implementation GBOpenGLView
@@ -27,13 +28,13 @@
- (instancetype)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat *)format
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(filterChanged) name:@"GBFilterChanged" object:nil];
return [super initWithFrame:frameRect pixelFormat:format];
}
__unsafe_unretained GBOpenGLView *weakSelf = self;
self = [super initWithFrame:frameRect pixelFormat:format];
[self observeStandardDefaultsKey:@"GBFilter" withBlock:^(id newValue) {
weakSelf.shader = nil;
[weakSelf setNeedsDisplay:true];
- (void) filterChanged
{
self.shader = nil;
[self setNeedsDisplay:true];
}];
return self;
}
@end
@@ -0,0 +1,20 @@
#import <AppKit/AppKit.h>
#import <Core/gb.h>
@interface GBPaletteEditorController : NSObject<NSTableViewDataSource, NSTableViewDelegate>
@property (weak) IBOutlet NSColorWell *colorWell0;
@property (weak) IBOutlet NSColorWell *colorWell1;
@property (weak) IBOutlet NSColorWell *colorWell2;
@property (weak) IBOutlet NSColorWell *colorWell3;
@property (weak) IBOutlet NSColorWell *colorWell4;
@property (weak) IBOutlet NSButton *disableLCDColorCheckbox;
@property (weak) IBOutlet NSButton *manualModeCheckbox;
@property (weak) IBOutlet NSSlider *brightnessSlider;
@property (weak) IBOutlet NSSlider *hueSlider;
@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
+414
View File
@@ -0,0 +1,414 @@
#import "GBPaletteEditorController.h"
#import "GBHueSliderCell.h"
#import "GBApp.h"
#import <Core/gb.h>
#define MAGIC 'SBPL'
typedef struct __attribute__ ((packed)) {
uint32_t magic;
bool manual:1;
bool disabled_lcd_color:1;
unsigned padding:6;
struct GB_color_s colors[5];
int32_t brightness_bias;
uint32_t hue_bias;
uint32_t hue_bias_strength;
} theme_t;
static double blend(double from, double to, double position)
{
return from * (1 - position) + to * position;
}
@implementation NSColor (GBColor)
- (struct GB_color_s)gbColor
{
NSColor *sRGB = [self colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
return (struct GB_color_s){round(sRGB.redComponent * 255), round(sRGB.greenComponent * 255), round(sRGB.blueComponent * 255)};
}
- (uint32_t)intValue
{
struct GB_color_s color = self.gbColor;
return (color.r << 0) | (color.g << 8) | (color.b << 16) | 0xFF000000;
}
@end
@implementation GBPaletteEditorController
- (NSArray<NSColorWell *> *)colorWells
{
return @[_colorWell0, _colorWell1, _colorWell2, _colorWell3, _colorWell4];
}
- (void)updateEnabledControls
{
if (self.manualModeCheckbox.state) {
_brightnessSlider.enabled = false;
_hueSlider.enabled = false;
_hueStrengthSlider.enabled = false;
_colorWell1.enabled = true;
_colorWell2.enabled = true;
_colorWell3.enabled = true;
if (!(_colorWell4.enabled = self.disableLCDColorCheckbox.state)) {
_colorWell4.color = _colorWell3.color;
}
}
else {
_colorWell1.enabled = false;
_colorWell2.enabled = false;
_colorWell3.enabled = false;
_colorWell4.enabled = true;
_brightnessSlider.enabled = true;
_hueSlider.enabled = true;
_hueStrengthSlider.enabled = true;
[self updateAutoColors];
}
}
- (NSColor *)autoColorAtPositon:(double)position
{
NSColor *first = [_colorWell0.color colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
NSColor *second = [_colorWell4.color colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
double brightness = 1 / pow(4, (_brightnessSlider.doubleValue - 128) / 128.0);
position = pow(position, brightness);
NSColor *hue = _hueSlider.colorValue;
double bias = _hueStrengthSlider.doubleValue / 256.0;
double red = 1 / pow(4, (hue.redComponent * 2 - 1) * bias);
double green = 1 / pow(4, (hue.greenComponent * 2 - 1) * bias);
double blue = 1 / pow(4, (hue.blueComponent * 2 - 1) * bias);
NSColor *ret = [NSColor colorWithRed:blend(first.redComponent, second.redComponent, pow(position, red))
green:blend(first.greenComponent, second.greenComponent, pow(position, green))
blue:blend(first.blueComponent, second.blueComponent, pow(position, blue))
alpha:1.0];
return ret;
}
- (IBAction)updateAutoColors:(id)sender
{
if (!self.manualModeCheckbox.state) {
[self updateAutoColors];
}
else {
[self savePalette:sender];
}
}
- (void)updateAutoColors
{
if (_disableLCDColorCheckbox.state) {
_colorWell1.color = [self autoColorAtPositon:8 / 25.0];
_colorWell2.color = [self autoColorAtPositon:16 / 25.0];
_colorWell3.color = [self autoColorAtPositon:24 / 25.0];
}
else {
_colorWell1.color = [self autoColorAtPositon:1 / 3.0];
_colorWell2.color = [self autoColorAtPositon:2 / 3.0];
_colorWell3.color = _colorWell4.color;
}
[self savePalette:nil];
}
- (IBAction)disabledLCDColorCheckboxChanged:(id)sender
{
[self updateEnabledControls];
}
- (IBAction)manualModeChanged:(id)sender
{
[self updateEnabledControls];
}
- (IBAction)updateColor4:(id)sender
{
if (!self.disableLCDColorCheckbox.state) {
self.colorWell4.color = self.colorWell3.color;
}
[self savePalette:self];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
if (themes.count == 0) {
[defaults setObject:@"Untitled Palette" forKey:@"GBCurrentTheme"];
[self savePalette:nil];
return 1;
}
return themes.count;
}
-(void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NSString *oldName = [self tableView:tableView objectValueForTableColumn:tableColumn row:row];
if ([oldName isEqualToString:object]) {
return;
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *themes = [[defaults dictionaryForKey:@"GBThemes"] ?: @{} mutableCopy];
NSString *newName = object;
unsigned i = 2;
if (!newName.length) {
newName = @"Untitled Palette";
}
while (themes[newName]) {
newName = [NSString stringWithFormat:@"%@ %d", object, i];
}
themes[newName] = themes[oldName];
[themes removeObjectForKey:oldName];
if ([oldName isEqualToString:[defaults stringForKey:@"GBCurrentTheme"]]) {
[defaults setObject:newName forKey:@"GBCurrentTheme"];
}
[defaults setObject:themes forKey:@"GBThemes"];
[tableView reloadData];
[self awakeFromNib];
}
- (IBAction)deleteTheme:(id)sender
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *name = [defaults stringForKey:@"GBCurrentTheme"];
NSMutableDictionary *themes = [[defaults dictionaryForKey:@"GBThemes"] ?: @{} mutableCopy];
[themes removeObjectForKey:name];
[defaults setObject:themes forKey:@"GBThemes"];
[_themesList reloadData];
[self awakeFromNib];
}
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
NSString *name = [self tableView:nil objectValueForTableColumn:nil row:_themesList.selectedRow];
[[NSUserDefaults standardUserDefaults] setObject:name forKey:@"GBCurrentTheme"];
[self loadPalette];
[[NSNotificationCenter defaultCenter] postNotificationName:@"GBColorPaletteChanged" object:nil];
}
- (void)tableViewSelectionIsChanging:(NSNotification *)notification
{
[self tableViewSelectionDidChange:notification];
}
- (void)awakeFromNib
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
NSString *theme = [defaults stringForKey:@"GBCurrentTheme"];
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
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
NSString *newName = @"Untitled Palette";
unsigned i = 2;
while (themes[newName]) {
newName = [NSString stringWithFormat:@"Untitled Palette %d", i++];
}
[defaults setObject:newName forKey:@"GBCurrentTheme"];
[self savePalette:sender];
[_themesList reloadData];
[self awakeFromNib];
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
return [themes.allKeys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)][row];
}
- (void)loadPalette
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *theme = [defaults dictionaryForKey:@"GBThemes"][[defaults stringForKey:@"GBCurrentTheme"]];
NSArray *colors = theme[@"Colors"];
if (colors.count == 5) {
unsigned i = 0;
for (NSNumber *color in colors) {
uint32_t c = [color unsignedIntValue];
self.colorWells[i++].color = [NSColor colorWithRed:(c & 0xFF) / 255.0
green:((c >> 8) & 0xFF) / 255.0
blue:((c >> 16) & 0xFF) / 255.0
alpha:1.0];
}
}
_disableLCDColorCheckbox.state = [theme[@"DisabledLCDColor"] boolValue];
_manualModeCheckbox.state = [theme[@"Manual"] boolValue];
_brightnessSlider.doubleValue = [theme[@"BrightnessBias"] doubleValue] * 128 + 128;
_hueSlider.doubleValue = [theme[@"HueBias"] doubleValue] * 360;
_hueStrengthSlider.doubleValue = [theme[@"HueBiasStrength"] doubleValue] * 256;
[self updateEnabledControls];
}
- (IBAction)savePalette:(id)sender
{
NSDictionary *theme = @{
@"Colors":
@[@(_colorWell0.color.intValue),
@(_colorWell1.color.intValue),
@(_colorWell2.color.intValue),
@(_colorWell3.color.intValue),
@(_colorWell4.color.intValue)],
@"DisabledLCDColor": _disableLCDColorCheckbox.state? @YES : @NO,
@"Manual": _manualModeCheckbox.state? @YES : @NO,
@"BrightnessBias": @((_brightnessSlider.doubleValue - 128) / 128.0),
@"HueBias": @(_hueSlider.doubleValue / 360.0),
@"HueBiasStrength": @(_hueStrengthSlider.doubleValue / 256.0)
};
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *themes = [[defaults dictionaryForKey:@"GBThemes"] ?: @{} mutableCopy];
themes[[defaults stringForKey:@"GBCurrentTheme"]] = theme;
[defaults setObject:themes forKey:@"GBThemes"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"GBColorPaletteChanged" object:nil];
}
+ (const GB_palette_t *)userPalette
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
switch ([defaults integerForKey:@"GBColorPalette"]) {
case 1: return &GB_PALETTE_DMG;
case 2: return &GB_PALETTE_MGB;
case 3: return &GB_PALETTE_GBL;
default: return &GB_PALETTE_GREY;
case -1: {
static GB_palette_t customPalette;
NSArray *colors = [defaults dictionaryForKey:@"GBThemes"][[defaults stringForKey:@"GBCurrentTheme"]][@"Colors"];
if (colors.count == 5) {
unsigned i = 0;
for (NSNumber *color in colors) {
uint32_t c = [color unsignedIntValue];
customPalette.colors[i++] = (struct GB_color_s) {c, c >> 8, c >> 16};
}
}
return &customPalette;
}
}
}
- (IBAction)export:(id)sender
{
NSSavePanel *savePanel = [NSSavePanel savePanel];
[savePanel setAllowedFileTypes:@[@"sbp"]];
savePanel.nameFieldStringValue = [NSString stringWithFormat:@"%@.sbp", [[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"]];
if ([savePanel runModal] == NSModalResponseOK) {
theme_t theme = {0,};
theme.magic = MAGIC;
theme.manual = _manualModeCheckbox.state;
theme.disabled_lcd_color = _disableLCDColorCheckbox.state;
unsigned i = 0;
for (NSColorWell *well in self.colorWells) {
theme.colors[i++] = well.color.gbColor;
}
theme.brightness_bias = (_brightnessSlider.doubleValue - 128) * (0x40000000 / 128);
theme.hue_bias = round(_hueSlider.doubleValue * (0x80000000 / 360.0));
theme.hue_bias_strength = (_hueStrengthSlider.doubleValue) * (0x80000000 / 256);
size_t size = sizeof(theme);
if (theme.manual) {
size = theme.disabled_lcd_color? 5 + 5 * sizeof(theme.colors[0]) : 5 + 4 * sizeof(theme.colors[0]);
}
[[NSData dataWithBytes:&theme length:size] writeToURL:savePanel.URL atomically:false];
}
}
- (IBAction)import:(id)sender
{
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setAllowedFileTypes:@[@"sbp"]];
if ([openPanel runModal] == NSModalResponseOK) {
NSData *data = [NSData dataWithContentsOfURL:openPanel.URL];
theme_t theme = {0,};
memcpy(&theme, data.bytes, MIN(sizeof(theme), data.length));
if (theme.magic != MAGIC) {
NSBeep();
return;
}
_manualModeCheckbox.state = theme.manual;
_disableLCDColorCheckbox.state = theme.disabled_lcd_color;
unsigned i = 0;
for (NSColorWell *well in self.colorWells) {
well.color = [NSColor colorWithRed:theme.colors[i].r / 255.0
green:theme.colors[i].g / 255.0
blue:theme.colors[i].b / 255.0
alpha:1.0];
i++;
}
if (!theme.disabled_lcd_color) {
_colorWell4.color = _colorWell3.color;
}
_brightnessSlider.doubleValue = theme.brightness_bias / (0x40000000 / 128.0) + 128;
_hueSlider.doubleValue = theme.hue_bias / (0x80000000 / 360.0);
_hueStrengthSlider.doubleValue = theme.hue_bias_strength / (0x80000000 / 256.0);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
NSString *baseName = openPanel.URL.lastPathComponent.stringByDeletingPathExtension;
NSString *newName = baseName;
i = 2;
while (themes[newName]) {
newName = [NSString stringWithFormat:@"%@ %d", baseName, i++];
}
[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)alloc
{
static id singleton = nil;
if (singleton) return singleton;
return (singleton = [super allocWithZone:nil]);
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
return [self alloc];
}
@end
+6
View File
@@ -0,0 +1,6 @@
#import <Cocoa/Cocoa.h>
#import "Document.h"
@interface GBPaletteView : NSView
- (void)reloadData:(Document *)document;
@end
Loaded 100 of 593 files, more files were not shown because too many files have changed in this diff. Show more