コミットグラフ

247 コミット

作成者 SHA1 メッセージ 日付
John Tur 0a8f25e7d8
Support default device in WASAPI driver (#1515)
The WASAPI sound driver now supports a "Default" audio output device:
<img
src="https://github.com/ares-emulator/ares/assets/27514983/fbf358d6-41e7-478d-8a76-fc86790d7774"
width="650" />

This uses the [Automatic Stream
Routing](https://learn.microsoft.com/en-us/windows/win32/coreaudio/automatic-stream-routing)
API that was introduced in Windows 10. A runtime check was added to
ensure that the feature does not appear on older versions of Windows.

I did some limited testing and found the feature to work without issues.

Closes https://github.com/ares-emulator/ares/issues/1514
2024-06-07 10:48:42 +01:00
jcm 117f4f7b4e
UI: Initialize all video options correctly on driver settings update (#1513)
Just a small fix to account for the new video settings in Metal; the
threaded renderer, native fullscreen behavior and color space option.
These options were not fully persistent because the `videoDriverUpdate`
function (run on startup, among other times) did not account for them.
They would be set correctly in `settings.bml` and the settings object,
but would never actually be set correctly on the driver struct.

Co-authored-by: jcm <butt@butts.com>
2024-06-03 11:09:17 +01:00
jcm 67fc9ea81b
ruby: Various Mac driver settings fix-ups (#1486)
This PR applies several minor fixes and improvements to macOS driver
settings and the driver settings pane.

#### Remove the "exclusive mode" video option on macOS.

* There is no real notion of exclusive presentation on macOS beyond what
already exists in normal fullscreen. If an application is covering the
screen and no other application or window is visible, the system
automatically switches to a "direct" presentation mode that optimizes
for single-application presentation performance. There is not a good
reason to show this option on macOS, even disabled.
* By contrast, it is possible (though not implemented by ares) to enter
exclusive mode on the audio device with CoreAudio, so leave that option
there, just disabled.
#### Add a "use native fullscreen" option on macOS.
* There are various good reasons to prefer either native platform
fullscreen behavior, or a custom borderless windowed fullscreen. Rather
than guess what the user wants, offer an option.
* If unchecked, make the window title bar enlarge the window rather than
fullscreen it, so we don't mix behaviors.
#### Implement fullscreen monitor selection behavior for Metal, and
correctly enumerate the user's monitor names.
* Fullscreen display on the selected monitor in the settings pane was
previously not implemented on macOS. This implementation only works if
"Use native fullscreen" is disabled, since the macOS fullscreen idiom
doesn't feature selecting a specific display.
* Additionally, the old function to retrieve the monitor's localized
name did not work reliably on newer macOS versions. Use the modern
property `localizedName` on NSScreen for macOS versions above 10.15, and
fall back to the old implementation otherwise.
* Implementing this meant adding a `uintptr` handle to the NSScreen
instance in the `Monitor` struct in ruby that uses a bridged cast to
interface with Objective-C. I would have preferred not to do this, but I
didn't see another good way to handle getting the `NSScreen` instance
that didn't involve a serious refactor.
#### (all platforms) Disable monitor selection if the video driver's
`hasMonitor()` is false.
* Just a minor fixup; the existing behavior is that the dropdown list
can be navigated and selected, but the selection does not persist. It
makes more sense to just disable it if the driver doesn't support it.

Co-authored-by: jcm <butt@butts.com>
2024-05-05 16:11:35 +01:00
remutro 6e8bcd9bda
Disable run ahead for 64DD, fixes load failures (#1474)
Turns out the problem some folks experienced trying to load 64DD games
was due to run ahead not being disabled by default. An exception for
this system has been added.
2024-05-02 19:18:18 +01:00
jcm 1b3e826575
n64: Unload and save before reset() on gamepad and disk (#1464)
7ad14ff6bf
inadvertently made it so that .pak saves (and other save data) are not
properly persisted to disk when unloading the n64 core. This PR resolves
that, calling `unload()`, which itself calls `save()`, before resetting
the gamepad and other memory.

Co-authored-by: jcm <butt@butts.com>
2024-04-30 10:43:07 +01:00
jcm b5cd509a77
ruby: Add Metal VRR support, various Metal driver fixes (#1455)
Adds to the Metal backend from #1431, extending host VSync functionality
to variable refresh rate (VRR) displays, enabling the ability to sync to
guest and host refresh rates simultaneously, along with an assortment of
minor changes and code cleanups:

- Adds a threaded renderer option (technically a GCD queue) to the Metal
backend; essential for VRR at lower audio latencies. At higher audio
latencies, the synchronous rendering option may function better.
- Add easier debug capabilities, including a shell script to compile a
debug `.metallib` shader library which will be used at runtime if ares
is compiled in debug mode. The debug `.metallib` enables GPU frame
capture.
- Implement `clear()` for the Metal backend; the last displayed frame
will no longer stay on the screen if a core is explicitly unloaded.
- Implement fullscreen mode. Uses a borderless window that covers the
entire screen, rather than idiomatic fullscreen, primarily in order to
render around the camera housing. Normal macOS fullscreen behavior is
available via the main window title bar controls.
- Remove unused custom window code.
- Remove redundant copy of `Shaders.metal`.
- Miscellaneous small fixes and code cleanups to resolve compiler
warnings.


https://github.com/ares-emulator/ares/assets/6864788/1e2d594a-c84f-4b95-a792-cacdde2a09b0

## ares vs. VRR
As discussed in #1431, there are some challenges in implementing smooth
VRR support for ares on Metal. Briefly:

- ares lacked a mechanism to tell the display backend the core's desired
refresh rate, in order to sync to it.
- ares on macOS lacked an effective mechanism for receiving callbacks
when frames were presented, in order to keep track of whether we were
running fast or slow, because of the way ares monopolizes the main
thread on macOS.

The first issue has been resolved by a3c57b4 and ec0b625. Cores now tell
the `Screen` instance how often they want to present, and the screen
instance will tell the display backend if it implements the
`refreshRateHint` function. This enables the display backend to quickly
respond to changing guest refresh rates even during runtime.

The second issue is a bit trickier. As discussed, `MTKViewDelegate` and
`CAMetalDisplayLink` are both effectively unavailable until ares moves
its primary emulation work off of the main thread. There is, however,
one Metal callback mechanism that can still be used by ares;
[[MTLDrawable
addPresentedHandler:]](https://developer.apple.com/documentation/metal/mtldrawable/2806858-addpresentedhandler?language=objc),
because it calls back on a dedicated serial queue
(`com.apple.coreanimation.CAMachPortUtilReplyQueue`) rather than the
main thread.

Using this presented handler, ares can use `drawable.presentedTime` to
keep a running average of how long our frames are being presented for,
determine if we are running ahead or behind, and modify our subsequent
present intervals accordingly. That is what we do for this initial VRR
implementation.

## macOS VRR

> [!NOTE]
> The following applies to "ProMotion" displays, as those are the ones
most tightly integrated with macOS and most likely to be used by Mac
users on VRR displays.

Unfortunately, VRR sync is not as simple as just picking a present
interval and telling macOS to present each frame for the guest's
requested interval. macOS only pretends to offer this capability in
exclusive fullscreen mode, and even then, present intervals cannot be
completely arbitrary. Realistically, we seem to be able to get
consistent present intervals for some integer refresh rates between 40
Hz and 120 Hz, and certain rational present intervals (59.97, 23.976
among them). The spread of achievable consistent present intervals seems
to be arbitrary enough that there isn't any sense in targeting them
specifically. Even if we can theoretically present at the exact interval
the guest wants, we inevitably end up falling behind due to transient
load conditions.

> [!NOTE]
> For background, the landscape of guest refresh rates in ares is quite
wide. Many systems present near 60 Hz; 59.97, 60.01, 59.73, 59.92,
59.82, etc. Many of these systems have PAL modes that present near 50
with similar variations. The WonderSwan presents at a maximum of ~75.47
Hz, with per-game variations. The Atari 2600 can present at completely
arbitrary intervals during runtime owing to its CRT- and
processor-centric presentation strategies. In short, It is difficult to
narrow the range of expected guest present intervals if we wanted to
simplify this problem.

Rather, we have to pursue a more holistic strategy. The strategy ares
uses with this PR is as follows:

1. The output function sends frames into a FIFO dispatch queue that can
present asynchronously, to reduce the burden of needing to present
immediately if we are in danger of blocking the main thread.
2. If we are more than 0.5% off of the targeted present interval as
determined by a weighted rolling average, start "nudging" the system to
present at earlier intervals calculated according to the difference
between the rolling average and the target, multiplied by a constant
`kVRRCorrectiveForce`.
- This is done because we can often prod the system into presenting at
rational intervals close to the target interval, resulting in an overall
smoother presentation to the user than if we were to correct more
forcefully.
3. If more than `kVRRImmediatePresentThreshold = 3` frames are in the
queue to be presented, start telling the system to present immediately
instead of "nudging."
- This is a more forceful correction toward the target present interval,
and must be kept low for systems that want to present at intervals that
are far away from any achievable consistent present interval.
4. If the queue gets much deeper, `kMaxSourceBuffersInFlight = 6`, start
dropping frames.
- This is necessary for synchronizing to neither audio nor video, or
else in rare cases where the GPU is overloaded, such as for a shader
that the system is not capable of rendering in time each frame.

This system achieves decent results across most systems in my testing. I
considered allowing these constants to be twiddled with sliders, but was
wary of presenting too many esoteric options to the user. If it's
determined to be worth exposing these constants, that can be done in
future work (if a superior VRR presentation strategy entirely is not
discovered by that point).

## Miscellany

- The threaded renderer is necessary so that we do not ever block the
main thread in the worst case present interval conditions. However, it
only works well at relatively low audio latencies. At higher audio
latencies (as for users on lower-specced systems), the queue overflows
easily and it works better to render synchronously.
- The threaded renderer can also have unintuitive results when
exclusively syncing to host VSync or GPU sync, so for users that expect
particular behavior from that functionality, it is better left disabled.
- For PAL refresh intervals, players will get generally better results
in exclusive fullscreen. macOS likes to render things at 60Hz and will
struggle to render near 50 Hz with other elements onscreen.
- To view the present interval graph as in these debug shots, input
`defaults write -g MetalForceHudEnabled -bool YES` at the command line
before launching ares.

## Future Work

We could possibly achieve better VRR results utilizing something like
`CAMetalDisplayLink` after freeing up the macOS main thread. In my
testing it seems to have the same limitations in terms of achievable
consistent present intervals, but it may offer a more precise picture of
host vs. guest present timing.

Regardless of the viability of other strategies, it would still be
valuable to free up the main thread on macOS for the sake of other
system APIs that may be used in the future, plus benefits of being able
to use the UI consistently and smoothly concurrently with emulation.

N64 and PS1 also do not fully implement the `refreshRateHint` API, and
the API may be buggy for some platforms. Metal refresh rate hints
currently appear in stdout, so if you are seeing an issue with VRR sync,
check the console to see the guest's requested present interval first.

## Gallery 


https://github.com/ares-emulator/ares/assets/6864788/1022c24b-fd83-4ede-b1ac-3f0c3a207972


https://github.com/ares-emulator/ares/assets/6864788/7e36bd4a-7acd-4d37-a572-7550ba1ad2b2

(PAL Super Mario World)


https://github.com/ares-emulator/ares/assets/6864788/9655fcbe-28de-48b2-88b7-7fb864991ef0

Co-authored-by: jcm <butt@butts.com>
2024-04-21 19:27:16 +01:00
Luke Usher 7ad14ff6bf n64: fix savedata duplication issue
This fixes an issue where upon loading a game that doesn't use a controller pak after a game that does, a .pak file would be created using the previous games data.
2024-04-10 20:18:00 +01:00
Luke Usher ca0044b663 desktop-ui: fix shaders not applying on startup 2024-04-10 10:39:40 +01:00
jcm a3c57b4fbd
screen/video: Add refresh rate hint mechanism (#1447)
This constitutes one puzzle piece that will help improve ares's frame
pacing, particularly for variable refresh rate displays.

While continued work on ares's audio drivers is likely to smooth the
pace at which ares generates video frames, transient changes in
application and system load inevitably means that frames will be
delivered earlier or later than expected. Additionally, relying on video
frames to be generated precisely when needed and presenting them
immediately is fairly demanding. If we can pace frames some distance in
advance, it can significantly lessen the burden on the CPU and GPU.

This PR is one tool to help the video backend deal with these issues.
Cores can now inform the screen of their expected rate of frame
generation at any given time, and the screen will inform the video
backend. The backend can then employ various strategies to perform
optimal frame pacing and drop frames when necessary.

The function is emphasized as a 'hint' to indicate that the rate is only
that which is expected, rather than certain. Unpredictable changes in
system conditions mean that we can never be entirely certain when a
frame will be generated or presented.

> [!NOTE]
> No concrete `refreshRateHint` implementations are added in this PR.
Given the variety of core refresh rates across ares, as well as the
consideration that for some cores refresh rates can change during
runtime, that work is left for separate PRs.

Co-authored-by: jcm <butt@butts.com>
2024-04-09 09:34:57 +01:00
Luke Usher ea7f9a8c0f desktop-ui: refactor menu gen/shader loading 2024-04-03 23:00:24 +01:00
Luke Usher 1ea995f78d arcade: use mame machine names for convenience
Update mame2bml to include mame romset version

Add script to update arcade rom database (requires a MAME installation)
2024-04-03 06:57:51 +01:00
jcm 5ee8f117a1
UI: update shader location when initializing (#1439)
Fix an error when cherry picking changes from a local branch for #1438.
Use the new variable for the base shaders directory when loading the
program start shader. Unbreak the build.

Co-authored-by: jcm <butt@butts.com>
2024-04-03 05:33:21 +01:00
jcm f515ed15c5
UI: Expose all .slangp shaders available (#1438)
Previously, the `LoadShaders()` function in `desktop-ui` searched only
two levels deep, which did not find all `.slangp` shader presets
available. The entirety of "megabezel" was not exposed, for example.

Now we properly traverse the entire directory structure of `Shaders/`
looking for `.slangp` files, exposing all that are available.

This PR does a small amount of rudimentary pruning for paths that do not
contain `.slangp` shaders, but future work, perhaps undertaken by
someone who has more fun with recursive directory traversal, should
probably properly prune all paths not containing presets.

Co-authored-by: jcm <butt@butts.com>
2024-04-02 22:20:09 +01:00
Luke Usher dd1ca486ec ruby: remove "Blur" shader, prefer slang bilinear. 2024-04-01 16:55:08 +01:00
jcm 72fa7d38c3
ruby: Add Metal display backend (#1431)
This PR adds a Metal display backend to ares.

<img width="1482" alt="Screenshot 2024-03-31 at 7 02 40 PM"
src="https://github.com/ares-emulator/ares/assets/6864788/48718f19-9916-491b-8301-c16b95f95c19">

*ares N64 core on a 60Hz P3 display. Shader: "crt-maximus-royale".*

## Context

With ares's recent introduction of librashader, ares users have enjoyed
access to the sizable library of shaders in the slang format, such as
those used by the RetroArch frontend. Simultaneously, up to now, the CGL
OpenGL backend shipped by ares for Mac users has offered enough
functionality to do the (relatively) simple job of an ares display
backend; display software-rendered frame buffers and pace them
appropriately.

librashader's advanced postprocessing, however, has asked a bit more of
the display backend, and in the case of OpenGL, has laid bare various
deficiencies in macOS's OpenGL driver. These deficiencies can kneecap
ares's librashader support on macOS with compiler errors and broken
shader behavior.

Rather than chase down these errors and try to work around what is
fundamentally a broken driver shipped by Apple, we take advantage of
librashader's native Metal support by adding a Metal backend to ares.
This greatly increases baseline shader compatibility, with the added
benefit of documentation and greater platform debugging information when
issues arise. The Metal backend will also generally future-proof ares on
macOS, with OpenGL's uncertain future on macOS.

## Basics

The first iteration of this Metal driver mostly offers feature parity
with the OpenGL driver. More advanced features, particularly in the
realm of frame pacing on ProMotion displays, will arrive in future
iterations. The priority with this PR is to start getting the driver in
the hands of users with basic features and greater librashader
compatibility.

Host refresh rate sync is still a work in progress and in this iteration
will only be enabled for users above 10.15.4 on non-VRR displays
(discussed more below).

Explicit sRGB color matching is offered as a new option for those on
wide gamut displays (by default, the Metal driver will map to the native
color space, conforming to OpenGL driver behavior). This option is only
exposed on macOS, since other operating systems lack per-surface color
matching.

<img width="400" alt="Screenshot 2024-03-31 at 6 37 38 PM"
src="https://github.com/ares-emulator/ares/assets/6864788/e177a256-bba2-4a02-ad5b-9ad84cb09740">
<img width="400" alt="Screenshot 2024-03-31 at 6 37 46 PM"
src="https://github.com/ares-emulator/ares/assets/6864788/dd517394-e97e-40f6-98de-4562d62bda98">

*Left: ares presenting in Display P3. Right: ares presenting more
accurately in sRGB with "Force sRGB" enabled. Shader: crt-hyllian.*

A simple vertex and fragment shader are compiled at runtime, so we avoid
the need to add another compiler toolchain to the ares build process.
There is unfortunately some code duplicated at present; `metal.cpp` and
`Shaders.metal` both include types defined in `ShaderTypes.h`, but we
also need to place `Shaders.metal` inside the .app bundle for runtime
compilation, making for awkward `#include`s. Presently, we just bundle a
copy of `Shaders.metal` appended with `ShaderTypes.h`, inside
`desktop-ui/resource`. This will be cleaned up in future work.

The driver's draw implementation itself is fairly simple; one render
pass renders to an offscreen texture, librashader performs its work on
that offscreen texture, and a second ares Metal render pass composites
the finished texture inside ares's viewport. Since we do not use
`MTKViewDelegate`, our output function finishes with a `[view draw]`
call and the system presents at the earliest opportunity.

## Details

When it came to the details of implementing this driver, there were some
nontrivial issues encountered. Some of these will need solving in
separate PRs before this driver is feature-complete.

### ares vs. VRR

Users on fixed refresh rate displays should enjoy good frame pacing with
this driver. Unfortunately, users of more recent Mac machines with
"ProMotion" refresh rates will not have an ideal experience in terms of
pacing. To understand why, we need to take a brief detour into how ares
works and then discuss some current limitations with ares's macOS
integration.

In ares "synchronize to audio" mode, ares creates and delivers video
frames as audio frames are created. This means that the video frame
timing is completely dependent on when exactly the audio driver
processes audio frames. For display modes with a refresh rate at or
close to the core refresh rate, this is mostly no problem; the system
seems to naturally present frames in a FIFO-esque fashion, and every
once in awhile the system will just drop or duplicate a frame if two or
no draw calls fall within one refresh interval.

For recent more advanced Mac displays with "up to 120Hz" refresh rate,
the story is more complicated. We have to explicitly tell the system
when we want it to draw the frame once available. It is tempting to
answer "now"; after all, if our audio timings are correct, then video
frames should be generated precisely when they need to be shown.
Unfortunately, in higher latency modes of OpenAL or with SDL audio in
general on macOS, audio frames are processed in large batches. That
means that we end up emitting several video frames in quick succession
at 8ms intervals on a 120Hz display, then waiting as long as 75ms for a
new batch of audio (and thus video) frames:

<img width="265" alt="Screenshot 2024-03-31 at 4 55 25 PM"
src="https://github.com/ares-emulator/ares/assets/6864788/69f887a0-8ded-4f47-ac4c-4cf2b58283a7">
<img width="265" alt="Screenshot 2024-03-31 at 4 55 35 PM"
src="https://github.com/ares-emulator/ares/assets/6864788/2f7a417a-0378-44b5-b0c0-f894542c0371">
<img width="265" alt="Screenshot 2024-03-31 at 4 55 56 PM"
src="https://github.com/ares-emulator/ares/assets/6864788/13b471d9-3e77-45cd-baf4-0d786ae83e22">

*VRR macOS frame pacing across audio driver settings in v0.1 of the
Metal driver. The graph in blue shows frame present intervals over time;
the values in red show the minimum and maximum present intervals over
the graph duration.*

If we do not answer "now," we have to decide when to present.
Unfortunately, currently, there is not a satisfying way to answer that
question. Core refresh rates vary somewhat widely, sometimes during
runtime, and there is no mechanism in ares by which to inform the
graphics driver of a core's desired refresh rate.

We could elect to just duplicate the behavior for a fixed display
refresh rate and pick, e.g. 60 Hz, but unfortunately even that option is
not available, because we currently have no way of receiving callbacks
when a frame is actually presented. Why not `CAMetalDisplayLink` or even
`MTKViewDelegate` you ask? Well...

### ares vs. macOS

For most of its cores, ares performs much of its work on a single
dedicated main thread that blocks for audio and video presentation to
drive hardware-accurate timing. Unfortunately, all of this work occurs
on the macOS main thread, with lots of blocking and CPU-intensive
activity. This interferes with the macOS application run loop's ability
to perform its callbacks and call out to observers.

In practice, this means that if we try to employ delegates that
interface with macOS, that could send a callback when a frame is
presented, or tell ares the exact moment a frame needs to be presented,
these system delegates cannot actually make these calls in time in
between ares's main thread activity; upwards of 50% of `MTKViewDelegate`
callbacks are lost, for example.

This means that tools like `MTKViewDelegate` or `CAMetalDisplayLink`
that would help us solve the frame pacing problem are, unfortunately,
useless to us. We cannot leverage these tools as ares is currently
architected.

To get around these issues, we will need one of: less main thread
blocking, so delegates can interface with ares on the main thread, or an
audio driver with a processing tolerance that falls within the display's
minimum refresh interval. Our best bet for now is to emit frames to the
system within ares's main thread work as they come available, let the
system draw them as it will, and hope that our audio driver is doing a
good job pacing them.

In practice, for Metal driver users on VRR displays you cannot set to a
fixed rate, this means you should use the OpenAL driver, and set the
latency to the lowest value possible.

## Future Work

The future for the Metal driver in ares takes us down a few different
paths.

The main issue at present is making macOS system delegates work well
with ares, which is the ideal path forward. Ideally, we could move all
of the emulation-intensive work off of the main thread in macOS and into
a high priority dedicated thread, reserving the main thread for actual
UI and rendering, giving the system plenty of overhead with which to
communicate.

For the future of VRR in ares, it would be good to create a mechanism to
tell the graphics driver what refresh rate the core wants to present at.
This would be one way to pace draw calls appropriately in the absence of
reliable feedback from the system about the state of the display.

It has gone without mentioning so far due to the other issues, but long
term, it would also be good for ares or librashader to have some way of
utilizing the entire viewport for shaders; currently, shaders are
limited to the output width and height area rather than the entire
window view size. This is limiting for "bezel"-style shaders that want
to use the entire screen in fullscreen, for example.

Co-authored-by: jcm <butt@butts.com>
2024-04-01 14:31:28 +01:00
Luke Usher 61b358e45b desktop-ui: group slang shaders by directory 2024-03-29 18:00:24 +00:00
jcm a29cd2ce58
UI: Fix confirmation logic when changing drivers with a game loaded (#1428)
Addresses a minor issue with driver change confirmation logic and the
"Apply" button in the UI.

Previously, if the player changed the video, audio, or input driver with
a title loaded and clicked "No" at the confirmation dialog, the "Apply"
button would be disabled as if the player had changed the driver, when
they had not.

With this PR the "Apply" button state correctly reflects the driver
state and the result of the confirmation modal.

Co-authored-by: jcm <butt@butts.com>
2024-03-27 08:01:24 +00:00
Luke Usher 4666cdb9b8 build: fix an issue where make clean would halt on the librasahder flag 2024-03-11 16:09:24 +00:00
Luke Usher c9c1a0d532 pc-engine: add support for Games Express games + other fixes
Use the Games Express system card for the games that require it
Use System Card 1.0 for Altered Beast (this game is broken on other bios versions, even on hardwar
Fix CD-ROM pregap offset (Fixes Super Air Zonk, allows Games Express games to boot)
Fix PC-Engine Duo/Super CD-ROM Ram Enable Register
e)
2024-03-08 15:53:44 +00:00
jcm 65264090b0
UI fix-ups for macOS (#1412)
### Status Bar 

When building with the macOS SDK included with macOS Sonoma, ares has
had a regression involving an overly large status bar that rendered over
the game viewport, causing confusion as well as being tricky to debug.

It turns out that this was due to a breaking change in AppKit in macOS
14 where an `NSView`'s `dirtyRect` was no longer clipped to its bounds
by default. In short, a view's `dirtyRect` is now often much larger than
its `bounds` if `clipsToBounds` is not defined explicitly. This creates
problems in views that draw by calling `NSFillRect` on the dirtyRect, a
common pattern, as it will fill a rect that is much larger than the
actual bounds.

This PR sets the `clipsToBounds` property for NSView to `true` for views
in ares that draw by filling `dirtyRect`. Accordingly these views'
`dirtyRect` will now always be the same size as their `bounds`.

This was true of `canvas.cpp`, `viewport.cpp`, and `label.cpp`. To avoid
making the change overly broad, and to enable macOS to perform whatever
optimizations it wants to perform, other view types are left alone.

### Splash Screen

This PR also addresses logo clipping issues in macOS on the splash
screen. The dimensions for the logo on the splash screen, as defined,
seemed to be a bit off previously, with the square logo rendering into a
non-square canvas area. For whatever reason, this only clipped the logo
rendering on macOS. The size and padding are adjusted slightly by this
PR. It should not result in regressions on other platforms, but should
be tested to make sure.

> [!IMPORTANT]  
> Pwease test on Windows and Linux to make sure the splash screen looks
OK.

macOS screenshot of adjusted splash screen and fixed status bar, built
with Xcode 15:
<img width="1072" alt="Screenshot 2024-03-02 at 1 43 20 AM"
src="https://github.com/ares-emulator/ares/assets/6864788/83504592-03dd-4881-8f3d-0db1fb771f44">

---------

Co-authored-by: jcm <butt@butts.com>
2024-03-03 15:52:58 +00:00
Luke Usher 71302c0938 shaders: switch to slang-shaders rather than quark shaders via librashader 2024-02-25 12:05:36 +00:00
Luke Usher 5cdefb088d desktop-ui: cleanup resource search paths
As well as simplifying the code a little, this also  fixes an oversight where users could not override application resources on macOS.
2024-02-21 17:49:12 +00:00
Luke Usher ed0a1c8852 cheats: only create a cheat file when cheats are added
This also cleans up empty cheat files on unload.
2024-02-18 08:41:56 +00:00
Luke Usher dd9c728a12 ares: preliminary cheat support
Adds a cheat editor to Tools->Cheats when a game is loaded.

The cheat editor should work for all systems except N64 and PS1: support for these will come later.

The code has currently only been tested for MS, MD and SFC but it is assumed all the other systems are also functioning; the code paths are the same.

Code format is standard patch codes in the format X:Y where X is a memory address and Y is a value to place there; most emulators also support this format.

You can use multiple codes in a single cheat by separating codes with a + sign.

Cheats that require memory comparisons are not currently supported, only replacements

Cheats are saved alongside the roms, eg "Game.sfc" will create "Game.cheats.bml".
2024-02-16 19:01:57 +00:00
Luke Usher 704fc91b9c desktop-ui: 'hide until ready' for Windows only 2024-02-01 18:58:50 +00:00
Luke Usher 757d74bac0 desktop-ui: hide window until startup completes
This also avoids calling inode::exists on every recent game at load time, reducing initial wait time.
2024-02-01 18:40:45 +00:00
Luke Usher ff36889d47 desktop-ui: exclude rumble inputs from poll timeout
Fixes rumble issues in many games, notably, OOT
2024-01-29 13:12:06 +00:00
Luke Usher acaa1cabb5 ares: border and overscan overhaul
This updates most pre-32bit systems to have hardware accurate borders and
aspect ratio where known, reasonable estimates are used where not known.

This also means that PAL games will use the correct PAL aspect rather than
using the NTSC pixel aspect ratio.

All TMS9918 VDP based consoles are thought to be be correct, as are Master
System, Mega Drive, and NES, while SNES and PC-Engine are (educated)
estimates.

The overscan option has been reworked to crop all non-desirable edges of the
screen, including borders and areas that often contain garbage data, previously
this option only cropped the bottom 16 lines of active display.

The reworked overscan is not yet implemented for Atari 2600, PC-Engine, N64 or
PlayStation.
2024-01-28 15:38:47 +00:00
Steveice10 801eaa4088
desktop-ui: Fix broken firmware path setting. (#1374)
* Fix the firmware search path not being saved or loaded from the
settings file.
* Fix `FirmwareSettings::findFirmware` not using the right casing when
locating the firmware directory.
2024-01-22 14:20:27 +00:00
Steveice10 d6b2ca53e2
nall: Account for macOS app bundles in program path. (#1373)
Contains three main changes:
* In `Path::program()`, account for the macOS app bundle, so that
portable config support works with the app bundle.
* Create a new function `Path::resources()` for the resources path,
since `Path::program()` can no longer trivially be used to construct the
bundle resources path (no guarantee what the .app is named). On macOS
this returns the path to "ares.app/Contents/Resources", on other
platforms (in case they use it in the future) it just returns the same
as `Path::program()`.
* Fix an issue where, if Ares is stored in a sub-directory of the
desktop, the path settings UI will display paths next to the program as
relative to the desktop instead of relative to the program directory.
2024-01-22 14:20:14 +00:00
jcm 9e4b3795f1
build: add macOS SDL to thirdparty, add .dylib to bundle (#1345)
### Description

Adds SDL (properly) to Mac builds.

This time, it has been added as a fully fledged optional dependency in
`thirdparty`, à la MoltenVK, and built from source before ares. We build
from source because brew installations are both single-architecture and
not fully portable.

The .dylib is copied inside the app bundle when linking, at the same
stage as MoltenVK.

The initialization of `ares.dylibs` has been moved from ares's Makefile
to the `desktop-ui` Makefile so that it's initialized when building
ruby, which it wasn't previously.

The SDL build is also added to CI, with the same caching methods as used
for MVK.

### Relevant Details

`HEAD` points at SDL 2.28.5 currently, which is the most recent stable
release. This should probably be periodically incremented as
appropriate.

~~SDL is currently built with the macOS deployment target of 10.13.
While SDL's minimum supported macOS version is 10.11, ares CI is using
Xcode 14.2, which has a minimum deployment target of 10.13. I am
currently testing to see if I can get the deployment target lower
without breaking other parts of ares's CI.~~ resolved, per below; SDL
supporting 10.11 is built + bundled.

### Testing

This has been tested to build properly locally and via GitHub CI. The
.dylib is packaged inside the bundle correctly and SDL functions
correctly in my testing, even if the user does not have SDL installed
elsewhere on their system.

This is seeking tests from other Mac users, especially on older
operating systems, to verify that SDL works correctly there.

Co-authored-by: jcm <butt@butts.com>
2023-12-28 09:24:04 +00:00
shinra-electric a82913c1f9
macOS: Add minimum macOS version and copyright to ares.plist (#1350)
Added the minimum macOS version key, but kept it at 10.9 which is what
macOS currently reports it as.
Now that the key is here, it will be easier to update it in the future. 

Also added the copyright line attributing the ares team and
contributors.
2023-12-28 09:19:47 +00:00
Jasmine Minter b7db1c074b
macOS: various UI fixes (#1355)
Some issues I noticed while playing with this on macOS. Took a bit of a
deep dive and attempted to fix them up:
- changing the tracer settings did not seem to change what was logged.
seems to be the row isn't selected when the `onToggle` callback is
called. solution was to instead use the toggled `cell` to get the row
its in. this caused some C++ template issues but removing the `auto`
fixes them all (the alternative being adding `template` to a few method
calls, I should add I'm not a C++ programmer so from my limited
understanding this was the best solution)
- text in text fields were invisible. this was due to
`setForegroundColor` in the macOS backend not properly handling a
0,0,0,0 color. changed to perform the ternary on the `Color` rather than
the `NSColor` (`SystemColor` did not support the ternary)

merry christmas :)
2023-12-28 09:19:24 +00:00
invertego 6d5ef628e8
ci: disable sdl2 on macOS to unbreak the build (#1343)
More work is required to support building universal binaries.
2023-12-12 23:38:21 +00:00
invertego f893afca89
nall: ensure utf-8 string encoding in cl builds (#1339)
As a bonus, use the Unicode ellipsis character in the ares UI on all
platforms instead of just macOS. In addition to looking nicer, it will
make regressions in this area very obvious.
2023-12-09 21:46:17 +00:00
invertego 0d131bf4d8
build: improve pkg-config support on windows (#1337)
Allow ares to be more easily built against external dependencies on
Windows outside of MSYS2 and using the MSVC ABI.

For example, dependencies can now acquired via vcpkg by installing the
relevant packages (pkgconf, gtk3, qt5, sdl2) and setting up the
environment appropriately before building.

```
CMD:
set PKG_CONFIG=C:\src\vcpkg\installed\x64-windows\tools\pkgconf\pkgconf.exe
set PKG_CONFIG_PATH=C:\src\vcpkg\installed\x64-windows\lib\pkgconfig

Bash:
export PKG_CONFIG=/c/src/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe
export PKG_CONFIG_PATH=/c/src/vcpkg/installed/x64-windows/lib/pkgconfig
```

Changes:
- hiro: fix building against gtk/qt with cl
- build: improve pkg-config detection and use with cl
- nall: support dynamic crt with clang-msvc/cl
2023-12-08 11:55:43 +00:00
remutro 7e99155f8e
Mega Mouse support for 32X + CD (#1336)
Doom Resurrection patch version 3.0 (currently at version 3.1) added
support for the Mega Mouse, as well as making use of Mega CD hardware if
available. When I added mouse support for the Mega CD, the patch for
Doom Resurrection was at version 2.2, and since there was no licensed
32X software that supported the Mega Mouse I declined to add support at
the time. But leave it to homebrew, especially one as comprehensive as
this patch to add support.

This adds Mega Mouse support for both the 32X and 32X/CD combo, so it is
now available for all Mega * consoles.
2023-12-08 11:55:16 +00:00
remutro bbe9a9b0a4
Make it more obvious that the apply button for drivers needs to be used (#1320)
We frequently get issue reports in GitHub and Discord about driver
settings not being saved. This is due to the fact that changes to
drivers requires using the Apply (formerly Reload) button for changes to
stick, which is different than other options in the settings window.

With this change, the Apply button is grayed out until a different
driver is selected, hopefully making it more obvious that the buttons
need to be used. A small note was also added at the bottom explicitly
stating that they Apply buttons must be used in order to switch/change
updates to driver selection.
2023-12-04 12:02:05 +00:00
invertego 6567d9dcf0
desktop-ui: destroy timers on system unload (#1315)
Fix two issues caused by disc swap timers:
1. Crash on exit in certain build configurations
2. Crash on system unload shortly after disc swap

Because these timers were simply members of Emulator derived classes
(which are in turn owned by a global variable), they were being
destructed after main() along with other static lifetime objects. This
was problematic because hiro also has global state that the timer
implementation depends on, at least on Windows. Whether this manifested
in a crash depended on a few factors, object destruction order among
them (which is at the mercy of the linker).

The second crash would reliably reproduce simply by initiating a disc
swap and unloading the emulated system (such as by closing the emulator)
within the next 3 seconds.
2023-12-02 14:11:26 +00:00
remutro 079295e2ca
Enable/Disable N64 Expansion Pak (#1302)
Add ability to enable/disable N64 4MB expansion pak. 

Similarly to the video settings window, I've added a Nintendo 64
specific section in the options window, which was mostly empty. Existing
options fall under a generic "Emulator Options" section. Seems like a
reasonable place to add a few console specific options.

Addresses issue: https://github.com/ares-emulator/ares/issues/939
2023-11-29 21:43:20 +00:00
Luke Usher df031a7d4c desktop-ui: rename FPS to VPS (VBlanks Per Second) to better represent what it is really showing 2023-11-28 21:52:55 +00:00
Luke Usher 0dd3edebe0 desktop-ui: fix an issue where "Deep Black Boost" did not save 2023-11-28 21:25:43 +00:00
Luke Usher f9d38f5daf desktop-ui: rename "Reload" to "Apply" in driver settings to clarify it's function 2023-11-28 21:24:09 +00:00
invertego 4f7feeafd7
build: fix level 2 msvc warnings (#1297)
Level 2 warnings are considered "significant" and turning them on
revealed one issue that could, in the future, have affected MSVC-ABI
builds using either CL or Clang.

MSVC's C++ name mangling distinguishes between classes and structs, and
throughout the ares codebase there were friend declarations using
"class" to refer to types that were defined with "struct".

I don't see any value in retaining this inconsistency, especially
considering that ares otherwise avoids the "class" keyword (though I
spotted a few uses that crept in from recent commits).
2023-11-20 09:26:35 +00:00
invertego 4544e1df69
desktop-ui: disable color bleed for HD content (#1287)
This effect runs on the CPU, which is expensive for HD content and
incredibly so for UHD content. It doesn't make much sense to apply to
non-SD content, in any case.

Currently this only affects the N64 core in HD and UHD modes.
2023-11-15 11:04:43 +00:00
LuigiBlood 87ae65a094
n64: add 64dd disk swapping + safety checks + change manufacture timestamp (#1280)
This adds:
- 64DD Disk Swapping for both 64DD standalone games and N64 Combo games
(only if a disk is loaded).
- Safety checks to prevent corruptions.
- Change manufacture timestamp and line to differenciate different disk
files from each other to avoid confusion
2023-11-08 20:09:27 +00:00
Luke Usher 0ceaf17be6 desktop-ui: emulator::construct must be called *before* settings are loaded
BIOS settings depend on being able to iterate through Emulators.
2023-11-08 10:46:39 +00:00
Adrian Siekierka c27f369e31
fc: Initial EPSM implementation. (#1274)
More information:
https://www.nesdev.org/wiki/Expansion_Port_Sound_Module

While this is a homebrew device, it has already shipped to consumers in
this manner.

TODO (I'm not sure how to fix these issues myself):

- [x] Switching from EPSM back to another peripheral (None or Family
Keyboard) unloads not just the additional EPSM-provided audio streams,
but seems to break *all* audio from the NES core.
- [x] NES 2.0 cartridges can declare that they wish to have the EPSM
peripheral installed by default (Extended Console Type 0x04), but I'm
not sure how to hook this nicely from the pak data to the expansion port
node.
- [ ] Missing serialization, but this affects the Family Keyboard to
some limited extent already, so...

Not urgent at all. It has shipped to consumers, but the amount of
software using it is still lacking.

---------

Co-authored-by: Luke Usher <luke@usher.cc>
2023-11-07 12:09:15 +00:00
Giovanni Bajo 020410ea0b
Add homebrew mode (with a few checks to N64 core) (#1278)
This PR adds a new general setting called "homebrew mode", that can be
used as an umbrella setting for all kind of developer-related aids in
the emulator. This will also allow resource intensives checks to be
added (eg: N64 RDP command list validation).

For now, we hook this to the N64 core only in two ways:

* ISVIewer emulation is now only performed in homebrew mode. This is
obviously not resource intensive, but it would have naturally been an
homebrew mode feature, if it existed at the time. Normally, games should
behave exactly like on a real N64, where there is no ISViewer peripheral
plugged in into the PI bus.
* A new cache coherency check is added to PI DMA. If a DMA is performed
to/from RDRAM locations for which the CPU holds a valid cacheline, a
warning is emitted to the console as the game is probably buggy.

Slightly unrelated, a commit also adds a new "DCache" memory viewer, to
see the memory from the point of view of the CPU (so with data cache
taken into account). This is useful to ROM hackers which don't care
about the physical RDRAM contents but rather the memory contents as
written by the CPU.
2023-11-07 10:53:12 +00:00
Luke Usher a47bbea7a2 desktop-ui: surround sg1000a with CORE_SG ifdef 2023-10-25 09:42:13 +01:00