Compare commits

...

283 Commits

Author SHA1 Message Date
rogerman 6f1a63fe89 Cocoa Port: Support Automatic Graphics Switching, allowing the use of the integrated GPU to run video display windows. (Requires a dual-GPU MacBook Pro with Metal-capable GPUs.)
- While this results in a 20% performance loss for video display window functions (like video filters), this also dramatically extends battery life. To return to the old way of using the discrete GPU for video display windows, the user must disable Automatic Graphics Switching in their System Preferences.
- The Troubleshooting Window now correctly reports the emulated 3D renderer that is currently active, rather than the one that is selected in the GUI.
- Also fix a bug where creating a OpenGL 3D renderer's context would immediately fall back to Apple Software Renderer if context creation failed. Now, context creation falls back to Apple Software Renderer as the last resort, only after all other Core Profile contexts have failed.
2025-03-26 16:55:25 -07:00
rogerman 25356b70f1 GPU: Add some more optimizations hints in CopyLineExpand() for SSSE3. 2025-03-26 13:26:42 -07:00
rogerman 75766495f9 Cocoa Port: Add some missing file references to the Xcode 3 project. 2025-03-20 22:55:40 -07:00
rogerman 1091e69726 Cocoa Port: Fix a bunch of bugs related to moving windows between Retina and non-Retina displays. (Related to commit 2bc5b0d.) 2025-03-19 03:11:16 -07:00
rogerman f6e0feb13e Cocoa Port: Report which OpenGL renderer is actually selected for 3D rendering. (Debug mode only.) 2025-03-18 15:55:01 -07:00
rogerman 33754b706e Cocoa Port: Add support for performing OpenGL 3D rendering on the 2013 Mac Pro's second GPU.
- For OpenGL 3D rendering, this yields a performance improvement of 2% - 4%.
2025-03-17 17:03:35 -07:00
rogerman 50e39989f7 GPU: Do some small optimizations to SSE2 and AVX2. 2025-03-16 23:15:46 -07:00
rogerman c73a7ffe53 GPU: Add NEON-accelerated functions for 2D layer compositing. (For 64-bit ARM CPUs only.)
- This improves GPU performance by up to 20% on the Raspberry Pi 5, and up to 50% on Apple Silicon CPUs.
2025-03-16 16:23:21 -07:00
rogerman e2379a66d6 matrix.h: Fix const-correctness for some *_fast function parameters.
- In practice, this only affected compiling for NEON on certain compilers. Other SIMD ISAs should remain unaffected.
2025-03-16 16:13:12 -07:00
zeromus 5cd9d36bba
Merge pull request #888 from Morilli/fix-movie-commands
fix movie command flags not actually being OR'd together
2025-02-14 03:16:42 -05:00
Morilli b756ffb1e6 fix movie command flags not actually being OR'd together 2025-02-14 08:57:30 +01:00
zeromus bec2329653
Merge pull request #886 from Anonym271/master
Bugfix: MemROMReaderWrite not working for size=1
2025-02-11 16:55:35 -05:00
Anonym271 06bef8b560 Bugfix: MemROMReaderWrite was not working for 1 byte length because it
would copy the current mem's byte into the source buffer instead of the
opposite way.
2025-02-11 22:49:20 +01:00
rofl0r dfcd482933 fix couple of header names to work on case-sensitive file systems 2024-12-06 02:37:38 +01:00
rofl0r 8a4fd0a9cb arm_jit: fix build when LOG_JIT_LEVEL != 0 2024-12-06 02:37:38 +01:00
zeromus b022181a05
Merge pull request #867 from lifehackerhansol/libnds-v2
Minor fixes for libnds v2.0.0 release
2024-11-14 23:54:53 -05:00
lifehackerhansol ee39a36f20
cp15: add support for process ID 2024-11-14 20:47:47 -08:00
lifehackerhansol c1624b2b33
MMU: support 8-bit write to REG_IPCSYNC 2024-11-14 20:47:47 -08:00
Max Fedotov 1192bf6f2c
EGL: use eglGetPlatformDisplay if available (#865)
POSIX Ports: When acquiring an EGL context, try calling the client-specific eglGetPlatformDisplay() before falling back to the more generic eglGetDisplay(). Hopefully fixes #864.
2024-11-12 22:50:35 -08:00
thesource 2c7fac57ff port 0.5 GPU scaling increments/window sizes to GTK3 2024-11-06 22:43:22 +01:00
Max Fedotov 3b1989a9d9
GTK*: add gamepad hotplug support (#855)
* add gamepad hotplug support
* Get rid of nbr_joy
2024-11-04 19:32:07 +01:00
zeromus f51e19b19b
Merge pull request #860 from En-En-Code/oglgetdriverversion-fix
fix: null-terminate versionSubstring in OGLGetDriverVersion
2024-11-02 22:24:35 -04:00
En-En 6f1d4e1d5c fix: null-terminate versionSubstring in OGLGetDriverVersion 2024-11-02 18:09:49 +00:00
rogerman 6690a8cedd posix: Update the Code::Blocks project file to include the new files that commit efdd938 added. 2024-10-28 14:39:17 -07:00
rofl0r 7d6f0982c8 gtk2: add some more presets to winsize menu 2024-10-28 19:16:45 +00:00
rofl0r 0ec9d74c39 gtk2: allow 0.5 increments on gpu scale
since the window size menu offers those as presets, and at least a 0.5
fraction on the scale doesn't seem to cause any problems in my testing.
2024-10-28 19:14:08 +00:00
rofl0r 76a6935dc8 gtk2: backport GPU scaling feature
feature was originally added via PR #764 to the gtk3 frontend.

this makes it possible to run the scaling on the GPU, avoiding the
incredibly slow software scaling that's otherwise done via cairo
when view->window size is set to anything > 1.0.
note that the window size "scale" needs to be identical to the
chosen GPU scale factor, otherwise software scaling kicks in again.

unlike the scale setting in the CLI port, which simply upscales the
native NDS framebuffer in hardware, this setting scales up even
the actual 3D textures, resulting in a sharper image, at the cost
of higher CPU/GPU usage. a game using demanding 3D scenes, like
zelda phantom hourglass' intro scene, may be able to still trash
the FPS.

the original PR also reported issues when setting the GPU scale to
a fraction, therefore the increments are currently locked to 1.0.
2024-10-28 13:50:27 +01:00
rofl0r 3ddb2669a9 cli: fix boost input detection
until now, the boost key was hardcoded to 'o' even when the config
said otherwise, and not treated in case of a joypad at all.
when triggered with the o key, it even behaved differently than
the gtk ui - the boost wasn't released together with the key,
but only when pressed again, so it was more like a shortcut for
"disable fps limiter".

this change implements the desired outcome of the second part of PR #822,
but without introducing more hacks and relying on magic values.

closes #822
2024-10-28 11:32:43 +01:00
rofl0r 58bbe693e1 cli: fix joypad and keyboard config retrieval
because the GTK frontends use GDK keysyms, not SDL ones, - the former
are being stored in the config file and used by the GTK ui) -  a temporary
workaround was put into place 14 years ago: the loaded config values
were simply being overwritten with the hardcoded defaults.

this commit removes the overriding of the config, and introduces
a cli frontend specific section "SDLKEYS", which is written by the
GTK2 frontend upon a configuration change.
it tries to convert the GDK keycodes into SDL2 ones while doing so.

an alternative solution (involving less code changes) would have been
to do the conversion in the cli frontend, but that would require having
the gdk header available for compilation, which may not be the case
if the user only wants the cli frontend. such a user could now create
the config file on another machine with the GTK frontend, or simply
manually take the desired values from the SDL_keycode.h header.

this change is instigated by one of the changes in PR #822, which simply
removed the workaround and kept parsing on error, which mitigated the
problem for some keys, but not all.
2024-10-28 11:32:43 +01:00
rofl0r 0a36e96f66
Merge pull request #845 from thesourcehim/master
[GTK*] Some gamepad input rework

- Unbind gamepad keys by default. The default bindings may fit one gamepad model but work weirdly with another causing issues like [LINUX/GTK3] Whitescreen freeze when pressing square on ds4 #834
- Use non-blocking method to obtain gamepad keys/axes during configuration to avoid visible emulator freeze and possible deadlock (see [linux] editing controlls sometimes (often) freezes the emulator #843)

closes #834
closes #843
2024-10-27 11:51:24 +01:00
thesource 5d498a97c4 Port previous two changes to gtk2 frontend. Add meson option to build
gtk2 frontend (disabled by default). Fix meson.build dependency for
gtk2.
2024-10-26 13:29:48 +03:00
zeromus fff5659879
Merge pull request #851 from dlbuhtig4096/master
Fix ensata sound register emulation.
2024-10-26 02:27:43 -04:00
En-En efdd938dc3
GTK*: Action Replay cheat menu (+ other cheat improvements) (#847)
* GTK cheats UI inputs/displays hex for address (offset)

* Added range bound to keep internal cheat data within specified size
The decision to change the value column to store G_TYPE_UINT is purely pragmatic--having all data be treated and displayed as unsized is simpler than writing a custom display to handle signedness and cleaner than 1-3 byte ints appearing unsigned and 4 byte int appearing signed.

* Added index and cheat type data to ListStore
My implementation plan is to use a GtkTreeModelFilter to create separate section for internal and ActionReplay cheats, but I was not convinced the indices in the tree path would correspond to the indices in , hence the additional column.

* Filter raw and AR cheats, display both filters in UI, patch up raw update/delete

* Action Replay UI elements [GTK]

* Memory leak fixes
+ some additional clean-up comments and small bug patches

* Backport to GTK2
2024-10-25 20:32:03 +02:00
dlbuhtig4096 ff84815acb Improve console allocation. 2024-10-24 19:20:24 +08:00
dlbuhtig4096 28f5c76035 Proper ensata handshake on reconnection. 2024-10-20 21:27:03 +08:00
dlbuhtig4096 7984eae357 Fix ensata sound register emulation. 2024-10-20 13:03:03 +08:00
Roger Manuel 2bc5b0d86b
Merge pull request #846 from BayLee4/fix_retina
Cocoa Port: Fix mixed retina/non-retina display touchscreen bug
2024-10-10 12:48:59 -07:00
BayLee4 a0386e535c Cocoa Port: Fix mixed retina/non-retina displays bug 2024-10-10 17:57:21 +02:00
thesource 72315fa339 Make gamepad key configuration non-blocking 2024-10-10 11:42:27 +03:00
thesource 1cf7c37896 Unbind joypad keys by default 2024-10-10 09:44:09 +03:00
zeromus 8fa0affab1
Merge pull request #839 from intra0/master
Update org.desmume.DeSmuME.metainfo.xml
2024-10-04 21:31:38 -04:00
zeromus e7442cc999
Merge pull request #841 from lifehackerhansol/cmdline-misleading-indentation
commandline: avoid misleading indentation
2024-10-01 05:43:24 -04:00
lifehackerhansol fa1879f9a7
commandline: avoid misleading indentation 2024-09-29 13:45:34 -07:00
intra0 bb1b6a1c80
Update org.desmume.DeSmuME.metainfo.xml
the current flatpack version is commit 640a1fdd93

was 2 years ago but is a 9.14 version
2024-09-25 21:54:14 -05:00
zeromus 91196788eb fix more screw-ups in unicode support. fixes #828 2024-08-31 22:34:38 -04:00
rogerman 8f9c6892d5 OpenGL Renderer: Fix an initialization issue with the clear image shader program when running the 3.2 Core Profile renderer for a driver that only supports OpenGL v3.2. (Regression from commit e2a25e2. Fixes #827.) 2024-08-28 10:33:27 -07:00
zeromus 42667020d8 fix ensata emulation? (re: #184) 2024-08-27 04:15:00 -04:00
rogerman 64132f765a OpenGL Renderer: Fix a bug where having Edge Mark enabled could cause fragments to disappear. (Regression from commit f910c61.) 2024-08-22 19:26:39 -07:00
rogerman 00b8df1b00 OpenGL Renderer: Add entry point for glClientWaitSync, fixing compiling on Windows. (Regression from commit f910c61.) 2024-08-15 17:50:53 -07:00
rogerman f910c6197c OpenGL Renderer: Add new rendering resource classes, and do some misc. refactoring.
- Using the new OpenGLGeometryResource and OpenGLRenderStatesResource classes, the 3.2 Core Profile and ES renderers now use triple-buffering for all geometry rendering resources and framebuffer constants.
- Delete the InitFinalRenderStates() method, which has been obsoleted over the years. Its functionality has been rolled into the InitExtensions() and _RenderGeometryLoopBegin() methods.
2024-08-15 16:49:42 -07:00
rogerman f84a804499 OpenGL Renderer: Fix bug where clear images were Y-flipped. (Regression from commit 3db6d56.) 2024-08-13 19:49:34 -07:00
rogerman 8197174d69 OpenGL ES Renderer: Fix a bug where the final output framebuffer is Y-flipped. (Regression from commit 3db6d56.) 2024-08-12 13:44:58 -07:00
rogerman 3db6d5676c OpenGL Renderer: Do some more code cleanup and tune-ups.
- In the 3.2 Core Profile and ES renderers, synchronization of vertex info uploads now occurs at a more reasonable time.
- Geometry rendering is now Y-flipped by default, eliminating the need to Y-flip the final output framebuffer under all conditions.
- Legacy OpenGL no longer needs to perform any color conversion of the final output framebuffer if FBOs are supported.
- Rename some functions and variables to better describe what things are doing now.
2024-08-12 11:23:23 -07:00
rogerman 9bbfca527a Remove redundant and currently unused Makefile. 2024-08-10 15:53:25 -07:00
rogerman 04f97d5755 OpenGL ES Renderer: Fix a major performance bug on many ARM-based mobile devices with integrated GPUs. 2024-08-10 15:06:30 -07:00
rogerman ea648f7110 OpenGL Renderer: Do some minor tune-ups.
- Remove some methods in OpenGLRenderer_2_0 and OpenGLRenderer_2_1 that have negligible contribution to either performance or code simplicity.
- OpenGLRenderer_1_2, OpenGLRenderer_2_0, and OpenGLRenderer_2_1 are now instantiated with their specific variant IDs.
- Calls to malloc_alignedCacheLine() have been replaced with the more appropriate malloc_alignedPage().
- Do some misc. code cleanup.
2024-08-10 13:48:13 -07:00
rogerman c75c1ce2c3 Linux Ports (All): Update Autotools and Meson scripts to add JIT support for ARM targets.
- Also fixes build errors related to explicitly building SIMD files for colorspacehandler. Don't do it! The proper way is to simply include "colorspacehandler.cpp" alone and let the compiler's preprocessor macros determine which SIMD file to use.
2024-08-09 12:55:13 -07:00
rogerman 2e01c0a840 Linux Ports (All): Update the Code::Blocks project file to add build targets for AArch64. Also do some other misc. updates.
- Release builds now use -Ofast optimization instead of -O3.
- Release builds no longer strip their symbols. This will be needed for profiling and debugging.
2024-08-08 17:34:26 -07:00
rogerman b799d94762 Colorspace Handler: Fix compiling for strict NEON.
- We could always use -flax-vector-conversions, but let's try to stay disciplined for now.
2024-08-08 12:11:20 -07:00
rogerman 176e38ce2f OpenGL Renderer: Simplify the code by removing the references to multiple output shaders, since commit 0c7cb99 has obsoleted them. 2024-08-07 12:20:35 -07:00
rogerman c5ab8a6ef6 OpenGL ES Renderer: Fix a bug where RGBA6665 color output would fail. (Regression from commit de9fc5a.)
- Also update some comments.
2024-08-06 23:48:54 -07:00
rogerman de9fc5ab75 OpenGL Renderer: Remove the additional FBOs that were introduced in commits 60385bd, 8b5ac56, and 3ef9271 in an attempt to fix rendering on old GPUs like the Intel HD 4000. (Fixes #820.) 2024-08-06 21:54:39 -07:00
rogerman 5baeb02754 Cocoa Port: Fix OpenGL context creation on older macOS. 2024-08-03 16:15:02 -07:00
rogerman d7dcc85d87 GTK / GTK2 Ports: EGL contexts running legacy OpenGL no longer require the EGL_KHR_surfaceless_context extension. 2024-08-03 11:14:55 -07:00
rogerman 79f3f94099 GTK2 Port: Set the audio volume in the same way as the GTK port so that the audio volume is consistent between the two ports. 2024-08-03 10:13:41 -07:00
rogerman 9aa2ddfc88 Linux Port (GTK/GTK2): Remove the requirement for libGLX.so when requesting a GLX context since libGL.so is all we need here.
- Also do some minor code cleanup in glx_3Demu.cpp
2024-08-02 12:10:21 -07:00
rogerman 4427b863ad Linux Port (GTK/GTK2): Fix compiling in glx_3Demu.cpp.
- Also fix a typo in egl_3Demu.cpp
2024-08-01 23:02:58 -07:00
rogerman 15f5b169cc Video Filters: Improve performance of Deposterize and XBRZ CPU-based filters. (Based on PR #631.)
- Special thanks to @m42a for the inspiration on this code!
2024-08-01 21:07:24 -07:00
rogerman be51e41c04 Ugh, let's try fixing the last stubborn Meson build script... 2024-08-01 18:00:54 -07:00
rogerman 46990f2d85 Fix some issues with Meson build scripts. (Regression from commit ca566eb.) 2024-08-01 17:51:12 -07:00
rogerman ca566eb11b OpenGL Renderer: Finalize all renderer-client integration to "just work".
- These changes now presume that standard OpenGL and OpenGL ES are mutually exclusive. We will NOT support running a standard OpenGL context and an OpenGL ES context in the same process.
- Clients must explicitly request supporting the OpenGL 3D renderer in their build configuration. Build configurations must define ENABLE_OPENGL_STANDARD (replacing the HAVE_OPENGL macro) or ENABLE_OPENGL_ES. If neither macro is defined, then the OpenGL 3D renderer will be assumed unavailable.
- Meson and Autotools now use better header/library checks for OpenGL functionality with their associated context type.
- Add a new Code::Blocks project file that can make builds for CLI, GTK, and GTK2.
- GTK and GTK2 ports now have the option to run a legacy OpenGL context, a 3.2 Core Profile context, or simply choosing the best context automatically like before.
- GTK and GTK2 ports have GLX and EGL as new context types. OSMesa and SDL have been updated to the latest design pattern.
- GTK and GTK2 ports can now be configured (via Meson or Autotools) to use a GLX, OSMesa, EGL, or SDL context.
- OSMesa contexts are now marked as deprecated. I don't know of anyone who still uses them, and I've never been able to get it to work correctly for years. Now that we have GLX contexts for compatibility purposes, OSMesa contexts are now completely redundant.
- Fix a bug with the GTK port where ancient GPUs without FBO support can still run framebuffers at custom sizes.
- For POSIX ports, move all "avout" and context creation files to the "shared" directory for better file organization.
2024-08-01 17:08:01 -07:00
rogerman 0a78fa2a2b OpenGL Renderer: Fix a few bugs here and there.
- Fix a compiling bug for ES due to missing tokens.
- Fix Fog and Edge Mark feature availability when running legacy OpenGL. (Regressions from commit 0c7cb99 and commit 8b5ac56.)
- glDrawBuffer() now determines its own algorithm at runtime instead of at compile time. This change is being done to be consistent with all of the other Standard vs ES changes.
2024-08-01 00:11:05 -07:00
rogerman 2f177d19a2 Cocoa Port: Update OpenGL renderer integration code to reflect current design patterns. 2024-07-26 14:56:36 -07:00
rogerman 4c90c2d9ee OpenGL ES Renderer: Finalize the last remaining bug fixes so that the ES renderer can work "out of the box".
- Respect the draw buffers ordering rules that are unique to ES.
- Report the actual OpenGL variant being requested when initializing the renderer.
- Add oglrender_deinit() function pointer so that clients can properly handle the destruction of their associated context resources at the correct time.
- Certain internal OpenGL info is now assigned at run time instead of at compile time. This change now allows any of the OpenGL renderers to run side-by-side.
2024-07-26 11:10:50 -07:00
rogerman d6532b9e91 OpenGL ES Renderer: Fix TBO-based polygon state uploading. 2024-07-24 15:28:56 -07:00
rogerman d58c0e9331 OpenGL Renderer: Oops! Fix a compiling issue introduced in commit e2a25e2. 2024-07-23 21:39:07 -07:00
rogerman e2a25e2412 OpenGL Renderer: Fix various rendering bugs.
- Fix a potential unaligned access crashing bug in ES when clear images are to be rendered.
- Fix an ES bug where clear images would fail to render when MSAA is enabled.
- Fix a legacy OpenGL bug where toon table colors were not ignoring their alpha bit, according to GBATEK.
2024-07-23 21:28:15 -07:00
rogerman f323dc464f Windows Port: Fix bug where the OpenGL 3D renderer would fail to initialize at program startup. (Regression from commit 76fe5f7. Fixes #815.) 2024-07-22 22:47:29 -07:00
zeromus 8e77a8d9f1
Merge pull request #818 from cyanea-bt/windows_paths
Windows Port: Fix empty defaults for path settings
2024-07-22 19:43:37 -05:00
cyanea-bt 5754425458 Windows Port: Fix empty defaults for path settings.
(Regression from commit 3511e14. Fixes #817.)
2024-07-23 01:57:59 +02:00
rogerman 12ed7dd054 Colorspace Handler: Fix alpha detection logic in ColorspaceConvert5551To8888_*() and ColorspaceConvert5551To6665_*(). 2024-07-21 21:02:50 -07:00
rogerman 368cd49fb6 OpenGL Renderer: Tighten up some code related to clear image. 2024-07-20 22:54:44 -07:00
rogerman 3ef927100b OpenGL Renderer: Fix some longstanding graphical glitches related to running Edge Mark and Fog with MSAA.
- These graphical glitches are resolved only when running 3.2 Core Profile with the GL_ARB_sample_shading extension, available on all modern GPUs.
- Do some minor optimizations to the Edge Mark and Fog shaders.
- Also fix an FBO attachment bug in legacy OpenGL that was introduced in commit 8b5ac56.
2024-07-20 20:49:44 -07:00
rogerman 8b5ac56d66 OpenGL Renderer: More FBO rework. 2024-07-19 14:38:05 -07:00
rogerman 60385bd099 OpenGL Renderer: Rework how the output framebuffers work.
- The output framebuffers now bind their own FBOs rather than changing draw targets with glDrawBuffer().
- Rework the general FBO management.
- Legacy OpenGL now outputs native RGBA color if FBOs are supported. This should give a minor performance increase on older GPUs.
- The fixed-function pipeline can now flip the framebuffer on GPU. This greatly reduces the CPU usage when doing the final color conversion and gives a significant performance increase on ancient GPUs.
2024-07-18 21:45:00 -07:00
rogerman 811e1de45e OpenGL Renderer: Oops! Roll back some internal test code that accidentally slipped into commit 0c7cb99. 2024-07-18 12:46:11 -07:00
rogerman 3e650f2f73 OpenGL Renderer: Add entry point for glBlendColor, fixing compiling on Windows. (Regression from commit 0c7cb99.) 2024-07-18 12:26:53 -07:00
rogerman 0c7cb99d78 OpenGL Renderer: Greatly simplify the fog rendering pass.
- There is no more need to switch to the working texture as the destination for the fog output. This change will be essential for future commits.
- The dual-source blending method has been obsoleted and removed.
- FBOs are no longer required for the fog feature, easing requirements for ancient GPUs.
- Ancient GPUs may see a small performance benefit due to shader simplification.
2024-07-18 12:17:25 -07:00
rogerman 70fef83ded OpenGL Renderer: Fix bug when the screen wasn't being cleared properly when no polygons are being sent to the renderer. (Regression from commit 241ca96.) 2024-07-16 16:15:47 -07:00
rogerman ff9231bb34 OpenGL Renderer: 16-bit texture data that is converted to 32-bit is now byte-swapped correctly on big endian systems. 2024-07-15 23:09:53 -07:00
rogerman ab1d37a44f Colorspace Handler: Fix compiling on AltiVec systems. (Regression from commit 586aea5.) 2024-07-15 23:07:24 -07:00
rogerman cc0b3ed00d Cocoa Port: Update the OpenGL blitter code to reflect the current code pattern in OGLRender.h.
- Centralize all header includes into OGLDisplayOutput.h.
- Update all extension versions of OpenGL functions/tokens that would be core in OpenGL v1.5.
2024-07-15 16:52:43 -07:00
rogerman 80694cd966 OpenGL ES Renderer: More ES fixes.
- Change the remaining FBO attachments that I missed the last time to use RGBA8 internal format.
- Fix picky ancient drivers that won't accept GL_RED as a texture internal format. It has been changed to GL_LUMINANCE.
- Fix picky ES drivers that demand that the external format used in both glTexImage2D() and glTexSubImage2D() are exactly the same.
- OpenGL ES doesn't support GL_UNSIGNED_SHORT_1_5_5_5_REV for texture data, and GL_UNSIGNED_SHORT_5_5_5_1 is incompatible with our data. So instead, all 16-bit data will be converted to 32-bit LE before uploading it via the textures, and such ES textures will now take GL_UNSIGNED_BYTE format.
- Remove the #include for EGL/egl.h in OGLRender.h, since EGL shouldn't exist at this level of the code stack.
2024-07-15 16:45:21 -07:00
rogerman 586aea5310 Colorspace Handler: Add new functions for 16-bit to 18-bit and 32-bit color conversion, now respecting the 16-bit color's alpha bit.
- ColorspaceConvert5551To8888()
- ColorspaceConvert5551To6665()
- ColorspaceConvertBuffer5551To8888()
- ColorspaceConvertBuffer5551To6665()
- Also rename the existing 16-bit color conversion functions to help further distinguish the functions from one another.
2024-07-15 16:24:02 -07:00
Roger Manuel 4b0805e139
Windows Port: Fix yet another compiling issue related to the OpenGL context. (Fixes #811.) 2024-07-15 10:00:38 -07:00
rogerman 15a6e51739 OpenGL Renderer: Add support for Fog, Edge Mark, and on-GPU framebuffer color conversion for ancient GPUs that have support for shaders and FBOs, but lack support for GL_EXT_framebuffer_blit. 2024-07-14 19:38:29 -07:00
rogerman de62116cc8 Windows Port: Fix OpenGL renderer init failure. (Regression from commit 76fe5f7. Fixes #810.) 2024-07-14 17:22:47 -07:00
rogerman 241ca96cf1 OpenGL Renderer: Fix issues that would throw a GL error.
- glTexParameteri() with GL_TEXTURE_2D_MULTISAMPLE throws INVALID_ENUM when trying to assign a sampler-related state, so these calls have been removed.
- glMapBufferRange() throws GL_INVALID_OPERATION if the buffer size is 0, so check for this condition first.
2024-07-13 10:43:04 -07:00
rogerman aaf88d9f14 OpenGL ES Renderer: More ES tune-ups.
- Any ES-specific error messages are now reported as "OpenGL ES" instead of "OpenGL".
- Explicitly declare the internal format of all textures and RBOs used as FBO attachments as "GL_RGBA8" instead of the generic "GL_RGBA". This may fix some extremely picky ES drivers that would throw GL_INVALID_ENUM if we don't use a sized internal format.
- Hard code the read pixels format as GL_RGBA and the read data type as GL_UNSIGNED_BYTE. It is meaningless to rely on GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE since we are reading from our own FBOs that are hard coded to GL_RGBA8 format.
- Require that OpenGL ES contexts support the GL_OES_surfaceless_context extension, since we are doing offscreen rendering strictly on FBOs only. This extension has been around for a very long time, and so this serves as a kind of compatibility check.
2024-07-12 15:41:09 -07:00
rogerman d480f95d79 Cocoa Port: Fix yet another crash-on-exit bug that could happen when running on an older system. 2024-07-12 12:00:49 -07:00
SimonAfek dd88556d53
CI: update github workflows (#809)
* Update macOS version in build_interface.yml

* Typo fixes in build_interface.yml

* build.yml: Update runner images

* build.yml: Update deprecated actions

* build_interface.yml: Update runner images

* build_interface.yml: Update deprecated actions

* build_interface.yml: Remove unnecessary packages from macOS "brew install" line to address warnings

* build_win.yml: Update runner image + remove vs-version parameter from setup-msbuild action

* build_win.yml: Update deprecated actions
2024-07-11 17:38:52 +02:00
rogerman 00dd6fb97a OpenGL ES Renderer: Use the proper ES extension header, and also avoid double #defining some of the tokens. 2024-07-10 21:53:49 -07:00
rogerman bb3011c262 OpenGL Renderer: Return to a more traditional method of doing texture reads in shaders, effectively removing dependent texture reads where appropriate.
- This change won't affect standard OpenGL on a desktop PC, but may improve performance on lesser GPUs trying to run OpenGL ES.
2024-07-10 16:01:13 -07:00
rogerman 86a29d768a OpenGL ES Renderer: Do some minor changes/fixes.
- Fix a bug where _isShaderFixedLocationSupported wasn't being set to true, causing shaders to fail.
- OpenGL version checks now account for non-compliant ES drivers that contain text before the version number.
- Manually set the default read/draw buffers for all FBOs upon creation. We shouldn't need to do this, since they should always be set later, but just in case...
- Add missing GL_BGRA macro.
- Tidy up the OpenGL naming in some error strings.
2024-07-10 13:59:02 -07:00
rogerman 3a6f2f6dc5 OpenGL ES Renderer: Add a new OpenGL ES 3.0 renderer. 2024-07-09 23:00:27 -07:00
rogerman 0e88f9aa94 OpenGL Renderer: Final changes for OpenGL ES compatibility. 2024-07-09 22:03:33 -07:00
rogerman 384854f6e7 OpenGL Renderer: More updates to the 3.2 Core Profile renderer to be more cross-compatible with OpenGL ES 3.0.
- Add support for fixed locations in shaders for OpenGL 3.3 and later.
- The fog density table texture is now a 2D texture instead of a 1D texture.
- Fix a memory leak where the polygon state texture wasn't being deleted upon the destruction of the OpenGLRenderer object.
2024-07-09 01:18:50 -07:00
rogerman 7dbece1082 OpenGL: Do some minor changes to the 3.2 Core Profile renderer to make it more cross-compatible with OpenGL ES 3.0.
- PBO handling now works via glMapBufferRange() instead of glMapBuffer().
- Polygon states can now be uploaded using plain integer textures. 64k UBOs and TBOs are no longer required.
2024-07-06 16:20:53 -07:00
rogerman 09090e93f9 GFX3D: Change POLYLIST_SIZE to 16384 to ensure proper memory alignment with buffers based on CLIPPED_POLYLIST_SIZE and VERTLIST_SIZE. 2024-07-06 13:58:05 -07:00
rogerman c962c550e7 OpenGL: Handle legacy functions and tokens more gracefully for OpenGL variants that may not have them. 2024-07-05 18:13:43 -07:00
rogerman 76fe5f758c OpenGL: More changes in preparation of OpenGL ES.
- Slightly change the names of attachment defines so that they can be distinguished from the native OpenGL attachment defines.
- The minimum version driver check now accounts for OpenGL ES.
- OpenGLRendererCreate() can now handle any possible OpenGL variant, as declared in the OpenGLVariantID enum.
- Framebuffer read backs may now assigned their format and data type. (Legacy OpenGL assigns the format as GL_BGRA, while 3.2 Core Profile assigns the format as GL_RGBA.)
2024-07-03 16:55:47 -07:00
rogerman ba56bbc7c2 OGLRender_3_2.cpp... try again... 2024-07-03 13:05:43 -07:00
rogerman 3ec0b0c2e1 OpenGL: Continue preparation for adding OpenGL ES. (Related to commit 086980d.) 2024-07-03 13:01:17 -07:00
rogerman fc6ff8edbd GPU: Fix a bug on big-endian systems where setting the backdrop color could cause a crash. 2024-07-02 01:35:10 -07:00
rogerman fe0ae83c40 Cocoa Port: Fix a longstanding, yet rare, crash that may occur when quitting the app. 2024-07-02 00:16:46 -07:00
rogerman d4163a1893 OpenGL: Fix building on Windows and Linux. (Regression from commit 086980d.) 2024-07-01 16:26:46 -07:00
rogerman 086980deaf OpenGL: Start reorganizing stuff in preparation for adding new OpenGL variants, such as OpenGL ES.
- All platform-specific header includes are now centralized in OGLRender.h.
- Remove all ARB and EXT versions of legacy functions (everything pre 3.0). Legacy functions now only reference their core versions.
- Do a some minor code cleanup.
2024-07-01 16:19:05 -07:00
rogerman 76bd1a5e35 Change line-ending style in OGLRender.h from Windows-style CRLF to Unix-style LF. 2024-06-29 14:50:47 -07:00
rogerman 6309a9c6a7 libretro: So apparently, _XOPEN_SOURCE has to be at the top of the file. Hopefully this makes both GCC14 users and Mac users happy. (Related to commit 779606e. Based on PR #793.) 2024-06-07 17:16:53 -07:00
rogerman 779606ec2f libretro: Fix building on Mach-based operating systems, otherwise known as Mac OS X and modern macOS (regression from commit 90d0abd). Based on PR #793. 2024-06-07 16:33:13 -07:00
zeromus ffb8666a8f winport - plumb S9X_JOY_NEUTRAL through inifile:
[Controls]
DigitalizationThreshold=50
2024-06-07 00:24:55 -04:00
zeromus ff6c33a8d6 winport - reduce joystick digitalization threshold from 60% to a more normal 50%. With a too-high threshold, it's impossible to specify diagonals. This is preferable for games without diagonals (else you accidentally crouch when you just meant to walk to the side) instead of 8-way games, so we have to be pretty aggressive about the threshold. But 50 is the more normal choice. 2024-06-07 00:18:09 -04:00
zeromus 90d0abdae0
Merge pull request #792 from atsampson/xopen-strdup
libretro-common: fix implicit declarations
2024-05-13 07:59:48 -05:00
Adam Sampson 738298a9e8 libretro-common: fix implicit declarations
strdup and realpath are only declared by glibc's headers if
_XOPEN_SOURCE >= 500.
2024-05-13 12:47:10 +01:00
zeromus 4a53a30b91 winport - fix bug where desmume would create working directory using some wrong locale encoding and produce a Pok魯n directory instead of using the Pokémon that was already there (fixes #791) 2024-05-12 21:33:49 -04:00
rofl0r 9515af82b2
add an issue template for github (#784) 2024-04-12 21:39:12 +02:00
rogerman bae67e2d0c GPU: Implement the DISPCNT register's ForceBlank bit by clearing the line to white if the ForceBlank bit is set. (Fixes #775.) 2024-03-02 15:18:51 -08:00
Max Fedotov 0a6eca6dce
GTK: hybrid layout support (#773)
* GTK: hybrid layout support
* Fix HUD with new layouts
* Simplify rotoscaled_hudedit logic a bit
2024-02-26 19:12:50 +00:00
Max Fedotov 45738beb88
GTK: make OSD scalable (#769)
* gtk: make OSD scalable

* Scale save slot indicator (oops), make text outlines look smoother, use
larger font when not scaling

* Save and load HUD layout, prefer raster font on low resolution, select
vector font size close to raster one, make OSDCLASS::scale floating point

* Build fix

* Add reset HUD layout action, only require fontconfig if libagg is found.

* Try another font in case we could not locate monospace

* Detect screen bytes per pixel instead of hardcoding it, define
AGG2D_USE_VECTORFONTS if fontconfig is found.

* Different pixel formats are handled by different draw target
implementations
2024-02-14 08:20:57 +00:00
zeromus 6508c2b115 placate -Werror=format-security (probably) (re: #768) 2024-02-01 04:26:38 -05:00
Max Fedotov f2cfd23ef2
gtk: implement GPU scale factor feature (#764)
* [WIP] gtk: implement GPU scale factor feature

* Replace combobox with spin button, fix taking screenshot

* Fix distorted image, add some checks for scale factor value

* Make OSD at least properly visible
2024-01-25 14:28:46 +00:00
rogerman b06537cf51 Cocoa Port: Fix building on Cocoa port related to new files being added in commit 8be30fe.
- Note that this commit ONLY fixes building, but DOES NOT actually add barcode reader support to the Cocoa port just yet.
2023-10-10 13:45:07 -07:00
zeromus 0b027d8cc0
Merge pull request #735 from windwakr/hcv1000-fixes
Slot2: Sega Card Reader fixes
2023-10-07 11:04:03 -05:00
windwakr 8be30fe971 Slot2: Sega Card Reader fixes 2023-10-07 00:35:48 -04:00
zeromus f3dee5d7ac
Merge pull request #733 from windwakr/hcv1000
Slot2: Add Sega Card Reader(HCV-1000)
2023-10-04 20:04:39 -04:00
windwakr 0a34ef8e0b Slot2: Add Sega Card Reader(HCV-1000) 2023-10-04 17:05:01 -04:00
Roger Manuel 7a3b748d77
Fix erroneous copyright date in slot1_retail_auto.cpp (related to commit 8fefb4f) 2023-10-04 09:45:02 -07:00
zeromus 25cbcd255e fix buffer overflow (by one value only) in spu that happened basically 100% of the time a sample ended. whether it corrupted the heap or not is a matter of luck. should fix #717 2023-09-03 06:00:41 -04:00
zeromus 3955480674
Merge pull request #720 from mjunix/master-1
Fix potential index out of bounds
2023-08-05 15:46:28 -07:00
Johan Mattsson ca799e60b7
Fix potential index out of bounds 2023-08-06 00:35:40 +02:00
Johan Mattsson 357ff8a2c5
Fix potential index out of bounds 2023-08-06 00:20:22 +02:00
rogerman 402e9f0a31 Cocoa Port: Add two new Cheat Manager actions, "Enable All Cheats" and "Disable All Cheats", which do exactly as their descriptions would suggest. 2023-08-02 13:50:41 -07:00
rogerman 41e3401765 Cocoa Port: In the Cheat Database Viewer, add the option to ignore any game compatibility checks when adding new cheats.
- At their own risk, this option allows the user to add any cheat from the database to any game that they want, regardless of any potential dangers that may arise from doing so. Use this option responsibly.
2023-08-02 13:23:18 -07:00
rogerman 751ab0255b Cocoa Port: The Cheat Database Viewer now displays the current game's serial and CRC to help users verify the existence of a game in the database file. 2023-08-02 10:53:58 -07:00
rogerman 6c5941689f Cocoa Port: In the Cheat Manager, the "Remove All Cheats" button has been moved into an Actions pop-up menu.
- This change is to help avoid misclicks on the button that may instantly wipe out the user's cheat list.
- The new Actions pop-up menu also exists to incorporate some new cheat list operations that will be coming very soon.
2023-08-02 10:51:00 -07:00
rogerman 35976edb5f Cocoa Port: Conversions between Internal cheats and Action Replay cheats now respect the value length. 2023-08-01 15:18:44 -07:00
rogerman 586c7ee199 Cocoa Port: In the cheat database viewer, make the current game entry's font slightly larger to further differentiate it from the other games. 2023-08-01 10:03:48 -07:00
rogerman e3167110b2 Cocoa Port: Completely redesign the cheat database viewing system with a whole slew of new features!
- Multiple cheat database files may now be opened simultaneously, each in their own individual windows.
- Cheat database files are now fully browsable.
- Game entries are now searchable by game title, serial, and CRC.
- Cheat entries are now viewed in a hierarchical layout, better representing the FAT format of the database entries.
- All cheats within a directory can now be selected or deselected in just a single click.
- Error handling is now more robust, informative, and nicer looking.
- Cheat database files are no longer assigned in DeSmuME Preferences; they are now opened through the "File > Open Cheat Database File" menu.
- Recent cheat database files are now saved, and can be quickly accessed through the "File > Open Recent Cheat Database File" menu.
- It is now possible to remove all cheats at once from the Cheat Manager's cheat list.
2023-08-01 01:41:15 -07:00
rogerman 4e6a7f0424 Cheat System: Fix a couple bugs with CheatDBFile::LoadGameList() when reading the entire database's game list.
- Fix a bug where loading all database game entries from an encrypted database would result in reading gobbledygook.
- Fix a bug where calling CheatDBFile::LoadGameList() for all database game entries would always return 0 entries rather than the actual number of found entries.
2023-07-24 13:46:05 -07:00
rogerman 9bf090b309 Cheat System: Fix a bug where the underlying cheat data would get deallocated earlier than intended. (Regression from commit 0c90e8f.)
- In CheatDBGame, also differentiate between actual entry size vs. working entry size.
2023-07-19 12:22:06 -07:00
rogerman d08a5dc56c Cocoa Port: Update build optimization profiles in Xcode project. 2023-07-18 16:43:15 -07:00
rogerman 6ee942ca5f types.h: Remove an extraneous file inclusion. 2023-07-18 12:10:55 -07:00
rogerman 0c90e8f4e3 Cheat System: Rearchitect the system for loading cheat database files in preparation for adding new features to the database file presentation. Also do a bunch of code cleanup and fix multiple bugs.
- The file description is no longer limited to 16 characters.
- Folder notes are now included in the description strings of exported cheat items. These can be important for cheats that include operating instructions in their associated folder notes.
- Fix a bug where reading the last game entry of the database file would fail.
- Fix a potential bug where reading a game entry from an encrypted database file would fail if the initial entry data resides very close to a 512-byte boundary.
- Fix a bug where deleting a CHEATSEXPORT object without calling CHEATSEXPORT.close() would result in its associated file remaining open.
- Fix a bug where deleting a CHEATSEXPORT object without calling CHEATSEXPORT.close() would result in CHEATSEXPORT.cheats leaking memory.
2023-07-18 11:13:42 -07:00
SimonAfek 50f02ae172
Fix broken macOS interface build (#679)
* Update macOS version in build_interface.yml
* Typo fixes in build_interface.yml
2023-07-12 08:49:01 +00:00
rogerman 0fc3306bfc Cocoa Port: Standardize all Internal cheat direct memory writes (clicking the 'Write Once' button) to write to NDS memory before NDS_exec() is called. 2023-07-08 20:28:01 -07:00
rogerman f240472f5e Cheat System: Standardize memory writes for all cheat types. Most notably, Internal cheats now reset the JIT in the same way as Action Replay cheats do. 2023-07-08 19:52:10 -07:00
rogerman 12347c7cd9 Cocoa Port: Continue refactoring the cheat system code, Part IV.
- Add the following C++ classes: ClientCheatSearcher, ClientCheatDatabase
- Remove the following Obj-C classes: CocoaDSCheatSearch, CocoaDSCheatSearchParams
- Remove duplicate GUI code from EmuControllerDelegate.mm and preferencesWindowDelegate.mm
- All basic functionality for managing game session cheat items, the cheat database list, and cheat search are now managed through CocoaDSCheatManager.
2023-07-07 19:31:26 -07:00
rogerman d00e6355da Cocoa Port: Continue refactoring the cheat system code.
- Add ClientCheatManager C++ class, further reducing dependence on Objective-C code.
2023-07-02 22:54:13 -07:00
rogerman 946f7df9bc Cocoa Port: Continue refactoring the cheat system code.
- Add new ClientCheatList C++ class, further reducing dependence on Objective-C code.
- Making any changes to the cheat list or to any cheat items no longer requires the acquisition of an R/W lock.
2023-06-30 20:04:19 -07:00
rogerman 4e7926eaa1 Windows Port: Fix compiling issue that prevented building. (Regression from commit 7fb5a58.) 2023-06-30 15:58:22 -07:00
rogerman 7fb5a5871b Cheat System: Minor code cleanup and robustness improvements. 2023-06-30 15:13:35 -07:00
zeromus f48aee928c fix bug from 9767f79346 that made the cheat search results list produce strange cheats without 0x02xxxxxx prefix that don't work 2023-06-25 18:24:53 -04:00
rogerman ba83b68b7f Cocoa Port: Begin work on cleaning up and refactoring the cheat system. Also add some quality-of-life improvements to the GUI while I'm at it.
- Add new ClientCheatItem C++ class to handle cheat items, greatly reducing dependence on Objective-C code.
- Remove a bunch of methods from CocoaDSCheatItem and CocoaDSCheatManager that were never used and are no longer planned to ever be used in the new code refactor.
- The Cheat Manager window may now be resized.
- The Action Replay code editor now uses Monaco 13 font instead of the system default font.
- The command for "Enable/Disable Cheats" has been renamed to "Enable/Disable Cheat System" to help clarify that the command affects the entire cheat system as a whole, as opposed to enabling/disabling individual cheat items.
2023-06-23 14:18:02 -07:00
rogerman aeefd86f57 Cocoa Port: In the cheat system code, remove Obj-C dot syntax for object properties to avoid ambiguity with features from other languages. 2023-06-21 14:53:49 -07:00
rogerman b468aee01a Linux GTK Port: Fix compiling issues that prevented building. (Regression from commit aa21454.) 2023-06-20 17:12:53 -07:00
rogerman aa21454373 Cheat System: Do some code cleanup and silence all of the compiler warnings (on Windows and Cocoa ports only).
- Some minor API changes were made, but only Windows and Cocoa were actually tested. Tried to make sure that Linux ports were updated to the new API, but haven't tested it.
2023-06-20 16:44:30 -07:00
rogerman cedc1c9f38 Cocoa Port: Add option for Catmull-Rom sound interpolation in the GUI. Also update tooltips for all interpolation methods to better reflect how they compare to one another. 2023-06-20 14:06:04 -07:00
rogerman 8bba9dc955 Cocoa Port: Due to commit fac70ce fixing FBO issues with older GPUs, OpenGL rendering is now returning to PowerPC Macs. This change effectively reverts commit 4708404. 2023-06-19 18:44:14 -07:00
rogerman 5c805b2de0 Cocoa Port: Fix some compiler warnings. 2023-06-14 13:57:30 -07:00
zeromus 7c2f281d25
Merge pull request #674 from oheikk/fix-audio-volume-resetting
Fix audio volume resetting on posix/gtk
2023-06-08 16:46:43 -04:00
Oskari Heikkinen 941c2e39be Fix audio volume resetting on posix/gtk 2023-06-08 22:47:26 +03:00
zeromus 1bde1c28ac fix non-windows compilation, maybe. could be bugged, didnt test 2023-05-28 14:31:50 -04:00
zeromus 3511e14ac6 winport: path settings support unicode now (fixes #669). old ini files may malfunction since they're now expected to be written with unicode. old ones can't be effectively upgraded (consequence of using obsolete ini file apis). 2023-05-28 14:22:09 -04:00
SimonAfek 3cefa5d78e
Update deprecated GitHub actions v2 (#666)
* Windows CI: Update deprecated github actions

* build_interface.yml: Update actions

* release_tarball.yml: Update checkout action

* build.yml: Update actions
2023-05-20 16:33:23 +01:00
SimonAfek fadd3b6e63 Windows CI: Update deprecated github actions 2023-05-10 13:56:54 +01:00
rogerman bf344e9a3e SoftRasterizer: Perform all calculations using fixed-point math instead of float-based math.
- CommonSettings.GFX3D_TXTHack has been repurposed to switch between fixed-point math and float-based math.
- Fix various rendering bugs that were caused by a loss of Z precision introduced in commit 7751b59.
- In Pokemon Diamond/Pearl, the bug that caused random black dots to appear on the ground has been fixed.
2023-05-04 12:36:49 -07:00
zeromus 1dbbeba3a7 add another mic sample 2023-04-24 15:21:45 -04:00
zeromus 65ec088918 add mic samples. we're gonna start distributing these eventually. 2023-04-23 16:18:51 -04:00
zeromus 6b7559c71b fix alignment of tempMultiplyMatrix and currentMatrix[4] in GeometryEngineLegacySave. Fixes #657. It would be better to fix this perhaps by making NDSMatrix a type that has the alignas(16) put on it while inheriting from std::array<u32,16> perhaps, so this mistake is not possible? 2023-04-21 15:18:32 -04:00
zeromus c97ba8fb16 fix spurious RRX variant selection in several disassembly macros (fixes #652 maybe) 2023-04-10 11:43:46 -04:00
rogerman ab17945377 GFX3D: Obsolete and remove the VERT struct, since OpenGL, and SoftRasterizer are now both receiving their vertex data in fixed-point.
- Also remove the unused NDSVertexf struct. There shall be only one representation of the NDS vertex data, and that shall be the fixed-point values of NDSVertex.
2023-03-06 22:19:09 -08:00
rogerman 952585eaae SoftRasterizer: Read in vertex data data as fixed-point instead of as floating-point. 2023-03-06 21:39:57 -08:00
rogerman be88a0b4c3 Remove superfluous x/y/z names from Vector2s16, Vector2s32, Vector2s64, and Vector2f32 union data types, since it is extremely unlikely that these extra names will ever be used. Just use names "x" and "y", which are the most likely to be used for these kinds of 2-element vectors. 2023-03-06 21:27:47 -08:00
rogerman 4e1ce23982 SoftRasterizer: Do some minor refactoring and code cleanup, and also prepare SoftRasterizer to accept fixed-point vertex data. 2023-03-06 14:35:47 -08:00
rogerman 56251cafd1 GFX3D: Clean up the big-endian compatibility code. 2023-03-03 13:58:37 -08:00
rogerman 111292ff15 GFX3D / SoftRasterizer: Small refactor to use some of the new data types introduced in commit cda8cb5.
- Also make SoftRasterizer's framebuffer out-of-bounds width check more robust.
2023-03-03 13:02:04 -08:00
rogerman 90c8411cbf GFX3D: Fix clear color on big-endian systems. (Regression from commit 97848fc.) 2023-02-28 01:34:27 -08:00
rofl0r dcd1072800 CI: limit autoconf build to 8 processes
hopefully will prevent the OOM killer from kicking in.
2023-02-28 03:07:43 +00:00
rogerman 1daebcd670 Silence some compiler warnings. 2023-02-27 16:36:08 -08:00
rogerman cda8cb5686 Core: Move low-level vector, vertex coordinate, and color data type declarations into types.h so that they can be used universally. Also update the data type names to be more descriptive and have better consistency.
- Add SIMD-float32 data types, and also add macros to track SIMD data-type availability.
- Also fix some bugs where 3D would fail to render on big-endian systems. (Regression from commit a67e040.)
2023-02-27 15:39:17 -08:00
rogerman d9be9c6bf6 Cocoa Port: Silence some compiler warnings. 2023-02-25 12:11:22 -08:00
rogerman a7bdd1e3a9 GFX3D: Remove the mistaken addition of color clamping when converting fixed-point vertex colors into floating-point. Fixes the proper coloring of Princess Peach in the opening sequence of Super Mario 64 DS. (Regression from commit 7751b59.) 2023-02-24 16:01:14 -08:00
rogerman fac70ce98b OpenGL Renderer: Use the fixed-point vertex list data instead of the floating-point based one, alongside other tune-ups.
- To determine polygon facing, use GFX3D's CPoly.isPolyBackFacing instead of using GLSL's gl_FrontFacing. This eases OpenGL version requirements and improves older GPU compatibility a little.
- Also fix a bug where GPUs that support FBOs, but not shaders, were unable to read out their framebuffers properly.
2023-02-24 13:49:07 -08:00
rogerman 37683a708e GFX3D: Y-sorting and writing out vertices to a save state are now handled using fixed-point instead of floating-point, where appropriate. 2023-02-23 13:12:13 -08:00
rogerman 7751b59882 GFX3D: Polygon clipping, viewport transformation, perspective correction, and face calculations are now done in fixed-point instead of floating point. 2023-02-22 22:07:37 -08:00
rogerman e1969c470b GFX3D: Vertex post-processing has been moved from the 3D renderers to GFX3D.
- Specifically, viewport transformation, face calculation, and face culling are now handled in GFX3D, and are now standard behaviors for all 3D renderers. This reorganization makes more sense since the 3D renderers are primarily responsible for rasterization and framebuffer post-processing, rather than for processing geometry.
- As a positive side-effect, the OpenGL renderer gains a small performance improvement as well as better accuracy in face culling.
2023-02-19 20:23:44 -08:00
rogerman 5457932d75 OpenGL Renderer: Fix bug where the Depth L-Equal Polygon Facing option would fail to become enabled when running OpenGL 3.2 or later. (Regression from commit ab38d17. Note that this bug does affect the 0.9.13 release build.) 2023-02-18 16:31:38 -08:00
rogerman cf75e26353 OpenGL Renderer: Silence compiler warnings. 2023-02-18 16:21:44 -08:00
rogerman 97848fce8c GFX3D: Move some last bits of static data floating around in gfx3d.cpp into the GFX3D struct, and then make the instantiation of the struct itself static. 2023-02-18 13:37:17 -08:00
rogerman 92d662cb71 GFX3D: Fix longstanding potential overflows related to polygon lists by reducing POLYLIST_SIZE from 20000 to 16383.
- Historically (ever since commit b1e4934 and commit d5bb6fd), VERTLIST_SIZE (based on POLYLIST_SIZE) could reference an index over 66535, but POLY.vertIndexes has always been an unsigned 16-bit value with a max value of 66535, making for a potential overflow. In practice, an overflow has never happened in the past 15 years because a hardware NDS has a limit of 6144 polygons (or 24576 vertices), and that even a VERTLIST_SIZE of 80000 is way more than plenty to accommodate that. Rather than increasing POLY.vertIndexes to 32-bit, it makes more sense to reduce POLYLIST_SIZE to 16383 to keep VERTLIST_SIZE below 66536. Even with this change, POLYLIST_SIZE and VERTLIST_SIZE should be more than plenty in practice.
- Also, now that we're performing polygon clipping for all client 3D renderers (ever since commit e06d11f), we're finally accounting for the fact that the clipped polygon list size is larger than POLYLIST_SIZE. Client 3D renderers have been updated to now reflect this change and avoid theoretical overflow issues that have never actually happened in practice.
2023-02-18 10:54:02 -08:00
rogerman 86b990f68a GFX3D: The shininess table is no longer a part of SWAP_BUFFERS.
- Since the shininess table is only ever used for vertex generation, it makes no sense for the table to included for the rasterization step. The shininess table has been moved to the NDSGeometryEngine class, which is a class dedicated to just vertex and polygon generation. This reorganization seems more sensible.
2023-02-17 18:32:42 -08:00
rogerman 4a95e9b8d1 GFX3D: Reorder members of the GeometryEngineLegacySave struct to better reflect the actual order of data in the existing save state format.
- Also rename some matrix-related members for better clarity.
2023-02-17 14:01:24 -08:00
rogerman d0d23cce7e GFX3D: Attempt to fix an MSVC compiling issue. (Related to commit 5d6e866.) 2023-02-17 12:00:27 -08:00
rogerman 5d6e8663c4 GFX3D: Finish refactoring geometry engine related stuff into the new NDSGeometryEngine class.
- Also, the vector test has been changed so that the result vector accounts for the 4 sign bits and proper sign expansion on overflow.
2023-02-16 21:58:28 -08:00
rogerman db365e849f GFX3D: Clean up some lighting-related code. 2023-02-16 02:59:05 -08:00
rogerman 79aa5b558e GFX3D: Continue encapsulating stuff into the new NDSGeometryEngine class, mostly focusing on matrix-related things.
- There are two significant behavior changes in this commit that will require further testing.
- Behavior change: Before, MTX_LOAD_4x4 and MTX_LOAD_4x3 commands would update the individual values in the current matrix for each command. Now, these commands will batch the values into a temporary matrix until the temp matrix is complete, and then copy the temp matrix into the current matrix. This now matches the batching behavior that the other matrix commands already do.
- Behavior change: Before, there was a single shared temporary multiplication matrix used to batch the values of incoming MTX_MULT_4x4, MTX_MULT_4x3, and MTX_MULT_3x3 commands, theoretically allowing these commands to be used interchangeably and overwrite values from previous commands until the last command made a completed multiplier matrix. Now, there are 3 separate temporary multiplier matrices, one for each of the MTX_MULT_* commands, which means that each command type must now complete its own multiplier matrix before it can perform a matrix multiply.
2023-02-15 19:59:59 -08:00
rogerman 669f1b05f5 GFX3D: Begin encapsulating stuff into the new NDSGeometryEngine() class.
- Also do some minor misc. code cleanup.
2023-02-15 00:52:23 -08:00
rogerman d03e4a6886 Cocoa Port: In the OpenGL blitter, prevent FBO-related GL calls if FBOs are not available.
- Also silence some compiler warnings.
2023-02-14 23:30:22 -08:00
zeromus d0ed57d1b3 fixed: EMUFILE_FILE eof() on textmode failed on windows (caused .dct files from mac systems freeze process while loading) 2023-02-11 15:59:40 -05:00
rogerman 5831099ebc GFX3D: The Box Test is now performed with integer operations instead of with floating point.
- The integer-based Box Test should be just as good as the old float-based one, as tested by "American Girl: Julie Finds a Way". Of course, there are still bugs compared to a hardware NDS, but we haven't transitioned to rendering with integer-based vertices yet to make a meaningful test possible.
2023-02-10 19:01:16 -08:00
rogerman 624f649acb Oops! Forgot a file. (Related to commit a67e040.) 2023-02-10 18:38:21 -08:00
rogerman a67e040a57 GFX3D: Do some major code cleanup.
- Rename a bunch of variables to better reflect their intended usage.
- Add new data types for organizing 3D vectors and coordinates.
- C functions that are called in response to 3D commands now follow the exact same pattern: “static void gfx3d_glFuncName(const u32 param)”
- Be super explicit about the usage of numeric data types and their typecasts to improve their code visibility.
- Remove implementation-specific ambiguity of right bit-shifting signed numerics (Logical-Shift-Right vs Arithmetic-Shift-Right) in the following functions: gfx3d_glLightDirection_cache(), gfx3d_glNormal(), gfx3d_glTexCoord(), gfx3d_glVertex16b(), gfx3d_glVertex10b(), gfx3d_glVertex3_cord(), gfx3d_glVertex_rel(), gfx3d_glVecTest().
2023-02-10 18:25:21 -08:00
rogerman 242cb63327 GFX3D: Remove POLY struct members that don't need to be swapped. This results in less buffer copying for all POLY lists.
- Also remove Viewer3D_State.indexList. This member is obsolete since Viewer3D_State.gList.clippedPolyList is generated in the same order described by indexList.
- Encapsulate and rename some more lists to make their intended purpose more descriptive.
2023-02-09 00:27:45 -08:00
zeromus 23400431a1
Merge pull request #632 from hjung4/fix/strchr-oob-check
Fix out-of-bounds index access
2023-02-08 12:25:41 -06:00
Henry Jung 0e538b0931 fix: strchr check 2023-02-08 07:54:08 -05:00
rogerman d8ee3480df GFX3D: Clipping functions now take VERT parameters as non-nullable references instead of as nullable pointers where appropriate.
- GFX3D_ClipPoint() (formerly named clipPoint()) now writes directly to the target VERT rather than copying a return value back to the target.
2023-02-06 23:20:46 -08:00
rogerman 9554595948 GFX3D: Various minor tweaks and optimizations, plus code cleanup.
- Most importantly, refactor the GFX3D_Clipper::ClipPoly() method into the standalone GFX3D_GenerateClippedPoly() function, which drops all class member dependencies and is much more straightforward to use.
- Remove the GFX3D_Clipper class. It has been slowly gutted over the years, but the loss of the ClipPoly() method makes the class obsolete, putting the final nail in its coffin.
- Using the new GFX3D_GenerateClippedPoly() function, gfx3d_PerformClipping() operates on the unsorted clipped polygon list directly. This means that the polygon clipping step requires one less buffer copy.
- Clipped polygons no longer retain direct pointers to POLY structs, instead using their index member to reference a POLY struct at a POLY array location. All 3D renderers have been updated to reflect this change.
- Rename a bunch of variables that reference POLY, CPoly, and VERT structs to clearly differentiate them between raw NDS data and our own internally processed data.
- Fix a potential bug in GFX3D_GenerateRenderLists() where sorting clipped polygons would reorder their polygon indices without reordering their other data members along with the indices, causing the data members to desync. OpenGL rendering was immune to this bug, but SoftRasterizer might have possibly seen it. In any case, this fix is the correct behavior.
2023-02-06 17:50:42 -08:00
rogerman 628eb6596a Cocoa Port: Fix some random compiling issues. 2023-02-04 19:33:35 -08:00
rogerman cbbacdbf59 GFX3D: The POLY and VERT structs have been converted to POD-style structs for better data consistency. 2023-02-02 02:19:49 -08:00
rogerman 9273c9ab13 GFX3D: Encapsulate some data into the GFX3D struct, and also do some minor code cleanup. 2023-02-01 16:54:04 -08:00
rogerman a3e84e28c2 Save States: Oops! Fix a bug where 3D vertices were getting double-loaded, causing save state file reads to desync. Fixes #629. (Regression from commit 5426509e.)
- Problems only occurred when LOADING a save state. However, SAVING a save state on commit 5426509e should be okay, so such save states should not be broken.
2023-02-01 15:17:20 -08:00
zeromus 5bcfd2f022
Merge pull request #628 from radioactiveman/master
Fix a few compiler warnings
2023-01-30 16:53:26 -06:00
Thomas Lange ef3f285f95
Fix a few compiler warnings
warning: use of bitwise '&' with boolean operands [-Wbitwise-instead-of-logical]

Reported by clang 15.
2023-01-30 23:40:50 +01:00
rogerman c9a4d9c4b8 SoftRasterizer: Fix compiling issue for non-SSE2 systems. (Regression from commit 5426509e.) 2023-01-25 19:09:21 -08:00
rogerman 5426509ede GFX3D: Render states and geometry lists are now copied/swapped more consistently on flush. (Related to commit 8438a5a6.)
- Viewports are now processed on VIEWPORT register write instead of being processed at render time.
- CLEAR_DEPTH, CLRIMAGE_OFFSET, EDGE_COLOR, FOG_TABLE, and TOON_TABLE register writes are now handled more consistently.
- The fogDensityTable check for force-drawing clear images in gfx3d_VBlankEndSignal() has been removed. Changes done in commit 8438a5a6 will always causes this check to fail, and this commit will always cause this check to fail. Therefore, this check is now obsolete.
- Change a bunch of GFX3D-related structs from C++ style constructed structs into C-style POD structs.
2023-01-25 18:52:45 -08:00
zeromus be287de623
Merge pull request #627 from RainingChain/fwSettingsMacAddress
Add mac address setting
2023-01-21 16:59:18 -06:00
Raining Chain 9d2ddfa648 Add mac address setting 2023-01-21 17:32:05 -05:00
rogerman f0b0afe18b Colorspace Handler: FragmentColor may now be accessed through a 4-element array, in which elements 0-1-2-3 represent color components R-G-B-A, respectively. 2023-01-19 14:24:35 -08:00
rogerman 2b66e756da Add support for page-aligned variables/arrays.
- Better account for UltraSPARC's unique memory page size.
- malloc_alignedCacheLine() no longer returns 16-byte aligned memory if the architecture is neither 32-bit or 64-bit. Now, the function only returns 64-byte alignment for 64-bit architectures OR 32-byte alignment for 32-bit architectures.
2023-01-19 14:18:58 -08:00
zeromus 8438a5a647 crude hack to fix problem where loadstate could crash if the GPU hasn't ever booted up. see TODO TODO TODO TODO in gfx3d.cpp -- somebody needs to revise the tables so they arent memory mapped but so that they work rather like shininess tables. if they aren't truly latched when the gpu is flushed, then put them in a table anyway and simply reference the live values instead of the latched ones. How to keep from accidentally referencing the latched ones? perhaps the 3d state could be divided into a latched part and an unlatched part via base classes. Could also be done by embedding a "latched" and "unlatched" struct in the gpu but that would involve touching every line of code that used something from it. 2023-01-17 23:32:47 -06:00
zeromus 29c077c165 winport - fix issues with save/load state to japanese filename (fixes #615) 2022-12-05 15:54:38 -05:00
zeromus 91efef9346
Merge pull request #602 from KellanClark/master
Fix division edge cases and prevent crash
2022-10-23 21:07:41 -04:00
Kellan Clark b5b7f29255 Fix division edge cases and prevent crash 2022-10-23 20:22:21 -04:00
rogerman 739f3162d5 Cocoa Port: Fix HUD rendering on the OpenGL blitter for GPUs that don't support shaders. 2022-09-15 15:42:12 -07:00
rogerman 698139ed8e saves.cpp: Fix compiling issue for all non-Windows platforms. (Regression from commit 3a6c8cf9.) 2022-08-04 21:26:55 -07:00
zeromus 3a6c8cf9f8
Merge pull request #523 from Keppl/backup_saves_max_patch
Limit maximum number of backups files for load state backup
2022-08-04 17:33:43 -04:00
zeromus 3614b45a6c
Merge pull request #575 from janisozaur/update-default-joystick-size
Update default joystick cofiguration size in line with #567
2022-08-04 17:32:25 -04:00
Michał Janiszewski 83396a88c0 Update default joystick cofiguration size in line with #567 2022-08-04 20:52:15 +02:00
zeromus 35d7561fd7 make hud editor actually save position (fixes #572) 2022-07-30 16:47:43 -04:00
rogerman 5ab59eac86 FIFO.cpp: Code cleanup; remove AltiVec-specific code from display FIFO, as it is no longer needed.
- The new code works by pre-swapping big-endian words on disp_fifo.buf write, rather than swapping the big-endian words during disp_fifo.buf read.
- There is a behavior change here. Before, 8-bit and 16-bit writes to disp_fifo.buf would increment disp_fifo.tail. Now, 8-bit and 16-bit writes only increment disp_fifo.tail when the most significant bit within the FIFO value's 32-bit boundary is written to.
- Behavior is unchanged when doing 32-bit writes. In practice, the rare games that use display FIFO have only ever done 32-bit writes, so this scenario is well tested.
2022-07-21 15:31:40 -07:00
zeromus f8a7723e86
Merge pull request #569 from janisozaur/patch-3
Remove self-reference in variable declaration
2022-07-21 15:30:04 -04:00
Michał Janiszewski f07cd5bae2
Remove self-reference in variable declaration 2022-07-21 12:57:49 +02:00
rofl0r b7dadd1797 CI: also upload linux cli/gtk2 build artifact 2022-07-20 21:09:45 +01:00
rofl0r 2664b03d93 CI: add build job for linux/GTK2 2022-07-20 21:09:45 +01:00
rofl0r b27b31c57d posix: properly fix size mismatch of keyboard/joystick_cfg arrays
fixes #563

unlike #566, this also fixes the gtk2 frontend automatically.
2022-07-20 21:09:11 +01:00
zeromus 22fd8b231d
Merge pull request #566 from janisozaur/patch-1
Fix #563: mismatched buffer sizes for memcpy
2022-07-20 12:04:19 -04:00
zeromus 16e7c126e2
Merge pull request #564 from janisozaur/fix-use-of-internal-buffer
Fix use of internal storage of temporary buffer
2022-07-20 12:03:52 -04:00
Michał Janiszewski a84a48dc75 Fix #563: mismatched buffer sizes for memcpy 2022-07-20 14:53:55 +02:00
Michał Janiszewski d107562a16 Fix use of internal storage of temporary buffer
The entry index gets converted to a (temporary) string, from which a
pointer to internal data is taken and only consumed outside the loop,
where parent variable no longer exists.
2022-07-19 13:43:53 +02:00
rofl0r 677c6bb907 gtk3/gtk2: fix mismatched types for keyboard config temp storage
fallout from c68cc14, closes #558
2022-06-28 22:16:13 +00:00
rogerman 146a6ac655 Preemptively fix a compiling issue for AltiVec systems when using GCC without running keyword-and-predefine mode. 2022-06-27 12:10:56 -07:00
rogerman 640a1fdd93 Fix yet another compiling issue on GCC for AArch64. Fixes #556. 2022-06-25 15:01:21 -07:00
rogerman d4afd4977c libretro-common: Compiling tune-up for ARM architectures.
- Fixes a mismatched register warning in arm_enable_runfast_mode() when compiling for AArch64.
- Fix compiling check_arm_cpu_feature() on non-ARM architectures by being super explicit and pedantic about checking for __ARM_ARCH; none of this compiler-assumes-a-macro-equals-zero-if-undefined stuff.
2022-06-20 11:22:26 -07:00
rogerman a95e4c57c6 Remove AltiVec compiling for ppcle and ppc64le architectures, since our AltiVec code only works on big-endian systems anyways. Fixes #550. 2022-06-19 20:36:50 -07:00
rogerman 24eb5ed95c Fix compiling on GCC for AArch64. Fixes #548. 2022-06-18 21:56:25 -07:00
zeromus a3499803ac
Merge pull request #532 from Aikku93/patch-3
Check `gameCode==####` for homebrew
2022-06-17 14:28:27 -04:00
zeromus 1ccbf52246
Merge pull request #546 from Aikku93/spu-enhanced-interpolation
Enhanced interpolation, and fixed-point sample positions
2022-06-16 15:16:25 -04:00
Aikku93 09f7ab13c7 fix overflow problems
Catmull-Rom can give outputs greater than 16bit, so we must use 15bit precision. Also, ensure to use floor() to force a round-down regardless of host rounding behaviour.
2022-06-13 16:44:24 +10:00
Aikku93 aa25e1dd54 tighter bounds on interpolation accuracy 2022-06-13 15:14:54 +10:00
Aikku93 589084ec74 Split 64bit counters into 2x32bit
This appears to generate slightly saner code
2022-06-13 14:28:44 +10:00
Aikku93 41edf7be5e fix broken adpcm 2022-06-12 20:10:26 +10:00
Aikku93 235d9efea7 attempt to fix for macos 2022-06-12 19:33:09 +10:00
Aikku93 b2c4d449ca fix PSG square wave
Was reading the wrong part of GBATek
2022-06-12 19:03:48 +10:00
Aikku93 6215418dc7 sampcnt/sampinc as .32fxp, add catmull-spline interpolation 2022-06-12 18:36:37 +10:00
zeromus 48f5a8289d attempt to fix some problems caused by users running desmume out of directories with non-english characters (could manifest as "could not get read/write access to the battery save file") 2022-06-04 20:35:53 -04:00
Lino5000 b2ad722473 CLI: Re-work KEYDOWN handling to allow both shift keys as control inputs
Right Shift is the default for Select key.
2022-05-31 11:37:54 +00:00
Lino5000 c68cc14f16 Fix Linux CLI keyboard input bug due to mismatched types 2022-05-31 11:37:48 +00:00
rogerman ba05516b7d Cocoa Port: When dealing with file paths, replace instances of [NSString cStringUsingEncoding:NSUTF8StringEncoding] with [NSString fileSystemRepresentation] and [NSFileManager stringWithFileSystemRepresentation:].
- This commit doesn't actually do anything, but it is the "proper" way for Apple OSes to deal with file paths that interact with lower-level C file functions.
2022-05-30 13:25:20 -07:00
zeromus 416b08d6f7
Merge pull request #537 from colton5007/patch-1
Fixed GBA SRAMPath in posix CLI
2022-05-29 02:45:25 -04:00
colton5007 bc85e0b165 Fixed GBA SRAMPath in posix CLI 2022-05-29 01:04:42 -05:00
rogerman b82c3d7bce GFX3D: The box test now partially works in fixed-point.
- Specifically, the vertex calculations are performed using fixed-point. However, clipping still occurs using floating-point.
2022-05-24 12:02:27 -07:00
rogerman 3632142547 JIT (ARM): Make the code a little more portable, and also silence a couple compiler warnings. 2022-05-23 16:08:06 -07:00
rogerman 356fe47df7 GFX3D: GEM_TransformVertex() now uses the SIMD-optimized generic matrix functions instead of using its own scalar-only version.
- This change results in a small, yet measurable, performance improvement.
- Note that this change has the side-effect of enabling saturation logic for the following functions: MatrixMultVec3x3(), MatrixTranslate(), MatrixScale(). This is a change in their behavior, since these functions did not perform saturation logic before. This will need additional testing.
2022-05-23 15:53:05 -07:00
rogerman d757d83b3d GFX3D: The position test and the vector test are now performed using fixed-point instead of floating-point. 2022-05-23 15:29:57 -07:00
rogerman 95b824b541 Cocoa Port: Update version number to support version bump from commit 60714f6d. 2022-05-23 15:19:55 -07:00
zeromus 60714f6d22 bump version to 0.9.14 for future interim builds. 2022-05-23 18:10:07 -04:00
zeromus d9479cd6d3 update make_scmrev.h.js for modern times by searching for 64bit git on 32bit msbuild/devenv 2022-05-23 18:03:42 -04:00
zeromus 75230bfe0a fix support link in help menu 2022-05-23 18:03:18 -04:00
Aikku93 aa2a5f2a34 check `gameCode==####` for homebrew 2022-05-23 18:35:25 +10:00
Keppl 631f2a265e Added check that index file was actually openned for writing.
If not, skip creating backup part of loading.
2022-04-12 19:07:06 -04:00
Keppl dec93fecfa Added configuration option to define number of max number of backups. Windows only at the moment. 2022-04-11 22:26:16 -04:00
Keppl 970663bf71 Fixed bug when writing index, set default max to 200 2022-04-11 17:59:17 -04:00
Keppl 53be5f6968 Changed loadstate_slot function to keep only 5 latest backups when saving curring state before loading.
Once more than 5 exist, oldest one will be overwritten.
2022-04-10 22:36:10 -04:00
248 changed files with 124684 additions and 103499 deletions

View File

@ -0,0 +1,19 @@
---
name: New Issue, Bug report, Question
about: New Issue, Bug report, Question
title: ''
labels: ''
assignees: ''
---
## State your operating system:
Windows/Mac/Linux. in case of linux, whether you use CLI, gtk2, or gtk3 version.
## DesMuME version
e.g. 0.9.13 or git master
## Isse
type here what's bothering you, in a detailed manner.

View File

@ -7,11 +7,11 @@ on:
jobs:
build:
name: Build DeSmuME (Linux)
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- name: checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: install dependencies
run: sudo apt update && sudo apt install meson libsdl2-dev libpcap-dev libgtk-3-dev
@ -24,13 +24,43 @@ jobs:
- name: ninja
run: ninja -C desmume/src/frontend/posix/build
build_macos:
name: Build DeSmuME (macOS)
runs-on: macOS-11
build_gtk2:
name: Build DeSmuME (Linux/GTK+2)
runs-on: ubuntu-24.04
steps:
- name: checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: install dependencies
run: sudo apt update && sudo apt install autoconf libglu1-mesa-dev libsdl2-dev libpcap-dev libgtk2.0-dev
- name: buildit
run: |
cd desmume/src/frontend/posix/
autoreconf -i
./configure --prefix=/usr --enable-gdb-stub --enable-wifi
make -j8
make DESTDIR=/tmp/DeSmuME install
- name: Pack artifact
run: |
cd /tmp
tar cJf DeSmuME.tar.xz DeSmuME/
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: desmume-linux-gtk2-cli-x86_64
path: /tmp/DeSmuME.tar.xz
build_macos:
name: Build DeSmuME (macOS)
runs-on: macos-14
steps:
- name: checkout
uses: actions/checkout@v4
- name: xcodebuild
run: |
@ -43,7 +73,7 @@ jobs:
7z a DeSmuME.app.zip DeSmuME.app
- name: Upload artifict
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: macos
path: desmume/src/frontend/cocoa/desmume.xcarchive/Products/Applications/DeSmuME.app.zip

View File

@ -6,11 +6,11 @@ on:
jobs:
build_linux:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
name: Build Linux
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install dependencies
run: sudo apt update && sudo apt install meson libsdl2-dev libpcap-dev
@ -23,21 +23,21 @@ jobs:
- name: Build - ninja
run: ninja -C desmume/src/frontend/interface/build
- name: Upload artificat
uses: actions/upload-artifact@v2
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: linux
path: desmume/src/frontend/interface/build/libdesmume.so
build_macos:
runs-on: macos-10.15
runs-on: macos-14
name: Build MacOS
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install MacOS build deps
run: brew install coreutils gcc sdl2 meson glib
run: brew install coreutils sdl2 meson
- name: Build - Meson
run: |
@ -53,14 +53,14 @@ jobs:
CC: clang
CXX: clang++
- name: Upload artificat
uses: actions/upload-artifact@v2
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: macos
path: desmume/src/frontend/interface/build/libdesmume.dylib
build_windows:
runs-on: windows-2019
runs-on: windows-2022
name: Build Windows
strategy:
fail-fast: false
@ -68,18 +68,20 @@ jobs:
arch: [ 'x64', 'x86' ]
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
uses: microsoft/setup-msbuild@v2
with:
msbuild-architecture: ${{ matrix.arch }}
- name: Build
run: |
cd desmume\src\frontend\interface\windows
MSBuild.exe DeSmuME_Interface.vcxproj /p:configuration="Release Fastbuild" /p:Platform=${{ matrix.arch }}
- name: Upload artificat
uses: actions/upload-artifact@v2
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: win-${{ matrix.arch }}
path: desmume/src/frontend/interface/windows/__bins/*.dll

View File

@ -6,16 +6,15 @@ on:
jobs:
build-sln:
runs-on: windows-2019
runs-on: windows-2022
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
with:
msbuild-architecture: x64
vs-version: 16.1
- name: Build solution
run: |
@ -24,7 +23,7 @@ jobs:
cmd /c desmume\src\frontend\windows\ci_postbuild.bat
- name: Upload artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: desmume-win-x64
path: desmume/src/frontend/windows/__bins/*.exe

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: recursive

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,8 @@
Tips:
* Set hotkeys for "Mic Prev Sample" and "Mic Next Sample" in the "Main" section of hotkey configuration (suggest [ and ])
* This will rotate through all the provided desmume_N.wav. You can add your own in the series, just pick the next number.
* Keep the microphone hotkey held down for as long as you want the noise to play! Just tapping it will make a very short sound indeed.
desmume_0.wav was formerly "PERFECT BLOW FOR DS EMULATORS.wav"
desmume_1.wav was formerly "noise_loud.wav"
desmume_4.wav came to us as "pcm0822m.wav"; these are alleged to work well for Giant Bowser fights in Bowser's Inside Story.

Binary file not shown.

View File

@ -374,7 +374,7 @@ namespace Database
size_t regions_num = ARRAY_SIZE(regions);
const char* found = strchr(regions_index,code);
if(found) return regions[found-regions_index];
if(found && found-regions_index < strlen(regions_index)) return regions[found-regions_index];
else return unknownAsString ? "???" : NULL;
}

View File

@ -1,7 +1,7 @@
/*
Copyright 2006 yopyop
Copyright 2007 shash
Copyright 2007-2022 DeSmuME team
Copyright 2007-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -44,7 +44,6 @@
#elif defined(ENABLE_ALTIVEC)
#define USEVECTORSIZE_128
#define VECTORSIZE 16
#include "./utils/colorspacehandler/colorspacehandler_AltiVec.h"
#endif
#if defined(USEVECTORSIZE_512) || defined(USEVECTORSIZE_256) || defined(USEVECTORSIZE_128)
@ -340,12 +339,96 @@ void DISP_FIFOinit()
memset(&disp_fifo, 0, sizeof(DISP_FIFO));
}
void DISP_FIFOsend_u32(u32 val)
template <typename T, size_t ADDROFFSET>
void DISP_FIFOsend(const T val)
{
//INFO("DISP_FIFO send value 0x%08X (head 0x%06X, tail 0x%06X)\n", val, disp_fifo.head, disp_fifo.tail);
disp_fifo.buf[disp_fifo.tail] = val;
disp_fifo.tail++;
const size_t numBytes = sizeof(T);
const size_t baseWriteAddress = disp_fifo.tail * sizeof(u32);
const size_t finalWriteAddress = baseWriteAddress + ADDROFFSET;
switch (numBytes)
{
case 1:
{
#ifndef MSB_FIRST
HostWriteByte((u8 *)disp_fifo.buf, (u32)finalWriteAddress, val);
#else
switch (ADDROFFSET)
{
case 0:
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 2, val);
break;
case 1:
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 3, val);
break;
case 2:
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 0, val);
break;
case 3:
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 1, val);
break;
default:
break;
}
#endif
#ifndef MSB_FIRST
if (ADDROFFSET == 3)
#else
if (ADDROFFSET == 1)
#endif
{
disp_fifo.tail++;
}
break;
}
case 2:
{
#ifndef MSB_FIRST
HostWriteWord((u8 *)disp_fifo.buf, (u32)finalWriteAddress, val);
#else
switch (ADDROFFSET)
{
case 0:
HostWriteWord((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 2, val);
break;
case 2:
HostWriteWord((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 0, val);
break;
default:
break;
}
#endif
#ifndef MSB_FIRST
if (ADDROFFSET == 2)
#else
if (ADDROFFSET == 0)
#endif
{
disp_fifo.tail++;
}
break;
}
case 4:
HostWriteTwoWords((u8 *)disp_fifo.buf, (u32)finalWriteAddress, val);
disp_fifo.tail++;
break;
default:
break;
}
if (disp_fifo.tail >= 0x6000)
{
disp_fifo.tail = 0;
@ -380,19 +463,7 @@ void DISP_FIFOrecv_Line16(u16 *__restrict dst)
#ifdef USEMANUALVECTORIZATION
if ( (disp_fifo.head + (GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)) / sizeof(u32) <= 0x6000) && (disp_fifo.head == (disp_fifo.head & ~(VECTORSIZE - 1))) )
{
#ifdef ENABLE_ALTIVEC
// Big-endian systems read the pixels in their correct bit order, but swap 16-bit chunks
// within 32-bit lanes, and so we can't use a standard buffer copy function here.
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16); i+=sizeof(v128u16))
{
v128u16 fifoColor = vec_ld(i, disp_fifo.buf + disp_fifo.head);
fifoColor = vec_perm( (v128u8)fifoColor, (v128u8)fifoColor, ((v128u8){2,3, 0,1, 6,7, 4,5, 10,11, 8,9, 14,15, 12,13}) );
vec_st(fifoColor, i, dst);
}
#else
buffer_copy_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)>(dst, disp_fifo.buf + disp_fifo.head);
#endif // ENABLE_ALTIVEC
_DISP_FIFOrecv_LineAdvance();
}
else
@ -401,82 +472,11 @@ void DISP_FIFOrecv_Line16(u16 *__restrict dst)
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16) / sizeof(u32); i++)
{
const u32 src = DISP_FIFOrecv_u32();
#ifdef MSB_FIRST
((u32 *)dst)[i] = (src >> 16) | (src << 16);
#else
((u32 *)dst)[i] = src;
#endif
}
}
}
#ifdef USEMANUALVECTORIZATION
template <NDSColorFormat OUTPUTFORMAT>
void _DISP_FIFOrecv_LineOpaque16_vec(u32 *__restrict dst)
{
#ifdef ENABLE_ALTIVEC
// Big-endian systems read the pixels in their correct bit order, but swap 16-bit chunks
// within 32-bit lanes, and so we can't use a standard buffer copy function here.
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16); i+=sizeof(v128u16))
{
v128u16 fifoColor = vec_ld(i, disp_fifo.buf + disp_fifo.head);
fifoColor = vec_perm( (v128u8)fifoColor, (v128u8)fifoColor, ((v128u8){2,3, 0,1, 6,7, 4,5, 10,11, 8,9, 14,15, 12,13}) );
fifoColor = vec_or(fifoColor, ((v128u16){0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000}));
vec_st(fifoColor, i, dst);
}
#else
buffer_copy_or_constant_s16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16), false>(dst, disp_fifo.buf + disp_fifo.head, 0x8000);
#endif // ENABLE_ALTIVEC
_DISP_FIFOrecv_LineAdvance();
}
template <NDSColorFormat OUTPUTFORMAT>
void _DISP_FIFOrecv_LineOpaque32_vec(u32 *__restrict dst)
{
#ifdef ENABLE_ALTIVEC
for (size_t i = 0, d = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16); i+=16, d+=32)
{
v128u16 fifoColor = vec_ld(0, disp_fifo.buf + disp_fifo.head);
disp_fifo.head += (sizeof(v128u16)/sizeof(u32));
if (disp_fifo.head >= 0x6000)
{
disp_fifo.head -= 0x6000;
}
v128u32 dstLo = ((v128u32){0,0,0,0});
v128u32 dstHi = ((v128u32){0,0,0,0});
fifoColor = vec_perm( (v128u8)fifoColor, (v128u8)fifoColor, ((v128u8){10,11, 8,9, 14,15, 12,13, 2,3, 0,1, 6,7, 4,5}) );
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555To6665Opaque_AltiVec<false, BESwapDst>(fifoColor, dstLo, dstHi);
}
else if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
{
ColorspaceConvert555To8888Opaque_AltiVec<false, BESwapDst>(fifoColor, dstLo, dstHi);
}
vec_st(dstLo, d + 0, dst);
vec_st(dstHi, d + 16, dst);
}
#else
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvertBuffer555To6665Opaque<false, false, BESwapDst>((u16 *)(disp_fifo.buf + disp_fifo.head), dst, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
else if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
{
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>((u16 *)(disp_fifo.buf + disp_fifo.head), dst, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
_DISP_FIFOrecv_LineAdvance();
#endif // ENABLE_ALTIVEC
}
#endif // USEMANUALVECTORIZATION
template <NDSColorFormat OUTPUTFORMAT>
void DISP_FIFOrecv_LineOpaque(u32 *__restrict dst)
{
@ -485,26 +485,28 @@ void DISP_FIFOrecv_LineOpaque(u32 *__restrict dst)
{
if (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev)
{
_DISP_FIFOrecv_LineOpaque16_vec<OUTPUTFORMAT>(dst);
buffer_copy_or_constant_s16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16), false>(dst, disp_fifo.buf + disp_fifo.head, 0x8000);
}
else
else if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
_DISP_FIFOrecv_LineOpaque32_vec<OUTPUTFORMAT>(dst);
ColorspaceConvertBuffer555xTo6665Opaque<false, false, BESwapDst>((u16 *)(disp_fifo.buf + disp_fifo.head), dst, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
else if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
{
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>((u16 *)(disp_fifo.buf + disp_fifo.head), dst, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
_DISP_FIFOrecv_LineAdvance();
}
else
#endif
#endif // USEMANUALVECTORIZATION
{
if (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev)
{
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16) / sizeof(u32); i++)
{
const u32 src = DISP_FIFOrecv_u32();
#ifdef MSB_FIRST
dst[i] = (src >> 16) | (src << 16) | 0x80008000;
#else
dst[i] = src | 0x80008000;
#endif
}
}
else
@ -534,6 +536,14 @@ void DISP_FIFOreset()
disp_fifo.tail = 0;
}
template void DISP_FIFOsend< u8, 0>(const u8 val);
template void DISP_FIFOsend< u8, 1>(const u8 val);
template void DISP_FIFOsend< u8, 2>(const u8 val);
template void DISP_FIFOsend< u8, 3>(const u8 val);
template void DISP_FIFOsend<u16, 0>(const u16 val);
template void DISP_FIFOsend<u16, 2>(const u16 val);
template void DISP_FIFOsend<u32, 0>(const u32 val);
template void DISP_FIFOrecv_LineOpaque<NDSColorFormat_BGR555_Rev>(u32 *__restrict dst);
template void DISP_FIFOrecv_LineOpaque<NDSColorFormat_BGR666_Rev>(u32 *__restrict dst);
template void DISP_FIFOrecv_LineOpaque<NDSColorFormat_BGR888_Rev>(u32 *__restrict dst);

View File

@ -1,7 +1,7 @@
/*
Copyright 2006 yopyop
Copyright 2007 shash
Copyright 2007-2021 DeSmuME team
Copyright 2007-2022 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -87,7 +87,7 @@ typedef struct
extern DISP_FIFO disp_fifo;
void DISP_FIFOinit();
void DISP_FIFOsend_u32(u32 val);
template<typename T, size_t ADDROFFSET> void DISP_FIFOsend(const T val);
u32 DISP_FIFOrecv_u32();
void DISP_FIFOrecv_Line16(u16 *__restrict dst);

View File

@ -2,7 +2,7 @@
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 Theo Berkau
Copyright (C) 2007 shash
Copyright (C) 2008-2021 DeSmuME team
Copyright (C) 2008-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -56,6 +56,9 @@
#elif defined(ENABLE_SSE2)
#define USEVECTORSIZE_128
#define VECTORSIZE 16
#elif defined(ENABLE_NEON_A64)
#define USEVECTORSIZE_128
#define VECTORSIZE 16
#endif
#if defined(USEVECTORSIZE_512) || defined(USEVECTORSIZE_256) || defined(USEVECTORSIZE_128)
@ -206,7 +209,7 @@ GPUEngineBase::GPUEngineBase()
_asyncClearLineCustom = 0;
_asyncClearInterrupt = 0;
_asyncClearBackdropColor16 = 0;
_asyncClearBackdropColor32.color = 0;
_asyncClearBackdropColor32.value = 0;
_asyncClearIsRunning = false;
_asyncClearUseInternalCustomBuffer = false;
@ -375,7 +378,7 @@ void GPUEngineBase::Reset()
renderState.selectedBGLayer = &this->_BGLayer[GPULayerID_BG0];
renderState.backdropColor16 = LE_TO_LOCAL_16(this->_paletteBG[0]) & 0x7FFF;
renderState.workingBackdropColor16 = renderState.backdropColor16;
renderState.workingBackdropColor32.color = LOCAL_TO_LE_32( (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR666_Rev) ? COLOR555TO666(LOCAL_TO_LE_16(renderState.workingBackdropColor16)) : COLOR555TO888(LOCAL_TO_LE_16(renderState.workingBackdropColor16)) );
renderState.workingBackdropColor32.value = LOCAL_TO_LE_32( (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR666_Rev) ? COLOR555TO666(LOCAL_TO_LE_16(renderState.workingBackdropColor16)) : COLOR555TO888(LOCAL_TO_LE_16(renderState.workingBackdropColor16)) );
renderState.colorEffect = (ColorEffect)this->_IORegisterMap->BLDCNT.ColorEffect;
renderState.blendEVA = 0;
renderState.blendEVB = 0;
@ -693,7 +696,7 @@ void GPUEngineBase::RenderLineClearAsync()
case NDSColorFormat_BGR666_Rev:
case NDSColorFormat_BGR888_Rev:
memset_u32(targetBufferHead + (lineInfo.blockOffsetCustom * sizeof(FragmentColor)), this->_asyncClearBackdropColor32.color, lineInfo.pixelCount);
memset_u32(targetBufferHead + (lineInfo.blockOffsetCustom * sizeof(Color4u8)), this->_asyncClearBackdropColor32.value, lineInfo.pixelCount);
break;
}
@ -716,9 +719,9 @@ void GPUEngineBase::RenderLineClearAsync()
}
void GPUEngineBase::RenderLineClearAsyncStart(bool willClearInternalCustomBuffer,
s32 startLineIndex,
size_t startLineIndex,
u16 clearColor16,
FragmentColor clearColor32)
Color4u8 clearColor32)
{
if (this->_asyncClearTask == NULL)
{
@ -727,7 +730,7 @@ void GPUEngineBase::RenderLineClearAsyncStart(bool willClearInternalCustomBuffer
this->RenderLineClearAsyncFinish();
this->_asyncClearLineCustom = startLineIndex;
this->_asyncClearLineCustom = (s32)startLineIndex;
this->_asyncClearBackdropColor16 = clearColor16;
this->_asyncClearBackdropColor32 = clearColor32;
this->_asyncClearUseInternalCustomBuffer = willClearInternalCustomBuffer;
@ -750,9 +753,10 @@ void GPUEngineBase::RenderLineClearAsyncFinish()
this->_asyncClearInterrupt = 0;
}
void GPUEngineBase::RenderLineClearAsyncWaitForCustomLine(const s32 l)
void GPUEngineBase::RenderLineClearAsyncWaitForCustomLine(const size_t l)
{
while (l >= atomic_and_barrier32(&this->_asyncClearLineCustom, 0x000000FF))
const s32 lineCompare = (s32)l;
while (lineCompare >= atomic_and_barrier32(&this->_asyncClearLineCustom, 0x000000FF))
{
// Do nothing -- just spin.
}
@ -847,7 +851,7 @@ void GPUEngineBase::UpdateRenderStates(const size_t l)
{
currRenderState.workingBackdropColor16 = currRenderState.backdropColor16;
}
currRenderState.workingBackdropColor32.color = LOCAL_TO_LE_32( (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR666_Rev) ? COLOR555TO666(LOCAL_TO_LE_16(currRenderState.workingBackdropColor16)) : COLOR555TO888(LOCAL_TO_LE_16(currRenderState.workingBackdropColor16)) );
currRenderState.workingBackdropColor32.value = LOCAL_TO_LE_32( (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR666_Rev) ? COLOR555TO666(currRenderState.workingBackdropColor16) : COLOR555TO888(currRenderState.workingBackdropColor16) );
// Save the current render states to this line's compositor info.
compInfo.renderState = currRenderState;
@ -923,6 +927,11 @@ const GPU_IOREG& GPUEngineBase::GetIORegisterMap() const
return *this->_IORegisterMap;
}
bool GPUEngineBase::IsForceBlankSet() const
{
return (this->_IORegisterMap->DISPCNT.ForceBlank != 0);
}
bool GPUEngineBase::IsMasterBrightMaxOrMin() const
{
return this->_currentRenderState.masterBrightnessIsMaxOrMin;
@ -1003,7 +1012,7 @@ void GPUEngineBase::_TransitionLineNativeToCustom(GPUEngineCompositorInfo &compI
case NDSColorFormat_BGR666_Rev:
case NDSColorFormat_BGR888_Rev:
memset_u32(compInfo.target.lineColorHeadCustom, compInfo.renderState.workingBackdropColor32.color, compInfo.line.pixelCount);
memset_u32(compInfo.target.lineColorHeadCustom, compInfo.renderState.workingBackdropColor32.value, compInfo.line.pixelCount);
break;
}
}
@ -1026,12 +1035,12 @@ void GPUEngineBase::_TransitionLineNativeToCustom(GPUEngineCompositorInfo &compI
{
if ( (compInfo.line.widthCustom == GPU_FRAMEBUFFER_NATIVE_WIDTH) && (compInfo.line.renderCount == 1) )
{
ColorspaceConvertBuffer555To6665Opaque<false, false, BESwapDst>((u16 *)compInfo.target.lineColorHeadNative, (u32 *)compInfo.target.lineColorHeadCustom, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo6665Opaque<false, false, BESwapDst>((u16 *)compInfo.target.lineColorHeadNative, (u32 *)compInfo.target.lineColorHeadCustom, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
else
{
u32 *workingNativeBuffer32 = this->_targetDisplay->GetWorkingNativeBuffer32();
ColorspaceConvertBuffer555To6665Opaque<false, false, BESwapDst>((u16 *)compInfo.target.lineColorHeadNative, workingNativeBuffer32 + compInfo.line.blockOffsetNative, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo6665Opaque<false, false, BESwapDst>((u16 *)compInfo.target.lineColorHeadNative, workingNativeBuffer32 + compInfo.line.blockOffsetNative, GPU_FRAMEBUFFER_NATIVE_WIDTH);
CopyLineExpandHinted<0x3FFF, true, false, false, 4>(compInfo.line, workingNativeBuffer32 + compInfo.line.blockOffsetNative, compInfo.target.lineColorHeadCustom);
}
break;
@ -1041,12 +1050,12 @@ void GPUEngineBase::_TransitionLineNativeToCustom(GPUEngineCompositorInfo &compI
{
if ( (compInfo.line.widthCustom == GPU_FRAMEBUFFER_NATIVE_WIDTH) && (compInfo.line.renderCount == 1) )
{
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>((u16 *)compInfo.target.lineColorHeadNative, (u32 *)compInfo.target.lineColorHeadCustom, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>((u16 *)compInfo.target.lineColorHeadNative, (u32 *)compInfo.target.lineColorHeadCustom, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
else
{
u32 *workingNativeBuffer32 = this->_targetDisplay->GetWorkingNativeBuffer32();
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>((u16 *)compInfo.target.lineColorHeadNative, workingNativeBuffer32 + compInfo.line.blockOffsetNative, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>((u16 *)compInfo.target.lineColorHeadNative, workingNativeBuffer32 + compInfo.line.blockOffsetNative, GPU_FRAMEBUFFER_NATIVE_WIDTH);
CopyLineExpandHinted<0x3FFF, true, false, false, 4>(compInfo.line, workingNativeBuffer32 + compInfo.line.blockOffsetNative, compInfo.target.lineColorHeadCustom);
}
break;
@ -1251,7 +1260,7 @@ FORCEINLINE void GPUEngineBase::_CompositePixelImmediate(GPUEngineCompositorInfo
compInfo.target.xCustom = _gpuDstPitchIndex[srcX];
compInfo.target.lineLayerID = compInfo.target.lineLayerIDHeadNative + srcX;
compInfo.target.lineColor16 = (u16 *)compInfo.target.lineColorHeadNative + srcX;
compInfo.target.lineColor32 = (FragmentColor *)compInfo.target.lineColorHeadNative + srcX;
compInfo.target.lineColor32 = (Color4u8 *)compInfo.target.lineColorHeadNative + srcX;
const bool enableColorEffect = (WILLPERFORMWINDOWTEST) ? (this->_enableColorEffectNative[compInfo.renderState.selectedLayerID][compInfo.target.xNative] != 0) : true;
pixelop.Composite16<COMPOSITORMODE, NDSColorFormat_BGR555_Rev, GPULayerType_BG>(compInfo, srcColor16, enableColorEffect, 0, 0);
@ -1277,12 +1286,12 @@ void GPUEngineBase::_PrecompositeNativeToCustomLineBG(GPUEngineCompositorInfo &c
}
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST>
void GPUEngineBase::_CompositeNativeLineOBJ(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const FragmentColor *__restrict srcColorNative32)
void GPUEngineBase::_CompositeNativeLineOBJ(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const Color4u8 *__restrict srcColorNative32)
{
compInfo.target.xNative = 0;
compInfo.target.xCustom = 0;
compInfo.target.lineColor16 = (u16 *)compInfo.target.lineColorHead;
compInfo.target.lineColor32 = (FragmentColor *)compInfo.target.lineColorHead;
compInfo.target.lineColor32 = (Color4u8 *)compInfo.target.lineColorHead;
compInfo.target.lineLayerID = compInfo.target.lineLayerIDHead;
#ifdef USEMANUALVECTORIZATION
@ -1326,7 +1335,7 @@ void GPUEngineBase::_CompositeLineDeferred(GPUEngineCompositorInfo &compInfo, co
compInfo.target.xNative = 0;
compInfo.target.xCustom = 0;
compInfo.target.lineColor16 = (u16 *)compInfo.target.lineColorHead;
compInfo.target.lineColor32 = (FragmentColor *)compInfo.target.lineColorHead;
compInfo.target.lineColor32 = (Color4u8 *)compInfo.target.lineColorHead;
compInfo.target.lineLayerID = compInfo.target.lineLayerIDHead;
size_t i = 0;
@ -1366,7 +1375,7 @@ void GPUEngineBase::_CompositeVRAMLineDeferred(GPUEngineCompositorInfo &compInfo
compInfo.target.xNative = 0;
compInfo.target.xCustom = 0;
compInfo.target.lineColor16 = (u16 *)compInfo.target.lineColorHead;
compInfo.target.lineColor32 = (FragmentColor *)compInfo.target.lineColorHead;
compInfo.target.lineColor32 = (Color4u8 *)compInfo.target.lineColorHead;
compInfo.target.lineLayerID = compInfo.target.lineLayerIDHead;
size_t i = 0;
@ -1395,7 +1404,7 @@ void GPUEngineBase::_CompositeVRAMLineDeferred(GPUEngineCompositorInfo &compInfo
}
const bool enableColorEffect = (WILLPERFORMWINDOWTEST) ? (colorEffectEnable[compInfo.target.xCustom] != 0) : true;
pixelop.Composite32<COMPOSITORMODE, OUTPUTFORMAT, LAYERTYPE>(compInfo, ((FragmentColor *)vramColorPtr)[i], enableColorEffect, this->_sprAlphaCustom[compInfo.target.xCustom], this->_sprTypeCustom[compInfo.target.xCustom]);
pixelop.Composite32<COMPOSITORMODE, OUTPUTFORMAT, LAYERTYPE>(compInfo, ((Color4u8 *)vramColorPtr)[i], enableColorEffect, this->_sprAlphaCustom[compInfo.target.xCustom], this->_sprTypeCustom[compInfo.target.xCustom]);
}
else
{
@ -1829,7 +1838,7 @@ void GPUEngineBase::_RenderSprite16(GPUEngineCompositorInfo &compInfo,
{
for (size_t i = 0; i < length; i++, frameX++, spriteX+=readXStep)
{
const u32 spriteX_word = spriteX >> 1;
const u32 spriteX_word = (u32)spriteX >> 1;
const u32 palIndexAddress = objAddress + (spriteX_word & 0x0003) + ((spriteX_word & 0xFFFC) << 3);
const u8 *__restrict palIndexBuffer = (u8 *)MMU_gpu_map(palIndexAddress);
const u8 palIndex = *palIndexBuffer;
@ -1968,7 +1977,7 @@ void GPUEngineBase::SpriteRenderDebug(const u16 lineIndex, u16 *dst)
compInfo.target.xCustom = 0;
compInfo.target.lineColor = (void **)&compInfo.target.lineColor16;
compInfo.target.lineColor16 = (u16 *)compInfo.target.lineColorHeadNative;
compInfo.target.lineColor32 = (FragmentColor *)compInfo.target.lineColorHeadNative;
compInfo.target.lineColor32 = (Color4u8 *)compInfo.target.lineColorHeadNative;
compInfo.target.lineLayerID = NULL;
this->_SpriteRender<true>(compInfo, dst, NULL, NULL, &this->_sprPrio[lineIndex][0]);
@ -2100,7 +2109,7 @@ void GPUEngineBase::_SpriteRenderPerform(GPUEngineCompositorInfo &compInfo, u16
if (auxX >= 0 && auxY >= 0 && auxX < sprSize.width && auxY < sprSize.height)
{
size_t objOffset = 0;
u32 objOffset = 0;
if (DISPCNT.OBJ_BMP_2D_dim)
{
@ -2262,7 +2271,7 @@ void GPUEngineBase::_RenderLine_Layers(GPUEngineCompositorInfo &compInfo)
compInfo.target.xNative = 0;
compInfo.target.xCustom = 0;
compInfo.target.lineColor16 = (u16 *)compInfo.target.lineColorHeadNative;
compInfo.target.lineColor32 = (FragmentColor *)compInfo.target.lineColorHeadNative;
compInfo.target.lineColor32 = (Color4u8 *)compInfo.target.lineColorHeadNative;
compInfo.target.lineLayerID = compInfo.target.lineLayerIDHead;
compInfo.renderState.previouslyRenderedLayerID = GPULayerID_Backdrop;
@ -2503,7 +2512,7 @@ void GPUEngineBase::_RenderLine_LayerOBJ(GPUEngineCompositorInfo &compInfo, item
compInfo.target.xNative = srcX;
compInfo.target.xCustom = _gpuDstPitchIndex[srcX];
compInfo.target.lineColor16 = (u16 *)compInfo.target.lineColorHead + srcX;
compInfo.target.lineColor32 = (FragmentColor *)compInfo.target.lineColorHead + srcX;
compInfo.target.lineColor32 = (Color4u8 *)compInfo.target.lineColorHead + srcX;
compInfo.target.lineLayerID = compInfo.target.lineLayerIDHead + srcX;
const bool enableColorEffect = (WILLPERFORMWINDOWTEST) ? (this->_enableColorEffectNative[GPULayerID_OBJ][compInfo.target.xNative] != 0) : true;
@ -2522,7 +2531,7 @@ void GPUEngineBase::_RenderLine_LayerOBJ(GPUEngineCompositorInfo &compInfo, item
for (size_t line = 0; line < compInfo.line.renderCount; line++)
{
compInfo.target.lineColor16 = (u16 *)dstColorPtr;
compInfo.target.lineColor32 = (FragmentColor *)dstColorPtr;
compInfo.target.lineColor32 = (Color4u8 *)dstColorPtr;
compInfo.target.lineLayerID = dstLayerIDPtr;
for (size_t i = 0; i < item->nbPixelsX; i++)
@ -2542,14 +2551,14 @@ void GPUEngineBase::_RenderLine_LayerOBJ(GPUEngineCompositorInfo &compInfo, item
const size_t dstX = compInfo.target.xCustom + p;
compInfo.target.lineColor16 = (u16 *)dstColorPtr + dstX;
compInfo.target.lineColor32 = (FragmentColor *)dstColorPtr + dstX;
compInfo.target.lineColor32 = (Color4u8 *)dstColorPtr + dstX;
compInfo.target.lineLayerID = dstLayerIDPtr + dstX;
const bool enableColorEffect = (WILLPERFORMWINDOWTEST) ? (this->_enableColorEffectNative[GPULayerID_OBJ][compInfo.target.xNative] != 0) : true;
if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
{
pixelop.Composite32<COMPOSITORMODE, OUTPUTFORMAT, GPULayerType_OBJ>(compInfo, ((FragmentColor *)vramColorPtr)[dstX], enableColorEffect, this->_sprAlpha[compInfo.line.indexNative][srcX], this->_sprType[compInfo.line.indexNative][srcX]);
pixelop.Composite32<COMPOSITORMODE, OUTPUTFORMAT, GPULayerType_OBJ>(compInfo, ((Color4u8 *)vramColorPtr)[dstX], enableColorEffect, this->_sprAlpha[compInfo.line.indexNative][srcX], this->_sprType[compInfo.line.indexNative][srcX]);
}
else
{
@ -2558,8 +2567,8 @@ void GPUEngineBase::_RenderLine_LayerOBJ(GPUEngineCompositorInfo &compInfo, item
}
}
vramColorPtr = (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((FragmentColor *)vramColorPtr + compInfo.line.widthCustom) : (void *)((u16 *)vramColorPtr + compInfo.line.widthCustom);
dstColorPtr = (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev) ? (void *)((u16 *)dstColorPtr + compInfo.line.widthCustom) : (void *)((FragmentColor *)dstColorPtr + compInfo.line.widthCustom);
vramColorPtr = (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((Color4u8 *)vramColorPtr + compInfo.line.widthCustom) : (void *)((u16 *)vramColorPtr + compInfo.line.widthCustom);
dstColorPtr = (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev) ? (void *)((u16 *)dstColorPtr + compInfo.line.widthCustom) : (void *)((Color4u8 *)dstColorPtr + compInfo.line.widthCustom);
dstLayerIDPtr += compInfo.line.widthCustom;
}
}
@ -2568,7 +2577,7 @@ void GPUEngineBase::_RenderLine_LayerOBJ(GPUEngineCompositorInfo &compInfo, item
for (size_t line = 0; line < compInfo.line.renderCount; line++)
{
compInfo.target.lineColor16 = (u16 *)dstColorPtr;
compInfo.target.lineColor32 = (FragmentColor *)dstColorPtr;
compInfo.target.lineColor32 = (Color4u8 *)dstColorPtr;
compInfo.target.lineLayerID = dstLayerIDPtr;
for (size_t i = 0; i < item->nbPixelsX; i++)
@ -2588,7 +2597,7 @@ void GPUEngineBase::_RenderLine_LayerOBJ(GPUEngineCompositorInfo &compInfo, item
const size_t dstX = compInfo.target.xCustom + p;
compInfo.target.lineColor16 = (u16 *)dstColorPtr + dstX;
compInfo.target.lineColor32 = (FragmentColor *)dstColorPtr + dstX;
compInfo.target.lineColor32 = (Color4u8 *)dstColorPtr + dstX;
compInfo.target.lineLayerID = dstLayerIDPtr + dstX;
const bool enableColorEffect = (WILLPERFORMWINDOWTEST) ? (this->_enableColorEffectNative[GPULayerID_OBJ][compInfo.target.xNative] != 0) : true;
@ -2596,7 +2605,7 @@ void GPUEngineBase::_RenderLine_LayerOBJ(GPUEngineCompositorInfo &compInfo, item
}
}
dstColorPtr = (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev) ? (void *)((u16 *)dstColorPtr + compInfo.line.widthCustom) : (void *)((FragmentColor *)dstColorPtr + compInfo.line.widthCustom);
dstColorPtr = (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev) ? (void *)((u16 *)dstColorPtr + compInfo.line.widthCustom) : (void *)((Color4u8 *)dstColorPtr + compInfo.line.widthCustom);
dstLayerIDPtr += compInfo.line.widthCustom;
}
}
@ -2920,7 +2929,7 @@ void GPUEngineBase::RenderLayerBG(const GPULayerID layerID, u16 *dstColorBuffer)
compInfo.target.xCustom = compInfo.target.xNative;
compInfo.target.lineColor = (void **)&compInfo.target.lineColor16;
compInfo.target.lineColor16 = (u16 *)compInfo.target.lineColorHeadNative;
compInfo.target.lineColor32 = (FragmentColor *)compInfo.target.lineColorHeadNative;
compInfo.target.lineColor32 = (Color4u8 *)compInfo.target.lineColorHeadNative;
compInfo.target.lineLayerID = NULL;
for (size_t lineIndex = 0; lineIndex < layerHeight; lineIndex++)
@ -2939,11 +2948,18 @@ void GPUEngineBase::RenderLayerBG(const GPULayerID layerID, u16 *dstColorBuffer)
}
}
void GPUEngineBase::_RenderLineBlank(const size_t l)
{
// Native rendering only.
// Just clear the line using white pixels.
memset_u16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH>(this->_targetDisplay->GetNativeBuffer16() + (l * GPU_FRAMEBUFFER_NATIVE_WIDTH), 0xFFFF);
}
void GPUEngineBase::_HandleDisplayModeOff(const size_t l)
{
// Native rendering only.
// In this display mode, the display is cleared to white.
memset_u16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH>(this->_targetDisplay->GetNativeBuffer16() + (l * GPU_FRAMEBUFFER_NATIVE_WIDTH), 0xFFFF);
// In this display mode, the line is cleared to white.
this->_RenderLineBlank(l);
}
void GPUEngineBase::_HandleDisplayModeNormal(const size_t l)
@ -3251,13 +3267,13 @@ GPUEngineA::GPUEngineA()
_isLineCaptureNative[3][l] = true;
}
_3DFramebufferMain = (FragmentColor *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(FragmentColor));
_3DFramebufferMain = (Color4u8 *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(Color4u8));
_3DFramebuffer16 = (u16 *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(u16));
_captureWorkingDisplay16 = (u16 *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16));
_captureWorkingA16 = (u16 *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16));
_captureWorkingB16 = (u16 *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16));
_captureWorkingA32 = (FragmentColor *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(FragmentColor));
_captureWorkingB32 = (FragmentColor *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(FragmentColor));
_captureWorkingA32 = (Color4u8 *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(Color4u8));
_captureWorkingB32 = (Color4u8 *)malloc_alignedPage(GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(Color4u8));
}
GPUEngineA::~GPUEngineA()
@ -3290,13 +3306,13 @@ void GPUEngineA::Reset()
const size_t customWidth = this->_targetDisplay->GetWidth();
const size_t customHeight = this->_targetDisplay->GetHeight();
memset(this->_3DFramebufferMain, 0, customWidth * customHeight * sizeof(FragmentColor));
memset(this->_3DFramebufferMain, 0, customWidth * customHeight * sizeof(Color4u8));
memset(this->_3DFramebuffer16, 0, customWidth * customHeight * sizeof(u16));
memset(this->_captureWorkingDisplay16, 0, customWidth * _gpuLargestDstLineCount * sizeof(u16));
memset(this->_captureWorkingA16, 0, customWidth * _gpuLargestDstLineCount * sizeof(u16));
memset(this->_captureWorkingB16, 0, customWidth * _gpuLargestDstLineCount * sizeof(u16));
memset(this->_captureWorkingA32, 0, customWidth * _gpuLargestDstLineCount * sizeof(FragmentColor));
memset(this->_captureWorkingB32, 0, customWidth * _gpuLargestDstLineCount * sizeof(FragmentColor));
memset(this->_captureWorkingA32, 0, customWidth * _gpuLargestDstLineCount * sizeof(Color4u8));
memset(this->_captureWorkingB32, 0, customWidth * _gpuLargestDstLineCount * sizeof(Color4u8));
memset(&this->_dispCapCnt, 0, sizeof(DISPCAPCNT_parsed));
this->_displayCaptureEnable = false;
@ -3382,7 +3398,7 @@ void GPUEngineA::ParseReg_DISPCAPCNT()
this->_dispCapCnt.srcA, this->_dispCapCnt.srcB);*/
}
FragmentColor* GPUEngineA::Get3DFramebufferMain() const
Color4u8* GPUEngineA::Get3DFramebufferMain() const
{
return this->_3DFramebufferMain;
}
@ -3406,30 +3422,30 @@ void GPUEngineA::AllocateWorkingBuffers(NDSColorFormat requestedColorFormat, siz
{
this->GPUEngineBase::AllocateWorkingBuffers(requestedColorFormat, w, h);
FragmentColor *old3DFramebufferMain = this->_3DFramebufferMain;
Color4u8 *old3DFramebufferMain = this->_3DFramebufferMain;
u16 *old3DFramebuffer16 = this->_3DFramebuffer16;
u16 *oldCaptureWorkingDisplay16 = this->_captureWorkingDisplay16;
u16 *oldCaptureWorkingA16 = this->_captureWorkingA16;
u16 *oldCaptureWorkingB16 = this->_captureWorkingB16;
FragmentColor *oldCaptureWorkingA32 = this->_captureWorkingA32;
FragmentColor *oldCaptureWorkingB32 = this->_captureWorkingB32;
Color4u8 *oldCaptureWorkingA32 = this->_captureWorkingA32;
Color4u8 *oldCaptureWorkingB32 = this->_captureWorkingB32;
this->_3DFramebufferMain = (FragmentColor *)malloc_alignedPage(w * h * sizeof(FragmentColor));
this->_3DFramebufferMain = (Color4u8 *)malloc_alignedPage(w * h * sizeof(Color4u8));
this->_3DFramebuffer16 = (u16 *)malloc_alignedPage(w * h * sizeof(u16));
this->_captureWorkingDisplay16 = (u16 *)malloc_alignedPage(w * _gpuLargestDstLineCount * sizeof(u16));
this->_captureWorkingA16 = (u16 *)malloc_alignedPage(w * _gpuLargestDstLineCount * sizeof(u16));
this->_captureWorkingB16 = (u16 *)malloc_alignedPage(w * _gpuLargestDstLineCount * sizeof(u16));
this->_captureWorkingA32 = (FragmentColor *)malloc_alignedPage(w * _gpuLargestDstLineCount * sizeof(FragmentColor));
this->_captureWorkingB32 = (FragmentColor *)malloc_alignedPage(w * _gpuLargestDstLineCount * sizeof(FragmentColor));
this->_captureWorkingA32 = (Color4u8 *)malloc_alignedPage(w * _gpuLargestDstLineCount * sizeof(Color4u8));
this->_captureWorkingB32 = (Color4u8 *)malloc_alignedPage(w * _gpuLargestDstLineCount * sizeof(Color4u8));
const GPUEngineLineInfo &lineInfo = this->_currentCompositorInfo[GPU_VRAM_BLOCK_LINES].line;
if (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR888_Rev)
{
this->_VRAMCustomBlockPtr[0] = (FragmentColor *)GPU->GetCustomVRAMBuffer();
this->_VRAMCustomBlockPtr[1] = (FragmentColor *)this->_VRAMCustomBlockPtr[0] + (1 * lineInfo.indexCustom * w);
this->_VRAMCustomBlockPtr[2] = (FragmentColor *)this->_VRAMCustomBlockPtr[0] + (2 * lineInfo.indexCustom * w);
this->_VRAMCustomBlockPtr[3] = (FragmentColor *)this->_VRAMCustomBlockPtr[0] + (3 * lineInfo.indexCustom * w);
this->_VRAMCustomBlockPtr[0] = (Color4u8 *)GPU->GetCustomVRAMBuffer();
this->_VRAMCustomBlockPtr[1] = (Color4u8 *)this->_VRAMCustomBlockPtr[0] + (1 * lineInfo.indexCustom * w);
this->_VRAMCustomBlockPtr[2] = (Color4u8 *)this->_VRAMCustomBlockPtr[0] + (2 * lineInfo.indexCustom * w);
this->_VRAMCustomBlockPtr[3] = (Color4u8 *)this->_VRAMCustomBlockPtr[0] + (3 * lineInfo.indexCustom * w);
}
else
{
@ -3535,23 +3551,30 @@ void GPUEngineA::RenderLine(const size_t l)
}
// Fill the display output
switch (compInfo.renderState.displayOutputMode)
if ( this->IsForceBlankSet() )
{
case GPUDisplayMode_Off: // Display Off (Display white)
this->_HandleDisplayModeOff(l);
break;
case GPUDisplayMode_Normal: // Display BG and OBJ layers
this->_HandleDisplayModeNormal(l);
break;
case GPUDisplayMode_VRAM: // Display VRAM framebuffer
this->_HandleDisplayModeVRAM<OUTPUTFORMAT>(compInfo.line);
break;
case GPUDisplayMode_MainMemory: // Display Memory FIFO
this->_HandleDisplayModeMainMemory(compInfo.line);
break;
this->_RenderLineBlank(l);
}
else
{
switch (compInfo.renderState.displayOutputMode)
{
case GPUDisplayMode_Off: // Display Off (clear line to white)
this->_HandleDisplayModeOff(l);
break;
case GPUDisplayMode_Normal: // Display BG and OBJ layers
this->_HandleDisplayModeNormal(l);
break;
case GPUDisplayMode_VRAM: // Display VRAM framebuffer
this->_HandleDisplayModeVRAM<OUTPUTFORMAT>(compInfo.line);
break;
case GPUDisplayMode_MainMemory: // Display Memory FIFO
this->_HandleDisplayModeMainMemory(compInfo.line);
break;
}
}
//capture after displaying so that we can safely display vram before overwriting it here
@ -3575,7 +3598,7 @@ void GPUEngineA::RenderLine(const size_t l)
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST>
void GPUEngineA::RenderLine_Layer3D(GPUEngineCompositorInfo &compInfo)
{
const FragmentColor *__restrict framebuffer3D = CurrentRenderer->GetFramebuffer();
const Color4u8 *__restrict framebuffer3D = CurrentRenderer->GetFramebuffer();
if (framebuffer3D == NULL)
{
return;
@ -3590,12 +3613,12 @@ void GPUEngineA::RenderLine_Layer3D(GPUEngineCompositorInfo &compInfo)
const u8 *colorEffectEnable = (CurrentRenderer->GetFramebufferWidth() == GPU_FRAMEBUFFER_NATIVE_WIDTH) ? this->_enableColorEffectNative[GPULayerID_BG0] : this->_enableColorEffectCustom[GPULayerID_BG0];
const float customWidthScale = (float)compInfo.line.widthCustom / (float)GPU_FRAMEBUFFER_NATIVE_WIDTH;
const FragmentColor *__restrict srcLinePtr = framebuffer3D + compInfo.line.blockOffsetCustom;
const Color4u8 *__restrict srcLinePtr = framebuffer3D + compInfo.line.blockOffsetCustom;
compInfo.target.xNative = 0;
compInfo.target.xCustom = 0;
compInfo.target.lineColor16 = (u16 *)compInfo.target.lineColorHead;
compInfo.target.lineColor32 = (FragmentColor *)compInfo.target.lineColorHead;
compInfo.target.lineColor32 = (Color4u8 *)compInfo.target.lineColorHead;
compInfo.target.lineLayerID = compInfo.target.lineLayerIDHead;
// Horizontally offset the 3D layer by this amount.
@ -3709,7 +3732,7 @@ void GPUEngineA::_RenderLine_DisplayCaptureCustom(const IOREG_DISPCAPCNT &DISPCA
{
if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
{
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(this->_fifoLine16, (u32 *)srcBPtr, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>(this->_fifoLine16, (u32 *)srcBPtr, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
this->_RenderLine_DispCapture_Copy<OUTPUTFORMAT, 1, CAPTURELENGTH, true, false>(lineInfo, srcBPtr, dstCustomPtr, captureLengthExt);
@ -3735,7 +3758,7 @@ void GPUEngineA::_RenderLine_DisplayCaptureCustom(const IOREG_DISPCAPCNT &DISPCA
else
{
u32 *workingNativeBuffer32 = this->_targetDisplay->GetWorkingNativeBuffer32();
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapNone>((u16 *)srcAPtr, workingNativeBuffer32 + lineInfo.blockOffsetNative, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapNone>((u16 *)srcAPtr, workingNativeBuffer32 + lineInfo.blockOffsetNative, GPU_FRAMEBUFFER_NATIVE_WIDTH);
CopyLineExpandHinted<0x3FFF, true, false, false, 4>(lineInfo, workingNativeBuffer32 + lineInfo.blockOffsetNative, this->_captureWorkingA32);
srcAPtr = this->_captureWorkingA32;
}
@ -3752,7 +3775,7 @@ void GPUEngineA::_RenderLine_DisplayCaptureCustom(const IOREG_DISPCAPCNT &DISPCA
{
if ((OUTPUTFORMAT == NDSColorFormat_BGR888_Rev) && (DISPCAPCNT.SrcB != 0))
{
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(this->_fifoLine16, (u32 *)srcBPtr, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>(this->_fifoLine16, (u32 *)srcBPtr, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
CopyLineExpandHinted<0x3FFF, true, false, false, 4>(lineInfo, srcBPtr, this->_captureWorkingB32);
@ -3879,7 +3902,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(const GPUEngineCompositorInfo &compI
}
const u16 *vramCustom16 = (u16 *)GPU->GetCustomVRAMBlankBuffer();
const FragmentColor *vramCustom32 = (FragmentColor *)GPU->GetCustomVRAMBlankBuffer();
const Color4u8 *vramCustom32 = (Color4u8 *)GPU->GetCustomVRAMBlankBuffer();
if (!willReadNativeVRAM)
{
@ -3890,7 +3913,7 @@ void GPUEngineA::_RenderLine_DisplayCapture(const GPUEngineCompositorInfo &compI
}
vramCustom16 = (u16 *)this->_VRAMCustomBlockPtr[DISPCNT.VRAM_Block] + vramCustomOffset;
vramCustom32 = (FragmentColor *)this->_VRAMCustomBlockPtr[DISPCNT.VRAM_Block] + vramCustomOffset;
vramCustom32 = (Color4u8 *)this->_VRAMCustomBlockPtr[DISPCNT.VRAM_Block] + vramCustomOffset;
}
if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
@ -3899,13 +3922,13 @@ void GPUEngineA::_RenderLine_DisplayCapture(const GPUEngineCompositorInfo &compI
{
if (willReadNativeVRAM)
{
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(vramNative16, (u32 *)vramCustom32, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>(vramNative16, (u32 *)vramCustom32, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
}
srcAPtr = (DISPCAPCNT.SrcA == 0) ? (FragmentColor *)compInfo.target.lineColorHead : (FragmentColor *)CurrentRenderer->GetFramebuffer() + compInfo.line.blockOffsetCustom;
srcAPtr = (DISPCAPCNT.SrcA == 0) ? (Color4u8 *)compInfo.target.lineColorHead : (Color4u8 *)CurrentRenderer->GetFramebuffer() + compInfo.line.blockOffsetCustom;
srcBPtr = (DISPCAPCNT.SrcB == 0) ? vramCustom32 : this->_fifoLine32;
dstCustomPtr = (FragmentColor *)this->_VRAMCustomBlockPtr[DISPCAPCNT.VRAMWriteBlock] + dstCustomOffset;
dstCustomPtr = (Color4u8 *)this->_VRAMCustomBlockPtr[DISPCAPCNT.VRAMWriteBlock] + dstCustomOffset;
}
else
{
@ -4272,10 +4295,10 @@ u16 GPUEngineA::_RenderLine_DispCapture_BlendFunc(const u16 srcA, const u16 srcB
}
template<NDSColorFormat COLORFORMAT>
FragmentColor GPUEngineA::_RenderLine_DispCapture_BlendFunc(const FragmentColor srcA, const FragmentColor srcB, const u8 blendEVA, const u8 blendEVB)
Color4u8 GPUEngineA::_RenderLine_DispCapture_BlendFunc(const Color4u8 srcA, const Color4u8 srcB, const u8 blendEVA, const u8 blendEVB)
{
FragmentColor outColor;
outColor.color = 0;
Color4u8 outColor;
outColor.value = 0;
u16 r = 0;
u16 g = 0;
@ -4328,17 +4351,17 @@ void GPUEngineA::_RenderLine_DispCapture_Blend_Buffer(const void *srcA, const vo
#endif
if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
{
const FragmentColor *srcA_32 = (const FragmentColor *)srcA;
const FragmentColor *srcB_32 = (const FragmentColor *)srcB;
FragmentColor *dst32 = (FragmentColor *)dst;
const Color4u8 *srcA_32 = (const Color4u8 *)srcA;
const Color4u8 *srcB_32 = (const Color4u8 *)srcB;
Color4u8 *dst32 = (Color4u8 *)dst;
#ifdef USEMANUALVECTORIZATION
#pragma LOOPVECTORIZE_DISABLE
#endif
for (; i < length; i++)
{
const FragmentColor colorA = srcA_32[i];
const FragmentColor colorB = srcB_32[i];
const Color4u8 colorA = srcA_32[i];
const Color4u8 colorB = srcB_32[i];
dst32[i] = this->_RenderLine_DispCapture_BlendFunc<OUTPUTFORMAT>(colorA, colorB, blendEVA, blendEVB);
}
@ -4383,9 +4406,9 @@ void GPUEngineA::_RenderLine_DispCapture_Blend(const GPUEngineLineInfo &lineInfo
for (size_t line = 0; line < lineInfo.renderCount; line++)
{
this->_RenderLine_DispCapture_Blend_Buffer<OUTPUTFORMAT>(srcA, srcB, dst, blendEVA, blendEVB, captureLengthExt);
srcA = (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((FragmentColor *)srcA + lineInfo.widthCustom) : (void *)((u16 *)srcA + lineInfo.widthCustom);
srcB = (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((FragmentColor *)srcB + lineInfo.widthCustom) : (void *)((u16 *)srcB + lineInfo.widthCustom);
dst = (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((FragmentColor *)dst + lineInfo.widthCustom) : (void *)((u16 *)dst + lineInfo.widthCustom);
srcA = (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((Color4u8 *)srcA + lineInfo.widthCustom) : (void *)((u16 *)srcA + lineInfo.widthCustom);
srcB = (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((Color4u8 *)srcB + lineInfo.widthCustom) : (void *)((u16 *)srcB + lineInfo.widthCustom);
dst = (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((Color4u8 *)dst + lineInfo.widthCustom) : (void *)((u16 *)dst + lineInfo.widthCustom);
}
}
}
@ -4415,7 +4438,7 @@ void GPUEngineA::_HandleDisplayModeVRAM(const GPUEngineLineInfo &lineInfo)
{
const u16 *src = (u16 *)this->_VRAMCustomBlockPtr[DISPCNT.VRAM_Block] + lineInfo.blockOffsetCustom;
u32 *dst = (u32 *)customBuffer + lineInfo.blockOffsetCustom;
ColorspaceConvertBuffer555To6665Opaque<false, false, BESwapSrcDst>(src, dst, lineInfo.pixelCount);
ColorspaceConvertBuffer555xTo6665Opaque<false, false, BESwapSrcDst>(src, dst, lineInfo.pixelCount);
break;
}
@ -4532,29 +4555,36 @@ void GPUEngineB::RenderLine(const size_t l)
{
GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[l];
switch (compInfo.renderState.displayOutputMode)
if ( this->IsForceBlankSet() )
{
case GPUDisplayMode_Off: // Display Off(Display white)
this->_HandleDisplayModeOff(l);
break;
case GPUDisplayMode_Normal: // Display BG and OBJ layers
this->_RenderLineBlank(l);
}
else
{
switch (compInfo.renderState.displayOutputMode)
{
if (compInfo.renderState.isAnyWindowEnabled)
{
this->_RenderLine_Layers<OUTPUTFORMAT, true>(compInfo);
}
else
{
this->_RenderLine_Layers<OUTPUTFORMAT, false>(compInfo);
}
case GPUDisplayMode_Off: // Display Off (clear line to white)
this->_HandleDisplayModeOff(l);
break;
this->_HandleDisplayModeNormal(l);
break;
case GPUDisplayMode_Normal: // Display BG and OBJ layers
{
if (compInfo.renderState.isAnyWindowEnabled)
{
this->_RenderLine_Layers<OUTPUTFORMAT, true>(compInfo);
}
else
{
this->_RenderLine_Layers<OUTPUTFORMAT, false>(compInfo);
}
this->_HandleDisplayModeNormal(l);
break;
}
default:
break;
}
default:
break;
}
if (compInfo.line.indexNative >= 191)
@ -4728,14 +4758,21 @@ void GPUSubsystem::_UpdateFPSRender3D()
this->_videoFrameIndex++;
if (this->_videoFrameIndex == 60)
{
this->_render3DFrameCount = gfx3d.render3DFrameCount;
gfx3d.render3DFrameCount = 0;
this->_render3DFrameCount = GFX3D_GetRender3DFrameCount();
GFX3D_ResetRender3DFrameCount();
this->_videoFrameIndex = 0;
}
}
void GPUSubsystem::SetEventHandler(GPUEventHandler *eventHandler)
{
if ( (eventHandler == NULL) && (this->_event != this->_defaultEventHandler) )
{
this->ForceFrameStop();
this->_event = this->_defaultEventHandler;
return;
}
this->_event = eventHandler;
}
@ -4943,7 +4980,7 @@ void GPUSubsystem::SetFramebufferPageCount(size_t pageCount)
pageCount = MAX_FRAMEBUFFER_PAGES;
}
this->_displayInfo.framebufferPageCount = pageCount;
this->_displayInfo.framebufferPageCount = (u32)pageCount;
}
size_t GPUSubsystem::GetCustomFramebufferWidth() const
@ -4977,9 +5014,9 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h)
u8 *oldGpuDstToSrcSSSE3_u16_8e = _gpuDstToSrcSSSE3_u16_8e;
u8 *oldGpuDstToSrcSSSE3_u32_4e = _gpuDstToSrcSSSE3_u32_4e;
for (size_t srcX = 0, currentPitchCount = 0; srcX < GPU_FRAMEBUFFER_NATIVE_WIDTH; srcX++)
for (u32 srcX = 0, currentPitchCount = 0; srcX < GPU_FRAMEBUFFER_NATIVE_WIDTH; srcX++)
{
const size_t pitch = (size_t)ceilf((srcX+1) * customWidthScale) - currentPitchCount;
const u32 pitch = (u32)ceilf(((float)srcX+1.0f) * customWidthScale) - (float)currentPitchCount;
_gpuDstPitchCount[srcX] = pitch;
_gpuDstPitchIndex[srcX] = currentPitchCount;
currentPitchCount += pitch;
@ -5067,8 +5104,8 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h)
this->_display[NDSDisplayID_Touch]->SetDisplaySize(w, h);
this->_displayInfo.isCustomSizeRequested = ( (w != GPU_FRAMEBUFFER_NATIVE_WIDTH) || (h != GPU_FRAMEBUFFER_NATIVE_HEIGHT) );
this->_displayInfo.customWidth = w;
this->_displayInfo.customHeight = h;
this->_displayInfo.customWidth = (u32)w;
this->_displayInfo.customHeight = (u32)h;
if (!this->_display[NDSDisplayID_Main]->IsCustomSizeRequested())
{
@ -5110,7 +5147,7 @@ void GPUSubsystem::SetColorFormat(const NDSColorFormat outputFormat)
this->_display[NDSDisplayID_Touch]->SetColorFormat(outputFormat);
this->_displayInfo.colorFormat = this->_display[NDSDisplayID_Main]->GetColorFormat();
this->_displayInfo.pixelBytes = this->_display[NDSDisplayID_Main]->GetPixelBytes();
this->_displayInfo.pixelBytes = (u32)this->_display[NDSDisplayID_Main]->GetPixelBytes();
if (!this->_displayInfo.isCustomSizeRequested)
{
@ -5128,7 +5165,7 @@ void GPUSubsystem::_AllocateFramebuffers(NDSColorFormat outputFormat, size_t w,
void *oldMasterFramebuffer = this->_masterFramebuffer;
void *oldCustomVRAM = this->_customVRAM;
const size_t pixelBytes = (outputFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(FragmentColor);
const size_t pixelBytes = (outputFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(Color4u8);
const size_t newCustomVRAMBlockSize = this->_lineInfo[GPU_VRAM_BLOCK_LINES].indexCustom * w;
const size_t newCustomVRAMBlankSize = _gpuLargestDstLineCount * GPU_VRAM_BLANK_REGION_LINES * w;
const size_t nativeFramebufferSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(u16);
@ -5136,8 +5173,8 @@ void GPUSubsystem::_AllocateFramebuffers(NDSColorFormat outputFormat, size_t w,
void *newCustomVRAM = NULL;
this->_displayInfo.framebufferPageCount = pageCount;
this->_displayInfo.framebufferPageSize = (nativeFramebufferSize * 2) + (customFramebufferSize * 2);
this->_displayInfo.framebufferPageCount = (u32)pageCount;
this->_displayInfo.framebufferPageSize = (u32)( (nativeFramebufferSize * 2) + (customFramebufferSize * 2) );
this->_masterFramebuffer = malloc_alignedPage(this->_displayInfo.framebufferPageSize * this->_displayInfo.framebufferPageCount);
if (outputFormat != NDSColorFormat_BGR555_Rev)
@ -5207,10 +5244,10 @@ void GPUSubsystem::_AllocateFramebuffers(NDSColorFormat outputFormat, size_t w,
break;
case NDSColorFormat_BGR888_Rev:
newCustomVRAM = (void *)malloc_alignedPage(((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * sizeof(FragmentColor));
memset(newCustomVRAM, 0, ((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * sizeof(FragmentColor));
newCustomVRAM = (void *)malloc_alignedPage(((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * sizeof(Color4u8));
memset(newCustomVRAM, 0, ((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * sizeof(Color4u8));
this->_customVRAM = newCustomVRAM;
this->_customVRAMBlank = (FragmentColor *)newCustomVRAM + (newCustomVRAMBlockSize * 4);
this->_customVRAMBlank = (Color4u8 *)newCustomVRAM + (newCustomVRAMBlockSize * 4);
break;
default:
@ -5334,7 +5371,7 @@ void* GPUSubsystem::GetCustomVRAMAddressUsingMappedAddress(const u32 mappedAddr,
const size_t blockLine = (vramPixel >> 8) & 0x000000FF; // blockLine = (vramPixel % (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_VRAM_BLOCK_LINES)) / GPU_FRAMEBUFFER_NATIVE_WIDTH
const size_t linePixel = vramPixel & 0x000000FF; // linePixel = (vramPixel % (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_VRAM_BLOCK_LINES)) % GPU_FRAMEBUFFER_NATIVE_WIDTH
return (COLORFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((FragmentColor *)this->GetEngineMain()->GetCustomVRAMBlockPtr(blockID) + (this->_lineInfo[blockLine].indexCustom * this->_lineInfo[blockLine].widthCustom) + _gpuDstPitchIndex[linePixel] + offset) : (void *)((u16 *)this->GetEngineMain()->GetCustomVRAMBlockPtr(blockID) + (this->_lineInfo[blockLine].indexCustom * this->_lineInfo[blockLine].widthCustom) + _gpuDstPitchIndex[linePixel] + offset);
return (COLORFORMAT == NDSColorFormat_BGR888_Rev) ? (void *)((Color4u8 *)this->GetEngineMain()->GetCustomVRAMBlockPtr(blockID) + (this->_lineInfo[blockLine].indexCustom * this->_lineInfo[blockLine].widthCustom) + _gpuDstPitchIndex[linePixel] + offset) : (void *)((u16 *)this->GetEngineMain()->GetCustomVRAMBlockPtr(blockID) + (this->_lineInfo[blockLine].indexCustom * this->_lineInfo[blockLine].widthCustom) + _gpuDstPitchIndex[linePixel] + offset);
}
bool GPUSubsystem::GetWillPostprocessDisplays() const
@ -5453,7 +5490,7 @@ void GPUSubsystem::RenderLine(const size_t l)
this->_engineSub->UpdateRenderStates(l);
}
if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || isDisplayCaptureNeeded) && !this->_willFrameSkip )
if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || this->_engineMain->IsForceBlankSet() || isDisplayCaptureNeeded) && !this->_willFrameSkip )
{
// GPUEngineA:WillRender3DLayer() and GPUEngineA:WillCapture3DLayerDirect() both rely on register
// states that might change on a per-line basis. Therefore, we need to check these states on a
@ -5501,7 +5538,7 @@ void GPUSubsystem::RenderLine(const size_t l)
this->_engineMain->UpdatePropertiesWithoutRender(l);
}
if (isFramebufferRenderNeeded[GPUEngineID_Sub] && !this->_willFrameSkip)
if ( (isFramebufferRenderNeeded[GPUEngineID_Sub] || this->_engineSub->IsForceBlankSet()) && !this->_willFrameSkip)
{
switch (this->_engineSub->GetTargetDisplay()->GetColorFormat())
{
@ -5540,13 +5577,13 @@ void GPUSubsystem::RenderLine(const size_t l)
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->DidPerformCustomRender();
this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetRenderedBuffer();
this->_displayInfo.renderedWidth[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetRenderedWidth();
this->_displayInfo.renderedHeight[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetRenderedHeight();
this->_displayInfo.renderedWidth[NDSDisplayID_Main] = (u32)this->_display[NDSDisplayID_Main]->GetRenderedWidth();
this->_displayInfo.renderedHeight[NDSDisplayID_Main] = (u32)this->_display[NDSDisplayID_Main]->GetRenderedHeight();
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->DidPerformCustomRender();
this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetRenderedBuffer();
this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetRenderedWidth();
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetRenderedHeight();
this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = (u32)this->_display[NDSDisplayID_Touch]->GetRenderedWidth();
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = (u32)this->_display[NDSDisplayID_Touch]->GetRenderedHeight();
this->_displayInfo.engineID[NDSDisplayID_Main] = this->_display[NDSDisplayID_Main]->GetEngineID();
this->_displayInfo.engineID[NDSDisplayID_Touch] = this->_display[NDSDisplayID_Touch]->GetEngineID();
@ -5638,16 +5675,16 @@ void GPUSubsystem::ClearWithColor(const u16 colorBGRA5551)
}
else
{
FragmentColor color32;
Color4u8 color32;
switch (this->_displayInfo.colorFormat)
{
case NDSColorFormat_BGR666_Rev:
color32.color = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>(colorBGRA5551 & 0x7FFF) );
color32.value = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>(colorBGRA5551 & 0x7FFF) );
break;
case NDSColorFormat_BGR888_Rev:
color32.color = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>(colorBGRA5551 & 0x7FFF) );
color32.value = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>(colorBGRA5551 & 0x7FFF) );
break;
default:
@ -5657,7 +5694,7 @@ void GPUSubsystem::ClearWithColor(const u16 colorBGRA5551)
for (size_t i = 0; i < this->_displayInfo.framebufferPageCount; i++)
{
memset_u16((u8 *)this->_masterFramebuffer + (this->_displayInfo.framebufferPageSize * i), color16, nativeFramebufferPixCount);
memset_u32((u8 *)this->_masterFramebuffer + (this->_displayInfo.framebufferPageSize * i) + (nativeFramebufferPixCount * sizeof(u16)), color32.color, customFramebufferPixCount);
memset_u32((u8 *)this->_masterFramebuffer + (this->_displayInfo.framebufferPageSize * i) + (nativeFramebufferPixCount * sizeof(u16)), color32.value, customFramebufferPixCount);
}
}
}
@ -5746,11 +5783,11 @@ void GPUSubsystem::_ConvertAndUpscaleForLoadstate(const NDSDisplayID displayID,
switch (this->_display[displayID]->GetColorFormat())
{
case NDSColorFormat_BGR666_Rev:
ColorspaceConvertBuffer555To6665Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
ColorspaceConvertBuffer555xTo6665Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
break;
case NDSColorFormat_BGR888_Rev:
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
break;
default:
@ -6178,11 +6215,11 @@ void NDSDisplay::ResolveLinesDisplayedNative()
{
if (this->_customColorFormat == NDSColorFormat_BGR888_Rev)
{
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
else
{
ColorspaceConvertBuffer555To6665Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH);
ColorspaceConvertBuffer555xTo6665Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH);
}
CopyLineExpandHinted<0x3FFF, true, false, false, 4>(lineInfo, working, dst);
@ -6222,7 +6259,7 @@ void NDSDisplay::ResolveFramebufferToCustom(NDSDisplayInfo &mutableInfo)
{
case NDSColorFormat_BGR666_Rev:
case NDSColorFormat_BGR888_Rev:
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>(src, working, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
break;
default:
@ -6264,7 +6301,7 @@ void NDSDisplay::ResolveFramebufferToCustom(NDSDisplayInfo &mutableInfo)
case NDSColorFormat_BGR666_Rev:
case NDSColorFormat_BGR888_Rev:
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(this->_nativeBuffer16, (u32 *)this->_customBuffer, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>(this->_nativeBuffer16, (u32 *)this->_customBuffer, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
break;
}
}
@ -6313,7 +6350,7 @@ NDSColorFormat NDSDisplay::GetColorFormat() const
void NDSDisplay::SetColorFormat(NDSColorFormat colorFormat)
{
this->_customColorFormat = colorFormat;
this->_customPixelBytes = (colorFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(FragmentColor);
this->_customPixelBytes = (colorFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(Color4u8);
}
size_t NDSDisplay::GetPixelBytes() const
@ -6441,8 +6478,8 @@ void NDSDisplay::ApplyMasterBrightness(void *dst, const size_t pixCount, const G
}
else
{
((FragmentColor *)dst)[i] = colorop.increase<OUTPUTFORMAT>(((FragmentColor *)dst)[i], intensityClamped);
((FragmentColor *)dst)[i].a = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F : 0xFF;
((Color4u8 *)dst)[i] = colorop.increase<OUTPUTFORMAT>(((Color4u8 *)dst)[i], intensityClamped);
((Color4u8 *)dst)[i].a = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F : 0xFF;
}
}
}
@ -6488,8 +6525,8 @@ void NDSDisplay::ApplyMasterBrightness(void *dst, const size_t pixCount, const G
}
else
{
((FragmentColor *)dst)[i] = colorop.decrease<OUTPUTFORMAT>(((FragmentColor *)dst)[i], intensityClamped);
((FragmentColor *)dst)[i].a = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F : 0xFF;
((Color4u8 *)dst)[i] = colorop.decrease<OUTPUTFORMAT>(((Color4u8 *)dst)[i], intensityClamped);
((Color4u8 *)dst)[i].a = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F : 0xFF;
}
}
}

View File

@ -2,7 +2,7 @@
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 Theo Berkau
Copyright (C) 2007 shash
Copyright (C) 2009-2022 DeSmuME team
Copyright (C) 2009-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -117,7 +117,7 @@ typedef union
u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB)
u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels
u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB)
u8 ForceBlank:1; // 7: A+B;
u8 ForceBlank:1; // 7: A+B; 0=Disable, 1=Enable (causes the line to render all white)
u8 BG0_Enable:1; // 8: A+B; 0=Disable, 1=Enable
u8 BG1_Enable:1; // 9: A+B; 0=Disable, 1=Enable
@ -143,7 +143,7 @@ typedef union
u8 ExBGxPalette_Enable:1; // 30: A+B; 0=Disable, 1=Enable BG extended Palette
u8 ExOBJPalette_Enable:1; // 31: A+B; 0=Disable, 1=Enable OBJ extended Palette
#else
u8 ForceBlank:1; // 7: A+B;
u8 ForceBlank:1; // 7: A+B; 0=Disable, 1=Enable (causes the line to render all white)
u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB)
u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels
u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB)
@ -581,7 +581,7 @@ typedef union
u8 PolygonShading:1; // 1: Polygon shading mode, interacts with POLYGON_ATTR (0x40004A4); 0=Toon Shading, 1=Highlight Shading
u8 EnableAlphaTest:1; // 2: Perform alpha test, interacts with ALPHA_TEST_REF (0x4000340); 0=Disable, 1=Enable
u8 EnableAlphaBlending:1; // 3: Perform alpha blending, interacts with POLYGON_ATTR (0x40004A4); 0=Disable, 1=Enable
u8 EnableAntiAliasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable
u8 EnableAntialiasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable
u8 EnableEdgeMarking:1; // 5: Perform polygon edge marking, interacts with EDGE_COLOR (0x4000330); 0=Disable, 1=Enable
u8 FogOnlyAlpha:1; // 6: Apply fog to the alpha channel only, interacts with FOG_COLOR (0x4000358) / FOG_TABLE (0x4000360); 0=Color+Alpha, 1=Alpha
u8 EnableFog:1; // 7: Perform fog rendering, interacts with FOG_COLOR (0x4000358) / FOG_OFFSET (0x400035C) / FOG_TABLE (0x4000360);
@ -600,7 +600,7 @@ typedef union
// 0=Disable, 1=Enable
u8 FogOnlyAlpha:1; // 6: Apply fog to the alpha channel only, interacts with FOG_COLOR (0x4000358) / FOG_TABLE (0x4000360); 0=Color+Alpha, 1=Alpha
u8 EnableEdgeMarking:1; // 5: Perform polygon edge marking, interacts with EDGE_COLOR (0x4000330); 0=Disable, 1=Enable
u8 EnableAntiAliasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable
u8 EnableAntialiasing:1; // 4: Render polygon edges with antialiasing; 0=Disable, 1=Enable
u8 EnableAlphaBlending:1; // 3: Perform alpha blending, interacts with POLYGON_ATTR (0x40004A4); 0=Disable, 1=Enable
u8 EnableAlphaTest:1; // 2: Perform alpha test, interacts with ALPHA_TEST_REF (0x4000340); 0=Disable, 1=Enable
u8 PolygonShading:1; // 1: Polygon shading mode, interacts with POLYGON_ATTR (0x40004A4); 0=Toon Shading, 1=Highlight Shading
@ -1330,7 +1330,7 @@ typedef struct
GPUDisplayMode displayOutputMode;
u16 backdropColor16;
u16 workingBackdropColor16;
FragmentColor workingBackdropColor32;
Color4u8 workingBackdropColor32;
ColorEffect colorEffect;
u8 blendEVA;
u8 blendEVB;
@ -1342,11 +1342,11 @@ typedef struct
TBlendTable *blendTable555;
u16 *brightnessUpTable555;
FragmentColor *brightnessUpTable666;
FragmentColor *brightnessUpTable888;
Color4u8 *brightnessUpTable666;
Color4u8 *brightnessUpTable888;
u16 *brightnessDownTable555;
FragmentColor *brightnessDownTable666;
FragmentColor *brightnessDownTable888;
Color4u8 *brightnessDownTable666;
Color4u8 *brightnessDownTable888;
u8 WIN0_enable[6];
u8 WIN1_enable[6];
@ -1387,7 +1387,7 @@ typedef struct
size_t xCustom;
void **lineColor;
u16 *lineColor16;
FragmentColor *lineColor32;
Color4u8 *lineColor32;
u8 *lineLayerID;
} GPUEngineTargetState;
@ -1503,7 +1503,7 @@ protected:
volatile s32 _asyncClearLineCustom;
volatile s32 _asyncClearInterrupt;
u16 _asyncClearBackdropColor16; // Do not modify this variable directly.
FragmentColor _asyncClearBackdropColor32; // Do not modify this variable directly.
Color4u8 _asyncClearBackdropColor32; // Do not modify this variable directly.
bool _asyncClearUseInternalCustomBuffer; // Do not modify this variable directly.
void _ResortBGLayers();
@ -1523,11 +1523,11 @@ protected:
template<bool MOSAIC> void _PrecompositeNativeToCustomLineBG(GPUEngineCompositorInfo &compInfo);
template<GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST> void _CompositeNativeLineOBJ(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const FragmentColor *__restrict srcColorNative32);
template<GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST> void _CompositeNativeLineOBJ(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const Color4u8 *__restrict srcColorNative32);
template<GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST> void _CompositeLineDeferred(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorCustom16, const u8 *__restrict srcIndexCustom);
template<GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST> void _CompositeVRAMLineDeferred(GPUEngineCompositorInfo &compInfo, const void *__restrict vramColorPtr);
template<GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST> void _CompositeNativeLineOBJ_LoopOp(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const FragmentColor *__restrict srcColorNative32);
template<GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST> void _CompositeNativeLineOBJ_LoopOp(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const Color4u8 *__restrict srcColorNative32);
template<GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST> size_t _CompositeLineDeferred_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const u16 *__restrict srcColorCustom16, const u8 *__restrict srcIndexCustom);
template<GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST> size_t _CompositeVRAMLineDeferred_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const void *__restrict vramColorPtr);
@ -1543,6 +1543,8 @@ protected:
void _RenderLine_SetupSprites(GPUEngineCompositorInfo &compInfo);
template<NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST> void _RenderLine_Layers(GPUEngineCompositorInfo &compInfo);
void _RenderLineBlank(const size_t l);
void _HandleDisplayModeOff(const size_t l);
void _HandleDisplayModeNormal(const size_t l);
@ -1609,6 +1611,7 @@ public:
const GPU_IOREG& GetIORegisterMap() const;
bool IsForceBlankSet() const;
bool IsMasterBrightMaxOrMin() const;
bool GetEnableState();
@ -1620,9 +1623,9 @@ public:
void ApplySettings();
void RenderLineClearAsync();
void RenderLineClearAsyncStart(bool willClearInternalCustomBuffer, s32 startLineIndex, u16 clearColor16, FragmentColor clearColor32);
void RenderLineClearAsyncStart(bool willClearInternalCustomBuffer, size_t startLineIndex, u16 clearColor16, Color4u8 clearColor32);
void RenderLineClearAsyncFinish();
void RenderLineClearAsyncWaitForCustomLine(const s32 l);
void RenderLineClearAsyncWaitForCustomLine(const size_t l);
void TransitionRenderStatesToDisplayInfo(NDSDisplayInfo &mutableInfo);
@ -1651,12 +1654,12 @@ private:
protected:
CACHE_ALIGN u16 _fifoLine16[GPU_FRAMEBUFFER_NATIVE_WIDTH];
CACHE_ALIGN FragmentColor _fifoLine32[GPU_FRAMEBUFFER_NATIVE_WIDTH];
CACHE_ALIGN Color4u8 _fifoLine32[GPU_FRAMEBUFFER_NATIVE_WIDTH];
CACHE_ALIGN u16 _VRAMNativeBlockCaptureCopy[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_VRAM_BLOCK_LINES * 4];
u16 *_VRAMNativeBlockCaptureCopyPtr[4];
FragmentColor *_3DFramebufferMain;
Color4u8 *_3DFramebufferMain;
u16 *_3DFramebuffer16;
u16 *_VRAMNativeBlockPtr[4];
@ -1668,8 +1671,8 @@ protected:
u16 *_captureWorkingDisplay16;
u16 *_captureWorkingA16;
u16 *_captureWorkingB16;
FragmentColor *_captureWorkingA32;
FragmentColor *_captureWorkingB32;
Color4u8 *_captureWorkingA32;
Color4u8 *_captureWorkingB32;
DISPCAPCNT_parsed _dispCapCnt;
bool _displayCaptureEnable;
@ -1692,10 +1695,10 @@ protected:
void _RenderLine_DispCapture_Copy(const GPUEngineLineInfo &lineInfo, const void *src, void *dst, const size_t captureLengthExt); // Do not use restrict pointers, since src and dst can be the same
u16 _RenderLine_DispCapture_BlendFunc(const u16 srcA, const u16 srcB, const u8 blendEVA, const u8 blendEVB);
template<NDSColorFormat COLORFORMAT> FragmentColor _RenderLine_DispCapture_BlendFunc(const FragmentColor srcA, const FragmentColor srcB, const u8 blendEVA, const u8 blendEVB);
template<NDSColorFormat COLORFORMAT> Color4u8 _RenderLine_DispCapture_BlendFunc(const Color4u8 srcA, const Color4u8 srcB, const u8 blendEVA, const u8 blendEVB);
template<GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST>
size_t _RenderLine_Layer3D_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const FragmentColor *__restrict srcLinePtr);
size_t _RenderLine_Layer3D_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const Color4u8 *__restrict srcLinePtr);
template<NDSColorFormat OUTPUTFORMAT>
void _RenderLine_DispCapture_Blend_Buffer(const void *srcA, const void *srcB, void *dst, const u8 blendEVA, const u8 blendEVB, const size_t pixCount); // Do not use restrict pointers, since srcB and dst can be the same
@ -1716,7 +1719,7 @@ public:
void ParseReg_DISPCAPCNT();
bool IsLineCaptureNative(const size_t blockID, const size_t blockLine);
void* GetCustomVRAMBlockPtr(const size_t blockID);
FragmentColor* Get3DFramebufferMain() const;
Color4u8* Get3DFramebufferMain() const;
u16* Get3DFramebuffer16() const;
virtual void AllocateWorkingBuffers(NDSColorFormat requestedColorFormat, size_t w, size_t h);
@ -1819,8 +1822,8 @@ public:
bool IsCustomSizeRequested() const;
void* GetRenderedBuffer() const;
size_t GetRenderedWidth() const;
size_t GetRenderedHeight() const;
size_t GetRenderedWidth() const;
size_t GetRenderedHeight() const;
bool IsEnabled() const;
void SetIsEnabled(bool stateIsEnabled);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2021 DeSmuME team
Copyright (C) 2021-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -32,11 +32,11 @@ static CACHE_ALIGN u32 _gpuDstPitchIndex[GPU_FRAMEBUFFER_NATIVE_WIDTH]; // Key:
u8 PixelOperation::BlendTable555[17][17][32][32];
u16 PixelOperation::BrightnessUpTable555[17][0x8000];
FragmentColor PixelOperation::BrightnessUpTable666[17][0x8000];
FragmentColor PixelOperation::BrightnessUpTable888[17][0x8000];
Color4u8 PixelOperation::BrightnessUpTable666[17][0x8000];
Color4u8 PixelOperation::BrightnessUpTable888[17][0x8000];
u16 PixelOperation::BrightnessDownTable555[17][0x8000];
FragmentColor PixelOperation::BrightnessDownTable666[17][0x8000];
FragmentColor PixelOperation::BrightnessDownTable888[17][0x8000];
Color4u8 PixelOperation::BrightnessDownTable666[17][0x8000];
Color4u8 PixelOperation::BrightnessDownTable888[17][0x8000];
static CACHE_ALIGN ColorOperation colorop;
static CACHE_ALIGN PixelOperation pixelop;
@ -71,9 +71,9 @@ FORCEINLINE u16 ColorOperation::blend(const u16 colA, const u16 colB, const TBle
}
template <NDSColorFormat COLORFORMAT>
FORCEINLINE FragmentColor ColorOperation::blend(const FragmentColor colA, const FragmentColor colB, const u16 blendEVA, const u16 blendEVB) const
FORCEINLINE Color4u8 ColorOperation::blend(const Color4u8 colA, const Color4u8 colB, const u16 blendEVA, const u16 blendEVB) const
{
FragmentColor outColor;
Color4u8 outColor;
u16 r16 = ( (colA.r * blendEVA) + (colB.r * blendEVB) ) / 16;
u16 g16 = ( (colA.g * blendEVA) + (colB.g * blendEVB) ) / 16;
@ -96,7 +96,7 @@ FORCEINLINE FragmentColor ColorOperation::blend(const FragmentColor colA, const
return outColor;
}
FORCEINLINE u16 ColorOperation::blend3D(const FragmentColor colA, const u16 colB) const
FORCEINLINE u16 ColorOperation::blend3D(const Color4u8 colA, const u16 colB) const
{
const u16 alpha = colA.a + 1;
COLOR c2;
@ -113,9 +113,9 @@ FORCEINLINE u16 ColorOperation::blend3D(const FragmentColor colA, const u16 colB
}
template <NDSColorFormat COLORFORMAT>
FORCEINLINE FragmentColor ColorOperation::blend3D(const FragmentColor colA, const FragmentColor colB) const
FORCEINLINE Color4u8 ColorOperation::blend3D(const Color4u8 colA, const Color4u8 colB) const
{
FragmentColor blendedColor;
Color4u8 blendedColor;
const u16 alpha = colA.a + 1;
if (COLORFORMAT == NDSColorFormat_BGR666_Rev)
@ -149,10 +149,10 @@ FORCEINLINE u16 ColorOperation::increase(const u16 col, const u16 blendEVY) cons
}
template <NDSColorFormat COLORFORMAT>
FORCEINLINE FragmentColor ColorOperation::increase(const FragmentColor col, const u16 blendEVY) const
FORCEINLINE Color4u8 ColorOperation::increase(const Color4u8 col, const u16 blendEVY) const
{
FragmentColor newColor;
newColor.color = 0;
Color4u8 newColor;
newColor.value = 0;
u32 r = col.r;
u32 g = col.g;
@ -188,10 +188,10 @@ FORCEINLINE u16 ColorOperation::decrease(const u16 col, const u16 blendEVY) cons
}
template <NDSColorFormat COLORFORMAT>
FORCEINLINE FragmentColor ColorOperation::decrease(const FragmentColor col, const u16 blendEVY) const
FORCEINLINE Color4u8 ColorOperation::decrease(const Color4u8 col, const u16 blendEVY) const
{
FragmentColor newColor;
newColor.color = 0;
Color4u8 newColor;
newColor.value = 0;
u32 r = col.r;
u32 g = col.g;
@ -242,8 +242,8 @@ void PixelOperation::InitLUTs()
cur.bits.blue = (cur.bits.blue + ((31 - cur.bits.blue) * i / 16));
cur.bits.alpha = 0;
PixelOperation::BrightnessUpTable555[i][j] = cur.val;
PixelOperation::BrightnessUpTable666[i][j].color = LOCAL_TO_LE_32( COLOR555TO666(cur.val) );
PixelOperation::BrightnessUpTable888[i][j].color = LOCAL_TO_LE_32( COLOR555TO888(cur.val) );
PixelOperation::BrightnessUpTable666[i][j].value = LOCAL_TO_LE_32( COLOR555TO666(cur.val) );
PixelOperation::BrightnessUpTable888[i][j].value = LOCAL_TO_LE_32( COLOR555TO888(cur.val) );
cur.val = j;
cur.bits.red = (cur.bits.red - (cur.bits.red * i / 16));
@ -251,8 +251,8 @@ void PixelOperation::InitLUTs()
cur.bits.blue = (cur.bits.blue - (cur.bits.blue * i / 16));
cur.bits.alpha = 0;
PixelOperation::BrightnessDownTable555[i][j] = cur.val;
PixelOperation::BrightnessDownTable666[i][j].color = LOCAL_TO_LE_32( COLOR555TO666(cur.val) );
PixelOperation::BrightnessDownTable888[i][j].color = LOCAL_TO_LE_32( COLOR555TO888(cur.val) );
PixelOperation::BrightnessDownTable666[i][j].value = LOCAL_TO_LE_32( COLOR555TO666(cur.val) );
PixelOperation::BrightnessDownTable888[i][j].value = LOCAL_TO_LE_32( COLOR555TO888(cur.val) );
}
}
@ -279,7 +279,7 @@ template <NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER>
FORCEINLINE void PixelOperation::_copy16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const
{
u16 &dstColor16 = *compInfo.target.lineColor16;
FragmentColor &dstColor32 = *compInfo.target.lineColor32;
Color4u8 &dstColor32 = *compInfo.target.lineColor32;
u8 &dstLayerID = *compInfo.target.lineLayerID;
switch (OUTPUTFORMAT)
@ -289,11 +289,11 @@ FORCEINLINE void PixelOperation::_copy16(GPUEngineCompositorInfo &compInfo, cons
break;
case NDSColorFormat_BGR666_Rev:
dstColor32.color = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>(srcColor16) );
dstColor32.value = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>(srcColor16) );
break;
case NDSColorFormat_BGR888_Rev:
dstColor32.color = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>(srcColor16) );
dstColor32.value = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>(srcColor16) );
break;
}
@ -304,10 +304,10 @@ FORCEINLINE void PixelOperation::_copy16(GPUEngineCompositorInfo &compInfo, cons
}
template <NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER>
FORCEINLINE void PixelOperation::_copy32(GPUEngineCompositorInfo &compInfo, const FragmentColor srcColor32) const
FORCEINLINE void PixelOperation::_copy32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const
{
u16 &dstColor16 = *compInfo.target.lineColor16;
FragmentColor &dstColor32 = *compInfo.target.lineColor32;
Color4u8 &dstColor32 = *compInfo.target.lineColor32;
u8 &dstLayerID = *compInfo.target.lineLayerID;
switch (OUTPUTFORMAT)
@ -341,7 +341,7 @@ template <NDSColorFormat OUTPUTFORMAT>
FORCEINLINE void PixelOperation::_brightnessUp16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const
{
u16 &dstColor16 = *compInfo.target.lineColor16;
FragmentColor &dstColor32 = *compInfo.target.lineColor32;
Color4u8 &dstColor32 = *compInfo.target.lineColor32;
u8 &dstLayerID = *compInfo.target.lineLayerID;
switch (OUTPUTFORMAT)
@ -365,10 +365,10 @@ FORCEINLINE void PixelOperation::_brightnessUp16(GPUEngineCompositorInfo &compIn
}
template <NDSColorFormat OUTPUTFORMAT>
FORCEINLINE void PixelOperation::_brightnessUp32(GPUEngineCompositorInfo &compInfo, const FragmentColor srcColor32) const
FORCEINLINE void PixelOperation::_brightnessUp32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const
{
u16 &dstColor16 = *compInfo.target.lineColor16;
FragmentColor &dstColor32 = *compInfo.target.lineColor32;
Color4u8 &dstColor32 = *compInfo.target.lineColor32;
u8 &dstLayerID = *compInfo.target.lineLayerID;
if (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev)
@ -390,7 +390,7 @@ template <NDSColorFormat OUTPUTFORMAT>
FORCEINLINE void PixelOperation::_brightnessDown16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const
{
u16 &dstColor16 = *compInfo.target.lineColor16;
FragmentColor &dstColor32 = *compInfo.target.lineColor32;
Color4u8 &dstColor32 = *compInfo.target.lineColor32;
u8 &dstLayerID = *compInfo.target.lineLayerID;
switch (OUTPUTFORMAT)
@ -414,10 +414,10 @@ FORCEINLINE void PixelOperation::_brightnessDown16(GPUEngineCompositorInfo &comp
}
template <NDSColorFormat OUTPUTFORMAT>
FORCEINLINE void PixelOperation::_brightnessDown32(GPUEngineCompositorInfo &compInfo, const FragmentColor srcColor32) const
FORCEINLINE void PixelOperation::_brightnessDown32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const
{
u16 &dstColor16 = *compInfo.target.lineColor16;
FragmentColor &dstColor32 = *compInfo.target.lineColor32;
Color4u8 &dstColor32 = *compInfo.target.lineColor32;
u8 &dstLayerID = *compInfo.target.lineLayerID;
if (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev)
@ -555,14 +555,14 @@ FORCEINLINE void PixelOperation::_unknownEffect16(GPUEngineCompositorInfo &compI
}
else
{
FragmentColor &dstColor32 = *compInfo.target.lineColor32;
Color4u8 &dstColor32 = *compInfo.target.lineColor32;
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
switch (selectedEffect)
{
case ColorEffect_Disable:
dstColor32.color = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>(srcColor16) );
dstColor32.value = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>(srcColor16) );
break;
case ColorEffect_IncreaseBrightness:
@ -575,8 +575,8 @@ FORCEINLINE void PixelOperation::_unknownEffect16(GPUEngineCompositorInfo &compI
case ColorEffect_Blend:
{
FragmentColor srcColor32;
srcColor32.color = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>(srcColor16) );
Color4u8 srcColor32;
srcColor32.value = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>(srcColor16) );
dstColor32 = (LAYERTYPE == GPULayerType_3D) ? colorop.blend3D<OUTPUTFORMAT>(srcColor32, dstColor32) : colorop.blend<OUTPUTFORMAT>(srcColor32, dstColor32, blendEVA, blendEVB);
break;
}
@ -587,7 +587,7 @@ FORCEINLINE void PixelOperation::_unknownEffect16(GPUEngineCompositorInfo &compI
switch (selectedEffect)
{
case ColorEffect_Disable:
dstColor32.color = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>(srcColor16) );
dstColor32.value = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>(srcColor16) );
break;
case ColorEffect_IncreaseBrightness:
@ -600,8 +600,8 @@ FORCEINLINE void PixelOperation::_unknownEffect16(GPUEngineCompositorInfo &compI
case ColorEffect_Blend:
{
FragmentColor srcColor32;
srcColor32.color = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>(srcColor16) );
Color4u8 srcColor32;
srcColor32.value = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>(srcColor16) );
dstColor32 = (LAYERTYPE == GPULayerType_3D) ? colorop.blend3D<OUTPUTFORMAT>(srcColor32, dstColor32) : colorop.blend<OUTPUTFORMAT>(srcColor32, dstColor32, blendEVA, blendEVB);
break;
}
@ -613,7 +613,7 @@ FORCEINLINE void PixelOperation::_unknownEffect16(GPUEngineCompositorInfo &compI
}
template <NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
FORCEINLINE void PixelOperation::_unknownEffect32(GPUEngineCompositorInfo &compInfo, const FragmentColor srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode) const
FORCEINLINE void PixelOperation::_unknownEffect32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode) const
{
u8 &dstLayerID = *compInfo.target.lineLayerID;
TBlendTable *selectedBlendTable = compInfo.renderState.blendTable555;
@ -663,7 +663,7 @@ FORCEINLINE void PixelOperation::_unknownEffect32(GPUEngineCompositorInfo &compI
}
else
{
FragmentColor &dstColor32 = *compInfo.target.lineColor32;
Color4u8 &dstColor32 = *compInfo.target.lineColor32;
switch (selectedEffect)
{
@ -716,7 +716,7 @@ FORCEINLINE void PixelOperation::Composite16(GPUEngineCompositorInfo &compInfo,
}
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
FORCEINLINE void PixelOperation::Composite32(GPUEngineCompositorInfo &compInfo, FragmentColor srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const u8 spriteMode) const
FORCEINLINE void PixelOperation::Composite32(GPUEngineCompositorInfo &compInfo, Color4u8 srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const u8 spriteMode) const
{
switch (COMPOSITORMODE)
{
@ -758,6 +758,8 @@ static FORCEINLINE void CopyLinesForVerticalCount(void *__restrict dstLineHead,
#include "GPU_Operations_AVX2.cpp"
#elif defined(ENABLE_SSE2)
#include "GPU_Operations_SSE2.cpp"
#elif defined(ENABLE_NEON_A64)
#include "GPU_Operations_NEON.cpp"
#else
template <s32 INTEGERSCALEHINT, bool SCALEVERTICAL, bool NEEDENDIANSWAP, size_t ELEMENTSIZE>
@ -1013,7 +1015,7 @@ void GPUEngineBase::_MosaicLine(GPUEngineCompositorInfo &compInfo)
}
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST>
void GPUEngineBase::_CompositeNativeLineOBJ_LoopOp(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const FragmentColor *__restrict srcColorNative32)
void GPUEngineBase::_CompositeNativeLineOBJ_LoopOp(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const Color4u8 *__restrict srcColorNative32)
{
// Do nothing. This is a placeholder for a manually vectorized version of this method.
}
@ -1086,7 +1088,7 @@ void GPUEngineBase::_PerformWindowTestingNative(GPUEngineCompositorInfo &compInf
}
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST>
size_t GPUEngineA::_RenderLine_Layer3D_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const FragmentColor *__restrict srcLinePtr)
size_t GPUEngineA::_RenderLine_Layer3D_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const Color4u8 *__restrict srcLinePtr)
{
// Do nothing. This is a placeholder for a manually vectorized version of this method.
return 0;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2021 DeSmuME team
Copyright (C) 2021-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -47,16 +47,16 @@ public:
FORCEINLINE u16 blend(const u16 colA, const u16 colB, const u16 blendEVA, const u16 blendEVB) const;
FORCEINLINE u16 blend(const u16 colA, const u16 colB, const TBlendTable *blendTable) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE FragmentColor blend(const FragmentColor colA, const FragmentColor colB, const u16 blendEVA, const u16 blendEVB) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 blend(const Color4u8 colA, const Color4u8 colB, const u16 blendEVA, const u16 blendEVB) const;
FORCEINLINE u16 blend3D(const FragmentColor colA, const u16 colB) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE FragmentColor blend3D(const FragmentColor colA, const FragmentColor colB) const;
FORCEINLINE u16 blend3D(const Color4u8 colA, const u16 colB) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 blend3D(const Color4u8 colA, const Color4u8 colB) const;
FORCEINLINE u16 increase(const u16 col, const u16 blendEVY) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE FragmentColor increase(const FragmentColor col, const u16 blendEVY) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 increase(const Color4u8 col, const u16 blendEVY) const;
FORCEINLINE u16 decrease(const u16 col, const u16 blendEVY) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE FragmentColor decrease(const FragmentColor col, const u16 blendEVY) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 decrease(const Color4u8 col, const u16 blendEVY) const;
};
class PixelOperation
@ -66,31 +66,31 @@ private:
protected:
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const;
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const FragmentColor srcColor32) const;
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const FragmentColor srcColor32) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const FragmentColor srcColor32) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const;
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void _unknownEffect16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode) const;
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void _unknownEffect32(GPUEngineCompositorInfo &compInfo, const FragmentColor srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode) const;
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void _unknownEffect32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode) const;
public:
static CACHE_ALIGN u8 BlendTable555[17][17][32][32];
static CACHE_ALIGN u16 BrightnessUpTable555[17][0x8000];
static CACHE_ALIGN FragmentColor BrightnessUpTable666[17][0x8000];
static CACHE_ALIGN FragmentColor BrightnessUpTable888[17][0x8000];
static CACHE_ALIGN Color4u8 BrightnessUpTable666[17][0x8000];
static CACHE_ALIGN Color4u8 BrightnessUpTable888[17][0x8000];
static CACHE_ALIGN u16 BrightnessDownTable555[17][0x8000];
static CACHE_ALIGN FragmentColor BrightnessDownTable666[17][0x8000];
static CACHE_ALIGN FragmentColor BrightnessDownTable888[17][0x8000];
static CACHE_ALIGN Color4u8 BrightnessDownTable666[17][0x8000];
static CACHE_ALIGN Color4u8 BrightnessDownTable888[17][0x8000];
static void InitLUTs();
PixelOperation() {};
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16, const bool enableColorEffect, const u8 spriteAlpha, const u8 spriteMode) const;
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo, FragmentColor srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const u8 spriteMode) const;
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo, Color4u8 srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const u8 spriteMode) const;
};
#endif // GPU_OPERATIONS_H

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2021-2022 DeSmuME team
Copyright (C) 2021-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -950,15 +950,17 @@ FORCEINLINE v256u16 ColorOperation_AVX2::blend3D(const v256u32 &colA_Lo, const v
{
// If the color format of B is 555, then the colA_Hi parameter is required.
// The color format of A is assumed to be RGB666.
v256u32 ra_lo = _mm256_and_si256( colA_Lo, _mm256_set1_epi32(0x000000FF) );
v256u32 ga_lo = _mm256_and_si256( _mm256_srli_epi32(colA_Lo, 8), _mm256_set1_epi32(0x000000FF) );
v256u32 ba_lo = _mm256_and_si256( _mm256_srli_epi32(colA_Lo, 16), _mm256_set1_epi32(0x000000FF) );
v256u32 aa_lo = _mm256_srli_epi32(colA_Lo, 24);
static const u8 X = 0x80;
v256u32 ra_hi = _mm256_and_si256( colA_Hi, _mm256_set1_epi32(0x000000FF) );
v256u32 ga_hi = _mm256_and_si256( _mm256_srli_epi32(colA_Hi, 8), _mm256_set1_epi32(0x000000FF) );
v256u32 ba_hi = _mm256_and_si256( _mm256_srli_epi32(colA_Hi, 16), _mm256_set1_epi32(0x000000FF) );
v256u32 aa_hi = _mm256_srli_epi32(colA_Hi, 24);
const v256u32 ra_lo = _mm256_shuffle_epi8( colA_Lo, _mm256_set_epi8( X, X, X,12, X, X, X, 8, X, X, X, 4, X, X, X, 0, X, X, X,12, X, X, X, 8, X, X, X, 4, X, X, X, 0) );
const v256u32 ga_lo = _mm256_shuffle_epi8( colA_Lo, _mm256_set_epi8( X, X, X,13, X, X, X, 9, X, X, X, 5, X, X, X, 1, X, X, X,13, X, X, X, 9, X, X, X, 5, X, X, X, 1) );
const v256u32 ba_lo = _mm256_shuffle_epi8( colA_Lo, _mm256_set_epi8( X, X, X,14, X, X, X,10, X, X, X, 6, X, X, X, 2, X, X, X,14, X, X, X,10, X, X, X, 6, X, X, X, 2) );
const v256u32 aa_lo = _mm256_shuffle_epi8( colA_Lo, _mm256_set_epi8( X, X, X,15, X, X, X,11, X, X, X, 7, X, X, X, 3, X, X, X,15, X, X, X,11, X, X, X, 7, X, X, X, 3) );
const v256u32 ra_hi = _mm256_shuffle_epi8( colA_Hi, _mm256_set_epi8( X, X, X,12, X, X, X, 8, X, X, X, 4, X, X, X, 0, X, X, X,12, X, X, X, 8, X, X, X, 4, X, X, X, 0) );
const v256u32 ga_hi = _mm256_shuffle_epi8( colA_Hi, _mm256_set_epi8( X, X, X,13, X, X, X, 9, X, X, X, 5, X, X, X, 1, X, X, X,13, X, X, X, 9, X, X, X, 5, X, X, X, 1) );
const v256u32 ba_hi = _mm256_shuffle_epi8( colA_Hi, _mm256_set_epi8( X, X, X,14, X, X, X,10, X, X, X, 6, X, X, X, 2, X, X, X,14, X, X, X,10, X, X, X, 6, X, X, X, 2) );
const v256u32 aa_hi = _mm256_shuffle_epi8( colA_Hi, _mm256_set_epi8( X, X, X,15, X, X, X,11, X, X, X, 7, X, X, X, 3, X, X, X,15, X, X, X,11, X, X, X, 7, X, X, X, 3) );
v256u16 ra = _mm256_packus_epi32(ra_lo, ra_hi);
v256u16 ga = _mm256_packus_epi32(ga_lo, ga_hi);
@ -991,9 +993,11 @@ FORCEINLINE v256u16 ColorOperation_AVX2::blend3D(const v256u32 &colA_Lo, const v
template <NDSColorFormat COLORFORMAT>
FORCEINLINE v256u32 ColorOperation_AVX2::blend3D(const v256u32 &colA, const v256u32 &colB) const
{
static const u8 X = 0x80;
// If the color format of B is 666 or 888, then the colA_Hi parameter is ignored.
// The color format of A is assumed to match the color format of B.
v256u32 alpha;
v256u8 alpha;
v256u16 alphaLo;
v256u16 alphaHi;
@ -1015,8 +1019,7 @@ FORCEINLINE v256u32 ColorOperation_AVX2::blend3D(const v256u32 &colA, const v256
v256u16 tempColorLo = _mm256_unpacklo_epi8(tempColor[0], tempColor[1]);
v256u16 tempColorHi = _mm256_unpackhi_epi8(tempColor[0], tempColor[1]);
alpha = _mm256_and_si256( _mm256_srli_epi32(colA, 24), _mm256_set1_epi32(0x0000001F) );
alpha = _mm256_or_si256( alpha, _mm256_or_si256(_mm256_slli_epi32(alpha, 8), _mm256_slli_epi32(alpha, 16)) );
alpha = _mm256_shuffle_epi8( colA, _mm256_set_epi8( X,15,15,15, X,11,11,11, X, 7, 7, 7, X, 3, 3, 3, X,15,15,15, X,11,11,11, X, 7, 7, 7, X, 3, 3, 3) );
alpha = _mm256_adds_epu8(alpha, _mm256_set1_epi8(1));
v256u32 invAlpha = _mm256_subs_epu8(_mm256_set1_epi8(32), alpha);
@ -1039,8 +1042,7 @@ FORCEINLINE v256u32 ColorOperation_AVX2::blend3D(const v256u32 &colA, const v256
v256u16 rgbBLo = _mm256_unpacklo_epi8(tempColor[1], _mm256_setzero_si256());
v256u16 rgbBHi = _mm256_unpackhi_epi8(tempColor[1], _mm256_setzero_si256());
alpha = _mm256_and_si256( _mm256_srli_epi32(colA, 24), _mm256_set1_epi32(0x000000FF) );
alpha = _mm256_or_si256( alpha, _mm256_or_si256(_mm256_slli_epi32(alpha, 8), _mm256_slli_epi32(alpha, 16)) );
alpha = _mm256_shuffle_epi8( colA, _mm256_set_epi8( X,15,15,15, X,11,11,11, X, 7, 7, 7, X, 3, 3, 3, X,15,15,15, X,11,11,11, X, 7, 7, 7, X, 3, 3, 3) );
alpha = _mm256_permute4x64_epi64(alpha, 0xD8);
alphaLo = _mm256_unpacklo_epi8(alpha, _mm256_setzero_si256());
@ -1128,13 +1130,13 @@ FORCEINLINE void PixelOperation_AVX2::_copy16(GPUEngineCompositorInfo &compInfo,
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555To6665Opaque_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555To6665Opaque_AVX2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo6665Opaque_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo6665Opaque_AVX2<false>(src1, src32[2], src32[3]);
}
else
{
ColorspaceConvert555To8888Opaque_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555To8888Opaque_AVX2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo8888Opaque_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo8888Opaque_AVX2<false>(src1, src32[2], src32[3]);
}
_mm256_store_si256( (v256u32 *)compInfo.target.lineColor32 + 0, src32[0] );
@ -1205,13 +1207,13 @@ FORCEINLINE void PixelOperation_AVX2::_copyMask16(GPUEngineCompositorInfo &compI
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555To6665Opaque_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555To6665Opaque_AVX2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo6665Opaque_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo6665Opaque_AVX2<false>(src1, src32[2], src32[3]);
}
else
{
ColorspaceConvert555To8888Opaque_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555To8888Opaque_AVX2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo8888Opaque_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo8888Opaque_AVX2<false>(src1, src32[2], src32[3]);
}
passMask16[0] = _mm256_permute4x64_epi64(passMask16[0], 0xD8);
@ -1304,13 +1306,13 @@ FORCEINLINE void PixelOperation_AVX2::_brightnessUp16(GPUEngineCompositorInfo &c
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_AVX2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555XTo666X_AVX2<false>(src1, dst[2], dst[3]);
ColorspaceConvert555xTo666x_AVX2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555xTo666x_AVX2<false>(src1, dst[2], dst[3]);
}
else
{
ColorspaceConvert555XTo888X_AVX2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555XTo888X_AVX2<false>(src1, dst[2], dst[3]);
ColorspaceConvert555xTo888x_AVX2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555xTo888x_AVX2<false>(src1, dst[2], dst[3]);
}
const v256u32 alphaBits = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? _mm256_set1_epi32(0x1F000000) : _mm256_set1_epi32(0xFF000000);
@ -1377,13 +1379,13 @@ FORCEINLINE void PixelOperation_AVX2::_brightnessUpMask16(GPUEngineCompositorInf
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555XTo666X_AVX2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo666x_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo666x_AVX2<false>(src1, src32[2], src32[3]);
}
else
{
ColorspaceConvert555XTo888X_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555XTo888X_AVX2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo888x_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo888x_AVX2<false>(src1, src32[2], src32[3]);
}
passMask16[0] = _mm256_permute4x64_epi64(passMask16[0], 0xD8);
@ -1471,13 +1473,13 @@ FORCEINLINE void PixelOperation_AVX2::_brightnessDown16(GPUEngineCompositorInfo
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_AVX2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555XTo666X_AVX2<false>(src1, dst[2], dst[3]);
ColorspaceConvert555xTo666x_AVX2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555xTo666x_AVX2<false>(src1, dst[2], dst[3]);
}
else
{
ColorspaceConvert555XTo888X_AVX2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555XTo888X_AVX2<false>(src1, dst[2], dst[3]);
ColorspaceConvert555xTo888x_AVX2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555xTo888x_AVX2<false>(src1, dst[2], dst[3]);
}
const v256u32 alphaBits = _mm256_set1_epi32((OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F000000 : 0xFF000000);
@ -1544,13 +1546,13 @@ FORCEINLINE void PixelOperation_AVX2::_brightnessDownMask16(GPUEngineCompositorI
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555XTo666X_AVX2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo666x_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo666x_AVX2<false>(src1, src32[2], src32[3]);
}
else
{
ColorspaceConvert555XTo888X_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555XTo888X_AVX2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo888x_AVX2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo888x_AVX2<false>(src1, src32[2], src32[3]);
}
passMask16[0] = _mm256_permute4x64_epi64(passMask16[0], 0xD8);
@ -1674,13 +1676,13 @@ FORCEINLINE void PixelOperation_AVX2::_unknownEffectMask16(GPUEngineCompositorIn
}
else if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_AVX2<false>(src0, tmpSrc[0], tmpSrc[1]);
ColorspaceConvert555XTo666X_AVX2<false>(src1, tmpSrc[2], tmpSrc[3]);
ColorspaceConvert555xTo666x_AVX2<false>(src0, tmpSrc[0], tmpSrc[1]);
ColorspaceConvert555xTo666x_AVX2<false>(src1, tmpSrc[2], tmpSrc[3]);
}
else
{
ColorspaceConvert555XTo888X_AVX2<false>(src0, tmpSrc[0], tmpSrc[1]);
ColorspaceConvert555XTo888X_AVX2<false>(src1, tmpSrc[2], tmpSrc[3]);
ColorspaceConvert555xTo888x_AVX2<false>(src0, tmpSrc[0], tmpSrc[1]);
ColorspaceConvert555xTo888x_AVX2<false>(src1, tmpSrc[2], tmpSrc[3]);
}
switch (compInfo.renderState.colorEffect)
@ -2179,7 +2181,7 @@ FORCEINLINE void PixelOperation_AVX2::_unknownEffectMask32(GPUEngineCompositorIn
_mm256_load_si256((v256u32 *)compInfo.target.lineColor32 + 0),
_mm256_load_si256((v256u32 *)compInfo.target.lineColor32 + 1),
_mm256_load_si256((v256u32 *)compInfo.target.lineColor32 + 2),
_mm256_load_si256((v256u32 *)compInfo.target.lineColor32 + 3),
_mm256_load_si256((v256u32 *)compInfo.target.lineColor32 + 3)
};
v256u32 blendSrc32[4];
@ -2505,7 +2507,7 @@ void GPUEngineBase::_MosaicLine(GPUEngineCompositorInfo &compInfo)
}
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST>
void GPUEngineBase::_CompositeNativeLineOBJ_LoopOp(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const FragmentColor *__restrict srcColorNative32)
void GPUEngineBase::_CompositeNativeLineOBJ_LoopOp(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const Color4u8 *__restrict srcColorNative32)
{
static const size_t step = sizeof(v256u8);
@ -2749,10 +2751,10 @@ size_t GPUEngineBase::_CompositeVRAMLineDeferred_LoopOp(GPUEngineCompositorInfo
case NDSColorFormat_BGR888_Rev:
{
const v256u32 src32[4] = {
_mm256_load_si256((v256u32 *)((FragmentColor *)vramColorPtr + i) + 0),
_mm256_load_si256((v256u32 *)((FragmentColor *)vramColorPtr + i) + 1),
_mm256_load_si256((v256u32 *)((FragmentColor *)vramColorPtr + i) + 2),
_mm256_load_si256((v256u32 *)((FragmentColor *)vramColorPtr + i) + 3)
_mm256_load_si256((v256u32 *)((Color4u8 *)vramColorPtr + i) + 0),
_mm256_load_si256((v256u32 *)((Color4u8 *)vramColorPtr + i) + 1),
_mm256_load_si256((v256u32 *)((Color4u8 *)vramColorPtr + i) + 2),
_mm256_load_si256((v256u32 *)((Color4u8 *)vramColorPtr + i) + 3)
};
if (LAYERTYPE != GPULayerType_OBJ)
@ -2906,7 +2908,7 @@ void GPUEngineBase::_PerformWindowTestingNative(GPUEngineCompositorInfo &compInf
}
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST>
size_t GPUEngineA::_RenderLine_Layer3D_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const FragmentColor *__restrict srcLinePtr)
size_t GPUEngineA::_RenderLine_Layer3D_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const Color4u8 *__restrict srcLinePtr)
{
static const size_t step = sizeof(v256u32);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,122 @@
/*
Copyright (C) 2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GPU_OPERATIONS_NEON_H
#define GPU_OPERATIONS_NEON_H
#include "GPU_Operations.h"
#ifndef ENABLE_NEON_A64
#warning This header requires ARM64 NEON support.
#else
class ColorOperation_NEON
{
public:
ColorOperation_NEON() {};
FORCEINLINE v128u16 blend(const v128u16 &colA, const v128u16 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
template<NDSColorFormat COLORFORMAT, bool USECONSTANTBLENDVALUESHINT> FORCEINLINE v128u32 blend(const v128u32 &colA, const v128u32 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
FORCEINLINE v128u16 blend3D(const v128u32 &colA_Lo, const v128u32 &colA_Hi, const v128u16 &colB) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 blend3D(const v128u32 &colA, const v128u32 &colB) const;
FORCEINLINE v128u16 increase(const v128u16 &col, const v128u16 &blendEVY) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 increase(const v128u32 &col, const v128u16 &blendEVY) const;
FORCEINLINE v128u16 decrease(const v128u16 &col, const v128u16 &blendEVY) const;
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 decrease(const v128u32 &col, const v128u16 &blendEVY) const;
};
class PixelOperation_NEON
{
protected:
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
FORCEINLINE void _unknownEffectMask16(GPUEngineCompositorInfo &compInfo,
const v128u8 &passMask8,
const v128u16 &evy16,
const v128u8 &srcLayerID,
const v128u16 &src1, const v128u16 &src0,
const v128u8 &srcEffectEnableMask,
const v128u8 &dstBlendEnableMaskLUT,
const v128u8 &enableColorEffectMask,
const v128u8 &spriteAlpha,
const v128u8 &spriteMode) const;
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
FORCEINLINE void _unknownEffectMask32(GPUEngineCompositorInfo &compInfo,
const v128u8 &passMask8,
const v128u16 &evy16,
const v128u8 &srcLayerID,
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
const v128u8 &srcEffectEnableMask,
const v128u8 &dstBlendEnableMaskLUT,
const v128u8 &enableColorEffectMask,
const v128u8 &spriteAlpha,
const v128u8 &spriteMode) const;
public:
PixelOperation_NEON() {};
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo,
const bool didAllPixelsPass,
const v128u8 &passMask8,
const v128u16 &evy16,
const v128u8 &srcLayerID,
const v128u16 &src1, const v128u16 &src0,
const v128u8 &srcEffectEnableMask,
const v128u8 &dstBlendEnableMaskLUT,
const u8 *__restrict enableColorEffectPtr,
const u8 *__restrict sprAlphaPtr,
const u8 *__restrict sprModePtr) const;
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo,
const bool didAllPixelsPass,
const v128u8 &passMask8,
const v128u16 &evy16,
const v128u8 &srcLayerID,
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
const v128u8 &srcEffectEnableMask,
const v128u8 &dstBlendEnableMaskLUT,
const u8 *__restrict enableColorEffectPtr,
const u8 *__restrict sprAlphaPtr,
const u8 *__restrict sprModePtr) const;
};
#endif // ENABLE_NEON_A64
#endif // GPU_OPERATIONS_NEON_H

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2021-2022 DeSmuME team
Copyright (C) 2021-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -279,6 +279,378 @@ static FORCEINLINE void CopyLineExpand(void *__restrict dst, const void *__restr
}
}
#ifdef ENABLE_SSSE3
else if (INTEGERSCALEHINT == 5)
{
__m128i srcPixOut[5];
for (size_t srcX = 0, dstX = 0; srcX < GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE); srcX++, dstX+=INTEGERSCALEHINT)
{
const __m128i srcVec = _mm_load_si128((__m128i *)src + srcX);
if (ELEMENTSIZE == 1)
{
srcPixOut[0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3));
srcPixOut[1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6));
srcPixOut[2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9));
srcPixOut[3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 9, 9,10,10,10,10,10,11,11,11,11,11,12,12,12,12));
srcPixOut[4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,13,13,13,13,13,14,14,14,14,14,15,15,15,15,15));
}
else if (ELEMENTSIZE == 2)
{
srcPixOut[0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3));
srcPixOut[1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 3, 2, 3, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 6, 7));
srcPixOut[2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 7, 6, 7, 6, 7, 6, 7, 8, 9, 8, 9, 8, 9, 8, 9));
srcPixOut[3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 9,10,11,10,11,10,11,10,11,10,11,12,13,12,13));
srcPixOut[4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,13,12,13,12,13,14,15,14,15,14,15,14,15,14,15));
}
else if (ELEMENTSIZE == 4)
{
srcPixOut[0] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[1] = _mm_shuffle_epi32(srcVec, 0x54);
srcPixOut[2] = _mm_shuffle_epi32(srcVec, 0xA5);
srcPixOut[3] = _mm_shuffle_epi32(srcVec, 0xEA);
srcPixOut[4] = _mm_shuffle_epi32(srcVec, 0xFF);
}
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + lx, srcPixOut[lx]);
}
if (SCALEVERTICAL)
{
for (size_t ly = 1; ly < (size_t)INTEGERSCALEHINT; ly++)
{
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + ((GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE) * INTEGERSCALEHINT) * ly) + lx, srcPixOut[lx]);
}
}
}
}
}
else if (INTEGERSCALEHINT == 6)
{
__m128i srcPixOut[6];
for (size_t srcX = 0, dstX = 0; srcX < GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE); srcX++, dstX+=INTEGERSCALEHINT)
{
const __m128i srcVec = _mm_load_si128((__m128i *)src + srcX);
if (ELEMENTSIZE == 1)
{
srcPixOut[0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2));
srcPixOut[1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5));
srcPixOut[2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7));
srcPixOut[3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9,10,10,10,10));
srcPixOut[4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,10,11,11,11,11,11,11,12,12,12,12,12,12,13,13));
srcPixOut[5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(13,13,13,13,14,14,14,14,14,14,15,15,15,15,15,15));
}
else if (ELEMENTSIZE == 2)
{
srcPixOut[0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3));
srcPixOut[1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 3, 2, 3, 2, 3, 2, 3, 4, 5, 4, 5, 4, 5, 4, 5));
srcPixOut[2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7));
srcPixOut[3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9,10,11,10,11));
srcPixOut[4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,11,10,11,10,11,10,11,12,13,12,13,12,13,12,13));
srcPixOut[5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,13,12,13,14,15,14,15,14,15,14,15,14,15,14,15));
}
else if (ELEMENTSIZE == 4)
{
srcPixOut[0] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[1] = _mm_shuffle_epi32(srcVec, 0x50);
srcPixOut[2] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[3] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[4] = _mm_shuffle_epi32(srcVec, 0xFA);
srcPixOut[5] = _mm_shuffle_epi32(srcVec, 0xFF);
}
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + lx, srcPixOut[lx]);
}
if (SCALEVERTICAL)
{
for (size_t ly = 1; ly < (size_t)INTEGERSCALEHINT; ly++)
{
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + ((GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE) * INTEGERSCALEHINT) * ly) + lx, srcPixOut[lx]);
}
}
}
}
}
else if (INTEGERSCALEHINT == 7)
{
__m128i srcPixOut[7];
for (size_t srcX = 0, dstX = 0; srcX < GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE); srcX++, dstX+=INTEGERSCALEHINT)
{
const __m128i srcVec = _mm_load_si128((__m128i *)src + srcX);
if (ELEMENTSIZE == 1)
{
srcPixOut[0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2));
srcPixOut[1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4));
srcPixOut[2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6));
srcPixOut[3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9));
srcPixOut[4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,11,11,11));
srcPixOut[5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(11,11,11,11,12,12,12,12,12,12,12,13,13,13,13,13));
srcPixOut[6] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(13,13,14,14,14,14,14,14,14,15,15,15,15,15,15,15));
}
else if (ELEMENTSIZE == 2)
{
srcPixOut[0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3));
srcPixOut[1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 4, 5, 4, 5));
srcPixOut[2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7));
srcPixOut[3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 7, 6, 7, 6, 7, 6, 7, 8, 9, 8, 9, 8, 9, 8, 9));
srcPixOut[4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 9, 8, 9, 8, 9,10,11,10,11,10,11,10,11,10,11));
srcPixOut[5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,11,10,11,12,13,12,13,12,13,12,13,12,13,12,13));
srcPixOut[6] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,13,14,15,14,15,14,15,14,15,14,15,14,15,14,15));
}
else if (ELEMENTSIZE == 4)
{
srcPixOut[0] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[1] = _mm_shuffle_epi32(srcVec, 0x40);
srcPixOut[2] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[3] = _mm_shuffle_epi32(srcVec, 0xA5);
srcPixOut[4] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[5] = _mm_shuffle_epi32(srcVec, 0xFE);
srcPixOut[6] = _mm_shuffle_epi32(srcVec, 0xFF);
}
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + lx, srcPixOut[lx]);
}
if (SCALEVERTICAL)
{
for (size_t ly = 1; ly < (size_t)INTEGERSCALEHINT; ly++)
{
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + ((GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE) * INTEGERSCALEHINT) * ly) + lx, srcPixOut[lx]);
}
}
}
}
}
else if (INTEGERSCALEHINT == 8)
{
__m128i srcPixOut[8];
for (size_t srcX = 0, dstX = 0; srcX < GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE); srcX++, dstX+=INTEGERSCALEHINT)
{
const __m128i srcVec = _mm_load_si128((__m128i *)src + srcX);
if (ELEMENTSIZE == 1)
{
srcPixOut[0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1));
srcPixOut[1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3));
srcPixOut[2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5));
srcPixOut[3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7));
srcPixOut[4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9));
srcPixOut[5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11));
srcPixOut[6] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13));
srcPixOut[7] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15));
}
else if (ELEMENTSIZE == 2)
{
srcPixOut[0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1));
srcPixOut[1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3));
srcPixOut[2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5));
srcPixOut[3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7));
srcPixOut[4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9));
srcPixOut[5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11));
srcPixOut[6] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13));
srcPixOut[7] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15));
}
else if (ELEMENTSIZE == 4)
{
srcPixOut[0] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[1] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[2] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[3] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[4] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[5] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[6] = _mm_shuffle_epi32(srcVec, 0xFF);
srcPixOut[7] = _mm_shuffle_epi32(srcVec, 0xFF);
}
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + lx, srcPixOut[lx]);
}
if (SCALEVERTICAL)
{
for (size_t ly = 1; ly < (size_t)INTEGERSCALEHINT; ly++)
{
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + ((GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE) * INTEGERSCALEHINT) * ly) + lx, srcPixOut[lx]);
}
}
}
}
}
else if (INTEGERSCALEHINT == 12)
{
__m128i srcPixOut[12];
for (size_t srcX = 0, dstX = 0; srcX < GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE); srcX++, dstX+=INTEGERSCALEHINT)
{
const __m128i srcVec = _mm_load_si128((__m128i *)src + srcX);
if (ELEMENTSIZE == 1)
{
srcPixOut[ 0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1));
srcPixOut[ 1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2));
srcPixOut[ 2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3));
srcPixOut[ 3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5));
srcPixOut[ 4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6));
srcPixOut[ 5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7));
srcPixOut[ 6] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9));
srcPixOut[ 7] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10));
srcPixOut[ 8] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11));
srcPixOut[ 9] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13));
srcPixOut[10] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14));
srcPixOut[11] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15));
}
else if (ELEMENTSIZE == 2)
{
srcPixOut[ 0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1));
srcPixOut[ 1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3));
srcPixOut[ 2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3));
srcPixOut[ 3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5));
srcPixOut[ 4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7));
srcPixOut[ 5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7));
srcPixOut[ 6] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9));
srcPixOut[ 7] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 9, 8, 9, 8, 9, 8, 9,10,11,10,11,10,11,10,11));
srcPixOut[ 8] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11));
srcPixOut[ 9] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13));
srcPixOut[10] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,13,12,13,12,13,12,13,14,15,14,15,14,15,14,15));
srcPixOut[11] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15));
}
else if (ELEMENTSIZE == 4)
{
srcPixOut[ 0] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[ 1] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[ 2] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[ 3] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[ 4] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[ 5] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[ 6] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[ 7] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[ 8] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[ 9] = _mm_shuffle_epi32(srcVec, 0xFF);
srcPixOut[10] = _mm_shuffle_epi32(srcVec, 0xFF);
srcPixOut[11] = _mm_shuffle_epi32(srcVec, 0xFF);
}
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + lx, srcPixOut[lx]);
}
if (SCALEVERTICAL)
{
for (size_t ly = 1; ly < (size_t)INTEGERSCALEHINT; ly++)
{
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + ((GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE) * INTEGERSCALEHINT) * ly) + lx, srcPixOut[lx]);
}
}
}
}
}
else if (INTEGERSCALEHINT == 16)
{
__m128i srcPixOut[16];
for (size_t srcX = 0, dstX = 0; srcX < GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE); srcX++, dstX+=INTEGERSCALEHINT)
{
const __m128i srcVec = _mm_load_si128((__m128i *)src + srcX);
if (ELEMENTSIZE == 1)
{
srcPixOut[ 0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
srcPixOut[ 1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
srcPixOut[ 2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2));
srcPixOut[ 3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3));
srcPixOut[ 4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4));
srcPixOut[ 5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5));
srcPixOut[ 6] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6));
srcPixOut[ 7] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7));
srcPixOut[ 8] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8));
srcPixOut[ 9] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9));
srcPixOut[10] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10));
srcPixOut[11] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11));
srcPixOut[12] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12));
srcPixOut[13] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13));
srcPixOut[14] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14));
srcPixOut[15] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15));
}
else if (ELEMENTSIZE == 2)
{
srcPixOut[ 0] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1));
srcPixOut[ 1] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1));
srcPixOut[ 2] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3));
srcPixOut[ 3] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3));
srcPixOut[ 4] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5));
srcPixOut[ 5] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5));
srcPixOut[ 6] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7));
srcPixOut[ 7] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7));
srcPixOut[ 8] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9));
srcPixOut[ 9] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8( 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9));
srcPixOut[10] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11));
srcPixOut[11] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11));
srcPixOut[12] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13));
srcPixOut[13] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(12,13,12,13,12,13,12,13,12,13,12,13,12,13,12,13));
srcPixOut[14] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15));
srcPixOut[15] = _mm_shuffle_epi8(srcVec, _mm_setr_epi8(14,15,14,15,14,15,14,15,14,15,14,15,14,15,14,15));
}
else if (ELEMENTSIZE == 4)
{
srcPixOut[ 0] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[ 1] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[ 2] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[ 3] = _mm_shuffle_epi32(srcVec, 0x00);
srcPixOut[ 4] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[ 5] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[ 6] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[ 7] = _mm_shuffle_epi32(srcVec, 0x55);
srcPixOut[ 8] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[ 9] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[10] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[11] = _mm_shuffle_epi32(srcVec, 0xAA);
srcPixOut[12] = _mm_shuffle_epi32(srcVec, 0xFF);
srcPixOut[13] = _mm_shuffle_epi32(srcVec, 0xFF);
srcPixOut[14] = _mm_shuffle_epi32(srcVec, 0xFF);
srcPixOut[15] = _mm_shuffle_epi32(srcVec, 0xFF);
}
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + lx, srcPixOut[lx]);
}
if (SCALEVERTICAL)
{
for (size_t ly = 1; ly < (size_t)INTEGERSCALEHINT; ly++)
{
for (size_t lx = 0; lx < (size_t)INTEGERSCALEHINT; lx++)
{
_mm_store_si128((__m128i *)dst + dstX + ((GPU_FRAMEBUFFER_NATIVE_WIDTH / (sizeof(__m128i) / ELEMENTSIZE) * INTEGERSCALEHINT) * ly) + lx, srcPixOut[lx]);
}
}
}
}
}
else if (INTEGERSCALEHINT > 1)
{
const size_t scale = dstWidth / GPU_FRAMEBUFFER_NATIVE_WIDTH;
@ -737,6 +1109,36 @@ FORCEINLINE v128u16 ColorOperation_SSE2::blend3D(const v128u32 &colA_Lo, const v
{
// If the color format of B is 555, then the colA_Hi parameter is required.
// The color format of A is assumed to be RGB666.
#ifdef ENABLE_SSSE3
static const u8 X = 0x80;
const v128u32 ra_lo = _mm_shuffle_epi8( colA_Lo, _mm_set_epi8( X, X, X,12, X, X, X, 8, X, X, X, 4, X, X, X, 0) );
const v128u32 ga_lo = _mm_shuffle_epi8( colA_Lo, _mm_set_epi8( X, X, X,13, X, X, X, 9, X, X, X, 5, X, X, X, 1) );
const v128u32 ba_lo = _mm_shuffle_epi8( colA_Lo, _mm_set_epi8( X, X, X,14, X, X, X,10, X, X, X, 6, X, X, X, 2) );
const v128u32 aa_lo = _mm_shuffle_epi8( colA_Lo, _mm_set_epi8( X, X, X,15, X, X, X,11, X, X, X, 7, X, X, X, 3) );
const v128u32 ra_hi = _mm_shuffle_epi8( colA_Hi, _mm_set_epi8( X, X, X,12, X, X, X, 8, X, X, X, 4, X, X, X, 0) );
const v128u32 ga_hi = _mm_shuffle_epi8( colA_Hi, _mm_set_epi8( X, X, X,13, X, X, X, 9, X, X, X, 5, X, X, X, 1) );
const v128u32 ba_hi = _mm_shuffle_epi8( colA_Hi, _mm_set_epi8( X, X, X,14, X, X, X,10, X, X, X, 6, X, X, X, 2) );
const v128u32 aa_hi = _mm_shuffle_epi8( colA_Hi, _mm_set_epi8( X, X, X,15, X, X, X,11, X, X, X, 7, X, X, X, 3) );
v128u16 ra = _mm_packs_epi32(ra_lo, ra_hi);
v128u16 ga = _mm_packs_epi32(ga_lo, ga_hi);
v128u16 ba = _mm_packs_epi32(ba_lo, ba_hi);
v128u16 aa = _mm_packs_epi32(aa_lo, aa_hi);
ra = _mm_or_si128( ra, _mm_and_si128(_mm_slli_epi16(colB, 9), _mm_set1_epi16(0x3E00)) );
ga = _mm_or_si128( ga, _mm_and_si128(_mm_slli_epi16(colB, 4), _mm_set1_epi16(0x3E00)) );
ba = _mm_or_si128( ba, _mm_and_si128(_mm_srli_epi16(colB, 1), _mm_set1_epi16(0x3E00)) );
aa = _mm_adds_epu8(aa, _mm_set1_epi16(1));
aa = _mm_or_si128( aa, _mm_slli_epi16(_mm_subs_epu16(_mm_set1_epi8(32), aa), 8) );
ra = _mm_maddubs_epi16(ra, aa);
ga = _mm_maddubs_epi16(ga, aa);
ba = _mm_maddubs_epi16(ba, aa);
#else
v128u32 ra_lo = _mm_and_si128( colA_Lo, _mm_set1_epi32(0x000000FF) );
v128u32 ga_lo = _mm_and_si128( _mm_srli_epi32(colA_Lo, 8), _mm_set1_epi32(0x000000FF) );
v128u32 ba_lo = _mm_and_si128( _mm_srli_epi32(colA_Lo, 16), _mm_set1_epi32(0x000000FF) );
@ -752,18 +1154,6 @@ FORCEINLINE v128u16 ColorOperation_SSE2::blend3D(const v128u32 &colA_Lo, const v
v128u16 ba = _mm_packs_epi32(ba_lo, ba_hi);
v128u16 aa = _mm_packs_epi32(aa_lo, aa_hi);
#ifdef ENABLE_SSSE3
ra = _mm_or_si128( ra, _mm_and_si128(_mm_slli_epi16(colB, 9), _mm_set1_epi16(0x3E00)) );
ga = _mm_or_si128( ga, _mm_and_si128(_mm_slli_epi16(colB, 4), _mm_set1_epi16(0x3E00)) );
ba = _mm_or_si128( ba, _mm_and_si128(_mm_srli_epi16(colB, 1), _mm_set1_epi16(0x3E00)) );
aa = _mm_adds_epu8(aa, _mm_set1_epi16(1));
aa = _mm_or_si128( aa, _mm_slli_epi16(_mm_subs_epu16(_mm_set1_epi8(32), aa), 8) );
ra = _mm_maddubs_epi16(ra, aa);
ga = _mm_maddubs_epi16(ga, aa);
ba = _mm_maddubs_epi16(ba, aa);
#else
aa = _mm_adds_epu16(aa, _mm_set1_epi16(1));
v128u16 rb = _mm_and_si128( _mm_slli_epi16(colB, 1), _mm_set1_epi16(0x003E) );
v128u16 gb = _mm_and_si128( _mm_srli_epi16(colB, 4), _mm_set1_epi16(0x003E) );
@ -785,6 +1175,9 @@ FORCEINLINE v128u16 ColorOperation_SSE2::blend3D(const v128u32 &colA_Lo, const v
template <NDSColorFormat COLORFORMAT>
FORCEINLINE v128u32 ColorOperation_SSE2::blend3D(const v128u32 &colA, const v128u32 &colB) const
{
#ifdef ENABLE_SSSE3
static const u8 X = 0x80;
#endif
// If the color format of B is 666 or 888, then the colA_Hi parameter is ignored.
// The color format of A is assumed to match the color format of B.
v128u16 rgbALo;
@ -804,13 +1197,12 @@ FORCEINLINE v128u32 ColorOperation_SSE2::blend3D(const v128u32 &colA, const v128
rgbALo = _mm_unpacklo_epi8(colA, colB);
rgbAHi = _mm_unpackhi_epi8(colA, colB);
v128u32 alpha = _mm_and_si128( _mm_srli_epi32(colA, 24), _mm_set1_epi32(0x0000001F) );
alpha = _mm_or_si128( alpha, _mm_or_si128(_mm_slli_epi32(alpha, 8), _mm_slli_epi32(alpha, 16)) );
v128u8 alpha = _mm_shuffle_epi8( colA, _mm_set_epi8( X,15,15,15, X,11,11,11, X, 7, 7, 7, X, 3, 3, 3) );
alpha = _mm_adds_epu8(alpha, _mm_set1_epi8(1));
v128u32 invAlpha = _mm_subs_epu8(_mm_set1_epi8(32), alpha);
v128u16 alphaLo = _mm_unpacklo_epi8(alpha, invAlpha);
v128u16 alphaHi = _mm_unpackhi_epi8(alpha, invAlpha);
const v128u8 invAlpha = _mm_subs_epu8(_mm_set1_epi8(32), alpha);
const v128u16 alphaLo = _mm_unpacklo_epi8(alpha, invAlpha);
const v128u16 alphaHi = _mm_unpackhi_epi8(alpha, invAlpha);
rgbALo = _mm_maddubs_epi16(rgbALo, alphaLo);
rgbAHi = _mm_maddubs_epi16(rgbAHi, alphaHi);
@ -823,9 +1215,12 @@ FORCEINLINE v128u32 ColorOperation_SSE2::blend3D(const v128u32 &colA, const v128
v128u16 rgbBLo = _mm_unpacklo_epi8(colB, _mm_setzero_si128());
v128u16 rgbBHi = _mm_unpackhi_epi8(colB, _mm_setzero_si128());
v128u32 alpha = _mm_and_si128( _mm_srli_epi32(colA, 24), _mm_set1_epi32(0x000000FF) );
#ifdef ENABLE_SSSE3
v128u8 alpha = _mm_shuffle_epi8( colA, _mm_set_epi8( X,15,15,15, X,11,11,11, X, 7, 7, 7, X, 3, 3, 3) );
#else
v128u8 alpha = _mm_and_si128( _mm_srli_epi32(colA, 24), _mm_set1_epi32(0x000000FF) );
alpha = _mm_or_si128( alpha, _mm_or_si128(_mm_slli_epi32(alpha, 8), _mm_slli_epi32(alpha, 16)) );
#endif
v128u16 alphaLo = _mm_unpacklo_epi8(alpha, _mm_setzero_si128());
v128u16 alphaHi = _mm_unpackhi_epi8(alpha, _mm_setzero_si128());
alphaLo = _mm_add_epi16(alphaLo, _mm_set1_epi16(1));
@ -922,13 +1317,13 @@ FORCEINLINE void PixelOperation_SSE2::_copy16(GPUEngineCompositorInfo &compInfo,
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555To6665Opaque_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555To6665Opaque_SSE2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo6665Opaque_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo6665Opaque_SSE2<false>(src1, src32[2], src32[3]);
}
else
{
ColorspaceConvert555To8888Opaque_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555To8888Opaque_SSE2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo8888Opaque_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo8888Opaque_SSE2<false>(src1, src32[2], src32[3]);
}
_mm_store_si128( (v128u32 *)compInfo.target.lineColor32 + 0, src32[0] );
@ -999,20 +1394,20 @@ FORCEINLINE void PixelOperation_SSE2::_copyMask16(GPUEngineCompositorInfo &compI
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555To6665Opaque_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555To6665Opaque_SSE2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo6665Opaque_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo6665Opaque_SSE2<false>(src1, src32[2], src32[3]);
}
else
{
ColorspaceConvert555To8888Opaque_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555To8888Opaque_SSE2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo8888Opaque_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo8888Opaque_SSE2<false>(src1, src32[2], src32[3]);
}
const v128u32 dst32[4] = {
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 0),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 1),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 2),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3)
};
const v128u32 passMask32[4] = {
@ -1072,7 +1467,7 @@ FORCEINLINE void PixelOperation_SSE2::_copyMask32(GPUEngineCompositorInfo &compI
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 0),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 1),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 2),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3)
};
const v128u32 alphaBits = _mm_set1_epi32((OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F000000 : 0xFF000000);
@ -1104,13 +1499,13 @@ FORCEINLINE void PixelOperation_SSE2::_brightnessUp16(GPUEngineCompositorInfo &c
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_SSE2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555XTo666X_SSE2<false>(src1, dst[2], dst[3]);
ColorspaceConvert555xTo666x_SSE2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555xTo666x_SSE2<false>(src1, dst[2], dst[3]);
}
else
{
ColorspaceConvert555XTo888X_SSE2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555XTo888X_SSE2<false>(src1, dst[2], dst[3]);
ColorspaceConvert555xTo888x_SSE2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555xTo888x_SSE2<false>(src1, dst[2], dst[3]);
}
const v128u32 alphaBits = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? _mm_set1_epi32(0x1F000000) : _mm_set1_epi32(0xFF000000);
@ -1182,20 +1577,20 @@ FORCEINLINE void PixelOperation_SSE2::_brightnessUpMask16(GPUEngineCompositorInf
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555XTo666X_SSE2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo666x_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo666x_SSE2<false>(src1, src32[2], src32[3]);
}
else
{
ColorspaceConvert555XTo888X_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555XTo888X_SSE2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo888x_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo888x_SSE2<false>(src1, src32[2], src32[3]);
}
const v128u32 dst32[4] = {
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 0),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 1),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 2),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3)
};
const v128u32 alphaBits = _mm_set1_epi32((OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F000000 : 0xFF000000);
@ -1246,7 +1641,7 @@ FORCEINLINE void PixelOperation_SSE2::_brightnessUpMask32(GPUEngineCompositorInf
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 0),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 1),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 2),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3)
};
const v128u32 alphaBits = _mm_set1_epi32((OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F000000 : 0xFF000000);
@ -1275,13 +1670,13 @@ FORCEINLINE void PixelOperation_SSE2::_brightnessDown16(GPUEngineCompositorInfo
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_SSE2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555XTo666X_SSE2<false>(src1, dst[2], dst[3]);
ColorspaceConvert555xTo666x_SSE2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555xTo666x_SSE2<false>(src1, dst[2], dst[3]);
}
else
{
ColorspaceConvert555XTo888X_SSE2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555XTo888X_SSE2<false>(src1, dst[2], dst[3]);
ColorspaceConvert555xTo888x_SSE2<false>(src0, dst[0], dst[1]);
ColorspaceConvert555xTo888x_SSE2<false>(src1, dst[2], dst[3]);
}
const v128u32 alphaBits = (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? _mm_set1_epi32(0x1F000000) : _mm_set1_epi32(0xFF000000);
@ -1353,20 +1748,20 @@ FORCEINLINE void PixelOperation_SSE2::_brightnessDownMask16(GPUEngineCompositorI
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555XTo666X_SSE2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo666x_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo666x_SSE2<false>(src1, src32[2], src32[3]);
}
else
{
ColorspaceConvert555XTo888X_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555XTo888X_SSE2<false>(src1, src32[2], src32[3]);
ColorspaceConvert555xTo888x_SSE2<false>(src0, src32[0], src32[1]);
ColorspaceConvert555xTo888x_SSE2<false>(src1, src32[2], src32[3]);
}
const v128u32 dst32[4] = {
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 0),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 1),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 2),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3)
};
const v128u32 alphaBits = _mm_set1_epi32((OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F000000 : 0xFF000000);
@ -1417,7 +1812,7 @@ FORCEINLINE void PixelOperation_SSE2::_brightnessDownMask32(GPUEngineCompositorI
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 0),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 1),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 2),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3)
};
const v128u32 alphaBits = _mm_set1_epi32((OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) ? 0x1F000000 : 0xFF000000);
@ -1494,13 +1889,13 @@ FORCEINLINE void PixelOperation_SSE2::_unknownEffectMask16(GPUEngineCompositorIn
}
else if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
{
ColorspaceConvert555XTo666X_SSE2<false>(src0, tmpSrc[0], tmpSrc[1]);
ColorspaceConvert555XTo666X_SSE2<false>(src1, tmpSrc[2], tmpSrc[3]);
ColorspaceConvert555xTo666x_SSE2<false>(src0, tmpSrc[0], tmpSrc[1]);
ColorspaceConvert555xTo666x_SSE2<false>(src1, tmpSrc[2], tmpSrc[3]);
}
else
{
ColorspaceConvert555XTo888X_SSE2<false>(src0, tmpSrc[0], tmpSrc[1]);
ColorspaceConvert555XTo888X_SSE2<false>(src1, tmpSrc[2], tmpSrc[3]);
ColorspaceConvert555xTo888x_SSE2<false>(src0, tmpSrc[0], tmpSrc[1]);
ColorspaceConvert555xTo888x_SSE2<false>(src1, tmpSrc[2], tmpSrc[3]);
}
switch (compInfo.renderState.colorEffect)
@ -1656,7 +2051,7 @@ FORCEINLINE void PixelOperation_SSE2::_unknownEffectMask16(GPUEngineCompositorIn
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 0),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 1),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 2),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3)
};
if (blendMaskValue != 0x00000000)
@ -1965,7 +2360,7 @@ FORCEINLINE void PixelOperation_SSE2::_unknownEffectMask32(GPUEngineCompositorIn
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 0),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 1),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 2),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3),
_mm_load_si128((v128u32 *)compInfo.target.lineColor32 + 3)
};
if (blendMaskValue != 0x00000000)
@ -2287,7 +2682,7 @@ void GPUEngineBase::_MosaicLine(GPUEngineCompositorInfo &compInfo)
}
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST>
void GPUEngineBase::_CompositeNativeLineOBJ_LoopOp(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const FragmentColor *__restrict srcColorNative32)
void GPUEngineBase::_CompositeNativeLineOBJ_LoopOp(GPUEngineCompositorInfo &compInfo, const u16 *__restrict srcColorNative16, const Color4u8 *__restrict srcColorNative32)
{
static const size_t step = sizeof(v128u8);
@ -2530,10 +2925,10 @@ size_t GPUEngineBase::_CompositeVRAMLineDeferred_LoopOp(GPUEngineCompositorInfo
case NDSColorFormat_BGR888_Rev:
{
const v128u32 src32[4] = {
_mm_load_si128((v128u32 *)((FragmentColor *)vramColorPtr + i) + 0),
_mm_load_si128((v128u32 *)((FragmentColor *)vramColorPtr + i) + 1),
_mm_load_si128((v128u32 *)((FragmentColor *)vramColorPtr + i) + 2),
_mm_load_si128((v128u32 *)((FragmentColor *)vramColorPtr + i) + 3)
_mm_load_si128((v128u32 *)((Color4u8 *)vramColorPtr + i) + 0),
_mm_load_si128((v128u32 *)((Color4u8 *)vramColorPtr + i) + 1),
_mm_load_si128((v128u32 *)((Color4u8 *)vramColorPtr + i) + 2),
_mm_load_si128((v128u32 *)((Color4u8 *)vramColorPtr + i) + 3)
};
if (LAYERTYPE != GPULayerType_OBJ)
@ -2688,7 +3083,7 @@ void GPUEngineBase::_PerformWindowTestingNative(GPUEngineCompositorInfo &compInf
}
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST>
size_t GPUEngineA::_RenderLine_Layer3D_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const FragmentColor *__restrict srcLinePtr)
size_t GPUEngineA::_RenderLine_Layer3D_LoopOp(GPUEngineCompositorInfo &compInfo, const u8 *__restrict windowTestPtr, const u8 *__restrict colorEffectEnablePtr, const Color4u8 *__restrict srcLinePtr)
{
static const size_t step = sizeof(v128u8);

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2007 shash
Copyright (C) 2007-2022 DeSmuME team
Copyright (C) 2007-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1068,7 +1068,6 @@ static void execsqrt() {
}
static void execdiv() {
s64 num,den;
s64 res,mod;
u8 mode = MMU_new.div.mode;
@ -1096,15 +1095,29 @@ static void execdiv() {
break;
}
if(den==0)
if(den == 0)
{
res = ((num < 0) ? 1 : -1);
mod = num;
// when the result is 32bits, the upper 32bits of the sign-extended result are inverted
if (mode == 0)
res ^= 0xFFFFFFFF00000000LL;
// the DIV0 flag in DIVCNT is set only if the full 64bit DIV_DENOM value is zero, even in 32bit mode
if ((u64)T1ReadQuad(MMU.ARM9_REG, 0x298) == 0)
MMU_new.div.div0 = 1;
}
else if((mode != 0) && (num == 0x8000000000000000LL) && (den == -1))
{
res = 0x8000000000000000LL;
mod = 0;
}
else if((mode == 0) && (num == (s64) (s32) 0x80000000) && (den == -1))
{
res = 0x80000000;
mod = 0;
}
else
{
res = num / den;
@ -1816,44 +1829,46 @@ static void writereg_POWCNT1(const int size, const u32 adr, const u32 val)
bool isGeomEnabled = !!nds.power1.gfx3d_geometry;
if(wasGeomEnabled && !isGeomEnabled)
{
//kill the geometry data when the power goes off
//but save these tables, first. they shouldnt be cleared.
//so, so bad. we need to model this with hardware-like operations instead of c++ code
GFX3D_State prior = gfx3d.state;
reconstruct(&gfx3d.state);
memcpy(gfx3d.state.u16ToonTable, prior.u16ToonTable, sizeof(prior.u16ToonTable));
//dont think we should save this one: it's sent with 3d commands, not random bonus immediate register writes like the toon table
//memcpy(gfx3d.state.shininessTable, prior.shininessTable, sizeof(prior.shininessTable));
GFX3D_HandleGeometryPowerOff();
}
}
static INLINE void MMU_IPCSync(u8 proc, u32 val)
{
//INFO("IPC%s sync 0x%04X (0x%02X|%02X)\n", proc?"7":"9", val, val >> 8, val & 0xFF);
u32 sync_l = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x180) & 0xFFFF;
u32 sync_r = T1ReadLong(MMU.MMU_MEM[proc^1][0x40], 0x180) & 0xFFFF;
u32 iter = (val & 0x0F00) >> 8;
sync_l = ( sync_l & 0x000F ) | ( val & 0x0F00 );
sync_r = ( sync_r & 0x6F00 ) | ( (val >> 8) & 0x000F );
sync_l = ( sync_l & 0x000F ) | ( val & 0x6F00 );
sync_r = ( sync_r & 0x6F00 ) | ( iter );
sync_l |= val & 0x6000;
// For some reason, the arm9 doesn't handshake when ensata is detected.
// So we complete the protocol here, which is to mirror the values 8..0 back to
// The arm7 as they are written by the arm7
if (nds.ensataEmulation) {
if(nds.ensataEmulation && proc==1 && nds.ensataIpcSyncCounter<9) {
u32 iteration = (val&0x0F00)>>8;
if(iteration==8-nds.ensataIpcSyncCounter)
nds.ensataIpcSyncCounter++;
else printf("ERROR: ENSATA IPC SYNC HACK FAILED; BAD THINGS MAY HAPPEN\n");
//for some reason, the arm9 doesn't handshake when ensata is detected.
//so we complete the protocol here, which is to mirror the values 8..0 back to
//the arm7 as they are written by the arm7
sync_r &= 0xF0FF;
sync_r |= (iteration<<8);
sync_l &= 0xFFF0;
sync_l |= iteration;
if (proc) {
// However this hack would break soft reset because it also syncs through ipcsync.
// So we have to add some additional checks to ensure that it's handshake instead of reset.
if ((iter & 8) || (nds.ensataIpcSyncCounter)) {
// sync_r = (sync_r & 0xF0FF) | (iter << 8); // This is not necessary.
sync_l = (sync_l & 0xFFF0) | iter;
nds.ensataIpcSyncCounter = iter;
}
}
else {
// After ensata handshake, arm9 will write 0x100 as a signal if Ensata is detected.
// This will prevent reset from working, so we have to ignore this.
if (nds.ensataHandshake == ENSATA_HANDSHAKE_complete) {
nds.ensataHandshake = ENSATA_HANDSHAKE_none;
return;
}
}
}
// printf("IPCSync(%d, %04x): %04x %04x %d\n", proc, val, sync_l, sync_r, nds.ensataIpcSyncCounter);
T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x180, sync_l);
T1WriteLong(MMU.MMU_MEM[proc^1][0x40], 0x180, sync_r);
@ -1947,8 +1962,8 @@ u32 TGXSTAT::read32()
// stack position always equal zero. possible timings is wrong
// using in "The Wild West"
int proj_level = mtxStackIndex[MATRIXMODE_PROJECTION] & 1;
int mv_level = mtxStackIndex[MATRIXMODE_POSITION] & 31;
u32 proj_level = (u32)GFX3D_GetMatrixStackIndex(MATRIXMODE_PROJECTION);
u32 mv_level = (u32)GFX3D_GetMatrixStackIndex(MATRIXMODE_POSITION);
ret |= ((proj_level << 13) | (mv_level << 8));
ret |= sb<<14; //stack busy
@ -1959,7 +1974,7 @@ u32 TGXSTAT::read32()
if(gxFIFO.size==0) ret |= BIT(26); //fifo empty
//determine busy flag.
//if we're waiting for a flush, we're busy
if(isSwapBuffers) ret |= BIT(27);
if(GFX3D_IsSwapBuffersPending()) ret |= BIT(27);
//if fifo is nonempty, we're busy
if(gxFIFO.size!=0) ret |= BIT(27);
@ -1968,7 +1983,7 @@ u32 TGXSTAT::read32()
ret |= ((gxfifo_irq & 0x3) << 30); //user's irq flags
//printf("vc=%03d Returning gxstat read: %08X (isSwapBuffers=%d)\n",nds.VCount,ret,isSwapBuffers);
//printf("vc=%03d Returning gxstat read: %08X (isSwapBuffers=%d)\n", nds.VCount, ret, (GFX3D_IsSwapBuffersPending()) ? 1 : 0);
//ret = (2 << 8);
//INFO("gxSTAT 0x%08X (proj %i, pos %i)\n", ret, _hack_getMatrixStackLevel(1), _hack_getMatrixStackLevel(2));
@ -1983,7 +1998,7 @@ void TGXSTAT::write32(const u32 val)
// Writing "1" to Bit15 does reset the Error Flag (Bit15),
// and additionally resets the Projection Stack Pointer (Bit13)
// (and probably (?) also the Texture Stack Pointer)??
mtxStackIndex[MATRIXMODE_PROJECTION] = 0;
GFX3D_ResetMatrixStackPointer();
se = 0; //clear stack error flag
}
//printf("gxstat write: %08X while gxfifo.size=%d\n",val,gxFIFO.size);
@ -2462,7 +2477,17 @@ bool validateIORegsWrite(u32 addr, u8 size, u32 val)
{
if (PROCNUM == ARMCPU_ARM9)
{
switch (addr & 0x0FFFFFFC)
u32 addrMasked = addr & 0x0FFFFFFC;
if(nds.ensataEmulation)
{
if(addrMasked == eng_3D_CLIPMTX_RESULT) return true;
if(addrMasked == 0x04FFF000) return true;
if(addrMasked == 0x04FFF010) return true;
if(addrMasked == 0x04FFF200) return true;
}
switch (addrMasked)
{
// Display Engine A
case REG_DISPA_DISPCNT:
@ -3210,6 +3235,99 @@ bool validateIORegsRead(u32 addr, u8 size)
#define VALIDATE_IO_REGS_READ(PROC, SIZE) ;
#endif
template <typename T, size_t LENGTH>
bool MMU_WriteFromExternal(const int targetProc, const u32 targetAddress, T newValue)
{
u32 oldValue32;
switch (LENGTH)
{
case 1:
if (sizeof(T) > LENGTH)
newValue &= 0x000000FF;
break;
case 2:
if (sizeof(T) > LENGTH)
newValue &= 0x0000FFFF;
break;
case 3:
oldValue32 = _MMU_read32(targetProc, MMU_AT_DEBUG, targetAddress);
if (sizeof(T) > LENGTH)
newValue = (oldValue32 & 0xFF000000) | (newValue & 0x00FFFFFF);
break;
case 4:
oldValue32 = _MMU_read32(targetProc, MMU_AT_DEBUG, targetAddress);
if (sizeof(T) > LENGTH)
newValue &= 0xFFFFFFFF;
break;
default:
break;
}
bool needsJitReset = ( (targetAddress >= 0x02000000) && (targetAddress < 0x02400000) );
if (needsJitReset)
{
bool willValueChange = false;
switch (LENGTH)
{
case 1:
willValueChange = (_MMU_read08(targetProc, MMU_AT_DEBUG, targetAddress) != (u8)newValue);
break;
case 2:
willValueChange = (_MMU_read16(targetProc, MMU_AT_DEBUG, targetAddress) != (u16)newValue);
break;
case 3:
case 4:
willValueChange = (oldValue32 != (u32)newValue);
break;
default:
break;
}
if (!willValueChange)
{
needsJitReset = false;
return needsJitReset;
}
}
switch (LENGTH)
{
case 1:
_MMU_write08(targetProc, MMU_AT_DEBUG, targetAddress, (u8)newValue);
break;
case 2:
_MMU_write16(targetProc, MMU_AT_DEBUG, targetAddress, (u16)newValue);
break;
case 3:
case 4:
_MMU_write32(targetProc, MMU_AT_DEBUG, targetAddress, (u32)newValue);
break;
default:
break;
}
return needsJitReset;
}
template bool MMU_WriteFromExternal< u8, 1>(const int targetProc, const u32 targetAddress, u8 newValue);
template bool MMU_WriteFromExternal<u16, 2>(const int targetProc, const u32 targetAddress, u16 newValue);
template bool MMU_WriteFromExternal<u32, 1>(const int targetProc, const u32 targetAddress, u32 newValue);
template bool MMU_WriteFromExternal<u32, 2>(const int targetProc, const u32 targetAddress, u32 newValue);
template bool MMU_WriteFromExternal<u32, 3>(const int targetProc, const u32 targetAddress, u32 newValue);
template bool MMU_WriteFromExternal<u32, 4>(const int targetProc, const u32 targetAddress, u32 newValue);
//================================================================================================== ARM9 *
//=========================================================================================================
//=========================================================================================================
@ -3258,6 +3376,28 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
return;
}
switch (adr >> 4)
{
case 0x400033: // Edge Mark Color Table
MMU.ARM9_REG[adr & 0xFFF] = val;
gfx3d_UpdateEdgeMarkColorTable<u8>((u8)(adr & 0x0000000F), val);
return;
case 0x400036:
case 0x400037: // Fog Table
MMU.ARM9_REG[adr & 0xFFF] = val & 0x7F;
gfx3d_UpdateFogTable<u8>((u8)(adr & 0x0000001F), val & 0x7F); // Drop the highest bit of each 8-bit value to limit the range to [0...127]
return;
case 0x400038:
case 0x400039:
case 0x40003A:
case 0x40003B: // Toon Table
MMU.ARM9_REG[adr & 0xFFF] = val;
gfx3d_UpdateToonTable<u8>((u8)(adr & 0x0000003F), val);
return;
}
GPUEngineA *mainEngine = GPU->GetEngineMain();
GPUEngineB *subEngine = GPU->GetEngineSub();
@ -3425,7 +3565,19 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
return;
case REG_DISPA_DISPMMEMFIFO:
DISP_FIFOsend_u32(val);
DISP_FIFOsend<u8, 0>(val);
return;
case REG_DISPA_DISPMMEMFIFO+1:
DISP_FIFOsend<u8, 1>(val);
return;
case REG_DISPA_DISPMMEMFIFO+2:
DISP_FIFOsend<u8, 2>(val);
return;
case REG_DISPA_DISPMMEMFIFO+3:
DISP_FIFOsend<u8, 3>(val);
return;
case REG_DISPB_BG0HOFS:
@ -3590,18 +3742,6 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
case REG_DIVCNT+3: printf("ERROR 8bit DIVCNT+3 WRITE\n"); return;
#endif
//fog table: only write bottom 7 bits
case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x01: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x03:
case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x05: case eng_3D_FOG_TABLE+0x06: case eng_3D_FOG_TABLE+0x07:
case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x09: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0B:
case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0D: case eng_3D_FOG_TABLE+0x0E: case eng_3D_FOG_TABLE+0x0F:
case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x11: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x13:
case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x15: case eng_3D_FOG_TABLE+0x16: case eng_3D_FOG_TABLE+0x17:
case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x19: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1B:
case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1D: case eng_3D_FOG_TABLE+0x1E: case eng_3D_FOG_TABLE+0x1F:
val &= 0x7F;
break;
//ensata putchar port
case 0x04FFF000:
if(nds.ensataEmulation)
@ -3614,7 +3754,21 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
case eng_3D_GXSTAT:
MMU_new.gxstat.write(8,adr,val);
break;
case REG_IPCSYNC:
{
u16 ipcsync = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x180);
ipcsync &= 0xFF00;
ipcsync |= (val & 0xFF);
MMU_IPCSync(ARMCPU_ARM9, ipcsync);
}
case REG_IPCSYNC+1:
{
u16 ipcsync = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x180);
ipcsync &= 0x00FF;
ipcsync |= ((val & 0xFF) << 8);
MMU_IPCSync(ARMCPU_ARM9, ipcsync);
}
case REG_AUXSPICNT:
case REG_AUXSPICNT+1:
write_auxspicnt(ARMCPU_ARM9, 8, adr & 1, val);
@ -3636,10 +3790,45 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
case REG_IF+2: REG_IF_WriteByte<ARMCPU_ARM9>(2,val); break;
case REG_IF+3: REG_IF_WriteByte<ARMCPU_ARM9>(3,val); break;
case eng_3D_CLEAR_COLOR+0: case eng_3D_CLEAR_COLOR+1:
case eng_3D_CLEAR_COLOR+2: case eng_3D_CLEAR_COLOR+3:
T1WriteByte((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val);
break;
case eng_3D_CLEAR_COLOR:
T1WriteByte(MMU.ARM9_REG, 0x0350, val);
gfx3d_glClearColor<u8>(0, val);
return;
case eng_3D_CLEAR_COLOR+1:
T1WriteByte(MMU.ARM9_REG, 0x0351, val);
gfx3d_glClearColor<u8>(1, val);
return;
case eng_3D_CLEAR_COLOR+2:
T1WriteByte(MMU.ARM9_REG, 0x0352, val);
gfx3d_glClearColor<u8>(2, val);
return;
case eng_3D_CLEAR_COLOR+3:
T1WriteByte(MMU.ARM9_REG, 0x0353, val);
gfx3d_glClearColor<u8>(3, val);
return;
case eng_3D_CLEAR_DEPTH:
HostWriteByte(MMU.ARM9_REG, 0x0354, val);
gfx3d_glClearDepth<u8, 0>(val);
return;
case eng_3D_CLEAR_DEPTH+1:
HostWriteByte(MMU.ARM9_REG, 0x0355, val);
gfx3d_glClearDepth<u8, 1>(val);
return;
case eng_3D_CLRIMAGE_OFFSET:
HostWriteByte(MMU.ARM9_REG, 0x0356, val);
gfx3d_glClearImageOffset<u8, 0>(val);
return;
case eng_3D_CLRIMAGE_OFFSET+1:
HostWriteByte(MMU.ARM9_REG, 0x0357, val);
gfx3d_glClearImageOffset<u8, 1>(val);
return;
case REG_VRAMCNTA:
case REG_VRAMCNTB:
@ -3653,6 +3842,11 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
case REG_VRAMCNTI:
MMU_VRAMmapControl(adr-REG_VRAMCNTA, val);
break;
// ensata sound register
case 0x04FFF200:
break;
#ifdef LOG_CARD
case 0x040001A0 : /* TODO (clear): ??? */
@ -3736,13 +3930,23 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
switch (adr >> 4)
{
//toon table
case 0x0400038:
case 0x0400039:
case 0x040003A:
case 0x040003B:
((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF)>>1] = val;
gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val);
case 0x400033: // Edge Mark Color Table
((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u16) >> 1)] = val;
gfx3d_UpdateEdgeMarkColorTable<u16>((u8)(adr & 0x0000000F), val);
return;
case 0x400036:
case 0x400037: // Fog Table
((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u16) >> 1)] = val & 0x7F7F;
gfx3d_UpdateFogTable<u16>((u8)(adr & 0x0000001F), val & 0x7F7F); // Drop the highest bit of each 8-bit value to limit the range to [0...127]
return;
case 0x400038:
case 0x400039:
case 0x40003A:
case 0x40003B: // Toon Table
((u16 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u16) >> 1)] = val;
gfx3d_UpdateToonTable<u16>((u8)(adr & 0x0000003F), val);
return;
}
@ -3992,7 +4196,11 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
return;
case REG_DISPA_DISPMMEMFIFO:
DISP_FIFOsend_u32(val);
DISP_FIFOsend<u16, 0>(val);
return;
case REG_DISPA_DISPMMEMFIFO+2:
DISP_FIFOsend<u16, 2>(val);
return;
case REG_DISPA_MASTERBRIGHT:
@ -4233,14 +4441,6 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
MMU_new.gxstat.write(16,adr,val);
break;
//fog table: only write bottom 7 bits
case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x06:
case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0E:
case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x16:
case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1E:
val &= 0x7F7F;
break;
// Alpha test reference value - Parameters:1
case eng_3D_ALPHA_TEST_REF:
HostWriteWord(MMU.ARM9_REG, 0x0340, val);
@ -4248,14 +4448,24 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
return;
case eng_3D_CLEAR_COLOR:
T1WriteWord(MMU.ARM9_REG, 0x0350, val);
gfx3d_glClearColor<u16>(0, val);
return;
case eng_3D_CLEAR_COLOR+2:
T1WriteWord((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val);
break;
T1WriteWord(MMU.ARM9_REG, 0x0352, val);
gfx3d_glClearColor<u16>(2, val);
return;
// Clear background depth setup - Parameters:2
case eng_3D_CLEAR_DEPTH:
HostWriteWord(MMU.ARM9_REG, 0x0354, val);
gfx3d_glClearDepth(val);
gfx3d_glClearDepth<u16, 0>(val);
return;
case eng_3D_CLRIMAGE_OFFSET:
HostWriteWord(MMU.ARM9_REG, 0x0356, val);
gfx3d_glClearImageOffset<u16, 0>(val);
return;
// Fog Color - Parameters:4b
@ -4448,16 +4658,23 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
// lookups by the compiler
switch (adr >> 4)
{
case 0x400033: //edge color table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val;
case 0x400033: // Edge Mark Color Table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u32) >> 1)] = val;
gfx3d_UpdateEdgeMarkColorTable<u32>((u8)(adr & 0x0000000F), val);
return;
case 0x400036:
case 0x400037: // Fog Table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u32) >> 1)] = val & 0x7F7F7F7F;
gfx3d_UpdateFogTable<u32>((u8)(adr & 0x0000001F), val & 0x7F7F7F7F); // Drop the highest bit of each 8-bit value to limit the range to [0...127]
return;
case 0x400038:
case 0x400039:
case 0x40003A:
case 0x40003B: //toon table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> 2] = val;
gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val);
case 0x40003B: // Toon Table
((u32 *)(MMU.ARM9_REG))[(adr & 0xFFF) >> (sizeof(u32) >> 1)] = val;
gfx3d_UpdateToonTable<u32>((u8)(adr & 0x0000003F), val);
return;
case 0x400040:
@ -4635,7 +4852,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
return;
case REG_DISPA_DISPMMEMFIFO:
DISP_FIFOsend_u32(val);
DISP_FIFOsend<u32, 0>(val);
return;
case REG_DISPA_MASTERBRIGHT:
@ -4761,12 +4978,6 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
case REG_POWCNT1: writereg_POWCNT1(32,adr,val); break;
//fog table: only write bottom 7 bits
case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0C:
case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1C:
val &= 0x7F7F7F7F;
break;
//ensata handshaking port?
case 0x04FFF010:
if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_ack && val == 0x13579bdf)
@ -4781,7 +4992,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
//todo - these are usually write only regs (these and 1000 more)
//shouldnt we block them from getting written? ugh
case eng_3D_CLIPMTX_RESULT:
if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_none && val==0x2468ace0)
if(nds.ensataEmulation /* && nds.ensataHandshake == ENSATA_HANDSHAKE_none */&& val==0x2468ace0)
{
printf("ENSATA HANDSHAKE BEGIN\n");
nds.ensataHandshake = ENSATA_HANDSHAKE_query;
@ -4799,13 +5010,15 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
return;
case eng_3D_CLEAR_COLOR:
T1WriteLong((u8*)&gfx3d.state.clearColor,0,val);
break;
T1WriteLong(MMU.ARM9_REG, 0x0350, val);
gfx3d_glClearColor<u32>(0, val);
return;
// Clear background depth setup - Parameters:2
case eng_3D_CLEAR_DEPTH:
HostWriteLong(MMU.ARM9_REG, 0x0354, val);
gfx3d_glClearDepth(val);
gfx3d_glClearDepth<u16, 0>((u16)(val & 0x0000FFFF));
gfx3d_glClearImageOffset<u16, 0>((u16)(val >> 16));
return;
// Fog Color - Parameters:4b
@ -5298,6 +5511,10 @@ u32 FASTCALL _MMU_ARM9_read32(u32 adr)
case REG_KEYINPUT:
LagFrameFlag=0;
break;
// Ensata sound register
case 0x04FFF200:
return 1;
}
return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]);
}
@ -5393,6 +5610,21 @@ void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val)
printf("Unsupported 8bit write to timer registers");
return;
case REG_IPCSYNC:
{
u16 ipcsync = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x180);
ipcsync &= 0xFF00;
ipcsync |= (val & 0xFF);
MMU_IPCSync(ARMCPU_ARM7, ipcsync);
}
case REG_IPCSYNC+1:
{
u16 ipcsync = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x180);
ipcsync &= 0x00FF;
ipcsync |= ((val & 0xFF) << 8);
MMU_IPCSync(ARMCPU_ARM7, ipcsync);
}
case REG_AUXSPIDATA:
{
//if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; //zero 20-aug-2013 - this seems pointless

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2007 shash
Copyright (C) 2007-2017 DeSmuME team
Copyright (C) 2007-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -626,6 +626,10 @@ FORCEINLINE void* MMU_gpu_map(const u32 vram_addr)
return MMU.ARM9_LCD + (vram_page << 14) + ofs;
}
// Call MMU_WriteFromExternal() when modifying memory outside of the normal execution process, such
// as when using cheats or when the client wants to write to memory directly. This function returns
// true if memory is modified in such a way that requires the JIT execution be reset.
template<typename T, size_t LENGTH> bool MMU_WriteFromExternal(const int targetProc, const u32 targetAddress, T newValue);
template<int PROCNUM, MMU_ACCESS_TYPE AT> u8 _MMU_read08(u32 addr);
template<int PROCNUM, MMU_ACCESS_TYPE AT> u16 _MMU_read16(u32 addr);

View File

@ -1,258 +0,0 @@
include desmume.mk
AM_CPPFLAGS += $(SDL_CFLAGS) $(GTHREAD_CFLAGS) $(X_CFLAGS) $(ALSA_CFLAGS) $(LIBAGG_CFLAGS) $(LIBSOUNDTOUCH_CFLAGS)
EXTRA_DIST = instruction_tabdef.inc thumb_tabdef.inc cocoa
if HAVE_GDB_STUB
SUBDIRS = . gdbstub $(UI_DIR)
else
SUBDIRS = . $(UI_DIR)
endif
#DIST_SUBDIRS = . gdbstub cli gtk gtk-glade
noinst_LIBRARIES = libdesmume.a
libdesmume_a_SOURCES = \
armcpu.cpp armcpu.h \
arm_instructions.cpp \
agg2d.h agg2d.inl \
bios.cpp bios.h bits.h cp15.cpp cp15.h \
commandline.h commandline.cpp \
common.cpp common.h \
debug.cpp debug.h \
Database.cpp Database.h Disassembler.cpp Disassembler.h \
emufile.h emufile.cpp encrypt.h encrypt.cpp FIFO.cpp FIFO.h \
firmware.cpp firmware.h GPU.cpp GPU.h \
GPU_osd.h \
instructions.h \
mem.h mc.cpp mc.h \
path.cpp path.h \
readwrite.cpp readwrite.h \
wifi.cpp wifi.h \
mic.h \
MMU.cpp MMU.h MMU_timing.h NDSSystem.cpp NDSSystem.h registers.h \
OGLRender.h OGLRender_3_2.h \
ROMReader.cpp ROMReader.h \
render3D.cpp render3D.h \
rtc.cpp rtc.h \
saves.cpp saves.h \
slot1.cpp slot1.h \
slot2.cpp slot2.h \
SPU.cpp SPU.h \
matrix.cpp matrix.h \
gfx3d.cpp gfx3d.h \
thumb_instructions.cpp types.h \
movie.cpp movie.h \
PACKED.h PACKED_END.h \
utils/advanscene.cpp utils/advanscene.h \
utils/datetime.cpp utils/datetime.h \
utils/ConvertUTF.c utils/ConvertUTF.h utils/guid.cpp utils/guid.h \
utils/emufat.cpp utils/emufat.h utils/emufat_types.h \
utils/fsnitro.cpp utils/fsnitro.h \
utils/md5.cpp utils/md5.h utils/valuearray.h utils/xstring.cpp utils/xstring.h \
utils/decrypt/crc.cpp utils/decrypt/crc.h utils/decrypt/decrypt.cpp \
utils/decrypt/decrypt.h utils/decrypt/header.cpp utils/decrypt/header.h \
utils/task.cpp utils/task.h \
utils/vfat.h utils/vfat.cpp \
utils/colorspacehandler/colorspacehandler.cpp \
utils/dlditool.cpp \
utils/libfat/bit_ops.h \
utils/libfat/cache.cpp \
utils/libfat/cache.h \
utils/libfat/common.h \
utils/libfat/directory.cpp \
utils/libfat/directory.h \
utils/libfat/disc.cpp \
utils/libfat/disc.h \
utils/libfat/disc_io.h \
utils/libfat/fat.h \
utils/libfat/fatdir.cpp \
utils/libfat/fatdir.h \
utils/libfat/fatfile.cpp \
utils/libfat/fatfile.h \
utils/libfat/filetime.cpp \
utils/libfat/filetime.h \
utils/libfat/file_allocation_table.cpp \
utils/libfat/file_allocation_table.h \
utils/libfat/libfat.cpp \
utils/libfat/libfat_pc.h \
utils/libfat/libfat_public_api.cpp \
utils/libfat/libfat_public_api.h \
utils/libfat/lock.cpp \
utils/libfat/lock.h \
utils/libfat/mem_allocate.h \
utils/libfat/partition.cpp \
utils/libfat/partition.h \
utils/tinyxml/tinystr.cpp \
utils/tinyxml/tinystr.h \
utils/tinyxml/tinyxml.cpp \
utils/tinyxml/tinyxml.h \
utils/tinyxml/tinyxmlerror.cpp \
utils/tinyxml/tinyxmlparser.cpp \
utils/glcorearb.h \
addons/slot2_auto.cpp \
addons/slot2_mpcf.cpp \
addons/slot2_paddle.cpp \
addons/slot2_gbagame.cpp \
addons/slot2_none.cpp \
addons/slot2_rumblepak.cpp \
addons/slot2_guitarGrip.cpp \
addons/slot2_expMemory.cpp \
addons/slot2_piano.cpp \
addons/slot2_passme.cpp \
addons/slot1_none.cpp \
addons/slot1_r4.cpp \
addons/slot1_retail_nand.cpp \
addons/slot1_retail_auto.cpp \
addons/slot1_retail_mcrom.cpp \
addons/slot1_retail_mcrom_debug.cpp \
addons/slot1comp_mc.cpp \
addons/slot1comp_mc.h \
addons/slot1comp_rom.h \
addons/slot1comp_rom.cpp \
addons/slot1comp_protocol.h \
addons/slot1comp_protocol.cpp \
cheatSystem.cpp cheatSystem.h \
texcache.cpp texcache.h rasterize.cpp rasterize.h \
metaspu/metaspu.cpp metaspu/metaspu.h \
filter/2xsai.cpp \
filter/bilinear.cpp \
filter/deposterize.cpp \
filter/epx.cpp \
filter/filter.h \
filter/hq2x.cpp \
filter/hq2x.h \
filter/hq3x.cpp \
filter/hq3x.dat \
filter/hq4x.cpp \
filter/hq4x.dat \
filter/interp.h \
filter/lq2x.cpp filter/lq2x.h \
filter/scanline.cpp \
filter/videofilter.cpp filter/videofilter.h \
filter/xbrz.cpp filter/xbrz.h \
version.cpp version.h \
desmume_config.cpp desmume_config.h \
libretro-common/compat/compat_getopt.c \
libretro-common/file/file_path.c \
libretro-common/compat/compat_strl.c \
libretro-common/features/features_cpu.c \
libretro-common/file/retro_dirent.c \
libretro-common/file/retro_stat.c \
libretro-common/rthreads/async_job.c \
libretro-common/rthreads/rsemaphore.c \
libretro-common/rthreads/rthreads.c
if SUPPORT_SSE2
libdesmume_a_SOURCES += \
utils/colorspacehandler/colorspacehandler_SSE2.cpp
endif
if SUPPORT_AVX2
libdesmume_a_SOURCES += \
utils/colorspacehandler/colorspacehandler_AVX2.cpp
endif
if SUPPORT_ALTIVEC
libdesmume_a_SOURCES += \
utils/colorspacehandler/colorspacehandler_AltiVec.cpp
endif
if HAVE_JIT
libdesmume_a_SOURCES += \
arm_jit.cpp arm_jit.h instruction_attributes.h \
utils/AsmJit/AsmJit.h \
utils/AsmJit/Config.h \
utils/AsmJit/core.h \
utils/AsmJit/x86.h \
utils/AsmJit/core/apibegin.h \
utils/AsmJit/core/apiend.h \
utils/AsmJit/core/assembler.cpp \
utils/AsmJit/core/assembler.h \
utils/AsmJit/core/assert.cpp \
utils/AsmJit/core/assert.h \
utils/AsmJit/core/buffer.cpp \
utils/AsmJit/core/buffer.h \
utils/AsmJit/core/build.h \
utils/AsmJit/core/compiler.cpp \
utils/AsmJit/core/compiler.h \
utils/AsmJit/core/compilercontext.cpp \
utils/AsmJit/core/compilercontext.h \
utils/AsmJit/core/compilerfunc.cpp \
utils/AsmJit/core/compilerfunc.h \
utils/AsmJit/core/compileritem.cpp \
utils/AsmJit/core/compileritem.h \
utils/AsmJit/core/context.cpp \
utils/AsmJit/core/context.h \
utils/AsmJit/core/cpuinfo.cpp \
utils/AsmJit/core/cpuinfo.h \
utils/AsmJit/core/defs.cpp \
utils/AsmJit/core/defs.h \
utils/AsmJit/core/func.cpp \
utils/AsmJit/core/func.h \
utils/AsmJit/core/intutil.h \
utils/AsmJit/core/lock.h \
utils/AsmJit/core/logger.cpp \
utils/AsmJit/core/logger.h \
utils/AsmJit/core/memorymanager.cpp \
utils/AsmJit/core/memorymanager.h \
utils/AsmJit/core/memorymarker.cpp \
utils/AsmJit/core/memorymarker.h \
utils/AsmJit/core/operand.cpp \
utils/AsmJit/core/operand.h \
utils/AsmJit/core/podvector.h \
utils/AsmJit/core/stringbuilder.cpp \
utils/AsmJit/core/stringbuilder.h \
utils/AsmJit/core/stringutil.cpp \
utils/AsmJit/core/stringutil.h \
utils/AsmJit/core/virtualmemory.cpp \
utils/AsmJit/core/virtualmemory.h \
utils/AsmJit/core/zonememory.cpp \
utils/AsmJit/core/zonememory.h \
utils/AsmJit/x86/x86assembler.cpp \
utils/AsmJit/x86/x86assembler.h \
utils/AsmJit/x86/x86compiler.cpp \
utils/AsmJit/x86/x86compiler.h \
utils/AsmJit/x86/x86compilercontext.cpp \
utils/AsmJit/x86/x86compilercontext.h \
utils/AsmJit/x86/x86compilerfunc.cpp \
utils/AsmJit/x86/x86compilerfunc.h \
utils/AsmJit/x86/x86compileritem.cpp \
utils/AsmJit/x86/x86compileritem.h \
utils/AsmJit/x86/x86cpuinfo.cpp \
utils/AsmJit/x86/x86cpuinfo.h \
utils/AsmJit/x86/x86defs.cpp \
utils/AsmJit/x86/x86defs.h \
utils/AsmJit/x86/x86func.cpp \
utils/AsmJit/x86/x86func.h \
utils/AsmJit/x86/x86operand.cpp \
utils/AsmJit/x86/x86operand.h \
utils/AsmJit/x86/x86util.cpp \
utils/AsmJit/x86/x86util.h
endif
if HAVE_GL
libdesmume_a_SOURCES += OGLRender.cpp OGLRender_3_2.cpp
endif
if HAVE_OPENAL
libdesmume_a_SOURCES += mic_openal.cpp
else
if HAVE_ALSA
libdesmume_a_SOURCES += mic_alsa.cpp
else
libdesmume_a_SOURCES += mic.cpp
endif
endif
if HAVE_LIBSOUNDTOUCH
libdesmume_a_SOURCES += metaspu/SndOut.cpp metaspu/SndOut.h metaspu/Timestretcher.cpp
endif
if HAVE_LIBAGG
libdesmume_a_SOURCES += aggdraw.cpp aggdraw.h GPU_osd.cpp
else
libdesmume_a_SOURCES += GPU_osd_stub.cpp
endif
if HAVE_LUA
AM_CPPFLAGS += $(LUA_CFLAGS)
libdesmume_a_SOURCES += lua-engine.cpp
endif

View File

@ -635,7 +635,8 @@ bool GameInfo::isDSiEnhanced()
bool GameInfo::isHomebrew()
{
return ((header.ARM9src < 0x4000) && (T1ReadLong(header.logo, 0) != 0x51AEFF24) && (T1ReadLong(header.logo, 4) != 0x699AA221));
return ((header.ARM9src < 0x4000) && (T1ReadLong(header.logo, 0) != 0x51AEFF24) && (T1ReadLong(header.logo, 4) != 0x699AA221)) ||
(!memcmp(header.gameCode, "####", 4)); // <- ndstool default signature
}
static int rom_init_path(const char *filename, const char *physicalName, const char *logicalFilename)
@ -1453,8 +1454,11 @@ static void execHardware_hstart_vblankStart()
//for ARM7, cheats process when a vblank IRQ fires. necessary for AR compatibility and to stop cheats from breaking game boot-ups.
//note that how we process raw cheats is up to us. so we'll do it the same way we used to, elsewhere
if (i==1 && cheats)
if ( (i == 1) && (cheats != NULL) )
{
cheats->process(CHEAT_TYPE_AR);
CHEATS::ResetJitIfNeeded();
}
}
}
@ -2196,7 +2200,11 @@ void NDS_exec(s32 nb)
}
currFrameCounter++;
DEBUG_Notify.NextFrame();
if(cheats) cheats->process(CHEAT_TYPE_INTERNAL);
if (cheats != NULL)
{
cheats->process(CHEAT_TYPE_INTERNAL);
CHEATS::ResetJitIfNeeded();
}
GDBSTUB_MUTEX_UNLOCK();
}

3314
desmume/src/OGLRender.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3009
desmume/src/OGLRender_3_2.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2019 DeSmuME team
Copyright (C) 2008-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -20,61 +20,106 @@
#ifndef OGLRENDER_3_2_H
#define OGLRENDER_3_2_H
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glcorearb.h>
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#elif defined(__APPLE__)
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
// Ignore dynamic linking on Apple OS
#define OGLEXT(procPtr, func)
#define INITOGLEXT(procPtr, func)
#define EXTERNOGLEXT(procPtr, func)
#else
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
#include "utils/glcorearb.h"
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#endif
// Check minimum OpenGL header version
#if !defined(GL_VERSION_3_2)
#error OpenGL requires v3.2 headers or later.
#endif
#include "OGLRender.h"
#define MAX_CLIPPED_POLY_COUNT_FOR_UBO 16384
extern const char *GeometryVtxShader_150;
extern const char *GeometryFragShader_150;
extern const char *GeometryZeroDstAlphaPixelMaskVtxShader_150;
extern const char *GeometryZeroDstAlphaPixelMaskFragShader_150;
extern const char *MSGeometryZeroDstAlphaPixelMaskFragShader_150;
extern const char *ClearImageVtxShader_150;
extern const char *ClearImageFragShader_150;
extern const char *EdgeMarkVtxShader_150;
extern const char *EdgeMarkFragShader_150;
extern const char *FogVtxShader_150;
extern const char *FogFragShader_150;
extern const char *FramebufferOutputVtxShader_150;
extern const char *FramebufferOutput6665FragShader_150;
// A port that wants to use the OpenGL 3.2 renderer must assign the two following functions
// to OGLLoadEntryPoints_3_2_Func and OGLCreateRenderer_3_2_Func, respectively.
//
// In addition, the port must add the following GPU3DInterface objects to core3DList:
// - gpu3Dgl: Automatically selects the most fully featured version of standard OpenGL that
// is available on the host system, prefering OpenGL 3.2 Core Profile.
// - gpu3Dgl_3_2: Selects the OpenGL 3.2 Core Profile renderer, and returns an error if it
// is not available on the host system.
//
// Finally, the port must call GPU->Set3DRendererByID() and pass in the index where
// gpu3Dgl_3_2 exists in core3DList so that the emulator can create the appropriate
// OpenGLRenderer object.
//
// Example code:
// OGLLoadEntryPoints_3_2_Func = &OGLLoadEntryPoints_3_2;
// OGLCreateRenderer_3_2_Func = &OGLCreateRenderer_3_2;
// GPU3DInterface *core3DList[] = { &gpu3DNull, &gpu3DRasterize, &gpu3Dgl_3_2, NULL };
// GPU->Set3DRendererByID(2);
void OGLLoadEntryPoints_3_2();
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr);
class OpenGLGeometryResource : public Render3DResourceGeometry
{
protected:
GLuint _vboID[3];
GLuint _eboID[3];
GLuint _vaoID[3];
GLuint _uboPolyStatesID[3];
GLuint _tboPolyStatesID[3];
GLuint _texPolyStatesID[3];
GLsync _syncGeometryRender[3];
u16 *_indexBuffer[3];
OGLPolyStates *_polyStatesBuffer[3];
public:
OpenGLGeometryResource(const OpenGLVariantID variantID);
~OpenGLGeometryResource();
size_t BindWrite(const size_t rawVtxCount, const size_t clippedPolyCount);
size_t BindUsage();
size_t UnbindUsage();
size_t RebindUsage();
u16* GetIndexBuffer(const size_t index);
OGLPolyStates* GetPolyStatesBuffer(const size_t index);
bool IsPolyStatesBufferUBO();
bool IsPolyStatesBufferTBO();
};
class OpenGLRenderStatesResource : public Render3DResource
{
protected:
GLsync _sync[3];
GLuint _uboRenderStatesID[3];
OGLRenderStates *_buffer[3];
public:
OpenGLRenderStatesResource();
~OpenGLRenderStatesResource();
size_t BindWrite();
size_t BindUsage();
size_t UnbindUsage();
OGLRenderStates* GetRenderStatesBuffer(const size_t index);
};
class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1
{
protected:
bool _is64kUBOSupported;
bool _isDualSourceBlendingSupported;
bool _isSampleShadingSupported;
bool _isShaderFixedLocationSupported;
bool _isConservativeDepthSupported;
bool _isConservativeDepthAMDSupported;
GLsync _syncBufferSetup;
CACHE_ALIGN OGLPolyStates _pendingPolyStates[POLYLIST_SIZE];
virtual Render3DError InitExtensions();
OpenGLGeometryResource *_gResource;
OpenGLRenderStatesResource *_rsResource;
virtual Render3DError CreateVBOs();
virtual Render3DError CreatePBOs();
virtual Render3DError CreateFBOs();
virtual void DestroyFBOs();
virtual Render3DError CreateMultisampledFBO(GLsizei numSamples);
@ -84,40 +129,48 @@ protected:
virtual void DestroyVAOs();
virtual Render3DError CreateGeometryPrograms();
virtual void DestroyGeometryPrograms();
virtual Render3DError CreateClearImageProgram(const char *vsCString, const char *fsCString);
virtual void DestroyClearImageProgram();
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateMSGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyMSGeometryZeroDstAlphaProgram();
virtual Render3DError CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFramebufferOutput8888Program(const char *vtxShaderCString, const char *fragShaderCString);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _RenderGeometryVertexAttribEnable();
virtual void _RenderGeometryVertexAttribDisable();
virtual Render3DError ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _RenderGeometryLoopBegin();
virtual void _RenderGeometryLoopEnd();
virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry();
virtual Render3DError ReadBackPixels();
virtual Render3DError BeginRender(const GFX3D &engine);
virtual void _ResolveFinalFramebuffer();
virtual void _FramebufferProcessVertexAttribEnable();
virtual void _FramebufferProcessVertexAttribDisable();
virtual Render3DError _FramebufferConvertColorFormat();
virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList);
virtual Render3DError PostprocessFramebuffer();
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes);
virtual Render3DError ClearUsingValues(const Color4u8 &clearColor6665, const FragmentAttributes &clearAttributes);
virtual void SetPolygonIndex(const size_t index);
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer);
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing);
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
public:
OpenGLRenderer_3_2();
~OpenGLRenderer_3_2();
virtual Render3DError InitExtensions();
virtual Render3DError RenderFinish();
virtual Render3DError RenderPowerOff();
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
};
#endif

View File

@ -0,0 +1,963 @@
/*
Copyright (C) 2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "OGLRender_ES3.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <sstream>
#include "utils/bits.h"
#include "common.h"
#include "debug.h"
#include "NDSSystem.h"
static const GLenum GeometryDrawBuffersEnumES[8][4] = {
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, GL_NONE, GL_NONE },
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, GL_NONE, OGL_FOGATTRIBUTES_ATTACHMENT_ID },
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, OGL_POLYID_ATTACHMENT_ID, GL_NONE },
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, OGL_POLYID_ATTACHMENT_ID, OGL_FOGATTRIBUTES_ATTACHMENT_ID },
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, GL_NONE, GL_NONE },
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, GL_NONE, OGL_FOGATTRIBUTES_ATTACHMENT_ID },
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, OGL_POLYID_ATTACHMENT_ID, GL_NONE },
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, OGL_POLYID_ATTACHMENT_ID, OGL_FOGATTRIBUTES_ATTACHMENT_ID }
};
static const GLint GeometryAttachmentWorkingBufferES[8] = { 1,1,1,1,1,1,1,1 };
static const GLint GeometryAttachmentPolyIDES[8] = { 2,2,2,2,2,2,2,2 };
static const GLint GeometryAttachmentFogAttributesES[8] = { 3,3,3,3,3,3,3,3 };
// Vertex shader for geometry, GLSL ES 3.00
static const char *GeometryVtxShader_ES300 = {"\
IN_VTX_POSITION vec4 inPosition;\n\
IN_VTX_TEXCOORD0 vec2 inTexCoord0;\n\
IN_VTX_COLOR vec3 inColor; \n\
\n\
#if IS_USING_UBO_POLY_STATES\n\
layout (std140) uniform PolyStates\n\
{\n\
ivec4 value[4096];\n\
} polyState;\n\
#elif IS_USING_TBO_POLY_STATES\n\
uniform highp isamplerBuffer PolyStates;\n\
#else\n\
uniform highp isampler2D PolyStates;\n\
#endif\n\
uniform mediump int polyIndex;\n\
uniform bool polyDrawShadow;\n\
\n\
out vec2 vtxTexCoord;\n\
out vec4 vtxColor;\n\
flat out lowp int polyID;\n\
flat out lowp int polyMode;\n\
flat out lowp int polyIsWireframe;\n\
flat out lowp int polyEnableFog;\n\
flat out lowp int polySetNewDepthForTranslucent;\n\
flat out lowp int polyEnableTexture;\n\
flat out lowp int texSingleBitAlpha;\n\
flat out lowp int polyIsBackFacing;\n\
flat out lowp int isPolyDrawable;\n\
\n\
void main()\n\
{\n\
#if IS_USING_UBO_POLY_STATES\n\
ivec4 polyStateVec = polyState.value[polyIndex >> 2];\n\
int polyStateBits = polyStateVec[polyIndex & 0x03];\n\
#elif IS_USING_TBO_POLY_STATES\n\
int polyStateBits = texelFetch(PolyStates, polyIndex).r;\n\
#else\n\
int polyStateBits = texelFetch(PolyStates, ivec2(polyIndex & 0x00FF, (polyIndex >> 8) & 0x007F), 0).r;\n\
#endif\n\
int texSizeShiftS = (polyStateBits >> 18) & 0x07;\n\
int texSizeShiftT = (polyStateBits >> 21) & 0x07;\n\
\n\
float polyAlpha = float((polyStateBits >> 8) & 0x1F) / 31.0;\n\
vec2 polyTexScale = vec2(1.0 / float(8 << texSizeShiftS), 1.0 / float(8 << texSizeShiftT));\n\
\n\
polyID = (polyStateBits >> 0) & 0x3F;\n\
polyMode = (polyStateBits >> 6) & 0x03;\n\
polyIsWireframe = (polyStateBits >> 13) & 0x01;\n\
polyEnableFog = (polyStateBits >> 14) & 0x01;\n\
polySetNewDepthForTranslucent = (polyStateBits >> 15) & 0x01;\n\
polyEnableTexture = (polyStateBits >> 16) & 0x01;\n\
texSingleBitAlpha = (polyStateBits >> 17) & 0x01;\n\
polyIsBackFacing = (polyStateBits >> 24) & 0x01;\n\
\n\
isPolyDrawable = int((polyMode != 3) || polyDrawShadow);\n\
\n\
mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\
vec2( 0.0, polyTexScale.y)); \n\
\n\
vtxTexCoord = (texScaleMtx * inTexCoord0) / 16.0;\n\
vtxColor = vec4(inColor / 63.0, polyAlpha);\n\
gl_Position = vec4(inPosition.x, -inPosition.y, inPosition.z, inPosition.w) / 4096.0;\n\
}\n\
"};
// Fragment shader for geometry, GLSL ES 3.00
static const char *GeometryFragShader_ES300 = {"\
in vec2 vtxTexCoord;\n\
in vec4 vtxColor;\n\
flat in lowp int polyID;\n\
flat in lowp int polyMode;\n\
flat in lowp int polyIsWireframe;\n\
flat in lowp int polyEnableFog;\n\
flat in lowp int polySetNewDepthForTranslucent;\n\
flat in lowp int polyEnableTexture;\n\
flat in lowp int texSingleBitAlpha;\n\
flat in lowp int polyIsBackFacing;\n\
flat in lowp int isPolyDrawable;\n\
\n\
layout (std140) uniform RenderStates\n\
{\n\
bool enableAntialiasing;\n\
bool enableFogAlphaOnly;\n\
int clearPolyID;\n\
float clearDepth;\n\
float alphaTestRef;\n\
float fogOffset;\n\
float fogStep;\n\
float pad_0;\n\
vec4 fogColor;\n\
vec4 edgeColor[8];\n\
vec4 toonColor[32];\n\
} state;\n\
\n\
uniform sampler2D texRenderObject;\n\
uniform bool texDrawOpaque;\n\
uniform bool drawModeDepthEqualsTest;\n\
uniform bool polyDrawShadow;\n\
uniform float polyDepthOffset;\n\
\n\
OUT_COLOR vec4 outFragColor;\n\
\n\
#if DRAW_MODE_OPAQUE\n\
OUT_WORKING_BUFFER vec4 outDstBackFacing;\n\
#elif USE_DEPTH_LEQUAL_POLYGON_FACING\n\
uniform sampler2D inDstBackFacing;\n\
#endif\n\
\n\
#if ENABLE_EDGE_MARK\n\
OUT_POLY_ID vec4 outPolyID;\n\
#endif\n\
#if ENABLE_FOG\n\
OUT_FOG_ATTRIBUTES vec4 outFogAttributes;\n\
#endif\n\
\n\
void main()\n\
{\n\
#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\
bool isOpaqueDstBackFacing = bool( texelFetch(inDstBackFacing, ivec2(gl_FragCoord.xy), 0).r );\n\
if ( drawModeDepthEqualsTest && (bool(polyIsBackFacing) || !isOpaqueDstBackFacing) )\n\
{\n\
discard;\n\
}\n\
#endif\n\
\n\
vec4 mainTexColor = (ENABLE_TEXTURE_SAMPLING && bool(polyEnableTexture)) ? texture(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0);\n\
\n\
if (!bool(texSingleBitAlpha))\n\
{\n\
if (texDrawOpaque)\n\
{\n\
if ( (polyMode != 1) && (mainTexColor.a <= 0.999) )\n\
{\n\
discard;\n\
}\n\
}\n\
else\n\
{\n\
if ( ((polyMode != 1) && (mainTexColor.a * vtxColor.a > 0.999)) || ((polyMode == 1) && (vtxColor.a > 0.999)) )\n\
{\n\
discard;\n\
}\n\
}\n\
}\n\
#if USE_TEXTURE_SMOOTHING\n\
else\n\
{\n\
if (mainTexColor.a < 0.500)\n\
{\n\
mainTexColor.a = 0.0;\n\
}\n\
else\n\
{\n\
mainTexColor.rgb = mainTexColor.rgb / mainTexColor.a;\n\
mainTexColor.a = 1.0;\n\
}\n\
}\n\
#endif\n\
\n\
outFragColor = mainTexColor * vtxColor;\n\
\n\
if (polyMode == 1)\n\
{\n\
outFragColor.rgb = (ENABLE_TEXTURE_SAMPLING && bool(polyEnableTexture)) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb;\n\
outFragColor.a = vtxColor.a;\n\
}\n\
else if (polyMode == 2)\n\
{\n\
vec3 newToonColor = state.toonColor[int((vtxColor.r * 31.0) + 0.5)].rgb;\n\
#if TOON_SHADING_MODE\n\
outFragColor.rgb = min((mainTexColor.rgb * vtxColor.r) + newToonColor.rgb, 1.0);\n\
#else\n\
outFragColor.rgb = mainTexColor.rgb * newToonColor.rgb;\n\
#endif\n\
}\n\
else if ((polyMode == 3) && polyDrawShadow)\n\
{\n\
outFragColor = vtxColor;\n\
}\n\
\n\
if ( (isPolyDrawable != 0) && ((outFragColor.a < 0.001) || (ENABLE_ALPHA_TEST && outFragColor.a < state.alphaTestRef)) )\n\
{\n\
discard;\n\
}\n\
#if ENABLE_EDGE_MARK\n\
outPolyID = (isPolyDrawable != 0) ? vec4( float(polyID)/63.0, float(polyIsWireframe == 1), 0.0, float(outFragColor.a > 0.999) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
#endif\n\
#if ENABLE_FOG\n\
outFogAttributes = (isPolyDrawable != 0) ? vec4( float(polyEnableFog), 0.0, 0.0, float((outFragColor.a > 0.999) ? 1.0 : 0.5) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
#endif\n\
#if DRAW_MODE_OPAQUE\n\
outDstBackFacing = vec4(float(polyIsBackFacing), 0.0, 0.0, 1.0);\n\
#endif\n\
\n\
#if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\
// It is tempting to perform the NDS depth calculation in the vertex shader rather than in the fragment shader.\n\
// Resist this temptation! It is much more reliable to do the depth calculation in the fragment shader due to\n\
// subtle interpolation differences between various GPUs and/or drivers. If the depth calculation is not done\n\
// here, then it is very possible for the user to experience Z-fighting in certain rendering situations.\n\
\n\
#if ENABLE_W_DEPTH\n\
gl_FragDepth = clamp( ((1.0/gl_FragCoord.w) * (4096.0/16777215.0)) + polyDepthOffset, 0.0, 1.0 );\n\
#else\n\
// hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly\n\
gl_FragDepth = clamp( (floor(gl_FragCoord.z * 4194303.0) * (4.0/16777215.0)) + polyDepthOffset, 0.0, 1.0 );\n\
#endif\n\
#endif\n\
}\n\
"};
void OGLLoadEntryPoints_ES_3_0()
{
OGLLoadEntryPoints_3_2();
}
void OGLCreateRenderer_ES_3_0(OpenGLRenderer **rendererPtr)
{
if (IsOpenGLDriverVersionSupported(3, 0, 0))
{
*rendererPtr = new OpenGLESRenderer_3_0;
(*rendererPtr)->SetVersion(3, 0, 0);
}
}
OpenGLESRenderer_3_0::OpenGLESRenderer_3_0()
{
_variantID = OpenGLVariantID_ES3_3_0;
_geometryDrawBuffersEnum = GeometryDrawBuffersEnumES;
_geometryAttachmentWorkingBuffer = GeometryAttachmentWorkingBufferES;
_geometryAttachmentPolyID = GeometryAttachmentPolyIDES;
_geometryAttachmentFogAttributes = GeometryAttachmentFogAttributesES;
ref->textureSrcTypeCIColor = GL_UNSIGNED_BYTE;
ref->textureSrcTypeCIFog = GL_UNSIGNED_BYTE;
ref->textureSrcTypeEdgeColor = GL_UNSIGNED_BYTE;
ref->textureSrcTypeToonTable = GL_UNSIGNED_BYTE;
}
Render3DError OpenGLESRenderer_3_0::InitExtensions()
{
OGLRenderRef &OGLRef = *this->ref;
Render3DError error = OGLERROR_NOERR;
// Get OpenGL extensions
std::set<std::string> oglExtensionSet;
this->GetExtensionSet(&oglExtensionSet);
// OpenGL ES 3.0 should fully support FBOs, so we don't need the default framebuffer.
// However, OpenGL ES has traditionally required some kind of surface buffer attached
// to the context before using it. We don't want it, nor would we ever use it here.
// Therefore, check if our context supports being surfaceless before doing anything else,
// as this works as a kind of compatibility check.
if (!this->IsExtensionPresent(&oglExtensionSet, "GL_OES_surfaceless_context"))
{
INFO("OpenGL ES: Client contexts are not expected to have any surfaces attached\n");
INFO(" to the default framebuffer. The fact that the context does not\n");
INFO(" work surfaceless may indicate an error in the context creation,\n");
INFO(" or that your platform's context creation is too old.\n");
error = OGLERROR_FEATURE_UNSUPPORTED;
return error;
}
// Mirrored Repeat Mode Support
OGLRef.stateTexMirroredRepeat = GL_MIRRORED_REPEAT;
// Blending Support
this->_isBlendFuncSeparateSupported = true;
this->_isBlendEquationSeparateSupported = true;
// Fixed locations in shaders are supported in ES 3.0 by default.
this->_isShaderFixedLocationSupported = true;
GLfloat maxAnisotropyOGL = 1.0f;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyOGL);
this->_deviceInfo.maxAnisotropy = (float)maxAnisotropyOGL;
// OpenGL ES 3.0 should be able to handle the GL_RGBA format in glReadPixels without any performance penalty.
OGLRef.readPixelsBestFormat = GL_RGBA;
OGLRef.readPixelsBestDataType = GL_UNSIGNED_BYTE;
this->_deviceInfo.isEdgeMarkSupported = true;
this->_deviceInfo.isFogSupported = true;
// Need to generate this texture first because FBO creation needs it.
// This texture is only required by shaders, and so if shader creation
// fails, then we can immediately delete this texture if an error occurs.
glGenTextures(1, &OGLRef.texFinalColorID);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glActiveTexture(GL_TEXTURE0);
// OpenGL ES 3.0 should have all the necessary features to be able to flip and convert the framebuffer.
this->_willConvertFramebufferOnGPU = true;
this->_enableTextureSmoothing = CommonSettings.GFX3D_Renderer_TextureSmoothing;
this->_emulateShadowPolygon = CommonSettings.OpenGL_Emulation_ShadowPolygon;
this->_emulateSpecialZeroAlphaBlending = CommonSettings.OpenGL_Emulation_SpecialZeroAlphaBlending;
this->_emulateNDSDepthCalculation = CommonSettings.OpenGL_Emulation_NDSDepthCalculation;
this->_emulateDepthLEqualPolygonFacing = CommonSettings.OpenGL_Emulation_DepthLEqualPolygonFacing;
// Load and create shaders. Return on any error, since ES 3.0 makes shaders mandatory.
this->isShaderSupported = true;
this->_rsResource = new OpenGLRenderStatesResource();
if (IsOpenGLDriverVersionSupported(3, 2, 0))
{
this->_gResource = new OpenGLGeometryResource(OpenGLVariantID_ES3_3_2);
}
else if (IsOpenGLDriverVersionSupported(3, 1, 0))
{
this->_gResource = new OpenGLGeometryResource(OpenGLVariantID_ES3_3_1);
}
else
{
this->_gResource = new OpenGLGeometryResource(OpenGLVariantID_ES3_3_0);
}
error = this->CreateGeometryPrograms();
if (error != OGLERROR_NOERR)
{
glUseProgram(0);
this->DestroyGeometryPrograms();
this->isShaderSupported = false;
return error;
}
error = this->CreateClearImageProgram(ClearImageVtxShader_150, ClearImageFragShader_150);
if (error != OGLERROR_NOERR)
{
glUseProgram(0);
this->DestroyGeometryPrograms();
this->isShaderSupported = false;
return error;
}
error = this->CreateGeometryZeroDstAlphaProgram(GeometryZeroDstAlphaPixelMaskVtxShader_150, GeometryZeroDstAlphaPixelMaskFragShader_150);
if (error != OGLERROR_NOERR)
{
glUseProgram(0);
this->DestroyGeometryPrograms();
this->DestroyClearImageProgram();
this->isShaderSupported = false;
return error;
}
INFO("OpenGL ES: Successfully created geometry shaders.\n");
error = this->InitPostprocessingPrograms(EdgeMarkVtxShader_150,
EdgeMarkFragShader_150,
FramebufferOutputVtxShader_150,
FramebufferOutput6665FragShader_150,
NULL);
if (error != OGLERROR_NOERR)
{
glUseProgram(0);
this->DestroyGeometryPrograms();
this->DestroyClearImageProgram();
this->DestroyGeometryZeroDstAlphaProgram();
this->isShaderSupported = false;
return error;
}
this->isVBOSupported = true;
this->CreateVBOs();
// PBOs are only used when reading back the rendered framebuffer for the emulated
// BG0 layer. For desktop-class GPUs, doing an asynchronous glReadPixels() call
// is always advantageous since such devices are expected to have their GPUs
// connected to a data bus.
//
// However, many ARM-based mobile devices use integrated GPUs of varying degrees
// of memory latency and implementation quality. This means that the performance
// of an asynchronous glReadPixels() call is NOT guaranteed on such devices.
//
// In fact, many ARM-based devices suffer devastating performance drops when trying
// to do asynchronous framebuffer reads. Therefore, since most OpenGL ES users will
// be running an ARM-based iGPU, we will disable PBOs for OpenGL ES and stick with
// a traditional synchronous glReadPixels() call instead.
this->isPBOSupported = false;
this->isVAOSupported = true;
this->CreateVAOs();
// Load and create FBOs. Return on any error, since OpenGL ES 3.0 includes FBOs as core functionality.
this->isFBOSupported = true;
error = this->CreateFBOs();
if (error != OGLERROR_NOERR)
{
this->isFBOSupported = false;
return error;
}
this->_isFBOBlitSupported = true;
this->isMultisampledFBOSupported = true;
this->_selectedMultisampleSize = CommonSettings.GFX3D_Renderer_MultisampleSize;
GLint maxSamplesOGL = 0;
glGetIntegerv(GL_MAX_SAMPLES, &maxSamplesOGL);
this->_deviceInfo.maxSamples = (u8)maxSamplesOGL;
if (this->_deviceInfo.maxSamples >= 2)
{
// Try and initialize the multisampled FBOs with the GFX3D_Renderer_MultisampleSize.
// However, if the client has this set to 0, then set sampleSize to 2 in order to
// force the generation and the attachments of the buffers at a meaningful sample
// size. If GFX3D_Renderer_MultisampleSize is 0, then we can deallocate the buffer
// memory afterwards.
GLsizei sampleSize = this->GetLimitedMultisampleSize();
if (sampleSize == 0)
{
sampleSize = 2;
}
error = this->CreateMultisampledFBO(sampleSize);
if (error != OGLERROR_NOERR)
{
this->isMultisampledFBOSupported = false;
}
// If GFX3D_Renderer_MultisampleSize is 0, then we can deallocate the buffers now
// in order to save some memory.
if (this->_selectedMultisampleSize == 0)
{
this->ResizeMultisampledFBOs(0);
}
}
else
{
this->isMultisampledFBOSupported = false;
INFO("OpenGL ES: Driver does not support at least 2x multisampled FBOs.\n");
}
this->_isDepthLEqualPolygonFacingSupported = true;
this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported);
return OGLERROR_NOERR;
}
Render3DError OpenGLESRenderer_3_0::CreateGeometryPrograms()
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
// Create shader resources.
glGenTextures(1, &OGLRef.texFogDensityTableID);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
glBindTexture(GL_TEXTURE_2D, OGLRef.texFogDensityTableID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 1, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
glActiveTexture(GL_TEXTURE0);
OGLGeometryFlags programFlags;
programFlags.value = 0;
std::stringstream shaderHeader;
shaderHeader << "#version 300 es\n";
shaderHeader << "precision highp float;\n";
shaderHeader << "precision highp int;\n";
shaderHeader << "\n";
std::stringstream vsHeader;
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
vsHeader << "\n";
vsHeader << "#define IS_USING_UBO_POLY_STATES " << ((this->_gResource->IsPolyStatesBufferUBO()) ? 1 : 0) << "\n";
vsHeader << "#define IS_USING_TBO_POLY_STATES " << ((this->_gResource->IsPolyStatesBufferTBO()) ? 1 : 0) << "\n";
vsHeader << "#define DEPTH_EQUALS_TEST_TOLERANCE " << DEPTH_EQUALS_TEST_TOLERANCE << ".0\n";
vsHeader << "\n";
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(GeometryVtxShader_ES300);
for (size_t flagsValue = 0; flagsValue < 128; flagsValue++, programFlags.value++)
{
std::stringstream shaderFlags;
shaderFlags << "#define OUT_COLOR layout (location = 0) out\n";
shaderFlags << "#define OUT_WORKING_BUFFER layout (location = " << (OGL_WORKING_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
shaderFlags << "#define OUT_POLY_ID layout (location = " << (OGL_POLYID_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
shaderFlags << "#define OUT_FOG_ATTRIBUTES layout (location = " << (OGL_FOGATTRIBUTES_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
shaderFlags << "\n";
shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n";
shaderFlags << "#define USE_NDS_DEPTH_CALCULATION " << ((this->_emulateNDSDepthCalculation) ? 1 : 0) << "\n";
shaderFlags << "#define USE_DEPTH_LEQUAL_POLYGON_FACING " << ((this->_emulateDepthLEqualPolygonFacing) ? 1 : 0) << "\n";
shaderFlags << "\n";
shaderFlags << "#define ENABLE_W_DEPTH " << ((programFlags.EnableWDepth) ? 1 : 0) << "\n";
shaderFlags << "#define ENABLE_ALPHA_TEST " << ((programFlags.EnableAlphaTest) ? "true\n" : "false\n");
shaderFlags << "#define ENABLE_TEXTURE_SAMPLING " << ((programFlags.EnableTextureSampling) ? "true\n" : "false\n");
shaderFlags << "#define TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n";
shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog) ? 1 : 0) << "\n";
shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark) ? 1 : 0) << "\n";
shaderFlags << "#define DRAW_MODE_OPAQUE " << ((programFlags.OpaqueDrawMode) ? 1 : 0) << "\n";
shaderFlags << "\n";
std::string fragShaderCode = shaderHeader.str() + shaderFlags.str() + std::string(GeometryFragShader_ES300);
error = this->ShaderProgramCreate(OGLRef.vertexGeometryShaderID,
OGLRef.fragmentGeometryShaderID[flagsValue],
OGLRef.programGeometryID[flagsValue],
vtxShaderCode.c_str(),
fragShaderCode.c_str());
if (error != OGLERROR_NOERR)
{
INFO("OpenGL ES: Failed to create the GEOMETRY shader program.\n");
glUseProgram(0);
this->DestroyGeometryPrograms();
return error;
}
glLinkProgram(OGLRef.programGeometryID[flagsValue]);
if (!this->ValidateShaderProgramLink(OGLRef.programGeometryID[flagsValue]))
{
INFO("OpenGL ES: Failed to link the GEOMETRY shader program.\n");
glUseProgram(0);
this->DestroyGeometryPrograms();
return OGLERROR_SHADER_CREATE_ERROR;
}
glValidateProgram(OGLRef.programGeometryID[flagsValue]);
glUseProgram(OGLRef.programGeometryID[flagsValue]);
// Set up render states UBO
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "RenderStates");
glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockRenderStates, OGLBindingPointID_RenderStates);
GLint uboSize = 0;
glGetActiveUniformBlockiv(OGLRef.programGeometryID[flagsValue], uniformBlockRenderStates, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize);
assert(uboSize == sizeof(OGLRenderStates));
const GLint uniformTexRenderObject = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texRenderObject");
glUniform1i(uniformTexRenderObject, 0);
if (this->_gResource->IsPolyStatesBufferUBO())
{
const GLuint uniformBlockPolyStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "PolyStates");
glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockPolyStates, OGLBindingPointID_PolyStates);
}
else
{
const GLint uniformTexBufferPolyStates = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "PolyStates");
glUniform1i(uniformTexBufferPolyStates, OGLTextureUnitID_PolyStates);
}
if (this->_emulateDepthLEqualPolygonFacing && !programFlags.OpaqueDrawMode)
{
const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inDstBackFacing");
glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor);
}
OGLRef.uniformTexDrawOpaque[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texDrawOpaque");
OGLRef.uniformDrawModeDepthEqualsTest[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "drawModeDepthEqualsTest");
OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow");
OGLRef.uniformPolyStateIndex[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyIndex");
OGLRef.uniformPolyDepthOffset[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffset");
}
return error;
}
Render3DError OpenGLESRenderer_3_0::CreateClearImageProgram(const char *vsCString, const char *fsCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
std::stringstream shaderHeader;
shaderHeader << "#version 300 es\n";
shaderHeader << "precision highp float;\n";
shaderHeader << "precision highp int;\n";
shaderHeader << "\n";
std::stringstream vsHeader;
if (this->_isShaderFixedLocationSupported)
{
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
}
else
{
vsHeader << "#define IN_VTX_POSITION in\n";
vsHeader << "#define IN_VTX_TEXCOORD0 in\n";
}
vsHeader << "\n";
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vsCString);
std::stringstream fsHeader;
if (this->_isShaderFixedLocationSupported)
{
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
fsHeader << "#define OUT_FOGATTR layout (location = 1) out\n";
}
else
{
fsHeader << "#define OUT_COLOR out\n";
fsHeader << "#define OUT_FOGATTR out\n";
}
fsHeader << "\n";
std::string fragShaderCodeFogColor = shaderHeader.str() + fsHeader.str() + std::string(fsCString);
error = this->ShaderProgramCreate(OGLRef.vsClearImageID,
OGLRef.fsClearImageID,
OGLRef.pgClearImageID,
vtxShaderCode.c_str(),
fragShaderCodeFogColor.c_str());
if (error != OGLERROR_NOERR)
{
INFO("OpenGL ES: Failed to create the CLEAR_IMAGE shader program.\n");
glUseProgram(0);
this->DestroyClearImageProgram();
return error;
}
glLinkProgram(OGLRef.pgClearImageID);
if (!this->ValidateShaderProgramLink(OGLRef.pgClearImageID))
{
INFO("OpenGL ES: Failed to link the CLEAR_IMAGE shader color/fog program.\n");
glUseProgram(0);
this->DestroyClearImageProgram();
return OGLERROR_SHADER_CREATE_ERROR;
}
glValidateProgram(OGLRef.pgClearImageID);
glUseProgram(OGLRef.pgClearImageID);
const GLint uniformTexCIColor = glGetUniformLocation(OGLRef.pgClearImageID, "texCIColor");
const GLint uniformTexCIFogAttr = glGetUniformLocation(OGLRef.pgClearImageID, "texCIFogAttr");
const GLint uniformTexCIDepthCF = glGetUniformLocation(OGLRef.pgClearImageID, "texCIDepth");
glUniform1i(uniformTexCIColor, OGLTextureUnitID_CIColor);
glUniform1i(uniformTexCIFogAttr, OGLTextureUnitID_CIFogAttr);
glUniform1i(uniformTexCIDepthCF, OGLTextureUnitID_CIDepth);
return error;
}
Render3DError OpenGLESRenderer_3_0::CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
{
return error;
}
std::stringstream shaderHeader;
shaderHeader << "#version 300 es\n";
shaderHeader << "precision highp float;\n";
shaderHeader << "precision highp int;\n";
shaderHeader << "\n";
std::stringstream vsHeader;
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
std::string fragShaderCode = shaderHeader.str() + std::string(fragShaderCString);
error = this->ShaderProgramCreate(OGLRef.vtxShaderGeometryZeroDstAlphaID,
OGLRef.fragShaderGeometryZeroDstAlphaID,
OGLRef.programGeometryZeroDstAlphaID,
vtxShaderCode.c_str(),
fragShaderCode.c_str());
if (error != OGLERROR_NOERR)
{
INFO("OpenGL ES: Failed to create the GEOMETRY ZERO DST ALPHA shader program.\n");
glUseProgram(0);
this->DestroyGeometryZeroDstAlphaProgram();
return error;
}
glLinkProgram(OGLRef.programGeometryZeroDstAlphaID);
if (!this->ValidateShaderProgramLink(OGLRef.programGeometryZeroDstAlphaID))
{
INFO("OpenGL ES: Failed to link the GEOMETRY ZERO DST ALPHA shader program.\n");
glUseProgram(0);
this->DestroyGeometryZeroDstAlphaProgram();
return OGLERROR_SHADER_CREATE_ERROR;
}
glValidateProgram(OGLRef.programGeometryZeroDstAlphaID);
glUseProgram(OGLRef.programGeometryZeroDstAlphaID);
const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programGeometryZeroDstAlphaID, "texInFragColor");
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
return OGLERROR_NOERR;
}
Render3DError OpenGLESRenderer_3_0::CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
{
return error;
}
std::stringstream shaderHeader;
shaderHeader << "#version 300 es\n";
shaderHeader << "precision highp float;\n";
shaderHeader << "precision highp int;\n";
shaderHeader << "\n";
shaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n";
shaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n";
shaderHeader << "\n";
std::stringstream vsHeader;
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
std::stringstream fsHeader;
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
error = this->ShaderProgramCreate(OGLRef.vertexEdgeMarkShaderID,
OGLRef.fragmentEdgeMarkShaderID,
OGLRef.programEdgeMarkID,
vtxShaderCode.c_str(),
fragShaderCode.c_str());
if (error != OGLERROR_NOERR)
{
INFO("OpenGL ES: Failed to create the EDGE MARK shader program.\n");
glUseProgram(0);
this->DestroyEdgeMarkProgram();
return error;
}
glLinkProgram(OGLRef.programEdgeMarkID);
if (!this->ValidateShaderProgramLink(OGLRef.programEdgeMarkID))
{
INFO("OpenGL ES: Failed to link the EDGE MARK shader program.\n");
glUseProgram(0);
this->DestroyEdgeMarkProgram();
return OGLERROR_SHADER_CREATE_ERROR;
}
glValidateProgram(OGLRef.programEdgeMarkID);
glUseProgram(OGLRef.programEdgeMarkID);
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programEdgeMarkID, "RenderStates");
glUniformBlockBinding(OGLRef.programEdgeMarkID, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
const GLint uniformTexGDepth = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth");
const GLint uniformTexGPolyID = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID");
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
glUniform1i(uniformTexGPolyID, OGLTextureUnitID_GPolyID);
return OGLERROR_NOERR;
}
Render3DError OpenGLESRenderer_3_0::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
if (vtxShaderCString == NULL)
{
INFO("OpenGL ES: The FOG vertex shader is unavailable.\n");
error = OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR;
return error;
}
else if (fragShaderCString == NULL)
{
INFO("OpenGL ES: The FOG fragment shader is unavailable.\n");
error = OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR;
return error;
}
const s32 fogOffset = fogProgramKey.offset;
const GLfloat fogOffsetf = (GLfloat)fogOffset / 32767.0f;
const s32 fogStep = 0x0400 >> fogProgramKey.shift;
std::stringstream shaderHeader;
shaderHeader << "#version 300 es\n";
shaderHeader << "precision highp float;\n";
shaderHeader << "precision highp int;\n";
shaderHeader << "\n";
std::stringstream vsHeader;
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
std::stringstream fsHeader;
fsHeader << "#define FOG_OFFSET " << fogOffset << "\n";
fsHeader << "#define FOG_OFFSETF " << fogOffsetf << (((fogOffsetf == 0.0f) || (fogOffsetf == 1.0f)) ? ".0" : "") << "\n";
fsHeader << "#define FOG_STEP " << fogStep << "\n";
fsHeader << "\n";
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
OGLFogShaderID shaderID;
shaderID.program = 0;
shaderID.fragShader = 0;
error = this->ShaderProgramCreate(OGLRef.vertexFogShaderID,
shaderID.fragShader,
shaderID.program,
vtxShaderCode.c_str(),
fragShaderCode.c_str());
this->_fogProgramMap[fogProgramKey.key] = shaderID;
if (error != OGLERROR_NOERR)
{
INFO("OpenGL ES: Failed to create the FOG shader program.\n");
glUseProgram(0);
this->DestroyFogProgram(fogProgramKey);
return error;
}
glLinkProgram(shaderID.program);
if (!this->ValidateShaderProgramLink(shaderID.program))
{
INFO("OpenGL ES: Failed to link the FOG shader program.\n");
glUseProgram(0);
this->DestroyFogProgram(fogProgramKey);
return OGLERROR_SHADER_CREATE_ERROR;
}
glValidateProgram(shaderID.program);
glUseProgram(shaderID.program);
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(shaderID.program, "RenderStates");
glUniformBlockBinding(shaderID.program, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
const GLint uniformTexGDepth = glGetUniformLocation(shaderID.program, "texInFragDepth");
const GLint uniformTexGFog = glGetUniformLocation(shaderID.program, "texInFogAttributes");
const GLint uniformTexFogDensityTable = glGetUniformLocation(shaderID.program, "texFogDensityTable");
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
glUniform1i(uniformTexGFog, OGLTextureUnitID_FogAttr);
glUniform1i(uniformTexFogDensityTable, OGLTextureUnitID_LookupTable);
return OGLERROR_NOERR;
}
Render3DError OpenGLESRenderer_3_0::CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
{
return error;
}
std::stringstream shaderHeader;
shaderHeader << "#version 300 es\n";
shaderHeader << "precision highp float;\n";
shaderHeader << "precision highp int;\n";
shaderHeader << "\n";
shaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n";
shaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n";
shaderHeader << "\n";
std::stringstream vsHeader;
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
std::stringstream fsHeader;
fsHeader << "#define OUT_COLOR layout (location = " << (OGL_WORKING_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
error = this->ShaderProgramCreate(OGLRef.vertexFramebufferOutput6665ShaderID,
OGLRef.fragmentFramebufferRGBA6665OutputShaderID,
OGLRef.programFramebufferRGBA6665OutputID,
vtxShaderCode.c_str(),
fragShaderCode.c_str());
if (error != OGLERROR_NOERR)
{
INFO("OpenGL ES: Failed to create the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n");
glUseProgram(0);
this->DestroyFramebufferOutput6665Programs();
return error;
}
glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID);
if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID))
{
INFO("OpenGL ES: Failed to link the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n");
glUseProgram(0);
this->DestroyFramebufferOutput6665Programs();
return OGLERROR_SHADER_CREATE_ERROR;
}
glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID);
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor");
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
return OGLERROR_NOERR;
}

View File

@ -0,0 +1,59 @@
/*
Copyright (C) 2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OGLRENDER_ES3_H
#define OGLRENDER_ES3_H
#include "OGLRender_3_2.h"
// A port that wants to use the OpenGL ES renderer must assign the two following functions
// to OGLLoadEntryPoints_ES_3_0_Func and OGLCreateRenderer_ES_3_0_Func, respectively.
//
// In addition, the port must add the following GPU3DInterface objects to core3DList:
// - gpu3Dgl_ES_3_0: Selects the OpenGL ES 3.0 renderer, and returns an error if it is
// not available on the host system.
//
// Finally, the port must call GPU->Set3DRendererByID() and pass in the index where
// gpu3Dgl_ES_3_0 exists in core3DList so that the emulator can create the appropriate
// OpenGLRenderer object.
//
// Example code:
// OGLLoadEntryPoints_ES_3_0_Func = &OGLLoadEntryPoints_ES_3_0;
// OGLCreateRenderer_ES_3_0_Func = &OGLCreateRenderer_ES_3_0;
// GPU3DInterface *core3DList[] = { &gpu3DNull, &gpu3DRasterize, &gpu3Dgl_ES_3_0, NULL };
// GPU->Set3DRendererByID(2);
void OGLLoadEntryPoints_ES_3_0();
void OGLCreateRenderer_ES_3_0(OpenGLRenderer **rendererPtr);
class OpenGLESRenderer_3_0 : public OpenGLRenderer_3_2
{
protected:
virtual Render3DError CreateGeometryPrograms();
virtual Render3DError CreateClearImageProgram(const char *vsCString, const char *fsCString);
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString);
public:
OpenGLESRenderer_3_0();
virtual Render3DError InitExtensions();
};
#endif // OGLRENDER_ES3_H

View File

@ -348,7 +348,7 @@ int MemROMReaderWrite(void * file, void * buffer, u32 size)
if(remain<todo)
todo = remain;
if(todo==1) *(u8*)buffer = ((u8*)mem.buf)[mem.pos];
if (todo == 1) ((u8*)mem.buf)[mem.pos] = *(u8*)buffer;
else memcpy((u8*)mem.buf + mem.pos,buffer, todo);
mem.pos += todo;
return todo;

View File

@ -49,7 +49,14 @@ static inline u8 read08(u32 addr) { return _MMU_read08<ARMCPU_ARM7,MMU_AT_DEBUG>
static inline s8 read_s8(u32 addr) { return (s8)_MMU_read08<ARMCPU_ARM7,MMU_AT_DEBUG>(addr); }
#define K_ADPCM_LOOPING_RECOVERY_INDEX 99999
#define COSINE_INTERPOLATION_RESOLUTION 8192
#define CATMULLROM_INTERPOLATION_RESOLUTION_BITS 11
#define CATMULLROM_INTERPOLATION_RESOLUTION (1<<CATMULLROM_INTERPOLATION_RESOLUTION_BITS)
#define COSINE_INTERPOLATION_RESOLUTION_BITS 13
#define COSINE_INTERPOLATION_RESOLUTION (1<<COSINE_INTERPOLATION_RESOLUTION_BITS)
#define SPUCHAN_PCM16B_AT(x) ((u32)(x) % SPUINTERPOLATION_TAPS)
//#ifdef FASTBUILD
#undef FORCEINLINE
@ -96,20 +103,10 @@ static const u16 adpcmtbl[89] =
0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF
};
static const s16 wavedutytbl[8][8] = {
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
{ -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
{ -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF },
{ -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF }
};
static s32 precalcdifftbl[89][16];
static u8 precalcindextbl[89][8];
static double cos_lut[COSINE_INTERPOLATION_RESOLUTION];
static u16 catmullrom_lut[CATMULLROM_INTERPOLATION_RESOLUTION][4];
static u16 cos_lut[COSINE_INTERPOLATION_RESOLUTION];
static const double ARM7_CLOCK = 33513982;
@ -129,6 +126,14 @@ static FORCEINLINE T MinMax(T val, T min, T max)
return val;
}
// T must be unsigned type
template<typename T>
static FORCEINLINE T AddAndReturnCarry(T *a, T b) {
T c = (*a >= (-b));
*a += b;
return c;
}
//--------------external spu interface---------------
int SPU_ChangeSoundCore(int coreid, int newBufferSizeBytes)
@ -200,9 +205,23 @@ void SPU_ReInit(bool fakeBoot)
int SPU_Init(int coreid, int newBufferSizeBytes)
{
// Build the cosine interpolation LUT
// Build the interpolation LUTs
for (size_t i = 0; i < CATMULLROM_INTERPOLATION_RESOLUTION; i++) {
// This is the Catmull-Rom spline, refactored into a FIR filter
// If we wanted to, we could stick entirely to integer maths
// here, but I doubt it's worth the hassle.
double x = i / (double)CATMULLROM_INTERPOLATION_RESOLUTION;
double a = x*(x*(-x + 2) - 1);
double b = x*x*(3*x - 5) + 2;
double c = x*(x*(-3*x + 4) + 1);
double d = x*x*(x - 1);
catmullrom_lut[i][0] = (u16)floor((1u<<15) * -0.5*a);
catmullrom_lut[i][1] = (u16)floor((1u<<15) * 0.5*b);
catmullrom_lut[i][2] = (u16)floor((1u<<15) * 0.5*c);
catmullrom_lut[i][3] = (u16)floor((1u<<15) * -0.5*d);
}
for (size_t i = 0; i < COSINE_INTERPOLATION_RESOLUTION; i++)
cos_lut[i] = (1.0 - cos(((double)i/(double)COSINE_INTERPOLATION_RESOLUTION) * M_PI)) * 0.5;
cos_lut[i] = (u16)floor((1u<<16) * ((1.0 - cos(((double)i/(double)COSINE_INTERPOLATION_RESOLUTION) * M_PI)) * 0.5));
SPU_core = new SPU_struct((int)ceil(samples_per_hline));
SPU_Reset();
@ -366,7 +385,11 @@ void SPU_struct::ShutUp()
static FORCEINLINE void adjust_channel_timer(channel_struct *chan)
{
chan->sampinc = (((double)ARM7_CLOCK) / (DESMUME_SAMPLE_RATE * 2)) / (double)(0x10000 - chan->timer);
// ARM7_CLOCK / (DESMUME_SAMPLE_RATE*2) / (2^16 - Timer)
// = ARM7_CLOCK / (DESMUME_SAMPLE_RATE*2 * (2^16 - Timer))
// ... and then round up for good measure
u64 sampinc = ((u32)ARM7_CLOCK*(1ull << 32) - 1) / (DESMUME_SAMPLE_RATE * 2ull * (0x10000 - chan->timer)) + 1;
chan->sampincInt = (u32)(sampinc >> 32), chan->sampincFrac = (u32)sampinc;
}
void SPU_struct::KeyProbe(int chan_num)
@ -399,6 +422,12 @@ void SPU_struct::KeyOn(int channel)
thischan.totlength = thischan.length + thischan.loopstart;
adjust_channel_timer(&thischan);
thischan.pcm16bOffs = 0;
for(int i=0;i<SPUINTERPOLATION_TAPS;i++)
{
thischan.pcm16b[i] = 0;
}
//printf("keyon %d totlength:%d\n",channel,thischan.totlength);
@ -411,39 +440,33 @@ void SPU_struct::KeyOn(int channel)
case 0: // 8-bit
// thischan.loopstart = thischan.loopstart << 2;
// thischan.length = (thischan.length << 2) + thischan.loopstart;
thischan.sampcnt = -3;
thischan.sampcntFrac = 0, thischan.sampcntInt = -3;
break;
case 1: // 16-bit
// thischan.loopstart = thischan.loopstart << 1;
// thischan.length = (thischan.length << 1) + thischan.loopstart;
thischan.sampcnt = -3;
thischan.sampcntFrac = 0, thischan.sampcntInt = -3;
break;
case 2: // ADPCM
{
thischan.pcm16b = (s16)read16(thischan.addr);
thischan.pcm16b_last = thischan.pcm16b;
thischan.index = read08(thischan.addr + 2) & 0x7F;;
thischan.lastsampcnt = 7;
thischan.sampcnt = -3;
thischan.loop_index = K_ADPCM_LOOPING_RECOVERY_INDEX;
// thischan.loopstart = thischan.loopstart << 3;
// thischan.length = (thischan.length << 3) + thischan.loopstart;
break;
}
thischan.pcm16b[0] = (s16)read16(thischan.addr);
thischan.index = read08(thischan.addr + 2) & 0x7F;
thischan.sampcntFrac = 0, thischan.sampcntInt = -3;
thischan.loop_index = K_ADPCM_LOOPING_RECOVERY_INDEX;
// thischan.loopstart = thischan.loopstart << 3;
// thischan.length = (thischan.length << 3) + thischan.loopstart;
break;
case 3: // PSG
{
thischan.sampcnt = -1;
thischan.x = 0x7FFF;
break;
}
thischan.sampcntFrac = 0, thischan.sampcntInt = -1;
thischan.x = 0x7FFF;
break;
default: break;
}
thischan.double_totlength_shifted = (double)(thischan.totlength << format_shift[thischan.format]);
thischan.totlength_shifted = thischan.totlength << format_shift[thischan.format];
if(thischan.format != 3)
{
if(thischan.double_totlength_shifted == 0)
if(thischan.totlength_shifted == 0)
{
printf("INFO: Stopping channel %d due to zero length\n",channel);
thischan.status = CHANSTAT_STOPPED;
@ -493,7 +516,7 @@ u8 SPU_struct::ReadByte(u32 addr)
//SOUNDBIAS
case 0x504: return regs.soundbias >> 0;
case 0x505: return regs.soundbias >> 8;
//SNDCAP0CNT/SNDCAP1CNT
case 0x508:
case 0x509:
@ -742,7 +765,7 @@ void SPU_struct::ProbeCapture(int which)
u32 len = cap.len;
if(len==0) len=1;
cap.runtime.maxdad = cap.dad + len*4;
cap.runtime.sampcnt = 0;
cap.runtime.sampcntFrac = cap.runtime.sampcntInt = 0;
cap.runtime.fifo.reset();
}
@ -1018,161 +1041,109 @@ void SPU_struct::WriteLong(u32 addr, u32 val)
} //switch on address
}
template<SPUInterpolationMode INTERPOLATE_MODE> static FORCEINLINE s32 Interpolate(s32 a, s32 b, double ratio)
//////////////////////////////////////////////////////////////////////////////
template<SPUInterpolationMode INTERPOLATE_MODE> static FORCEINLINE s32 Interpolate(const s16 *pcm16b, u8 pcm16bOffs, u32 subPos)
{
double sampleA = (double)a;
double sampleB = (double)b;
ratio = ratio - sputrunc(ratio);
switch (INTERPOLATE_MODE)
{
case SPUInterpolation_CatmullRom:
{
// Catmull-Rom spline
// Delay: 2 samples, Maximum gain: 1.25
s32 a = pcm16b[SPUCHAN_PCM16B_AT(pcm16bOffs - 3)];
s32 b = pcm16b[SPUCHAN_PCM16B_AT(pcm16bOffs - 2)];
s32 c = pcm16b[SPUCHAN_PCM16B_AT(pcm16bOffs - 1)];
s32 d = pcm16b[SPUCHAN_PCM16B_AT(pcm16bOffs - 0)];
const u16 *w = catmullrom_lut[subPos >> (32 - CATMULLROM_INTERPOLATION_RESOLUTION_BITS)];
return (-a*(s32)w[0] + b*(s32)w[1] + c*(s32)w[2] - d*(s32)w[3]) >> 15;
}
case SPUInterpolation_Cosine:
{
// Cosine Interpolation Formula:
// ratio2 = (1 - cos(ratio * M_PI)) / 2
// sampleI = sampleA * (1 - ratio2) + sampleB * ratio2
return s32floor((cos_lut[(unsigned int)(ratio * (double)COSINE_INTERPOLATION_RESOLUTION)] * (sampleB - sampleA)) + sampleA);
break;
// Delay: 1 sample, Maximum gain: 1.0
s32 a = pcm16b[SPUCHAN_PCM16B_AT(pcm16bOffs - 1)];
s32 b = pcm16b[SPUCHAN_PCM16B_AT(pcm16bOffs - 0)];
s32 subPos16 = (s32)cos_lut[subPos >> (32 - COSINE_INTERPOLATION_RESOLUTION_BITS)];
return a + ((b - a)*subPos16 >> 16);
}
case SPUInterpolation_Linear:
{
// Linear Interpolation Formula:
// sampleI = sampleA * (1 - ratio) + sampleB * ratio
return s32floor((ratio * (sampleB - sampleA)) + sampleA);
break;
// Delay: 1 sample, Maximum gain: 1.0
s32 a = pcm16b[SPUCHAN_PCM16B_AT(pcm16bOffs - 1)];
s32 b = pcm16b[SPUCHAN_PCM16B_AT(pcm16bOffs - 0)];
s32 subPos16 = subPos >> (32 - 16);
return a + ((b - a)*subPos16 >> 16);
}
default:
break;
// Delay: 0 samples, Maximum gain: 1.0
return pcm16b[SPUCHAN_PCM16B_AT(pcm16bOffs)];
}
}
static FORCEINLINE s32 Fetch8BitData(channel_struct *chan, s32 pos)
{
if(pos < 0) return 0;
return read_s8(chan->addr + pos*1) << 8;
}
static FORCEINLINE s32 Fetch16BitData(channel_struct *chan, s32 pos)
{
if(pos < 0) return 0;
return read16(chan->addr + pos*2);
}
static FORCEINLINE s32 FetchADPCMData(channel_struct *chan, s32 pos)
{
if(pos < 8) return 0;
s16 last = chan->pcm16b[SPUCHAN_PCM16B_AT(chan->pcm16bOffs)];
if(pos == (chan->loopstart<<3)) {
//if(chan->loop_index != K_ADPCM_LOOPING_RECOVERY_INDEX) printf("over-snagging\n");
chan->loop_pcm16b = last;
chan->loop_index = chan->index;
}
return a;
const u32 shift = (pos&1) * 4;
const u32 data4bit = ((u32)read08(chan->addr + (pos>>1))) >> shift;
const s32 diff = precalcdifftbl [chan->index][data4bit & 0xF];
chan->index = precalcindextbl[chan->index][data4bit & 0x7];
return MinMax(last + diff, -0x8000, 0x7FFF);
}
//////////////////////////////////////////////////////////////////////////////
template<SPUInterpolationMode INTERPOLATE_MODE> static FORCEINLINE void Fetch8BitData(channel_struct *chan, s32 *data)
static FORCEINLINE s32 FetchPSGData(channel_struct *chan, s32 pos)
{
if (chan->sampcnt < 0)
{
*data = 0;
return;
}
if(pos < 0 || chan->num < 8) return 0;
u32 loc = sputrunc(chan->sampcnt);
if(INTERPOLATE_MODE != SPUInterpolation_None)
// Chan 8..13: Square wave, Chan 14..15: Noise
if(chan->num < 14)
{
s32 a = (s32)(read_s8(chan->addr + loc) << 8), b = a;
if(loc < (chan->totlength << 2) - 1)
b = (s32)(read_s8(chan->addr + loc + 1) << 8);
else if(chan->repeat == 1)
b = (s32)(read_s8(chan->addr + chan->loopstart*4) << 8);
*data = Interpolate<INTERPOLATE_MODE>(a, b, chan->sampcnt);
// Doing this avoids using a LUT
return ((pos%8u) > chan->waveduty) ? (-0x7FFF) : (+0x7FFF);
}
else
*data = (s32)read_s8(chan->addr + loc)<< 8;
}
template<SPUInterpolationMode INTERPOLATE_MODE> static FORCEINLINE void Fetch16BitData(const channel_struct * const chan, s32 *data)
{
if (chan->sampcnt < 0)
{
*data = 0;
return;
}
u32 loc = sputrunc(chan->sampcnt);
if(INTERPOLATE_MODE != SPUInterpolation_None)
{
s32 a = (s32)read16(loc*2 + chan->addr), b = a;
if(loc < (chan->totlength << 1) - 1)
b = (s32)read16(chan->addr + loc*2 + 2);
else if(chan->repeat == 1)
b = (s32)read16(chan->addr + chan->loopstart*2);
*data = Interpolate<INTERPOLATE_MODE>(a, b, chan->sampcnt);
}
else
*data = read16(chan->addr + loc*2);
}
template<SPUInterpolationMode INTERPOLATE_MODE> static FORCEINLINE void FetchADPCMData(channel_struct * const chan, s32 * const data)
{
if (chan->sampcnt < 8)
{
*data = 0;
return;
}
// No sense decoding, just return the last sample
if (chan->lastsampcnt != sputrunc(chan->sampcnt)){
const u32 endExclusive = sputrunc(chan->sampcnt+1);
for (u32 i = chan->lastsampcnt+1; i < endExclusive; i++)
if(chan->x & 0x1)
{
const u32 shift = (i&1)<<2;
const u32 data4bit = ((u32)read08(chan->addr + (i>>1))) >> shift;
const s32 diff = precalcdifftbl[chan->index][data4bit & 0xF];
chan->index = precalcindextbl[chan->index][data4bit & 0x7];
chan->pcm16b_last = chan->pcm16b;
chan->pcm16b = MinMax(chan->pcm16b+diff, -0x8000, 0x7FFF);
if(i == (chan->loopstart<<3)) {
if(chan->loop_index != K_ADPCM_LOOPING_RECOVERY_INDEX) printf("over-snagging\n");
chan->loop_pcm16b = chan->pcm16b;
chan->loop_index = chan->index;
}
chan->x = (chan->x >> 1) ^ 0x6000;
return -0x7FFF;
}
chan->lastsampcnt = sputrunc(chan->sampcnt);
}
if(INTERPOLATE_MODE != SPUInterpolation_None)
*data = Interpolate<INTERPOLATE_MODE>((s32)chan->pcm16b_last,(s32)chan->pcm16b,chan->sampcnt);
else
*data = (s32)chan->pcm16b;
}
static FORCEINLINE void FetchPSGData(channel_struct *chan, s32 *data)
{
if (chan->sampcnt < 0)
{
*data = 0;
return;
}
if(chan->num < 8)
{
*data = 0;
}
else if(chan->num < 14)
{
*data = (s32)wavedutytbl[chan->waveduty][(sputrunc(chan->sampcnt)) & 0x7];
}
else
{
if(chan->lastsampcnt == sputrunc(chan->sampcnt))
else
{
*data = (s32)chan->psgnoise_last;
return;
chan->x >>= 1;
return +0x7FFF;
}
u32 max = sputrunc(chan->sampcnt);
for(u32 i = chan->lastsampcnt; i < max; i++)
{
if(chan->x & 0x1)
{
chan->x = (chan->x >> 1) ^ 0x6000;
chan->psgnoise_last = -0x7FFF;
}
else
{
chan->x >>= 1;
chan->psgnoise_last = 0x7FFF;
}
}
chan->lastsampcnt = sputrunc(chan->sampcnt);
*data = (s32)chan->psgnoise_last;
}
}
@ -1201,66 +1172,41 @@ static FORCEINLINE void MixLR(SPU_struct* SPU, channel_struct *chan, s32 data)
template<int FORMAT> static FORCEINLINE void TestForLoop(SPU_struct *SPU, channel_struct *chan)
{
const int shift = (FORMAT == 0 ? 2 : 1);
// Do nothing if we haven't reached the end
if(chan->sampcntInt < chan->totlength_shifted) return;
chan->sampcnt += chan->sampinc;
if (chan->sampcnt > chan->double_totlength_shifted)
// Kill the channel if we don't repeat
if(chan->repeat != 1)
{
// Do we loop? Or are we done?
if (chan->repeat == 1)
SPU->KeyOff(chan->num);
return;
}
// ADPCM needs special handling
if(FORMAT == 2)
{
// Minimum length (the sum of PNT+LEN) is 4 words (16 bytes),
// smaller values (0..3 words) are causing hang-ups
// (busy bit remains set infinite, but no sound output occurs).
// fix: 7th Dragon (JP) - http://sourceforge.net/p/desmume/bugs/1357/
if (chan->totlength < 4) return;
// Stash loop sample and index
if(chan->loop_index == K_ADPCM_LOOPING_RECOVERY_INDEX)
{
while (chan->sampcnt > chan->double_totlength_shifted)
chan->sampcnt -= chan->double_totlength_shifted - (double)(chan->loopstart << shift);
//chan->sampcnt = (double)(chan->loopstart << shift);
chan->pcm16b[SPUCHAN_PCM16B_AT(chan->pcm16bOffs)] = (s16)read16(chan->addr);
chan->index = read08(chan->addr+2) & 0x7F;
}
else
{
SPU->KeyOff(chan->num);
SPU->bufpos = SPU->buflength;
chan->pcm16b[SPUCHAN_PCM16B_AT(chan->pcm16bOffs)] = chan->loop_pcm16b;
chan->index = chan->loop_index;
}
}
}
static FORCEINLINE void TestForLoop2(SPU_struct *SPU, channel_struct *chan)
{
// Minimum length (the sum of PNT+LEN) is 4 words (16 bytes),
// smaller values (0..3 words) are causing hang-ups
// (busy bit remains set infinite, but no sound output occurs).
// fix: 7th Dragon (JP) - http://sourceforge.net/p/desmume/bugs/1357/
if (chan->totlength < 4) return;
chan->sampcnt += chan->sampinc;
if (chan->sampcnt > chan->double_totlength_shifted)
{
// Do we loop? Or are we done?
if (chan->repeat == 1)
{
double step = (chan->double_totlength_shifted - (double)(chan->loopstart << 3));
while (chan->sampcnt > chan->double_totlength_shifted) chan->sampcnt -= step;
if(chan->loop_index == K_ADPCM_LOOPING_RECOVERY_INDEX)
{
chan->pcm16b = (s16)read16(chan->addr);
chan->index = read08(chan->addr+2) & 0x7F;
chan->lastsampcnt = 7;
}
else
{
chan->pcm16b = chan->loop_pcm16b;
chan->index = chan->loop_index;
chan->lastsampcnt = (chan->loopstart << 3);
}
}
else
{
chan->status = CHANSTAT_STOPPED;
SPU->KeyOff(chan->num);
SPU->bufpos = SPU->buflength;
}
}
// Wrap sampcnt
u32 step = chan->totlength_shifted - (chan->loopstart << format_shift[FORMAT]);
while (chan->sampcntInt >= chan->totlength_shifted) chan->sampcntInt -= step;
}
template<int CHANNELS> FORCEINLINE static void SPU_Mix(SPU_struct* SPU, channel_struct *chan, s32 data)
@ -1281,25 +1227,35 @@ template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE, int CHANNELS>
{
for (; SPU->bufpos < SPU->buflength; SPU->bufpos++)
{
if(CHANNELS != -1)
// Advance sampcnt one sample at a time. This is
// needed to keep pcm16b[] filled for interpolation.
u32 nSamplesToSkip = chan->sampincInt + AddAndReturnCarry(&chan->sampcntFrac, chan->sampincFrac);
while(nSamplesToSkip--)
{
s32 data;
switch(FORMAT)
s16 data = 0;
s32 pos = chan->sampcntInt;
if(chan->status != CHANSTAT_STOPPED)
{
case 0: Fetch8BitData<INTERPOLATE_MODE>(chan, &data); break;
case 1: Fetch16BitData<INTERPOLATE_MODE>(chan, &data); break;
case 2: FetchADPCMData<INTERPOLATE_MODE>(chan, &data); break;
case 3: FetchPSGData(chan, &data); break;
default: break;
switch(FORMAT)
{
case 0: data = Fetch8BitData (chan, pos); break;
case 1: data = Fetch16BitData(chan, pos); break;
case 2: data = FetchADPCMData(chan, pos); break;
case 3: data = FetchPSGData (chan, pos); break;
default: break;
}
}
SPU_Mix<CHANNELS>(SPU, chan, data);
chan->pcm16bOffs++;
chan->pcm16b[SPUCHAN_PCM16B_AT(chan->pcm16bOffs)] = data;
chan->sampcntInt++;
if (FORMAT != 3) TestForLoop<FORMAT>(SPU, chan);
}
switch(FORMAT) {
case 0: case 1: TestForLoop<FORMAT>(SPU, chan); break;
case 2: TestForLoop2(SPU, chan); break;
case 3: chan->sampcnt += chan->sampinc; break;
default: break;
if(CHANNELS != -1)
{
s32 data = Interpolate<INTERPOLATE_MODE>(chan->pcm16b, chan->pcm16bOffs, chan->sampcntFrac);
SPU_Mix<CHANNELS>(SPU, chan, data);
}
}
}
@ -1320,12 +1276,14 @@ template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE>
template<SPUInterpolationMode INTERPOLATE_MODE>
FORCEINLINE static void __SPU_ChanUpdate(const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan)
{
// NOTE: PSG doesn't use interpolation, or it would try to
// interpolate between the raw sample points (very bad)
switch(chan->format)
{
case 0: ___SPU_ChanUpdate<0,INTERPOLATE_MODE>(actuallyMix, SPU, chan); break;
case 1: ___SPU_ChanUpdate<1,INTERPOLATE_MODE>(actuallyMix, SPU, chan); break;
case 2: ___SPU_ChanUpdate<2,INTERPOLATE_MODE>(actuallyMix, SPU, chan); break;
case 3: ___SPU_ChanUpdate<3,INTERPOLATE_MODE>(actuallyMix, SPU, chan); break;
case 3: ___SPU_ChanUpdate<3,SPUInterpolation_None>(actuallyMix, SPU, chan); break;
default: assert(false);
}
}
@ -1334,9 +1292,10 @@ FORCEINLINE static void _SPU_ChanUpdate(const bool actuallyMix, SPU_struct* cons
{
switch(CommonSettings.spuInterpolationMode)
{
case SPUInterpolation_None: __SPU_ChanUpdate<SPUInterpolation_None>(actuallyMix, SPU, chan); break;
case SPUInterpolation_Linear: __SPU_ChanUpdate<SPUInterpolation_Linear>(actuallyMix, SPU, chan); break;
case SPUInterpolation_Cosine: __SPU_ChanUpdate<SPUInterpolation_Cosine>(actuallyMix, SPU, chan); break;
case SPUInterpolation_None: __SPU_ChanUpdate<SPUInterpolation_None>(actuallyMix, SPU, chan); break;
case SPUInterpolation_Linear: __SPU_ChanUpdate<SPUInterpolation_Linear>(actuallyMix, SPU, chan); break;
case SPUInterpolation_Cosine: __SPU_ChanUpdate<SPUInterpolation_Cosine>(actuallyMix, SPU, chan); break;
case SPUInterpolation_CatmullRom: __SPU_ChanUpdate<SPUInterpolation_CatmullRom>(actuallyMix, SPU, chan); break;
default: assert(false);
}
}
@ -1487,13 +1446,13 @@ static void SPU_MixAudio_Advanced(bool actuallyMix, SPU_struct *SPU, int length)
for (int capchan = 0; capchan < 2; capchan++)
{
SPU_struct::REGS::CAP& cap = SPU->regs.cap[capchan];
channel_struct& srcChan = SPU->channels[1 + 2 * capchan];
if (SPU->regs.cap[capchan].runtime.running)
{
SPU_struct::REGS::CAP& cap = SPU->regs.cap[capchan];
u32 last = sputrunc(cap.runtime.sampcnt);
cap.runtime.sampcnt += SPU->channels[1+2*capchan].sampinc;
u32 curr = sputrunc(cap.runtime.sampcnt);
for (u32 j = last; j < curr; j++)
u32 nSamplesToProcess = srcChan.sampincInt + AddAndReturnCarry(&cap.runtime.sampcntFrac, srcChan.sampincFrac);
cap.runtime.sampcntInt += nSamplesToProcess;
while(nSamplesToProcess--)
{
//so, this is a little strange. why go through a fifo?
//it seems that some games will set up a reverb effect by capturing
@ -1544,7 +1503,7 @@ static void SPU_MixAudio_Advanced(bool actuallyMix, SPU_struct *SPU, int length)
if (cap.runtime.curdad >= cap.runtime.maxdad)
{
cap.runtime.curdad = cap.dad;
cap.runtime.sampcnt -= cap.len*multiplier;
cap.runtime.sampcntInt -= cap.len*multiplier;
}
} //sampinc loop
} //if capchan running
@ -1604,14 +1563,14 @@ static void SPU_MixAudio(bool actuallyMix, SPU_struct *SPU, int length)
for (int capchan = 0; capchan < 2; capchan++)
{
SPU_struct::REGS::CAP& cap = SPU->regs.cap[capchan];
channel_struct& srcChan = SPU->channels[1 + 2 * capchan];
if (cap.runtime.running)
{
for (int samp = 0; samp < length; samp++)
{
u32 last = sputrunc(cap.runtime.sampcnt);
cap.runtime.sampcnt += SPU->channels[1+2*capchan].sampinc;
u32 curr = sputrunc(cap.runtime.sampcnt);
for (u32 j = last; j < curr; j++)
u32 nSamplesToProcess = srcChan.sampincInt + AddAndReturnCarry(&cap.runtime.sampcntFrac, srcChan.sampincFrac);
cap.runtime.sampcntInt += nSamplesToProcess;
while (nSamplesToProcess--)
{
if (cap.bits8)
{
@ -1627,7 +1586,7 @@ static void SPU_MixAudio(bool actuallyMix, SPU_struct *SPU, int length)
if (cap.runtime.curdad >= cap.runtime.maxdad)
{
cap.runtime.curdad = cap.dad;
cap.runtime.sampcnt -= cap.len*(cap.bits8?4:2);
cap.runtime.sampcntInt -= cap.len*(cap.bits8?4:2);
}
}
}
@ -1733,7 +1692,7 @@ void SPU_Emulate_user(bool mix)
postProcessBufferSize = freeSampleCount * 2 * sizeof(s16);
postProcessBuffer = (s16 *)realloc(postProcessBuffer, postProcessBufferSize);
}
if (soundProcessor->PostProcessSamples != NULL)
{
processedSampleCount = soundProcessor->PostProcessSamples(postProcessBuffer, freeSampleCount, _currentSynchMode, _currentSynchronizer);
@ -1957,7 +1916,7 @@ void WAV_WavSoundUpdate(void* soundData, int numSamples, WAVMode mode)
void spu_savestate(EMUFILE &os)
{
//version
os.write_32LE(6);
os.write_32LE(7);
SPU_struct *spu = SPU_core;
@ -1973,18 +1932,18 @@ void spu_savestate(EMUFILE &os)
os.write_u8(chan.repeat);
os.write_u8(chan.format);
os.write_u8(chan.status);
os.write_u8(chan.pcm16bOffs);
os.write_32LE(chan.addr);
os.write_16LE(chan.timer);
os.write_16LE(chan.loopstart);
os.write_32LE(chan.length);
os.write_doubleLE(chan.sampcnt);
os.write_doubleLE(chan.sampinc);
os.write_32LE(chan.lastsampcnt);
os.write_16LE(chan.pcm16b);
os.write_16LE(chan.pcm16b_last);
os.write_32LE(chan.sampcntFrac);
os.write_32LE(chan.sampcntInt);
os.write_32LE(chan.sampincFrac);
os.write_32LE(chan.sampincInt);
for (int i = 0; i < SPUINTERPOLATION_TAPS; i++) os.write_16LE(chan.pcm16b[i]);
os.write_32LE(chan.index);
os.write_16LE(chan.x);
os.write_16LE(chan.psgnoise_last);
os.write_u8(chan.keyon);
}
@ -2010,7 +1969,8 @@ void spu_savestate(EMUFILE &os)
os.write_u8(spu->regs.cap[i].runtime.running);
os.write_32LE(spu->regs.cap[i].runtime.curdad);
os.write_32LE(spu->regs.cap[i].runtime.maxdad);
os.write_doubleLE(spu->regs.cap[i].runtime.sampcnt);
os.write_32LE(spu->regs.cap[i].runtime.sampcntFrac);
os.write_32LE(spu->regs.cap[i].runtime.sampcntInt);
}
for (int i = 0; i < 2; i++)
@ -2044,29 +2004,53 @@ bool spu_loadstate(EMUFILE &is, int size)
is.read_u8(chan.repeat);
is.read_u8(chan.format);
is.read_u8(chan.status);
if (version >= 7) is.read_u8(chan.pcm16bOffs); else chan.pcm16bOffs = 0;
is.read_32LE(chan.addr);
is.read_16LE(chan.timer);
is.read_16LE(chan.loopstart);
is.read_32LE(chan.length);
chan.totlength = chan.length + chan.loopstart;
chan.double_totlength_shifted = (double)(chan.totlength << format_shift[chan.format]);
//printf("%f\n",chan.double_totlength_shifted);
if (version >= 2)
chan.totlength_shifted = chan.totlength << format_shift[chan.format];
if(version >= 7) {
is.read_32LE(chan.sampcntFrac);
is.read_32LE(chan.sampcntInt);
is.read_32LE(chan.sampincFrac);
is.read_32LE(chan.sampincInt);
}
else if (version >= 2)
{
is.read_doubleLE(chan.sampcnt);
is.read_doubleLE(chan.sampinc);
double temp;
s64 temp2;
is.read_doubleLE(temp); temp2 = (s64)(temp * (1ll << 32));
chan.sampcntFrac = (u32)temp2;
chan.sampcntInt = (s32)(temp2 >> 32);
is.read_doubleLE(temp); temp2 = (u64)(temp * (1ull << 32)); // Intentionally unsigned
chan.sampincFrac = (u32)temp2;
chan.sampincInt = (u32)(temp2 >> 32);
}
else
{
is.read_32LE(*(u32 *)&chan.sampcnt);
is.read_32LE(*(u32 *)&chan.sampinc);
// FIXME
// What even is supposed to be happening here?
// sampcnt and sampinc were double type before
// I even made any changes, so this is broken.
chan.sampcntFrac = 0;
is.read_32LE(chan.sampcntInt);
chan.sampincFrac = 0;
is.read_32LE(chan.sampincInt);
}
if (version >= 7) {
for (int i = 0; i < SPUINTERPOLATION_TAPS; i++) is.read_16LE(chan.pcm16b[i]);
}
else
{
is.fseek(4, SEEK_CUR); // chan.lastsampcnt (LE32)
is.read_16LE(chan.pcm16b[0]); // chan.pcm16b
is.fseek(2, SEEK_CUR); // chan.pcm16b_last
}
is.read_32LE(chan.lastsampcnt);
is.read_16LE(chan.pcm16b);
is.read_16LE(chan.pcm16b_last);
is.read_32LE(chan.index);
is.read_16LE(chan.x);
is.read_16LE(chan.psgnoise_last);
if (version < 7) is.fseek(2, SEEK_CUR); // chan.psgnoise_last (LE16)
if (version >= 4)
is.read_u8(chan.keyon);
@ -2105,7 +2089,18 @@ bool spu_loadstate(EMUFILE &is, int size)
is.read_u8(spu->regs.cap[i].runtime.running);
is.read_32LE(spu->regs.cap[i].runtime.curdad);
is.read_32LE(spu->regs.cap[i].runtime.maxdad);
is.read_doubleLE(spu->regs.cap[i].runtime.sampcnt);
if (version >= 7) {
is.read_32LE(spu->regs.cap[i].runtime.sampcntFrac);
is.read_32LE(spu->regs.cap[i].runtime.sampcntInt);
}
else
{
double temp;
u64 temp2;
is.read_doubleLE(temp); temp2 = (u64)(temp * (1ull << 32));
spu->regs.cap[i].runtime.sampcntFrac = (u32)temp2;
spu->regs.cap[i].runtime.sampcntInt = (u32)(temp2 >> 32);
}
}
}

View File

@ -36,10 +36,9 @@ class EMUFILE;
#define CHANSTAT_STOPPED 0
#define CHANSTAT_PLAY 1
#define SPUINTERPOLATION_TAPS 4 // Must be at least 4 for Catmull-Rom interpolation
//who made these static? theyre used in multiple places.
FORCEINLINE u32 sputrunc(float f) { return u32floor(f); }
FORCEINLINE u32 sputrunc(double d) { return u32floor(d); }
FORCEINLINE s32 spumuldiv7(s32 val, u8 multiplier) {
assert(multiplier <= 127);
return (multiplier == 127) ? val : ((val * multiplier) >> 7);
@ -49,7 +48,8 @@ enum SPUInterpolationMode
{
SPUInterpolation_None = 0,
SPUInterpolation_Linear = 1,
SPUInterpolation_Cosine = 2
SPUInterpolation_Cosine = 2,
SPUInterpolation_CatmullRom = 3
};
struct SoundInterface_struct
@ -84,22 +84,21 @@ struct channel_struct
format(0),
keyon(0),
status(0),
pcm16bOffs(0),
addr(0),
timer(0),
loopstart(0),
length(0),
totlength(0),
double_totlength_shifted(0.0),
sampcnt(0.0),
sampinc(0.0),
lastsampcnt(0),
pcm16b(0),
pcm16b_last(0),
totlength_shifted(0),
sampcntFrac(0),
sampcntInt(0),
sampincFrac(0),
sampincInt(0),
loop_pcm16b(0),
index(0),
loop_index(0),
x(0),
psgnoise_last(0)
x(0)
{}
u32 num;
u8 vol;
@ -111,22 +110,24 @@ struct channel_struct
u8 format;
u8 keyon;
u8 status;
u8 pcm16bOffs;
u32 addr;
u16 timer;
u16 loopstart;
u32 length;
u32 totlength;
double double_totlength_shifted;
double sampcnt;
double sampinc;
s32 totlength_shifted;
u32 sampcntFrac;
s32 sampcntInt;
u32 sampincFrac;
u32 sampincInt;
s16 pcm16b[SPUINTERPOLATION_TAPS];
// ADPCM specific
u32 lastsampcnt;
s16 pcm16b, pcm16b_last;
s16 loop_pcm16b;
s32 index;
int loop_index;
// PSG noise
u16 x;
s16 psgnoise_last;
};
class SPUFifo
@ -196,7 +197,8 @@ public:
u8 running;
u32 curdad;
u32 maxdad;
double sampcnt;
u32 sampcntFrac;
u32 sampcntInt;
SPUFifo fifo;
} runtime;
} cap[2];

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2013-2105 DeSmuME team
Copyright (C) 2013-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -0,0 +1,87 @@
//HCV-1000 emulation code adapted from GBE+: https://github.com/shonumi/gbe-plus
/*
Modifications Copyright (C) 2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "../slot2.h"
u8 hcv1000_cnt;
char hcv1000_data[16];
class Slot2_HCV1000 : public ISlot2Interface
{
public:
virtual Slot2Info const* info()
{
static Slot2InfoSimple info("Sega Card Reader", "Sega Card Reader(HCV-1000) add-on", 0x09);
return &info;
}
virtual bool init()
{
hcv1000_cnt = 0;
memset(hcv1000_data, 0x5F, 16);
return TRUE;
}
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
{
if (addr == 0xA000000) { hcv1000_cnt = (val & 0x83); }
}
virtual u8 readByte(u8 PROCNUM, u32 addr)
{
u8 slot_byte = 0xFF;
//Reading these cart addresses is for detection
if (addr < 0x8020000)
{
u8 data = 0xF0 | ((addr & 0x1F) >> 1);
slot_byte = (addr & 0x1) ? 0xFD : data;
}
//HCV_CNT
else if (addr == 0xA000000) { slot_byte = hcv1000_cnt; }
//HCV_DATA
else if ((addr >= 0xA000010) && (addr <= 0xA00001F))
{
slot_byte = (u8)hcv1000_data[addr & 0xF];
}
return slot_byte;
}
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xFDFD; };
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFDFDFDFD; };
};
ISlot2Interface* construct_Slot2_HCV1000() { return new Slot2_HCV1000(); }
void HCV1000_setReady()
{
hcv1000_cnt &= ~0x80;
}
void HCV1000_setBarcode(std::string barcode)
{
barcode.resize(16, '_');
memcpy(hcv1000_data, barcode.c_str(), barcode.length());
}

View File

@ -2419,7 +2419,7 @@ TEMPLATE static u32 FASTCALL OP_UMLAL_S(const u32 i)
cpu->R[REG_POS(i,12)] += tmp;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) && (cpu->R[REG_POS(i,12)]==0);
MUL_UMxxL_END(3);
}
@ -2479,7 +2479,7 @@ TEMPLATE static u32 FASTCALL OP_SMULL_S(const u32 i)
cpu->R[REG_POS(i,16)] = (u32)(res>>32);
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) && (cpu->R[REG_POS(i,12)]==0);
MUL_SMxxL_END(2);
}
@ -2494,7 +2494,7 @@ TEMPLATE static u32 FASTCALL OP_SMLAL_S(const u32 i)
cpu->R[REG_POS(i,12)] += tmp;
cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) && (cpu->R[REG_POS(i,12)]==0);
MUL_SMxxL_END(3);
}

View File

@ -60,6 +60,7 @@
using namespace AsmJit;
#if (LOG_JIT_LEVEL > 0)
#include "../modules/Disassembler.h"
#define LOG_JIT 1
#define JIT_COMMENT(...) c.comment(__VA_ARGS__)
#define printJIT(buf, val) { \

2002
desmume/src/cheatSystem.cpp Normal file → Executable file

File diff suppressed because it is too large Load Diff

329
desmume/src/cheatSystem.h Normal file → Executable file
View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2009-2021 DeSmuME team
Copyright (C) 2009-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -24,31 +24,51 @@
#define CHEAT_VERSION_MAJOR 2
#define CHEAT_VERSION_MINOR 0
#define MAX_CHEAT_LIST 100
#define MAX_XX_CODE 1024
#define CHEAT_FILE_MIN_FGETS_BUFFER 32768
#define CHEAT_DB_GAME_TITLE_SIZE 256
#define CHEAT_TYPE_EMPTY 0xFF
#define CHEAT_TYPE_INTERNAL 0
#define CHEAT_TYPE_AR 1
#define CHEAT_TYPE_CODEBREAKER 2
enum CheatSystemError
{
CheatSystemError_NoError = 0,
CheatSystemError_FileOpenFailed = 1,
CheatSystemError_FileFormatInvalid = 2,
CheatSystemError_GameNotFound = 3,
CheatSystemError_LoadEntryError = 4,
CheatSystemError_FileSaveFailed = 5,
CheatSystemError_FileDoesNotExist = 6
};
struct CHEATS_LIST
{
CHEATS_LIST()
{
memset(this,0,sizeof(*this));
type = 0xFF;
type = CHEAT_TYPE_EMPTY;
}
u8 type;
BOOL enabled;
u8 enabled;
// TODO
u8 freezeType; // 0 - normal freeze
// 1 - can decrease
// 2 - can increase
u32 code[MAX_XX_CODE][2];
char description[1024];
union
{
char description[1024];
struct
{
char descriptionMajor[512];
char descriptionMinor[512];
};
};
u32 num;
u8 size;
};
@ -56,56 +76,85 @@ struct CHEATS_LIST
class CHEATS
{
private:
std::vector<CHEATS_LIST> list;
u8 filename[MAX_PATH];
u32 currentGet;
std::vector<CHEATS_LIST> _list;
u8 _filename[MAX_PATH];
size_t _currentGet;
void clear();
void ARparser(CHEATS_LIST& cheat);
char *clearCode(char *s);
public:
CHEATS()
: currentGet(0)
: _currentGet(0)
{
memset(filename, 0, sizeof(filename));
memset(_filename, 0, sizeof(_filename));
}
~CHEATS() {}
void init(char *path);
BOOL add(u8 size, u32 address, u32 val, char *description, BOOL enabled);
BOOL update(u8 size, u32 address, u32 val, char *description, BOOL enabled, u32 pos);
BOOL move(u32 srcPos, u32 dstPos);
BOOL add_AR(char *code, char *description, BOOL enabled);
BOOL update_AR(char *code, char *description, BOOL enabled, u32 pos);
BOOL add_AR_Direct(CHEATS_LIST cheat);
BOOL add_CB(char *code, char *description, BOOL enabled);
BOOL update_CB(char *code, char *description, BOOL enabled, u32 pos);
BOOL remove(u32 pos);
void getListReset();
BOOL getList(CHEATS_LIST *cheat);
CHEATS_LIST* getListPtr();
BOOL get(CHEATS_LIST *cheat, u32 pos);
CHEATS_LIST* getItemByIndex(const u32 pos);
u32 getSize();
size_t getActiveCount();
void setDescription(const char *description, u32 pos);
BOOL save();
BOOL load();
void process(int targetType);
void getXXcodeString(CHEATS_LIST theList, char *res_buf);
void clear();
void init(const char *thePath);
const char* getFilePath() const;
void setFilePath(const char *thePath);
static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const std::string codeString);
static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const char *codeString);
size_t addItem(const CHEATS_LIST &srcCheat);
bool add(u8 size, u32 address, u32 val, char *description, bool enabled);
bool add(u8 size, u32 address, u32 val, char *description, u8 enabled);
bool updateItemAtIndex(const CHEATS_LIST &srcCheat, const size_t pos);
bool update(u8 size, u32 address, u32 val, char *description, bool enabled, const size_t pos);
bool update(u8 size, u32 address, u32 val, char *description, u8 enabled, const size_t pos);
bool move(size_t srcPos, size_t dstPos);
size_t add_AR_Direct(const CHEATS_LIST &srcCheat);
bool add_AR(char *code, char *description, bool enabled);
bool add_AR(char *code, char *description, u8 enabled);
bool update_AR(char *code, char *description, bool enabled, const size_t pos);
bool update_AR(char *code, char *description, u8 enabled, const size_t pos);
bool add_CB(char *code, char *description, bool enabled);
bool add_CB(char *code, char *description, u8 enabled);
bool update_CB(char *code, char *description, bool enabled, const size_t pos);
bool update_CB(char *code, char *description, u8 enabled, const size_t pos);
bool remove(const size_t pos);
void toggle(bool enabled, const size_t pos);
void toggle(u8 enablbed, const size_t pos);
void getListReset();
bool getList(CHEATS_LIST *cheat);
CHEATS_LIST* getListPtr();
bool copyItemFromIndex(const size_t pos, CHEATS_LIST &outCheatItem);
CHEATS_LIST* getItemPtrAtIndex(const size_t pos) const;
size_t getListSize() const;
size_t getActiveCount() const;
void setDescription(const char *description, const size_t pos);
bool save();
bool load();
bool process(int targetType) const;
static void JitNeedsReset();
static bool ResetJitIfNeeded();
template<size_t LENGTH> static bool DirectWrite(const int targetProc, const u32 targetAddress, u32 newValue);
static bool DirectWrite(const size_t newValueLength, const int targetProc, const u32 targetAddress, u32 newValue);
static bool ARparser(const CHEATS_LIST &cheat);
static void StringFromXXCode(const CHEATS_LIST &srcCheatItem, char *outCStringBuffer);
static bool XXCodeFromString(const std::string codeString, CHEATS_LIST &outCheatItem);
static bool XXCodeFromString(const char *codeString, CHEATS_LIST &outCheatItem);
};
class CHEATSEARCH
{
private:
u8 *statMem;
u8 *mem;
u32 amount;
u32 lastRecord;
u8 *_statMem;
u8 *_mem;
u32 _amount;
u32 _lastRecord;
u32 _type;
u32 _size;
@ -113,90 +162,168 @@ private:
public:
CHEATSEARCH()
: statMem(0), mem(0), amount(0), lastRecord(0), _type(0), _size(0), _sign(0)
: _statMem(0), _mem(0), _amount(0), _lastRecord(0), _type(0), _size(0), _sign(0)
{}
~CHEATSEARCH() { close(); }
BOOL start(u8 type, u8 size, u8 sign);
BOOL close();
~CHEATSEARCH() { this->close(); }
bool start(u8 type, u8 size, u8 sign);
void close();
u32 search(u32 val);
u32 search(u8 comp);
u32 getAmount();
BOOL getList(u32 *address, u32 *curVal);
bool getList(u32 *address, u32 *curVal);
void getListReset();
};
enum CHEATS_DB_TYPE
#define CHEATDB_OFFSET_FILE_DESCRIPTION 0x00000010
#define CHEATDB_FILEOFFSET_FIRST_FAT_ENTRY 0x00000100
enum CheatDBFileFormat
{
CHEATS_DB_R4 = 0
CheatDBFileFormat_Undefined = 0,
CheatDBFileFormat_R4 = 1,
CheatDBFileFormat_Unknown = 65535
};
// This struct maps to the FAT entries in the R4 cheat database file.
#pragma pack(push)
#pragma pack(1)
typedef struct FAT_R4
{
u8 serial[4];
u32 CRC;
u8 serial[4];
u32 CRC;
u64 addr;
} FAT_R4;
#pragma pack(pop)
// Wrapper for a single entry in a memory block that contains data read from a cheat database file.
// This struct also maintains the hierarchical relationships between entries.
struct CheatDBEntry
{
u8 *base; // Pointer to the entry's base location in memory.
char *name; // Pointer to the entry's name string.
char *note; // Pointer to the entry's note string.
u32 *codeLength; // Pointer to the entry's 32-bit code length in bytes. This value is NULL if the entry is a directory.
u32 *codeData; // Pointer to the entry's code data, provided in pairs of 32-bit values. This value is NULL if the entry is a directory.
CheatDBEntry *parent;
std::vector<CheatDBEntry> child;
};
typedef struct CheatDBEntry CheatDBEntry;
class CheatDBGame
{
protected:
u32 _baseOffset; // This offset is relative to the file head.
u32 _firstEntryOffset; // This offset is relative to the file head.
u32 _encryptOffset; // This offset is relative to the memory address of this->_entryDataRawPtr.
u32 _rawDataSize;
u32 _workingDataSize;
u32 _crc;
u32 _entryCount;
std::string _title;
char _serial[4 + 1];
u8 *_entryDataRawPtr;
u8 *_entryData;
CheatDBEntry _entryRoot;
u32 _cheatItemCount;
void _UpdateDirectoryParents(CheatDBEntry &directory);
bool _CreateCheatItemFromCheatEntry(const CheatDBEntry &inEntry, const bool isHierarchical, CHEATS_LIST &outCheatItem);
size_t _DirectoryAddCheatsFlat(const CheatDBEntry &directory, const bool isHierarchical, size_t cheatIndex, CHEATS_LIST *outCheatsList);
public:
CheatDBGame();
CheatDBGame(const u32 encryptOffset, const FAT_R4 &fat, const u32 rawDataSize);
CheatDBGame(FILE *fp, const bool isEncrypted, const u32 encryptOffset, const FAT_R4 &fat, const u32 rawDataSize, u8 (&workingBuffer)[1024]);
~CheatDBGame();
void SetInitialProperties(const u32 rawDataSize, const u32 encryptOffset, const FAT_R4 &fat);
void LoadPropertiesFromFile(FILE *fp, const bool isEncrypted, u8 (&workingBuffer)[1024]);
u32 GetBaseOffset() const;
u32 GetFirstEntryOffset() const;
u32 GetEncryptOffset() const;
u32 GetRawDataSize() const;
u32 GetWorkingDataSize() const;
u32 GetCRC() const;
u32 GetEntryCount() const;
u32 GetCheatItemCount() const;
const char* GetTitle() const;
const char* GetSerial() const;
const CheatDBEntry& GetEntryRoot() const;
const u8* GetEntryRawData() const;
bool IsEntryDataLoaded() const;
u8* LoadEntryData(FILE *fp, const bool isEncrypted);
size_t ParseEntriesToCheatsListFlat(CHEATS_LIST *outCheatsList);
};
typedef std::vector<CheatDBGame> CheatDBGameList;
class CheatDBFile
{
protected:
std::string _path;
std::string _description;
std::string _formatString;
CheatDBFileFormat _format;
bool _isEncrypted;
size_t _size;
FILE *_fp;
CheatDBGame _ReadGame(const u32 encryptOffset, const FAT_R4 &fat, const u32 gameDataSize, u8 (&workingBuffer)[1024]);
public:
CheatDBFile();
~CheatDBFile();
static void R4Decrypt(u8 *buf, const size_t len, u64 n);
static bool ReadToBuffer(FILE *fp, const size_t fileOffset, const bool isEncrypted, const size_t encryptOffset, const size_t requestedSize, u8 *outBuffer);
FILE* GetFilePtr() const;
bool IsEncrypted() const;
const char* GetDescription() const;
CheatDBFileFormat GetFormat() const;
const char* GetFormatString() const;
CheatSystemError OpenFile(const char *filePath);
void CloseFile();
u32 LoadGameList(const char *gameCode, const u32 gameDatabaseCRC, CheatDBGameList &outList);
};
class CHEATSEXPORT
{
private:
CHEATS_DB_TYPE type;
bool encrypted;
FILE *fp;
u32 fsize;
u32 dataSize;
u32 encOffset;
FAT_R4 fat;
bool search();
bool getCodes();
void R4decrypt(u8 *buf, u32 len, u32 n);
u32 numCheats;
CHEATS_LIST *cheats;
u8 error; // 0 - no errors
// 1 - open failed/file not found
// 2 - file format is wrong (no valid header ID)
// 3 - cheat not found in database
// 4 - export error from database
CheatDBFile _dbFile;
CheatDBGameList _tempGameList;
CheatDBGame *_selectedDbGame;
CHEATS_LIST *_cheats;
CheatSystemError _lastError;
public:
CHEATSEXPORT() :
fp(NULL),
fsize(0),
dataSize(0),
encOffset(0),
type(CHEATS_DB_R4),
encrypted(false),
numCheats(0),
cheats(0),
CRC(0),
error(0)
{
memset(date, 0, sizeof(date));
gametitle = (u8 *)malloc(CHEAT_DB_GAME_TITLE_SIZE);
memset(gametitle, 0, CHEAT_DB_GAME_TITLE_SIZE);
}
~CHEATSEXPORT()
{
free(gametitle);
gametitle = NULL;
}
u8 *gametitle;
u8 date[17];
u32 CRC;
bool load(char *path);
void close();
CHEATS_LIST *getCheats();
u32 getCheatsNum();
u8 getErrorCode() { return error; }
CHEATSEXPORT();
~CHEATSEXPORT();
bool load(const char *path);
void close();
CHEATS_LIST *getCheats() const;
size_t getCheatsNum() const;
const char* getGameTitle() const;
const char* getDescription() const;
CheatSystemError getErrorCode() const;
};
CheatDBGame* GetCheatDBGameEntryFromList(const CheatDBGameList &gameList, const char *gameCode, const u32 gameDatabaseCRC);
void CheatItemGenerateDescriptionHierarchical(const char *itemName, const char *itemNote, CHEATS_LIST &outCheatItem);
void CheatItemGenerateDescriptionFlat(const char *folderName, const char *folderNote, const char *itemName, const char *itemNote, CHEATS_LIST &outCheatItem);
extern CHEATS *cheats;
extern CHEATSEARCH *cheatSearch;

View File

@ -397,7 +397,7 @@ bool CommandLine::parse(int argc,char **argv)
if(opt_help)
{
printf(help_string);
printf("%s",help_string);
exit(1);
}
@ -571,7 +571,7 @@ bool CommandLine::validate()
void CommandLine::errorHelp(const char* binName)
{
printerror(help_string);
printerror("%s",help_string);
}
void CommandLine::process_movieCommands()
@ -612,23 +612,23 @@ void CommandLine::process_addonCommands()
slot1_Change(NDS_SLOT1_R4);
else if(slot1 == "RETAILNAND")
slot1_Change(NDS_SLOT1_RETAIL_NAND);
else if(slot1 == "RETAILMCROM")
slot1_Change(NDS_SLOT1_RETAIL_MCROM);
else if(slot1 == "RETAILDEBUG")
slot1_Change(NDS_SLOT1_RETAIL_DEBUG);
else if(slot1 == "RETAILMCROM")
slot1_Change(NDS_SLOT1_RETAIL_MCROM);
else if(slot1 == "RETAILDEBUG")
slot1_Change(NDS_SLOT1_RETAIL_DEBUG);
if (_rtc_day != -1 || _rtc_hour != -1) {
DateTime now = DateTime::get_Now();
int cur_day = now.get_DayOfWeek();
int cur_hour = now.get_Hour();
int cur_total = cur_day * 24 + cur_hour;
int day = (_rtc_day != -1 ? _rtc_day : cur_day);
int hour = (_rtc_hour != -1 ? _rtc_hour : cur_hour);
int total = day * 24 + hour;
int diff = total - cur_total;
if (diff < 0)
diff += 24 * 7;
rtcHourOverride = diff;
}
if (_rtc_day != -1 || _rtc_hour != -1) {
DateTime now = DateTime::get_Now();
int cur_day = now.get_DayOfWeek();
int cur_hour = now.get_Hour();
int cur_total = cur_day * 24 + cur_hour;
int day = (_rtc_day != -1 ? _rtc_day : cur_day);
int hour = (_rtc_hour != -1 ? _rtc_hour : cur_hour);
int total = day * 24 + hour;
int diff = total - cur_total;
if (diff < 0)
diff += 24 * 7;
rtcHourOverride = diff;
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2008-2017 DeSmuME team
Copyright (C) 2008-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -105,22 +105,12 @@ void* malloc_aligned64(size_t length)
void* malloc_alignedCacheLine(size_t length)
{
#if defined(HOST_32)
return malloc_aligned32(length);
#elif defined(HOST_64)
return malloc_aligned64(length);
#else
return malloc_aligned16(length);
#endif
return malloc_aligned(length, CACHE_ALIGN_SIZE);
}
void* malloc_alignedPage(size_t length)
{
// WARNING!
//
// This may fail for SPARC users, which have a page size
// of 8KB instead of the more typical 4KB.
return malloc_aligned(length, 4096);
return malloc_aligned(length, PAGE_ALIGN_SIZE);
}
void free_aligned(void *ptr)

View File

@ -366,6 +366,13 @@ BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1,
}
}
return FALSE;
case 13:
if(opcode1 == 0 && opcode2 == 1)
{
*R = armcp15->processID;
return TRUE;
}
return FALSE;
default:
LOG("Unsupported CP15 operation : MRC\n");
return FALSE;
@ -488,6 +495,13 @@ BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1,
}
}
return FALSE;
case 13:
if(opcode1 == 0 && opcode2 == 1)
{
armcp15->processID = val;
return TRUE;
}
return FALSE;
default:
return FALSE;
}

View File

@ -65,7 +65,7 @@ public:
bool fail(bool unset=false) { bool ret = this->_failbit; if(unset) unfail(); return ret; }
void unfail() { this->_failbit = false; }
bool eof() { return size()==ftell(); }
virtual bool eof() { return size()==ftell(); }
size_t fread(const void *ptr, size_t bytes){
return _fread(ptr,bytes);
@ -327,6 +327,8 @@ public:
virtual void truncate(s32 length);
virtual bool eof() { return !!::feof(this->_fp); }
virtual int fprintf(const char *format, ...) {
va_list argptr;
va_start(argptr, format);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2016-2017 DeSmuME team
Copyright (C) 2016-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -21,83 +21,125 @@
#define DEPOSTERIZE_THRESHOLD 23 // Possible values are [0-255], where lower a value prevents blending and a higher value allows for more blending
static u32 Deposterize_InterpLTE(const u32 pixA, const u32 pixB)
namespace
{
const u32 aB = (pixB & 0xFF000000) >> 24;
if (aB == 0)
template <u32 DEN>
struct UnpackedPixel
{
return pixA;
}
const u32 rA = (pixA & 0x000000FF);
const u32 gA = (pixA & 0x0000FF00) >> 8;
const u32 bA = (pixA & 0x00FF0000) >> 16;
const u32 aA = (pixA & 0xFF000000) >> 24;
const u32 rB = (pixB & 0x000000FF);
const u32 gB = (pixB & 0x0000FF00) >> 8;
const u32 bB = (pixB & 0x00FF0000) >> 16;
const u32 rC = ( (rB - rA <= DEPOSTERIZE_THRESHOLD) || (rA - rB <= DEPOSTERIZE_THRESHOLD) ) ? ((rA+rB)>>1) : rA;
const u32 gC = ( (gB - gA <= DEPOSTERIZE_THRESHOLD) || (gA - gB <= DEPOSTERIZE_THRESHOLD) ) ? ((gA+gB)>>1) : gA;
const u32 bC = ( (bB - bA <= DEPOSTERIZE_THRESHOLD) || (bA - bB <= DEPOSTERIZE_THRESHOLD) ) ? ((bA+bB)>>1) : bA;
const u32 aC = ( (aB - aA <= DEPOSTERIZE_THRESHOLD) || (aA - aB <= DEPOSTERIZE_THRESHOLD) ) ? ((aA+aB)>>1) : aA;
u32 r;
u32 g;
u32 b;
u32 a;
return (rC | (gC << 8) | (bC << 16) | (aC << 24));
}
static u32 Deposterize_Blend(const u32 pixA, const u32 pixB, const u32 weightA, const u32 weightB)
{
const u32 aB = (pixB & 0xFF000000) >> 24;
if (aB == 0)
{
return pixA;
}
const u32 rbA = pixA & 0x00FF00FF;
const u32 gA = pixA & 0x0000FF00;
const u32 aA = (pixA & 0xFF000000) >> 24;
const u32 rbB = pixB & 0x00FF00FF;
const u32 gB = pixB & 0x0000FF00;
// Note: The sum of weightA and weightB must equal 16.
const u32 rbC = ( ((rbA * weightA) + (rbB * weightB)) / 16 ) & 0x00FF00FF;
const u32 gC = ( (( gA * weightA) + ( gB * weightB)) / 16 ) & 0x0000FF00;
const u32 aC = ( (( aA * weightA) + ( aB * weightB)) / 16 ) << 24;
return (rbC | gC | aC);
}
static u32 Deposterize_BlendPixel(const u32 color[9])
{
const u32 blend[9] = {
color[0],
Deposterize_InterpLTE(color[0], color[1]),
Deposterize_InterpLTE(color[0], color[2]),
Deposterize_InterpLTE(color[0], color[3]),
Deposterize_InterpLTE(color[0], color[4]),
Deposterize_InterpLTE(color[0], color[5]),
Deposterize_InterpLTE(color[0], color[6]),
Deposterize_InterpLTE(color[0], color[7]),
Deposterize_InterpLTE(color[0], color[8])
u32 pack() const
{
return ( ((r/DEN) << 0) |
((g/DEN) << 8) |
((b/DEN) << 16) |
((a/DEN) << 24) );
}
};
return Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[5], 2, 14),
Deposterize_Blend(blend[0], blend[1], 2, 14),
8, 8),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[7], 2, 14),
Deposterize_Blend(blend[0], blend[3], 2, 14),
8, 8),
8, 8),
Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[6], 7, 9),
Deposterize_Blend(blend[0], blend[2], 7, 9),
8, 8),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[8], 7, 9),
Deposterize_Blend(blend[0], blend[4], 7, 9),
8, 8),
8, 8),
12, 4);
static FORCEINLINE UnpackedPixel<2> Deposterize_InterpLTE(const UnpackedPixel<1> &pixA, const UnpackedPixel<1> &pixB)
{
UnpackedPixel<2> pixOut = {
pixA.r,
pixA.g,
pixA.b,
pixA.a
};
if (pixB.a == 0)
{
pixOut.r = pixOut.r << 1;
pixOut.g = pixOut.g << 1;
pixOut.b = pixOut.b << 1;
pixOut.a = pixOut.a << 1;
return pixOut;
}
const s32 rDiff = pixA.r - pixB.r;
const s32 gDiff = pixA.g - pixB.g;
const s32 bDiff = pixA.b - pixB.b;
const s32 aDiff = pixA.a - pixB.a;
pixOut.r = ( (-DEPOSTERIZE_THRESHOLD <= rDiff) && (rDiff <= DEPOSTERIZE_THRESHOLD) ) ? (pixOut.r + pixB.r) : (pixOut.r << 1);
pixOut.g = ( (-DEPOSTERIZE_THRESHOLD <= gDiff) && (gDiff <= DEPOSTERIZE_THRESHOLD) ) ? (pixOut.g + pixB.g) : (pixOut.g << 1);
pixOut.b = ( (-DEPOSTERIZE_THRESHOLD <= bDiff) && (bDiff <= DEPOSTERIZE_THRESHOLD) ) ? (pixOut.b + pixB.b) : (pixOut.b << 1);
pixOut.a = ( (-DEPOSTERIZE_THRESHOLD <= aDiff) && (aDiff <= DEPOSTERIZE_THRESHOLD) ) ? (pixOut.a + pixB.a) : (pixOut.a << 1);
return pixOut;
}
static FORCEINLINE UnpackedPixel<2> Deposterize_InterpLTE(const UnpackedPixel<1> &pixA, const u32 color32B)
{
const UnpackedPixel<1> pixB = {
(color32B >> 0) & 0x000000FF,
(color32B >> 8) & 0x000000FF,
(color32B >> 16) & 0x000000FF,
(color32B >> 24) & 0x000000FF
};
return Deposterize_InterpLTE(pixA, pixB);
}
template <u32 WEIGHTA, u32 WEIGHTB, u32 DEN>
static FORCEINLINE UnpackedPixel<DEN*(WEIGHTA+WEIGHTB)> Deposterize_Blend(const UnpackedPixel<DEN> &pixA, const UnpackedPixel<DEN> &pixB)
{
UnpackedPixel<DEN*(WEIGHTA+WEIGHTB)> ret;
ret.r = (pixA.r * WEIGHTA) + (pixB.r * WEIGHTB);
ret.g = (pixA.g * WEIGHTA) + (pixB.g * WEIGHTB);
ret.b = (pixA.b * WEIGHTA) + (pixB.b * WEIGHTB);
ret.a = (pixA.a * WEIGHTA) + (pixB.a * WEIGHTB);
return ret;
}
static u32 Deposterize_BlendPixel(const u32 color32[9])
{
const UnpackedPixel<1> center = {
(color32[0] >> 0) & 0x000000FF,
(color32[0] >> 8) & 0x000000FF,
(color32[0] >> 16) & 0x000000FF,
(color32[0] >> 24) & 0x000000FF
};
const UnpackedPixel<2> center2 = {
center.r << 1,
center.g << 1,
center.b << 1,
center.a << 1
};
#define DF_INTERP(i) Deposterize_InterpLTE(center, color32[i])
UnpackedPixel<512> pixOut = Deposterize_Blend<3, 1>(
Deposterize_Blend<1, 1>(
Deposterize_Blend<1, 1>(
Deposterize_Blend<2, 14>(center2, DF_INTERP(5)),
Deposterize_Blend<2, 14>(center2, DF_INTERP(1))
),
Deposterize_Blend<1, 1>(
Deposterize_Blend<2, 14>(center2, DF_INTERP(7)),
Deposterize_Blend<2, 14>(center2, DF_INTERP(3))
)
),
Deposterize_Blend<1, 1>(
Deposterize_Blend<1, 1>(
Deposterize_Blend<7, 9>(center2, DF_INTERP(6)),
Deposterize_Blend<7, 9>(center2, DF_INTERP(2))
),
Deposterize_Blend<1, 1>(
Deposterize_Blend<7, 9>(center2, DF_INTERP(8)),
Deposterize_Blend<7, 9>(center2, DF_INTERP(4))
)
)
);
#undef DF_INTERP
return pixOut.pack();
}
}
void RenderDeposterize(SSurface Src, SSurface Dst)
@ -127,15 +169,15 @@ void RenderDeposterize(SSurface Src, SSurface Dst)
continue;
}
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = (x < w-1) ? src[i+w+1] : src[i];
color[3] = src[i];
color[4] = (x > 0) ? src[i+w-1] : src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = src[i];
color[7] = src[i];
color[8] = src[i];
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = (x < w-1) ? src[i+w+1] : src[i];
color[3] = src[i];
color[4] = (x > 0) ? src[i+w-1] : src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = src[i];
color[7] = src[i];
color[8] = src[i];
workingDst[i] = Deposterize_BlendPixel(color);
}
@ -150,15 +192,15 @@ void RenderDeposterize(SSurface Src, SSurface Dst)
continue;
}
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = (x < w-1) ? src[i+w+1] : src[i];
color[3] = src[i+w];
color[4] = (x > 0) ? src[i+w-1] : src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = (x > 0) ? src[i-w-1] : src[i];
color[7] = src[i-w];
color[8] = (x < w-1) ? src[i-w+1] : src[i];
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = (x < w-1) ? src[i+w+1] : src[i];
color[3] = src[i+w];
color[4] = (x > 0) ? src[i+w-1] : src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = (x > 0) ? src[i-w-1] : src[i];
color[7] = src[i-w];
color[8] = (x < w-1) ? src[i-w+1] : src[i];
workingDst[i] = Deposterize_BlendPixel(color);
}
@ -172,15 +214,15 @@ void RenderDeposterize(SSurface Src, SSurface Dst)
continue;
}
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = src[i];
color[3] = src[i];
color[4] = src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = (x > 0) ? src[i-w-1] : src[i];
color[7] = src[i];
color[8] = (x < w-1) ? src[i-w+1] : src[i];
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = src[i];
color[3] = src[i];
color[4] = src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = (x > 0) ? src[i-w-1] : src[i];
color[7] = src[i];
color[8] = (x < w-1) ? src[i-w+1] : src[i];
workingDst[i] = Deposterize_BlendPixel(color);
}
@ -195,15 +237,15 @@ void RenderDeposterize(SSurface Src, SSurface Dst)
continue;
}
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = (x < w-1) ? workingDst[i+w+1] : workingDst[i];
color[3] = workingDst[i];
color[4] = (x > 0) ? workingDst[i+w-1] : workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = workingDst[i];
color[7] = workingDst[i];
color[8] = workingDst[i];
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = (x < w-1) ? workingDst[i+w+1] : workingDst[i];
color[3] = workingDst[i];
color[4] = (x > 0) ? workingDst[i+w-1] : workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = workingDst[i];
color[7] = workingDst[i];
color[8] = workingDst[i];
finalDst[i] = Deposterize_BlendPixel(color);
}
@ -218,15 +260,15 @@ void RenderDeposterize(SSurface Src, SSurface Dst)
continue;
}
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = (x < w-1) ? workingDst[i+w+1] : workingDst[i];
color[3] = workingDst[i+w];
color[4] = (x > 0) ? workingDst[i+w-1] : workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = (x > 0) ? workingDst[i-w-1] : workingDst[i];
color[7] = workingDst[i-w];
color[8] = (x < w-1) ? workingDst[i-w+1] : workingDst[i];
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = (x < w-1) ? workingDst[i+w+1] : workingDst[i];
color[3] = workingDst[i+w];
color[4] = (x > 0) ? workingDst[i+w-1] : workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = (x > 0) ? workingDst[i-w-1] : workingDst[i];
color[7] = workingDst[i-w];
color[8] = (x < w-1) ? workingDst[i-w+1] : workingDst[i];
finalDst[i] = Deposterize_BlendPixel(color);
}
@ -240,15 +282,15 @@ void RenderDeposterize(SSurface Src, SSurface Dst)
continue;
}
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = workingDst[i];
color[3] = workingDst[i];
color[4] = workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = (x > 0) ? workingDst[i-w-1] : workingDst[i];
color[7] = workingDst[i];
color[8] = (x < w-1) ? workingDst[i-w+1] : workingDst[i];
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = workingDst[i];
color[3] = workingDst[i];
color[4] = workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = (x > 0) ? workingDst[i-w-1] : workingDst[i];
color[7] = workingDst[i];
color[8] = (x < w-1) ? workingDst[i-w+1] : workingDst[i];
finalDst[i] = Deposterize_BlendPixel(color);
}

View File

@ -16,12 +16,15 @@
// * do so, delete this exception statement from your version. *
// ****************************************************************************
// 2024-08-01 (rogerman): Small performance optimization to
// ColorDistanceARGB::dist(). (Special thanks to m42a
// for this.)
// 2016-03-04 (rogerman): Update to XBRZ 1.4.
//
// 2014-11-18 (rogerman): Update to XBRZ 1.1.
// 2014-11-18 (rogerman): Update to XBRZ 1.1.
//
// 2014-02-06 (rogerman): Modified for use in DeSmuME by removing C++11 code.
// Also add render functions compatible with filter.h.
// 2014-02-06 (rogerman): Modified for use in DeSmuME by removing C++11 code.
// Also add render functions compatible with filter.h.
#include "xbrz.h"
#include "filter.h"
@ -1152,23 +1155,31 @@ struct ColorDistanceARGB
{
static double dist(uint32_t pix1, uint32_t pix2, double luminanceWeight)
{
const double a1 = getAlpha(pix1) / 255.0 ;
const double a2 = getAlpha(pix2) / 255.0 ;
/*
Requirements for a color distance handling alpha channel: with a1, a2 in [0, 1]
const int a1 = getAlpha(pix1);
const int a2 = getAlpha(pix2);
// Requirements for a color distance handling alpha channel: with a1, a2 in [0, 1]
1. if a1 = a2, distance should be: a1 * distYCbCr()
2. if a1 = 0, distance should be: a2 * distYCbCr(black, white) = a2 * 255
3. if a1 = 1, ??? maybe: 255 * (1 - a2) + a2 * distYCbCr()
*/
// 1. if a1 = a2, distance should be: a1 * distYCbCr()
// 2. if a1 = 0, distance should be: a2 * distYCbCr(black, white) = a2 * 255
// 3. if a1 = 1, ??? maybe: 255 * (1 - a2) + a2 * distYCbCr()
if (a1 == 0)
return a2;
if (a2 == 0)
return a1;
//return std::min(a1, a2) * DistYCbCrBuffer::dist(pix1, pix2) + 255 * abs(a1 - a2);
//=> following code is 15% faster:
const double d = DistYCbCrBuffer::dist(pix1, pix2);
const double d = DistYCbCrBuffer::dist(pix1, pix2);
if (a1 == 255 && a2 == 255)
return d;
if (a1 == a2)
return a1 * d / 255.0;
if (a1 < a2)
return a1 * d + 255 * (a2 - a1);
return a1 * d / 255.0 + (a2 - a1);
else
return a2 * d + 255 * (a1 - a2);
return a2 * d / 255.0 + (a1 - a2);
//alternative? return std::sqrt(a1 * a2 * square(DistYCbCrBuffer::dist(pix1, pix2)) + square(255 * (a1 - a2)));
}

View File

@ -13,12 +13,15 @@
// * do so, delete this exception statement from your version. *
// ****************************************************************************
// 2024-08-01 (rogerman): Small performance optimization to
// ColorDistanceARGB::dist(). (Special thanks to m42a
// for this.)
// 2016-03-04 (rogerman): Update to XBRZ 1.4.
//
// 2014-11-18 (rogerman): Update to XBRZ 1.1.
// 2014-11-18 (rogerman): Update to XBRZ 1.1.
//
// 2014-02-06 (rogerman): Modified for use in DeSmuME by removing C++11 code.
// Also integrate xbrz's config.h file into this one.
// 2014-02-06 (rogerman): Modified for use in DeSmuME by removing C++11 code.
// Also integrate xbrz's config.h file into this one.
#ifndef XBRZ_HEADER_3847894708239054
#define XBRZ_HEADER_3847894708239054

View File

@ -34,6 +34,7 @@
static _KEY1 enc(&MMU.ARM7_BIOS[0x0030]);
const char *defaultNickname = DESMUME_NAME;
const char *defaultMessage = DESMUME_NAME " makes you happy!";
const char *defaultMacAddressStr = "0009BF123456";
u16 CFIRMWARE::_getBootCodeCRC16(const u8 *arm9Data, const u32 arm9Size, const u8 *arm7Data, const u32 arm7Size)
{
@ -675,6 +676,47 @@ int copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data)
return copy_good;
}
void NDS_GetFirmwareMACAddressAsStr(const FirmwareConfig& config, char outMacStr[13])
{
for (u8 i = 0; i < 6; i++) {
for (u8 j = 0; j < 2; j++) {
u8 u4Bits = j == 0 ? config.MACAddress[i] / 16 : config.MACAddress[i] % 16;
outMacStr[i * 2 + j] = u4Bits >= 10 ? 'A' + (u4Bits - 10) : '0' + u4Bits;
}
}
outMacStr[12] = '\0';
}
void NDS_SetFirmwareMACAddressFromStr(FirmwareConfig& config, const char* macStr)
{
for (size_t i = 0; i < sizeof(config.MACAddress); i++)
config.MACAddress[i] = 0;
// Each letter in macStr represents a 4-bits value (u4) of the mac address.
size_t macStrLen = strlen(macStr);
if (macStrLen > 12)
macStrLen = 12;
const size_t missingLetterCount = 12 - macStrLen;
for (size_t i = 0; i < macStrLen; i++) {
char letter = macStr[i];
u8 macU4Val = 0;
if (letter >= '0' && letter <= '9')
macU4Val = letter - '0';
else if (letter >= 'A' && letter <= 'F')
macU4Val = letter - 'A' + 10;
else if (letter >= 'a' && letter <= 'f')
macU4Val = letter - 'a' + 10;
// Invalid letters are treated as 0.
const size_t u4Idx = i + missingLetterCount; // u4Idx is between 0-12
const size_t u8Idx = u4Idx / 2;
const bool isHighBits = u4Idx % 2 == 0;
config.MACAddress[u8Idx] += isHighBits ? macU4Val << 4 : macU4Val;
}
}
void NDS_GetDefaultFirmwareConfig(FirmwareConfig &outConfig)
{
memset(&outConfig, 0, sizeof(FirmwareConfig));

View File

@ -35,6 +35,7 @@
extern const char *defaultNickname;
extern const char *defaultMessage;
extern const char* defaultMacAddressStr;
struct FirmwareConfig
{
@ -447,6 +448,8 @@ public:
int copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data);
void NDS_GetFirmwareMACAddressAsStr(const FirmwareConfig& config, char outMacStr[13]);
void NDS_SetFirmwareMACAddressFromStr(FirmwareConfig& config, const char* MacStr);
void NDS_GetDefaultFirmwareConfig(FirmwareConfig &outConfig);
void NDS_GetCurrentWFCUserID(u8 *outMAC, u8 *outUserID);
void NDS_ApplyFirmwareSettings(NDSFirmwareData *outFirmware,

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 DeSmuME team
Copyright (C) 2018-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -134,7 +134,7 @@ void ClientAVCaptureFileStream::InitBaseProperties(const AVFileTypeID fileTypeID
this->_expectedMaxFrameSize = videoFrameSize + audioFrameSize;
_semQueue = ssem_new(pendingFrameCount);
_semQueue = ssem_new((int)pendingFrameCount);
}
AVFileTypeVideoCodecID ClientAVCaptureFileStream::GetVideoCodecID()
@ -484,7 +484,7 @@ void ClientAVCaptureObject::ConvertVideoSlice555Xto888(const VideoConvertParam &
const u16 *__restrict src = (const u16 *__restrict)param.src;
u8 *__restrict dst = param.dst;
ColorspaceConvertBuffer555XTo888<false, false>(src, dst, param.frameWidth * lineCount);
ColorspaceConvertBuffer555xTo888<false, false>(src, dst, param.frameWidth * lineCount);
}
//converts 32bpp to 24bpp and flips
@ -494,7 +494,7 @@ void ClientAVCaptureObject::ConvertVideoSlice888Xto888(const VideoConvertParam &
const u32 *__restrict src = (const u32 *__restrict)param.src;
u8 *__restrict dst = param.dst;
ColorspaceConvertBuffer888XTo888<false, false>(src, dst, param.frameWidth * lineCount);
ColorspaceConvertBuffer888xTo888<false, false>(src, dst, param.frameWidth * lineCount);
}
void ClientAVCaptureObject::CaptureVideoFrame(const void *srcVideoFrame, const size_t inFrameWidth, const size_t inFrameHeight, const NDSColorFormat colorFormat)

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2017-2018 DeSmuME team
Copyright (C) 2017-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -256,15 +256,18 @@ double ClientDisplayPresenter::GetScaleFactor() const
void ClientDisplayPresenter::SetScaleFactor(const double scaleFactor)
{
const bool willChangeScaleFactor = (this->_scaleFactor != scaleFactor);
this->_scaleFactor = scaleFactor;
if (willChangeScaleFactor)
if (!willChangeScaleFactor)
{
this->_glyphTileSize = (double)HUD_TEXTBOX_BASEGLYPHSIZE * scaleFactor;
this->_glyphSize = (double)this->_glyphTileSize * 0.75;
this->LoadHUDFont();
return;
}
this->_scaleFactor = scaleFactor;
this->_glyphTileSize = (double)HUD_TEXTBOX_BASEGLYPHSIZE * scaleFactor;
this->_glyphSize = (double)this->_glyphTileSize * 0.75;
this->LoadHUDFont();
this->_UpdateViewScale();
}
void ClientDisplayPresenter::_UpdateClientSize()
@ -292,6 +295,10 @@ void ClientDisplayPresenter::_UpdateViewScale()
}
this->_hudObjectScale *= this->_scaleFactor;
pthread_mutex_lock(&this->_mutexHUDString);
this->_hudNeedsUpdate = true;
pthread_mutex_unlock(&this->_mutexHUDString);
}
// NDS screen layout

View File

@ -1543,6 +1543,27 @@
AB681025187D4AEF0049F2C2 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = AB681018187D4AEF0049F2C2 /* Icon_PaddleKnob_256x256.png */; };
AB681027187D4AEF0049F2C2 /* Icon_Piano_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = AB681019187D4AEF0049F2C2 /* Icon_Piano_256x256.png */; };
AB68A0DD16B139BC00DE0546 /* OGLRender_3_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */; };
AB6E17F52A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17F62A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17F72A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17F82A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17F92A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FA2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FB2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FC2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FD2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FE2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E18012A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18022A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18032A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18042A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18052A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18062A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18072A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18082A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18092A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E180A2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E180B2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB74EC8A1738499C0026C41E /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB74EC891738499C0026C41E /* Carbon.framework */; };
AB78B5C11E384F2100297FED /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3BF4401E262943003E2B24 /* Metal.framework */; settings = {ATTRIBUTES = (Required, ); }; };
AB78B5C21E384F2200297FED /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3BF4401E262943003E2B24 /* Metal.framework */; settings = {ATTRIBUTES = (Required, ); }; };
@ -2425,6 +2446,17 @@
AB8493C01B4E614D00CD1C73 /* Icon_VolumeOneThird_16x16@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB8493AD1B4E614D00CD1C73 /* Icon_VolumeOneThird_16x16@2x.png */; };
AB8493C11B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB8493AE1B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png */; };
AB8493C31B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB8493AE1B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png */; };
AB8800542AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB8800552AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB8800562AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB8800572AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB8800582AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB8800592AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB88005A2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB88005B2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB88005C2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB88005D2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB88005E2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
AB8967D916D2ED0700F826F1 /* DisplayWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8967D816D2ED0700F826F1 /* DisplayWindowController.mm */; };
AB8967DD16D2ED2700F826F1 /* DisplayWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB8967DB16D2ED2700F826F1 /* DisplayWindow.xib */; };
AB8B7AAC17CE8C440051CEBF /* slot1comp_protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8B7AAB17CE8C440051CEBF /* slot1comp_protocol.cpp */; };
@ -4012,6 +4044,9 @@
AB681018187D4AEF0049F2C2 /* Icon_PaddleKnob_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_PaddleKnob_256x256.png; path = images/Icon_PaddleKnob_256x256.png; sourceTree = "<group>"; };
AB681019187D4AEF0049F2C2 /* Icon_Piano_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Piano_256x256.png; path = images/Icon_Piano_256x256.png; sourceTree = "<group>"; };
AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OGLRender_3_2.cpp; sourceTree = "<group>"; };
AB6E17F32A675BF1003A564D /* CheatDatabaseWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheatDatabaseWindowController.h; sourceTree = "<group>"; };
AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CheatDatabaseWindowController.mm; sourceTree = "<group>"; };
AB6E18002A6B218D003A564D /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = translations/English.lproj/CheatDatabaseViewer.xib; sourceTree = "<group>"; };
AB6FBEF5139B6258007BB045 /* slot1_retail_nand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot1_retail_nand.cpp; sourceTree = "<group>"; };
AB74EC891738499C0026C41E /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
AB75226D14C7BB51009B97B3 /* AppIcon_FirmwareConfig.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_FirmwareConfig.icns; sourceTree = "<group>"; };
@ -4022,6 +4057,7 @@
AB796CA215CDCB6B00C59155 /* instruction_attributes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = instruction_attributes.h; sourceTree = "<group>"; };
AB796CA315CDCB6B00C59155 /* instructions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = instructions.h; sourceTree = "<group>"; };
AB796D7015CDCBA200C59155 /* DeSmuME (Debug).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DeSmuME (Debug).app"; sourceTree = BUILT_PRODUCTS_DIR; };
AB7DA2432833EEBA001E9A9E /* DeSmuME_arm64.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_arm64.profdata; sourceTree = "<group>"; };
AB7EC7F2189B2B92009D198A /* Icon_AutoholdClear_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_AutoholdClear_420x420.png; path = images/Icon_AutoholdClear_420x420.png; sourceTree = "<group>"; };
AB7EC7F3189B2B92009D198A /* Icon_AutoholdSet_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_AutoholdSet_420x420.png; path = images/Icon_AutoholdSet_420x420.png; sourceTree = "<group>"; };
AB80E04C142BC4A800A52038 /* cocoa_util.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_util.mm; sourceTree = "<group>"; };
@ -4037,6 +4073,7 @@
AB8493AC1B4E614D00CD1C73 /* Icon_VolumeMute_16x16@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon_VolumeMute_16x16@2x.png"; path = "images/Icon_VolumeMute_16x16@2x.png"; sourceTree = "<group>"; };
AB8493AD1B4E614D00CD1C73 /* Icon_VolumeOneThird_16x16@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon_VolumeOneThird_16x16@2x.png"; path = "images/Icon_VolumeOneThird_16x16@2x.png"; sourceTree = "<group>"; };
AB8493AE1B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon_VolumeTwoThird_16x16@2x.png"; path = "images/Icon_VolumeTwoThird_16x16@2x.png"; sourceTree = "<group>"; };
AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot2_hcv1000.cpp; sourceTree = "<group>"; };
AB8967D716D2ED0700F826F1 /* DisplayWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayWindowController.h; sourceTree = "<group>"; };
AB8967D816D2ED0700F826F1 /* DisplayWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DisplayWindowController.mm; sourceTree = "<group>"; };
AB8967DC16D2ED2700F826F1 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = translations/English.lproj/DisplayWindow.xib; sourceTree = "<group>"; };
@ -4107,6 +4144,7 @@
AB9971CE134EDA0800531BA7 /* cocoa_globals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_globals.h; sourceTree = "<group>"; };
ABA48DF527F95C2E00D961FB /* colorspacehandler_NEON.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = colorspacehandler_NEON.h; sourceTree = "<group>"; };
ABA48DF627F95C2E00D961FB /* colorspacehandler_NEON.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = colorspacehandler_NEON.cpp; sourceTree = "<group>"; };
ABA5AB11282E63E20005F25D /* DeSmuME_x86_64.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_x86_64.profdata; sourceTree = "<group>"; };
ABA6574914511EC90077E5E9 /* cocoa_cheat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_cheat.h; sourceTree = "<group>"; };
ABA6574A14511EC90077E5E9 /* cocoa_cheat.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_cheat.mm; sourceTree = "<group>"; };
ABA67CA52808B8D000B5208D /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
@ -4212,6 +4250,7 @@
ABC570D4134431DA00E7B0B1 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
ABC719E1138CB25E002827A9 /* DefaultKeyMappings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DefaultKeyMappings.plist; sourceTree = "<group>"; };
ABC8599028273FEE00A03EA9 /* DeSmuME (x86_64).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DeSmuME (x86_64).app"; sourceTree = BUILT_PRODUCTS_DIR; };
ABCC191C2831F3E100B795C4 /* DeSmuME_x86_64h.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_x86_64h.profdata; sourceTree = "<group>"; };
ABCC19332287879000DFA471 /* colorspacehandler_AVX512.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = colorspacehandler_AVX512.cpp; sourceTree = "<group>"; };
ABCC19342287879000DFA471 /* colorspacehandler_AVX512.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = colorspacehandler_AVX512.h; sourceTree = "<group>"; };
ABCFA9F2178BDE920030C8BA /* encrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = encrypt.h; sourceTree = "<group>"; };
@ -4377,10 +4416,13 @@
ABD2CE4426E05CB000FB15F7 /* DeSmuME (x86_64h).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DeSmuME (x86_64h).app"; sourceTree = BUILT_PRODUCTS_DIR; };
ABD42045172319D1006A9B46 /* FileMigrationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileMigrationDelegate.h; sourceTree = "<group>"; };
ABD42046172319D1006A9B46 /* FileMigrationDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FileMigrationDelegate.mm; sourceTree = "<group>"; };
ABD86C832D83E20500505422 /* GPU_Operations_NEON.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPU_Operations_NEON.h; sourceTree = "<group>"; };
ABD86C842D83E20500505422 /* GPU_Operations_NEON.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GPU_Operations_NEON.cpp; sourceTree = "<group>"; };
ABDD89EF2C30BE97003482B7 /* OGLRender_ES3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OGLRender_ES3.h; sourceTree = "<group>"; };
ABDD89F02C30BE97003482B7 /* OGLRender_ES3.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OGLRender_ES3.cpp; sourceTree = "<group>"; };
ABDDF7C41898F024007583C1 /* Icon_DisplayToggle_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_DisplayToggle_420x420.png; path = images/Icon_DisplayToggle_420x420.png; sourceTree = "<group>"; };
ABDDF7C71898F032007583C1 /* Icon_FrameAdvance_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameAdvance_420x420.png; path = images/Icon_FrameAdvance_420x420.png; sourceTree = "<group>"; };
ABDDF7C81898F032007583C1 /* Icon_FrameJump_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameJump_420x420.png; path = images/Icon_FrameJump_420x420.png; sourceTree = "<group>"; };
ABE187E928274F0100B68164 /* DeSmuME_i386.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_i386.profdata; sourceTree = "<group>"; };
ABE5DFE3143FB1DA00835AD8 /* cocoa_videofilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_videofilter.h; sourceTree = "<group>"; };
ABE5DFE4143FB1DA00835AD8 /* cocoa_videofilter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_videofilter.mm; sourceTree = "<group>"; };
ABE670251415DE6C00E8E4C9 /* tinystr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinystr.cpp; sourceTree = "<group>"; };
@ -4393,6 +4435,7 @@
ABE6840E189E33D5007FD69C /* OGLDisplayOutput.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OGLDisplayOutput.h; sourceTree = "<group>"; };
ABE7F53C13EE1C7900FD3A71 /* cocoa_firmware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_firmware.h; sourceTree = "<group>"; };
ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_firmware.mm; sourceTree = "<group>"; };
ABECD444282DF23100AA6C0C /* DeSmuME_i386.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_i386.profdata; sourceTree = "<group>"; };
ABEFCF5D141AB82A000CC0CD /* AppIcon_ROMSave.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_ROMSave.icns; sourceTree = "<group>"; };
ABEFCF5E141AB82A000CC0CD /* AppIcon_DeSmuME.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_DeSmuME.icns; sourceTree = "<group>"; };
ABEFCF5F141AB82A000CC0CD /* AppIcon_NintendoDS_ROM.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_NintendoDS_ROM.icns; sourceTree = "<group>"; };
@ -4932,6 +4975,7 @@
ABC2ECD613B1C87000FAAA2A /* Images */,
AB00E87C14205EBC00DE561F /* MainMenu.xib */,
AB8967DB16D2ED2700F826F1 /* DisplayWindow.xib */,
AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */,
AB350D3A147A1D93007165AC /* HID_usage_strings.plist */,
8D1107310486CEB800E47090 /* Info.plist */,
AB02791814415E4C0075E58C /* Info (Debug).plist */,
@ -5224,6 +5268,7 @@
children = (
AB3ACB6614C2361100D7D192 /* appDelegate.h */,
AB3ACB6814C2361100D7D192 /* cheatWindowDelegate.h */,
AB6E17F32A675BF1003A564D /* CheatDatabaseWindowController.h */,
AB3BF4361E25D6B4003E2B24 /* DisplayViewCALayer.h */,
AB8967D716D2ED0700F826F1 /* DisplayWindowController.h */,
AB3A655C16CC5416001F5D4A /* EmuControllerDelegate.h */,
@ -5243,6 +5288,7 @@
AB3FBD7E2176DE95005722D0 /* WifiSettingsPanel.h */,
AB54718A1E27610500508C5C /* MacMetalDisplayViewShaders.metal */,
AB3ACB6714C2361100D7D192 /* appDelegate.mm */,
AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */,
AB3ACB6914C2361100D7D192 /* cheatWindowDelegate.mm */,
AB3BF4371E25D9AE003E2B24 /* DisplayViewCALayer.mm */,
AB8967D816D2ED0700F826F1 /* DisplayWindowController.mm */,
@ -5346,7 +5392,10 @@
AB407F381A620D6E00313213 /* OptimizationProfiles */ = {
isa = PBXGroup;
children = (
ABE187E928274F0100B68164 /* DeSmuME_i386.profdata */,
ABECD444282DF23100AA6C0C /* DeSmuME_i386.profdata */,
ABA5AB11282E63E20005F25D /* DeSmuME_x86_64.profdata */,
ABCC191C2831F3E100B795C4 /* DeSmuME_x86_64h.profdata */,
AB7DA2432833EEBA001E9A9E /* DeSmuME_arm64.profdata */,
);
path = OptimizationProfiles;
sourceTree = "<group>";
@ -5638,6 +5687,7 @@
AB1D4BB126E6F8D700A9AE42 /* GPU_Operations.cpp */,
AB1D4BB426E6F8D700A9AE42 /* GPU_Operations_SSE2.cpp */,
AB1D4BAF26E6F8D700A9AE42 /* GPU_Operations_AVX2.cpp */,
ABD86C842D83E20500505422 /* GPU_Operations_NEON.cpp */,
ABD1FEB81345AC8400AF11D1 /* lua-engine.cpp */,
ABD1FEB91345AC8400AF11D1 /* matrix.cpp */,
ABD1FEBA1345AC8400AF11D1 /* mc.cpp */,
@ -5647,6 +5697,7 @@
ABD1FEC01345AC8400AF11D1 /* NDSSystem.cpp */,
ABD1FEC11345AC8400AF11D1 /* OGLRender.cpp */,
AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */,
ABDD89F02C30BE97003482B7 /* OGLRender_ES3.cpp */,
ABD1FEC21345AC8400AF11D1 /* path.cpp */,
ABD1FEC31345AC8400AF11D1 /* rasterize.cpp */,
ABD1FEC41345AC8400AF11D1 /* readwrite.cpp */,
@ -5681,6 +5732,7 @@
AB1D4BB326E6F8D700A9AE42 /* GPU_Operations.h */,
AB1D4BB226E6F8D700A9AE42 /* GPU_Operations_SSE2.h */,
AB1D4BB026E6F8D700A9AE42 /* GPU_Operations_AVX2.h */,
ABD86C832D83E20500505422 /* GPU_Operations_NEON.h */,
AB796CA215CDCB6B00C59155 /* instruction_attributes.h */,
AB796CA315CDCB6B00C59155 /* instructions.h */,
ABD1FE841345AC8400AF11D1 /* lua-engine.h */,
@ -5694,6 +5746,7 @@
ABD1FE8C1345AC8400AF11D1 /* NDSSystem.h */,
ABD1FE8D1345AC8400AF11D1 /* OGLRender.h */,
ABBB421516B4A5F30012E5AB /* OGLRender_3_2.h */,
ABDD89EF2C30BE97003482B7 /* OGLRender_ES3.h */,
ABD1FE8F1345AC8400AF11D1 /* PACKED.h */,
ABD1FE8E1345AC8400AF11D1 /* PACKED_END.h */,
ABD1FE901345AC8400AF11D1 /* path.h */,
@ -5732,6 +5785,7 @@
ABD1FF031345AC9B00AF11D1 /* slot2_expMemory.cpp */,
ABD1FF041345AC9B00AF11D1 /* slot2_gbagame.cpp */,
ABD1FF051345AC9B00AF11D1 /* slot2_guitarGrip.cpp */,
AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */,
ABD1FF061345AC9B00AF11D1 /* slot2_mpcf.cpp */,
ABD1FF071345AC9C00AF11D1 /* slot2_none.cpp */,
ABD1FF081345AC9C00AF11D1 /* slot2_paddle.cpp */,
@ -6445,6 +6499,7 @@
8C43E79727E3CD0100A35F65 /* Icon_Input_420x420.png in Resources */,
8C43E79827E3CD0100A35F65 /* Icon_AutoholdSet_420x420.png in Resources */,
8C43E79927E3CD0100A35F65 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18032A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
8C43E79A27E3CD0100A35F65 /* Icon_OpenROM_420x420.png in Resources */,
8C43E79B27E3CD0100A35F65 /* Icon_Reset_420x420.png in Resources */,
8C43E79C27E3CD0100A35F65 /* Icon_RotateCCW_420x420.png in Resources */,
@ -6564,6 +6619,7 @@
8C43E8F527E3CD4C00A35F65 /* Icon_Input_420x420.png in Resources */,
8C43E8F627E3CD4C00A35F65 /* Icon_AutoholdSet_420x420.png in Resources */,
8C43E8F727E3CD4C00A35F65 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18042A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
8C43E8F827E3CD4C00A35F65 /* Icon_OpenROM_420x420.png in Resources */,
8C43E8F927E3CD4C00A35F65 /* Icon_Reset_420x420.png in Resources */,
8C43E8FA27E3CD4C00A35F65 /* Icon_RotateCCW_420x420.png in Resources */,
@ -6683,6 +6739,7 @@
8CCD840827E40B730024BDD5 /* Icon_Input_420x420.png in Resources */,
8CCD840927E40B730024BDD5 /* Icon_AutoholdSet_420x420.png in Resources */,
8CCD840A27E40B730024BDD5 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E180B2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
8CCD840B27E40B730024BDD5 /* Icon_OpenROM_420x420.png in Resources */,
8CCD840C27E40B730024BDD5 /* Icon_Reset_420x420.png in Resources */,
8CCD840D27E40B730024BDD5 /* Icon_RotateCCW_420x420.png in Resources */,
@ -6802,6 +6859,7 @@
AB36C78827F2C8AE00C763C8 /* Icon_Input_420x420.png in Resources */,
AB36C78927F2C8AE00C763C8 /* Icon_AutoholdSet_420x420.png in Resources */,
AB36C78A27F2C8AE00C763C8 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18082A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB36C78B27F2C8AE00C763C8 /* Icon_OpenROM_420x420.png in Resources */,
AB36C78C27F2C8AE00C763C8 /* Icon_Reset_420x420.png in Resources */,
AB36C78D27F2C8AE00C763C8 /* Icon_RotateCCW_420x420.png in Resources */,
@ -6921,6 +6979,7 @@
AB497A0E27F2E97A00E8A244 /* Icon_Input_420x420.png in Resources */,
AB497A0F27F2E97A00E8A244 /* Icon_AutoholdSet_420x420.png in Resources */,
AB497A1027F2E97A00E8A244 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18072A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB497A1127F2E97A00E8A244 /* Icon_OpenROM_420x420.png in Resources */,
AB497A1227F2E97A00E8A244 /* Icon_Reset_420x420.png in Resources */,
AB497A1327F2E97A00E8A244 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7040,6 +7099,7 @@
AB790193215B84F20082AE82 /* Icon_Input_420x420.png in Resources */,
AB790194215B84F20082AE82 /* Icon_AutoholdSet_420x420.png in Resources */,
AB790195215B84F20082AE82 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18062A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB790196215B84F20082AE82 /* Icon_OpenROM_420x420.png in Resources */,
AB790197215B84F20082AE82 /* Icon_Reset_420x420.png in Resources */,
AB790198215B84F20082AE82 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7159,6 +7219,7 @@
AB796CE015CDCBA200C59155 /* Icon_Input_420x420.png in Resources */,
AB7EC7F6189B2B92009D198A /* Icon_AutoholdSet_420x420.png in Resources */,
ABB0FBCC1A9EED350060C55A /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18012A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB796CE215CDCBA200C59155 /* Icon_OpenROM_420x420.png in Resources */,
AB796CE315CDCBA200C59155 /* Icon_Reset_420x420.png in Resources */,
AB796CE415CDCBA200C59155 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7278,6 +7339,7 @@
AB790036215B84E50082AE82 /* Icon_Input_420x420.png in Resources */,
AB790037215B84E50082AE82 /* Icon_AutoholdSet_420x420.png in Resources */,
AB790038215B84E50082AE82 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18052A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB790039215B84E50082AE82 /* Icon_OpenROM_420x420.png in Resources */,
AB79003A215B84E50082AE82 /* Icon_Reset_420x420.png in Resources */,
AB79003B215B84E50082AE82 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7397,6 +7459,7 @@
AB8F3C5F1A53AC2600A80BF6 /* Icon_Input_420x420.png in Resources */,
AB8F3C601A53AC2600A80BF6 /* Icon_AutoholdSet_420x420.png in Resources */,
ABB0FBCE1A9EED350060C55A /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18022A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB8F3C621A53AC2600A80BF6 /* Icon_OpenROM_420x420.png in Resources */,
AB8F3C631A53AC2600A80BF6 /* Icon_Reset_420x420.png in Resources */,
AB8F3C641A53AC2600A80BF6 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7526,6 +7589,7 @@
ABC8588628273FEE00A03EA9 /* Icon_Input_420x420.png in Resources */,
ABC8588728273FEE00A03EA9 /* Icon_AutoholdSet_420x420.png in Resources */,
ABC8588828273FEE00A03EA9 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18092A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
ABC8588928273FEE00A03EA9 /* Icon_OpenROM_420x420.png in Resources */,
ABC8588A28273FEE00A03EA9 /* Icon_Reset_420x420.png in Resources */,
ABC8588B28273FEE00A03EA9 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7645,6 +7709,7 @@
ABD2CD3C26E05CB000FB15F7 /* Icon_Input_420x420.png in Resources */,
ABD2CD3D26E05CB000FB15F7 /* Icon_AutoholdSet_420x420.png in Resources */,
ABD2CD3E26E05CB000FB15F7 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E180A2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
ABD2CD3F26E05CB000FB15F7 /* Icon_OpenROM_420x420.png in Resources */,
ABD2CD4026E05CB000FB15F7 /* Icon_Reset_420x420.png in Resources */,
ABD2CD4126E05CB000FB15F7 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7914,6 +7979,7 @@
8C43E7F027E3CD0100A35F65 /* ClientExecutionControl.cpp in Sources */,
8C43E7F127E3CD0100A35F65 /* rsemaphore.c in Sources */,
8C43E7F227E3CD0100A35F65 /* movie.cpp in Sources */,
AB6E17F72A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
8C43E7F327E3CD0100A35F65 /* slot1comp_rom.cpp in Sources */,
8C43E7F427E3CD0100A35F65 /* NDSSystem.cpp in Sources */,
8C43E7F527E3CD0100A35F65 /* MacBaseCaptureTool.mm in Sources */,
@ -8019,6 +8085,7 @@
8C43E86627E3CD0100A35F65 /* ftfstype.c in Sources */,
8C43E86B27E3CD0100A35F65 /* macosx_10_5_compat.cpp in Sources */,
8C43E86C27E3CD0100A35F65 /* retro_dirent.c in Sources */,
AB8800562AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
8C43E87427E3CD0100A35F65 /* slot2_passme.cpp in Sources */,
8C43E87727E3CD0100A35F65 /* psnames.c in Sources */,
8C43E87827E3CD0100A35F65 /* ftotval.c in Sources */,
@ -8083,6 +8150,7 @@
8C43E92F27E3CD4C00A35F65 /* common.cpp in Sources */,
8C43E93027E3CD4C00A35F65 /* cp15.cpp in Sources */,
8C43E93127E3CD4C00A35F65 /* psaux.c in Sources */,
AB8800572AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
8C43E93227E3CD4C00A35F65 /* cpu_detect_x86_gcc.cpp in Sources */,
8C43E93327E3CD4C00A35F65 /* crc.cpp in Sources */,
8C43E93427E3CD4C00A35F65 /* MacOGLDisplayView.mm in Sources */,
@ -8156,6 +8224,7 @@
8C43E97827E3CD4C00A35F65 /* slot2_rumblepak.cpp in Sources */,
8C43E97927E3CD4C00A35F65 /* sndOSX.cpp in Sources */,
8C43E97A27E3CD4C00A35F65 /* SndOut.cpp in Sources */,
AB6E17F82A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
8C43E97B27E3CD4C00A35F65 /* psnames.c in Sources */,
8C43E97C27E3CD4C00A35F65 /* Slot2WindowDelegate.mm in Sources */,
8C43E97D27E3CD4C00A35F65 /* truetype.c in Sources */,
@ -8313,6 +8382,7 @@
8CCD846127E40B730024BDD5 /* ClientExecutionControl.cpp in Sources */,
8CCD846227E40B730024BDD5 /* slot1.cpp in Sources */,
8CCD846327E40B730024BDD5 /* slot1_none.cpp in Sources */,
AB6E17FE2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
8CCD846427E40B730024BDD5 /* slot1_r4.cpp in Sources */,
8CCD846527E40B730024BDD5 /* cff.c in Sources */,
8CCD846627E40B730024BDD5 /* MacBaseCaptureTool.mm in Sources */,
@ -8418,6 +8488,7 @@
8CCD84DF27E40B730024BDD5 /* type1cid.c in Sources */,
8CCD84E427E40B730024BDD5 /* cocoa_slot2.mm in Sources */,
8CCD84E627E40B730024BDD5 /* ftbase.c in Sources */,
AB88005D2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
8CCD84EA27E40B730024BDD5 /* fsnitro.cpp in Sources */,
8CCD84EB27E40B730024BDD5 /* macosx_10_5_compat.cpp in Sources */,
8CCD84EC27E40B730024BDD5 /* OGLRender_3_2.cpp in Sources */,
@ -8462,6 +8533,7 @@
AB36C7AF27F2C8AE00C763C8 /* decrypt.cpp in Sources */,
AB36C7B027F2C8AE00C763C8 /* directory.cpp in Sources */,
AB36C7B127F2C8AE00C763C8 /* Disassembler.cpp in Sources */,
AB88005A2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
AB36C7B227F2C8AE00C763C8 /* disc.cpp in Sources */,
AB36C7B327F2C8AE00C763C8 /* dlditool.cpp in Sources */,
AB36C7B427F2C8AE00C763C8 /* driver.cpp in Sources */,
@ -8647,6 +8719,7 @@
AB36C86B27F2C8AE00C763C8 /* macosx_10_5_compat.cpp in Sources */,
AB36C86C27F2C8AE00C763C8 /* OGLRender_3_2.cpp in Sources */,
AB36C86D27F2C8AE00C763C8 /* ftfntfmt.c in Sources */,
AB6E17FB2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB36C86E27F2C8AE00C763C8 /* EmuControllerDelegate.mm in Sources */,
AB36C86F27F2C8AE00C763C8 /* ClientAVCaptureObject.cpp in Sources */,
AB36C87027F2C8AE00C763C8 /* cocoa_GPU.mm in Sources */,
@ -8704,6 +8777,7 @@
AB79006E215B84E50082AE82 /* emufile.cpp in Sources */,
AB79006F215B84E50082AE82 /* fatdir.cpp in Sources */,
AB790070215B84E50082AE82 /* ftbase.c in Sources */,
AB6E17F92A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB790071215B84E50082AE82 /* fatfile.cpp in Sources */,
AB790072215B84E50082AE82 /* FIFO.cpp in Sources */,
AB790073215B84E50082AE82 /* sfnt.c in Sources */,
@ -8835,6 +8909,7 @@
AB7900EF215B84E50082AE82 /* coreaudiosound.cpp in Sources */,
AB7900F0215B84E50082AE82 /* ringbuffer.cpp in Sources */,
AB7900F1215B84E50082AE82 /* arm_jit.cpp in Sources */,
AB8800582AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
AB7900F2215B84E50082AE82 /* smooth.c in Sources */,
AB7900F3215B84E50082AE82 /* troubleshootingWindowDelegate.mm in Sources */,
AB7900F4215B84E50082AE82 /* macOS_driver.cpp in Sources */,
@ -8951,6 +9026,7 @@
AB7901DD215B84F20082AE82 /* driver.cpp in Sources */,
AB7901DE215B84F20082AE82 /* emufat.cpp in Sources */,
AB7901DF215B84F20082AE82 /* type1cid.c in Sources */,
AB8800592AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
AB7901E0215B84F20082AE82 /* emufile.cpp in Sources */,
AB7901E1215B84F20082AE82 /* fatdir.cpp in Sources */,
AB7901E2215B84F20082AE82 /* fatfile.cpp in Sources */,
@ -9004,6 +9080,7 @@
AB790211215B84F20082AE82 /* type1.c in Sources */,
AB790212215B84F20082AE82 /* slot2_paddle.cpp in Sources */,
AB790213215B84F20082AE82 /* slot2_piano.cpp in Sources */,
AB6E17FA2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB790214215B84F20082AE82 /* slot2_rumblepak.cpp in Sources */,
AB790215215B84F20082AE82 /* sndOSX.cpp in Sources */,
AB790216215B84F20082AE82 /* SndOut.cpp in Sources */,
@ -9161,6 +9238,7 @@
AB796D0415CDCBA200C59155 /* emufile.cpp in Sources */,
AB796D0515CDCBA200C59155 /* fatdir.cpp in Sources */,
ABFEA8011BB4EC1000B08C25 /* ftbase.c in Sources */,
AB6E17F52A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB796D0615CDCBA200C59155 /* fatfile.cpp in Sources */,
AB796D0715CDCBA200C59155 /* FIFO.cpp in Sources */,
ABFEA8A31BB4EC1100B08C25 /* sfnt.c in Sources */,
@ -9292,6 +9370,7 @@
AB796D6215CDCBA200C59155 /* coreaudiosound.cpp in Sources */,
AB796D6315CDCBA200C59155 /* ringbuffer.cpp in Sources */,
AB796D6415CDCBA200C59155 /* arm_jit.cpp in Sources */,
AB8800542AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
ABFEA8CA1BB4EC1100B08C25 /* smooth.c in Sources */,
ABF2B9FB16904133000FF7C0 /* troubleshootingWindowDelegate.mm in Sources */,
AB28625920AE3E9F00EAED43 /* macOS_driver.cpp in Sources */,
@ -9408,6 +9487,7 @@
AB8F3C871A53AC2600A80BF6 /* driver.cpp in Sources */,
AB8F3C881A53AC2600A80BF6 /* emufat.cpp in Sources */,
ABA7316A1BB51FDC00B26147 /* type1cid.c in Sources */,
AB8800552AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
AB8F3C891A53AC2600A80BF6 /* emufile.cpp in Sources */,
AB8F3C8A1A53AC2600A80BF6 /* fatdir.cpp in Sources */,
AB8F3C8B1A53AC2600A80BF6 /* fatfile.cpp in Sources */,
@ -9461,6 +9541,7 @@
ABA731701BB51FDC00B26147 /* type1.c in Sources */,
AB8F3CBA1A53AC2600A80BF6 /* slot2_paddle.cpp in Sources */,
AB8F3CBB1A53AC2600A80BF6 /* slot2_piano.cpp in Sources */,
AB6E17F62A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB8F3CBC1A53AC2600A80BF6 /* slot2_rumblepak.cpp in Sources */,
AB8F3CBD1A53AC2600A80BF6 /* sndOSX.cpp in Sources */,
AB8F3CBE1A53AC2600A80BF6 /* SndOut.cpp in Sources */,
@ -9711,6 +9792,7 @@
AB2ABA461C9F9CFA00173B15 /* rthreads.c in Sources */,
ABB3C6CB1501C04F00E0C22E /* rasterize.cpp in Sources */,
ABB3C6CC1501C04F00E0C22E /* readwrite.cpp in Sources */,
AB88005E2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
AB49B553281687B90069F1D7 /* truetype.c in Sources */,
ABB3C6CD1501C04F00E0C22E /* render3D.cpp in Sources */,
ABB3C6CE1501C04F00E0C22E /* ROMReader.cpp in Sources */,
@ -9790,6 +9872,7 @@
ABC858BF28273FEE00A03EA9 /* filetime.cpp in Sources */,
ABC858C028273FEE00A03EA9 /* FIRFilter.cpp in Sources */,
ABC858C128273FEE00A03EA9 /* firmware.cpp in Sources */,
AB6E17FC2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
ABC858C228273FEE00A03EA9 /* async_job.c in Sources */,
ABC858C328273FEE00A03EA9 /* gfx3d.cpp in Sources */,
ABC858C428273FEE00A03EA9 /* DisplayViewCALayer.mm in Sources */,
@ -9921,6 +10004,7 @@
ABC8594228273FEE00A03EA9 /* buffer.cpp in Sources */,
ABC8594328273FEE00A03EA9 /* ftotval.c in Sources */,
ABC8594428273FEE00A03EA9 /* compiler.cpp in Sources */,
AB88005B2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
ABC8594528273FEE00A03EA9 /* compilercontext.cpp in Sources */,
ABC8594628273FEE00A03EA9 /* rthreads.c in Sources */,
ABC8594728273FEE00A03EA9 /* macOS_driver.cpp in Sources */,
@ -10018,6 +10102,7 @@
ABD2CD7326E05CB000FB15F7 /* filetime.cpp in Sources */,
ABD2CD7426E05CB000FB15F7 /* FIRFilter.cpp in Sources */,
ABD2CD7526E05CB000FB15F7 /* firmware.cpp in Sources */,
AB6E17FD2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
ABD2CD7626E05CB000FB15F7 /* async_job.c in Sources */,
ABD2CD7726E05CB000FB15F7 /* gfx3d.cpp in Sources */,
ABD2CD7826E05CB000FB15F7 /* DisplayViewCALayer.mm in Sources */,
@ -10149,6 +10234,7 @@
ABD2CDF626E05CB000FB15F7 /* buffer.cpp in Sources */,
ABD2CDF726E05CB000FB15F7 /* ftotval.c in Sources */,
ABD2CDF826E05CB000FB15F7 /* compiler.cpp in Sources */,
AB88005C2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
ABD2CDF926E05CB000FB15F7 /* compilercontext.cpp in Sources */,
ABD2CDFA26E05CB000FB15F7 /* rthreads.c in Sources */,
ABD2CDFB26E05CB000FB15F7 /* macOS_driver.cpp in Sources */,
@ -10233,6 +10319,14 @@
name = HID_usage_strings.plist;
sourceTree = "<group>";
};
AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */ = {
isa = PBXVariantGroup;
children = (
AB6E18002A6B218D003A564D /* English */,
);
name = CheatDatabaseViewer.xib;
sourceTree = "<group>";
};
AB8967DB16D2ED2700F826F1 /* DisplayWindow.xib */ = {
isa = PBXVariantGroup;
children = (
@ -10333,7 +10427,6 @@
buildSettings = {
ARCHS = arm64;
CLANG_OPTIMIZATION_PROFILE_FILE = "$(SRCROOT)/OptimizationProfiles/DeSmuME_arm64.profdata";
CLANG_USE_OPTIMIZATION_PROFILE = YES;
GCC_FAST_OBJC_DISPATCH = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = fast;
@ -10666,7 +10759,6 @@
ARCHS = x86_64;
CLANG_CXX_LIBRARY = "libstdc++";
CLANG_OPTIMIZATION_PROFILE_FILE = "$(SRCROOT)/OptimizationProfiles/DeSmuME_x86_64.profdata";
CLANG_USE_OPTIMIZATION_PROFILE = YES;
GCC_FAST_OBJC_DISPATCH = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = fast;
@ -10715,7 +10807,6 @@
buildSettings = {
ARCHS = x86_64h;
CLANG_OPTIMIZATION_PROFILE_FILE = "$(SRCROOT)/OptimizationProfiles/DeSmuME_x86_64h.profdata";
CLANG_USE_OPTIMIZATION_PROFILE = YES;
GCC_FAST_OBJC_DISPATCH = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = fast;

View File

@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:DeSmuME (Latest).xcodeproj">
location = "self:">
</FileRef>
</Workspace>

View File

@ -266,6 +266,11 @@
AB142028186E2CD80015D52F /* Image_MemoryExpansionPak.png in Resources */ = {isa = PBXBuildFile; fileRef = AB142025186E2CD80015D52F /* Image_MemoryExpansionPak.png */; };
AB142029186E2CD80015D52F /* Image_MemoryExpansionPak.png in Resources */ = {isa = PBXBuildFile; fileRef = AB142025186E2CD80015D52F /* Image_MemoryExpansionPak.png */; };
AB14202A186E2CD80015D52F /* Image_MemoryExpansionPak.png in Resources */ = {isa = PBXBuildFile; fileRef = AB142025186E2CD80015D52F /* Image_MemoryExpansionPak.png */; };
AB1B20AC2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
AB1B20AD2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
AB1B20AE2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
AB1B20AF2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
AB1B20B02AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
AB1CC8001AA509C2008B0A16 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1CC7FF1AA509C2008B0A16 /* CoreAudio.framework */; };
AB1CC80A1AA509DF008B0A16 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1CC7FF1AA509C2008B0A16 /* CoreAudio.framework */; };
AB1CC80B1AA509E0008B0A16 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1CC7FF1AA509C2008B0A16 /* CoreAudio.framework */; };
@ -1558,6 +1563,11 @@
ABD59849187D4A6C00069403 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = ABD59846187D4A6C00069403 /* Icon_PaddleKnob_256x256.png */; };
ABD5984A187D4A6C00069403 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = ABD59846187D4A6C00069403 /* Icon_PaddleKnob_256x256.png */; };
ABD5984B187D4A6C00069403 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = ABD59846187D4A6C00069403 /* Icon_PaddleKnob_256x256.png */; };
ABEBCE372A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABEBCE382A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABEBCE392A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABEBCE3A2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABEBCE3B2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABECB50918A460710052D52A /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABECB50818A460710052D52A /* xbrz.cpp */; };
ABECB50A18A460710052D52A /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABECB50818A460710052D52A /* xbrz.cpp */; };
ABECB50B18A460710052D52A /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABECB50818A460710052D52A /* xbrz.cpp */; };
@ -1572,6 +1582,11 @@
ABEF84831873578F00E99ADC /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C6E56186CD07E00E3EC64 /* ForceFeedback.framework */; };
ABEF84841873579400E99ADC /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C6E56186CD07E00E3EC64 /* ForceFeedback.framework */; };
ABEF84851873579700E99ADC /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C6E56186CD07E00E3EC64 /* ForceFeedback.framework */; };
ABEFFDDE2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABEFFDDF2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABEFFDE02A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABEFFDE12A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABEFFDE22A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABF50ABA169F5FDA0018C08D /* assembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABF50A7B169F5FDA0018C08D /* assembler.cpp */; };
ABF50ABB169F5FDA0018C08D /* assert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABF50A7D169F5FDA0018C08D /* assert.cpp */; };
ABF50ABC169F5FDA0018C08D /* buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABF50A7F169F5FDA0018C08D /* buffer.cpp */; };
@ -1905,6 +1920,7 @@
AB0F29A514BE7213009ABC6F /* Icon_Speaker_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Speaker_420x420.png; path = images/Icon_Speaker_420x420.png; sourceTree = "<group>"; };
AB126D06182ECB9500EBCF22 /* slot2_passme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot2_passme.cpp; sourceTree = "<group>"; };
AB142025186E2CD80015D52F /* Image_MemoryExpansionPak.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Image_MemoryExpansionPak.png; path = images/Image_MemoryExpansionPak.png; sourceTree = "<group>"; };
AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot2_hcv1000.cpp; sourceTree = "<group>"; };
AB1CC7FF1AA509C2008B0A16 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
AB1CC8161AA50C8D008B0A16 /* Icon_MicrophoneBlack_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_MicrophoneBlack_256x256.png; path = images/Icon_MicrophoneBlack_256x256.png; sourceTree = "<group>"; };
AB1CC8171AA50C8D008B0A16 /* Icon_MicrophoneBlueGlow_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_MicrophoneBlueGlow_256x256.png; path = images/Icon_MicrophoneBlueGlow_256x256.png; sourceTree = "<group>"; };
@ -1995,6 +2011,14 @@
AB3ACC3A14C24D5400D7D192 /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = COPYING; path = ../../../COPYING; sourceTree = SOURCE_ROOT; };
AB3ACC3B14C24D5400D7D192 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README; path = ../../../README; sourceTree = SOURCE_ROOT; };
AB3ACC3D14C24D5400D7D192 /* README.MAC */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.MAC; path = ../../../README.MAC; sourceTree = SOURCE_ROOT; };
AB3B8DC62D8A35A000C9CBFD /* GPU_Operations_NEON.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GPU_Operations_NEON.cpp; sourceTree = "<group>"; };
AB3B8DC72D8A35A000C9CBFD /* GPU_Operations_NEON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPU_Operations_NEON.h; sourceTree = "<group>"; };
AB3B8DC82D8A35A000C9CBFD /* OGLRender_ES3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OGLRender_ES3.cpp; sourceTree = "<group>"; };
AB3B8DC92D8A35A000C9CBFD /* OGLRender_ES3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OGLRender_ES3.h; sourceTree = "<group>"; };
AB3B8DCA2D8A35D900C9CBFD /* OGLDisplayOutput_3_2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OGLDisplayOutput_3_2.cpp; sourceTree = "<group>"; };
AB3B8DCB2D8A35D900C9CBFD /* OGLDisplayOutput_3_2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OGLDisplayOutput_3_2.h; sourceTree = "<group>"; };
AB3B8DCC2D8A35FE00C9CBFD /* colorspacehandler_NEON.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = colorspacehandler_NEON.cpp; sourceTree = "<group>"; };
AB3B8DCD2D8A35FE00C9CBFD /* colorspacehandler_NEON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colorspacehandler_NEON.h; sourceTree = "<group>"; };
AB3E34C7134AF4500056477A /* cocoa_output.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_output.h; sourceTree = "<group>"; };
AB3E34C8134AF4500056477A /* cocoa_output.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_output.mm; sourceTree = "<group>"; };
AB3E690E1E231E9900D4CC75 /* MacOGLDisplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacOGLDisplayView.h; sourceTree = "<group>"; };
@ -2326,6 +2350,8 @@
ABE6702A1415DE6C00E8E4C9 /* tinyxmlparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyxmlparser.cpp; sourceTree = "<group>"; };
ABE7F53C13EE1C7900FD3A71 /* cocoa_firmware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_firmware.h; sourceTree = "<group>"; };
ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_firmware.mm; sourceTree = "<group>"; };
ABEBCE352A703E260028CE8A /* CheatDatabaseWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheatDatabaseWindowController.h; sourceTree = "<group>"; };
ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CheatDatabaseWindowController.mm; sourceTree = "<group>"; };
ABECB50718A460710052D52A /* xbrz.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbrz.h; sourceTree = "<group>"; };
ABECB50818A460710052D52A /* xbrz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbrz.cpp; sourceTree = "<group>"; };
ABECB51218A460910052D52A /* OGLDisplayOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OGLDisplayOutput.h; sourceTree = "<group>"; };
@ -2334,6 +2360,7 @@
ABEFCF5E141AB82A000CC0CD /* AppIcon_DeSmuME.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_DeSmuME.icns; sourceTree = "<group>"; };
ABEFCF5F141AB82A000CC0CD /* AppIcon_NintendoDS_ROM.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_NintendoDS_ROM.icns; sourceTree = "<group>"; };
ABEFCF60141AB82A000CC0CD /* AppIcon_SaveState.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_SaveState.icns; sourceTree = "<group>"; };
ABEFFDDD2A78CB67009C3A2D /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = translations/English.lproj/CheatDatabaseViewer.xib; sourceTree = "<group>"; };
ABF50A74169F5FDA0018C08D /* AsmJit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsmJit.h; sourceTree = "<group>"; };
ABF50A75169F5FDA0018C08D /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Config.h; sourceTree = "<group>"; };
ABF50A76169F5FDA0018C08D /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core.h; sourceTree = "<group>"; };
@ -2544,6 +2571,7 @@
ABC04DC91F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp */,
ABD9A46413DB99B300777194 /* mic_ext.cpp */,
ABECB51318A460910052D52A /* OGLDisplayOutput.cpp */,
AB3B8DCA2D8A35D900C9CBFD /* OGLDisplayOutput_3_2.cpp */,
ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */,
ABD104141346652500AF11D1 /* sndOSX.cpp */,
AB2145211714DFF4006DDB0F /* audiosamplegenerator.h */,
@ -2567,6 +2595,7 @@
ABD1267420AE812900EFE1B2 /* macOS_driver.h */,
ABD9A46313DB99B300777194 /* mic_ext.h */,
ABECB51218A460910052D52A /* OGLDisplayOutput.h */,
AB3B8DCB2D8A35D900C9CBFD /* OGLDisplayOutput_3_2.h */,
ABD0A5371501AA5A0074A094 /* ringbuffer.h */,
ABD104011346652500AF11D1 /* sndOSX.h */,
AB2F56EE1704C86900E28885 /* utilities.h */,
@ -2657,6 +2686,7 @@
AB05E8201BBFD41200065D18 /* source-sans-pro */,
ABC2ECD613B1C87000FAAA2A /* Images */,
AB00E87C14205EBC00DE561F /* MainMenu.xib */,
ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */,
AB700DB816CDDBC400FBD336 /* DisplayWindow.xib */,
AB350D3A147A1D93007165AC /* HID_usage_strings.plist */,
8D1107310486CEB800E47090 /* Info.plist */,
@ -3185,11 +3215,13 @@
AB37E3721D6188BC004A2C0D /* colorspacehandler_SSE2.cpp */,
AB6FE67226E6F815002B2106 /* colorspacehandler_AVX2.cpp */,
AB6FE67426E6F815002B2106 /* colorspacehandler_AVX512.cpp */,
AB3B8DCC2D8A35FE00C9CBFD /* colorspacehandler_NEON.cpp */,
AB37E36E1D6188BC004A2C0D /* colorspacehandler_AltiVec.cpp */,
AB37E36D1D6188BC004A2C0D /* colorspacehandler.h */,
AB37E3731D6188BC004A2C0D /* colorspacehandler_SSE2.h */,
AB6FE67326E6F815002B2106 /* colorspacehandler_AVX2.h */,
AB6FE67526E6F815002B2106 /* colorspacehandler_AVX512.h */,
AB3B8DCD2D8A35FE00C9CBFD /* colorspacehandler_NEON.h */,
AB37E36F1D6188BC004A2C0D /* colorspacehandler_AltiVec.h */,
);
path = colorspacehandler;
@ -3199,6 +3231,7 @@
isa = PBXGroup;
children = (
AB3ACB6614C2361100D7D192 /* appDelegate.h */,
ABEBCE352A703E260028CE8A /* CheatDatabaseWindowController.h */,
AB3ACB6814C2361100D7D192 /* cheatWindowDelegate.h */,
AB3E69811E25FBBF00D4CC75 /* DisplayViewCALayer.h */,
AB700DDC16CDE4C300FBD336 /* DisplayWindowController.h */,
@ -3217,6 +3250,7 @@
ABA0356E169127BB00817C69 /* troubleshootingWindowDelegate.h */,
AB4B5A1F217E47E400381363 /* WifiSettingsPanel.h */,
AB3ACB6714C2361100D7D192 /* appDelegate.mm */,
ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */,
AB3ACB6914C2361100D7D192 /* cheatWindowDelegate.mm */,
AB3E69821E25FBBF00D4CC75 /* DisplayViewCALayer.mm */,
AB700DDD16CDE4C300FBD336 /* DisplayWindowController.mm */,
@ -3401,6 +3435,7 @@
AB6FE66E26E6F7C2002B2106 /* GPU_Operations.cpp */,
AB6FE66C26E6F7C2002B2106 /* GPU_Operations_SSE2.cpp */,
AB6FE66A26E6F7C2002B2106 /* GPU_Operations_AVX2.cpp */,
AB3B8DC62D8A35A000C9CBFD /* GPU_Operations_NEON.cpp */,
ABD1FEB81345AC8400AF11D1 /* lua-engine.cpp */,
ABD1FEB91345AC8400AF11D1 /* matrix.cpp */,
ABD1FEBA1345AC8400AF11D1 /* mc.cpp */,
@ -3410,6 +3445,7 @@
ABD1FEC01345AC8400AF11D1 /* NDSSystem.cpp */,
ABD1FEC11345AC8400AF11D1 /* OGLRender.cpp */,
AB6FE67026E6F7C2002B2106 /* OGLRender_3_2.cpp */,
AB3B8DC82D8A35A000C9CBFD /* OGLRender_ES3.cpp */,
ABD1FEC21345AC8400AF11D1 /* path.cpp */,
ABD1FEC31345AC8400AF11D1 /* rasterize.cpp */,
ABD1FEC41345AC8400AF11D1 /* readwrite.cpp */,
@ -3444,6 +3480,7 @@
AB6FE66F26E6F7C2002B2106 /* GPU_Operations.h */,
AB6FE66D26E6F7C2002B2106 /* GPU_Operations_SSE2.h */,
AB6FE66B26E6F7C2002B2106 /* GPU_Operations_AVX2.h */,
AB3B8DC72D8A35A000C9CBFD /* GPU_Operations_NEON.h */,
ABBCE29D15ACB26100A2C965 /* instruction_attributes.h */,
ABBCE29E15ACB26100A2C965 /* instructions.h */,
ABD1FE841345AC8400AF11D1 /* lua-engine.h */,
@ -3457,6 +3494,7 @@
ABD1FE8C1345AC8400AF11D1 /* NDSSystem.h */,
ABD1FE8D1345AC8400AF11D1 /* OGLRender.h */,
AB6FE67126E6F7C2002B2106 /* OGLRender_3_2.h */,
AB3B8DC92D8A35A000C9CBFD /* OGLRender_ES3.h */,
ABD1FE8F1345AC8400AF11D1 /* PACKED.h */,
ABD1FE8E1345AC8400AF11D1 /* PACKED_END.h */,
ABD1FE901345AC8400AF11D1 /* path.h */,
@ -3495,6 +3533,7 @@
ABD1FF031345AC9B00AF11D1 /* slot2_expMemory.cpp */,
ABD1FF041345AC9B00AF11D1 /* slot2_gbagame.cpp */,
ABD1FF051345AC9B00AF11D1 /* slot2_guitarGrip.cpp */,
AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */,
ABD1FF061345AC9B00AF11D1 /* slot2_mpcf.cpp */,
ABD1FF071345AC9C00AF11D1 /* slot2_none.cpp */,
ABD1FF081345AC9C00AF11D1 /* slot2_paddle.cpp */,
@ -3870,7 +3909,7 @@
attributes = {
ORGANIZATIONNAME = "DeSmuME Team";
};
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (XCode 3)" */;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (Xcode 3)" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1;
@ -4014,6 +4053,7 @@
ABA1659B2808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA1659C2808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78942809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDDF2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4133,6 +4173,7 @@
ABA165A92808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA165AA2808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78952809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDE02A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4252,6 +4293,7 @@
ABA165D32808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA165D42808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78982809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDDE2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4371,6 +4413,7 @@
ABA165C52808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA165C62808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78972809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDE22A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4490,6 +4533,7 @@
ABA165B72808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA165B82808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78962809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDE12A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4835,6 +4879,8 @@
ABD1267720AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267820AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A22217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE382A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
AB1B20AD2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5029,6 +5075,8 @@
ABD1267920AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267A20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A23217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE392A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
AB1B20AE2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5253,6 +5301,8 @@
ABD1267520AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267620AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A21217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE372A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
AB1B20AC2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5477,6 +5527,8 @@
ABD1267D20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267E20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A25217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE3B2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
AB1B20B02AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5671,6 +5723,8 @@
ABD1267B20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267C20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A24217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE3A2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
AB1B20AF2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5717,6 +5771,14 @@
name = Localizable.strings;
sourceTree = "<group>";
};
ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */ = {
isa = PBXVariantGroup;
children = (
ABEFFDDD2A78CB67009C3A2D /* English */,
);
name = CheatDatabaseViewer.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@ -6007,7 +6069,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (XCode 3)" */ = {
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (Xcode 3)" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C01FCF4F08A954540054247B /* Debug */,

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2012-2021 DeSmuME team
Copyright (C) 2012-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -22,7 +22,7 @@
#define HOST_DARWIN
#define DESMUME_COCOA
#define HAVE_OPENGL
#define ENABLE_OPENGL_STANDARD
#define HAVE_LIBZ
//#define HAVE_LUA
//#define HAVE_AV_CONFIG_H

View File

@ -54,7 +54,7 @@
<string>Set Speed</string>
<string>Enable/Disable Speed Limiter</string>
<string>Enable/Disable Auto Frame Skip</string>
<string>Enable/Disable Cheats</string>
<string>Enable/Disable Cheat System</string>
<string>Enable/Disable GPU State</string>
</array>
<key>DefaultInputProfiles</key>
@ -805,7 +805,7 @@
<array/>
<key>Enable/Disable Auto Frame Skip</key>
<array/>
<key>Enable/Disable Cheats</key>
<key>Enable/Disable Cheat System</key>
<array/>
<key>Enable/Disable GPU State</key>
<array/>

View File

@ -4,6 +4,8 @@
<dict>
<key>Advanscene_AutoDetectRomSaveType</key>
<true/>
<key>CheatDatabase_RecentFilePath</key>
<array/>
<key>CoreControl_EnableAutoFrameSkip</key>
<true/>
<key>CoreControl_FramesToSkipSetting</key>
@ -829,7 +831,7 @@
<array/>
<key>Enable/Disable Auto Frame Skip</key>
<array/>
<key>Enable/Disable Cheats</key>
<key>Enable/Disable Cheat System</key>
<array/>
<key>Enable/Disable GPU State</key>
<array/>

View File

@ -53,6 +53,11 @@
<string>Cocoa</string>
<string>OpenEmu</string>
</array>
<key>0.9.14</key>
<array>
<string>Cocoa</string>
<string>OpenEmu</string>
</array>
</dict>
<key>DefaultPaths</key>
<dict>
@ -204,6 +209,27 @@
<string>${OPENEMU}</string>
</dict>
</dict>
<key>0.9.14</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>${APPSUPPORT}</string>
<key>Cheat</key>
<string>${APPSUPPORT}</string>
<key>Firmware Configuration</key>
<string>${APPSUPPORT}</string>
<key>Save State</key>
<string>${APPSUPPORT}</string>
</dict>
<key>OpenEmu</key>
<dict>
<key>ROM Save</key>
<string>${OPENEMU}</string>
<key>Save State</key>
<string>${OPENEMU}</string>
</dict>
</dict>
</dict>
<key>DirectoryNames</key>
<dict>
@ -415,6 +441,32 @@
<string>SoundSamples</string>
</dict>
</dict>
<key>0.9.14</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>Battery</string>
<key>Cheat</key>
<string>Cheats</string>
<key>Firmware Configuration</key>
<string>Battery</string>
<key>Lua Script</key>
<string>Lua</string>
<key>Video</key>
<string>AviFiles</string>
<key>R4 Format</key>
<string>R4format</string>
<key>ROM</key>
<string>Roms</string>
<key>Save State</key>
<string>States</string>
<key>Screenshot</key>
<string>Screenshots</string>
<key>Sound Sample</key>
<string>SoundSamples</string>
</dict>
</dict>
</dict>
<key>FileExtensionByTypes</key>
<dict>
@ -562,6 +614,24 @@
<string>nds</string>
</dict>
</dict>
<key>0.9.14</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>dsv</string>
<key>Cheat</key>
<string>dct</string>
<key>Firmware Configuration</key>
<string>dfc</string>
<key>Lua Script</key>
<string>lua</string>
<key>Save State</key>
<string>dst</string>
<key>ROM</key>
<string>nds</string>
</dict>
</dict>
</dict>
<key>FileTypeByExtensions</key>
<dict>
@ -709,6 +779,24 @@
<string>ROM</string>
</dict>
</dict>
<key>0.9.14</key>
<dict>
<key>Cocoa</key>
<dict>
<key>dsv</key>
<string>ROM Save</string>
<key>dct</key>
<string>Cheat</string>
<key>dfc</key>
<string>Firmware Configuration</string>
<key>lua</key>
<string>Lua Script</string>
<key>dst</key>
<string>Save State</string>
<key>nds</key>
<string>ROM</string>
</dict>
</dict>
</dict>
</dict>
</plist>

View File

@ -4,6 +4,8 @@
<dict>
<key>NSRequiresAquaSystemAppearance</key>
<false/>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>NSMicrophoneUsageDescription</key>
<string>DeSmuME requires your host microphone to emulate the NDS microphone.</string>
<key>CFBundleDevelopmentRegion</key>
@ -244,11 +246,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>v0.9.13 (Debug)</string>
<string>v0.9.14 (Debug)</string>
<key>CFBundleSignature</key>
<string>DSmM</string>
<key>CFBundleVersion</key>
<string>0.9.13</string>
<string>0.9.14</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>LSMinimumSystemVersion</key>

View File

@ -4,6 +4,8 @@
<dict>
<key>NSRequiresAquaSystemAppearance</key>
<false/>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>NSMicrophoneUsageDescription</key>
<string>DeSmuME requires your host microphone to emulate the NDS microphone.</string>
<key>CFBundleDevelopmentRegion</key>
@ -244,11 +246,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>v0.9.13</string>
<string>v0.9.14</string>
<key>CFBundleSignature</key>
<string>DSmM</string>
<key>CFBundleVersion</key>
<string>0.9.13</string>
<string>0.9.14</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>LSMinimumSystemVersion</key>

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2014-2022 DeSmuME team
Copyright (C) 2014-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -4233,8 +4233,7 @@ OGLContextInfo_Legacy::OGLContextInfo_Legacy()
glDeleteVertexArraysDESMUME = &glDeleteVertexArrays_LegacyAPPLE;
glGenVertexArraysDESMUME = &glGenVertexArrays_LegacyAPPLE;
_isVAOSupported = isShaderSupported &&
_isVBOSupported &&
_isVAOSupported = _isVBOSupported &&
(this->IsExtensionPresent(oglExtensionSet, "GL_ARB_vertex_array_object") ||
this->IsExtensionPresent(oglExtensionSet, "GL_APPLE_vertex_array_object"));
@ -4720,7 +4719,7 @@ void OGLClientSharedData::FetchNativeDisplayToSrcClone(const NDSDisplayInfo *dis
return;
}
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapNone>(displayInfoList[bufferIndex].nativeBuffer16[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapNone>(displayInfoList[bufferIndex].nativeBuffer16[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
this->_srcCloneNeedsUpdate[displayID][bufferIndex] = false;
if (needsLock)
@ -4745,7 +4744,7 @@ void OGLClientSharedData::FetchCustomDisplayToSrcClone(const NDSDisplayInfo *dis
return;
}
ColorspaceConvertBuffer888XTo8888Opaque<false, false>((u32 *)displayInfoList[bufferIndex].customBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
ColorspaceConvertBuffer888xTo8888Opaque<false, false>((u32 *)displayInfoList[bufferIndex].customBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
this->_srcCloneNeedsUpdate[displayID][bufferIndex] = false;
if (needsLock)
@ -5039,14 +5038,14 @@ void OGLVideoOutput::_ResizeCPUPixelScaler(const VideoFilterTypeID filterID)
this->ClientDisplay3DPresenter::_ResizeCPUPixelScaler(filterID);
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, this->_vfMasterDstBufferSize, this->_vfMasterDstBuffer);
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, (GLsizei)this->_vfMasterDstBufferSize, this->_vfMasterDstBuffer);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[NDSDisplayID_Main]);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_vf[NDSDisplayID_Main]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide, this->_vf[NDSDisplayID_Main]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_vf[NDSDisplayID_Main]->GetDstBufferPtr());
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, (GLsizei)(this->_vf[NDSDisplayID_Main]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide), (GLsizei)(this->_vf[NDSDisplayID_Main]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_vf[NDSDisplayID_Main]->GetDstBufferPtr());
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[NDSDisplayID_Touch]);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_vf[NDSDisplayID_Touch]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide, this->_vf[NDSDisplayID_Touch]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_vf[NDSDisplayID_Touch]->GetDstBufferPtr());
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, (GLsizei)(this->_vf[NDSDisplayID_Touch]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide), (GLsizei)(this->_vf[NDSDisplayID_Touch]->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_vf[NDSDisplayID_Touch]->GetDstBufferPtr());
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
@ -5083,7 +5082,7 @@ void OGLVideoOutput::Init()
this->PrerenderStateSetupOGL();
// Set up textures
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, this->_vfMasterDstBufferSize, this->_vfMasterDstBuffer);
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, (GLsizei)this->_vfMasterDstBufferSize, this->_vfMasterDstBuffer);
glGenTextures(2, this->_texCPUFilterDstID);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[NDSDisplayID_Main]);
@ -5092,7 +5091,7 @@ void OGLVideoOutput::Init()
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_vf[NDSDisplayID_Main]->GetDstWidth(), this->_vf[NDSDisplayID_Main]->GetDstHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_vf[NDSDisplayID_Main]->GetDstBufferPtr());
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, (GLsizei)this->_vf[NDSDisplayID_Main]->GetDstWidth(), (GLsizei)this->_vf[NDSDisplayID_Main]->GetDstHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_vf[NDSDisplayID_Main]->GetDstBufferPtr());
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[NDSDisplayID_Touch]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -5100,11 +5099,14 @@ void OGLVideoOutput::Init()
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_vf[NDSDisplayID_Touch]->GetDstWidth(), this->_vf[NDSDisplayID_Touch]->GetDstHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_vf[NDSDisplayID_Touch]->GetDstBufferPtr());
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, (GLsizei)this->_vf[NDSDisplayID_Touch]->GetDstWidth(), (GLsizei)this->_vf[NDSDisplayID_Touch]->GetDstHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_vf[NDSDisplayID_Touch]->GetDstBufferPtr());
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glGenFramebuffersEXT(1, &this->_fboFrameCopyID);
if (this->_contextInfo->IsFBOSupported())
{
glGenFramebuffersEXT(1, &this->_fboFrameCopyID);
}
}
void OGLVideoOutput::SetOutputFilter(const OutputFilterTypeID filterID)
@ -5175,6 +5177,11 @@ void OGLVideoOutput::ProcessDisplays()
void OGLVideoOutput::CopyFrameToBuffer(uint32_t *dstBuffer)
{
if (!this->_contextInfo->IsFBOSupported())
{
return;
}
GLuint texFrameCopyID = 0;
glGenTextures(1, &texFrameCopyID);
@ -5216,11 +5223,12 @@ void OGLVideoOutput::PrerenderStateSetupOGL()
// requires.
// Render State Setup (common to both shaders and fixed-function pipeline)
glEnable(GL_BLEND);
glDisable(GL_BLEND); // The display layer can disable this, but the HUD layer needs this enabled.
glDisable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glDisable(GL_STENCIL_TEST);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
glDisable(GL_SCISSOR_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Set up fixed-function pipeline render states.
@ -5229,8 +5237,13 @@ void OGLVideoOutput::PrerenderStateSetupOGL()
glDisable(GL_ALPHA_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
// Note that in fixed-function mode, you can only enable GL_TEXTURE_2D or
// GL_TEXTURE_RECTANGLE_ARB at any one time, but you cannot ahve both enabled
// at the same time. The display layer requires GL_TEXTURE_RECTANGLE_ARB
// enabled, while the HUD layer requires GL_TEXTURE_2D enabled.
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
}
}
@ -5466,7 +5479,7 @@ void OGLFilter::DownloadDstBufferOGL(uint32_t *dstBuffer, size_t lineOffset, siz
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->_fboID);
glReadPixels(0, lineOffset, this->_dstWidth, readLineCount, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, dstBuffer);
glReadPixels(0, (GLint)lineOffset, this->_dstWidth, (GLsizei)readLineCount, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, dstBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
@ -5569,6 +5582,23 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
UpdateTexCoords(_vf->GetDstWidth(), _vf->GetDstHeight());
// Render State Setup (common to both shaders and fixed-function pipeline)
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glDisable(GL_STENCIL_TEST);
glDisable(GL_SCISSOR_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Set up fixed-function pipeline render states.
if (!contextInfo->IsShaderSupported())
{
glDisable(GL_ALPHA_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
}
// Set up textures
glGenTextures(1, &_texCPUFilterDstID);
glGenTextures(1, &_texVideoInputDataID);
@ -5587,7 +5617,7 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, _vf->GetSrcWidth(), _vf->GetSrcHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _vf->GetSrcBufferPtr());
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, (GLsizei)_vf->GetSrcWidth(), (GLsizei)_vf->GetSrcHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _vf->GetSrcBufferPtr());
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
const GLint vtxBuffer[8] = {
@ -5598,14 +5628,14 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
};
// Set up VBOs
glGenBuffersARB(1, &_vboVertexID);
glGenBuffersARB(1, &_vboTexCoordID);
glGenBuffers(1, &_vboVertexID);
glGenBuffers(1, &_vboTexCoordID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboVertexID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vtxBuffer), vtxBuffer, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(_texCoordBuffer), _texCoordBuffer, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBuffer(GL_ARRAY_BUFFER, _vboVertexID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vtxBuffer), vtxBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID);
glBufferData(GL_ARRAY_BUFFER, sizeof(_texCoordBuffer), _texCoordBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Set up VAO
glGenVertexArraysDESMUME(1, &_vaoMainStatesID);
@ -5613,9 +5643,9 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
if (contextInfo->IsShaderSupported())
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboVertexID);
glBindBuffer(GL_ARRAY_BUFFER, _vboVertexID);
glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_INT, GL_FALSE, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID);
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
@ -5623,9 +5653,9 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
}
else
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboVertexID);
glBindBuffer(GL_ARRAY_BUFFER, _vboVertexID);
glVertexPointer(2, GL_INT, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
@ -5663,9 +5693,9 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
_canUseShaderBasedFilters = (contextInfo->IsShaderSupported() && contextInfo->IsFBOSupported());
if (_canUseShaderBasedFilters)
{
_filterDeposterize = new OGLFilterDeposterize(_vf->GetSrcWidth(), _vf->GetSrcHeight(), _shaderSupport, _useShader150);
_filterDeposterize = new OGLFilterDeposterize((GLsizei)_vf->GetSrcWidth(), (GLsizei)_vf->GetSrcHeight(), _shaderSupport, _useShader150);
_shaderFilter = new OGLFilter(_vf->GetSrcWidth(), _vf->GetSrcHeight(), 1);
_shaderFilter = new OGLFilter((GLsizei)_vf->GetSrcWidth(), (GLsizei)_vf->GetSrcHeight(), 1);
OGLShaderProgram *shaderFilterProgram = _shaderFilter->GetProgram();
shaderFilterProgram->SetShaderSupport(_shaderSupport);
shaderFilterProgram->SetVertexAndFragmentShaderOGL(Sample1x1_VertShader_110, PassthroughFragShader_110, false, _useShader150);
@ -5679,7 +5709,7 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
}
_useShaderBasedPixelScaler = false;
_filtersPreferGPU = true;
_filtersPreferGPU = _canUseShaderBasedFilters && _canUseShaderOutput;
_outputFilter = OutputFilterTypeID_Bilinear;
}
@ -5691,8 +5721,8 @@ OGLImage::~OGLImage()
_isVAOPresent = false;
}
glDeleteBuffersARB(1, &this->_vboVertexID);
glDeleteBuffersARB(1, &this->_vboTexCoordID);
glDeleteBuffers(1, &this->_vboVertexID);
glDeleteBuffers(1, &this->_vboTexCoordID);
glDeleteTextures(1, &this->_texCPUFilterDstID);
glDeleteTextures(1, &this->_texVideoInputDataID);
@ -6110,10 +6140,10 @@ void OGLImage::SetCPUPixelScalerOGL(const VideoFilterTypeID filterID)
{
bool needResizeTexture = false;
const VideoFilterAttributes newFilterAttr = VideoFilter::GetAttributesByID(filterID);
const GLsizei oldDstBufferWidth = this->_vf->GetDstWidth();
const GLsizei oldDstBufferHeight = this->_vf->GetDstHeight();
const GLsizei newDstBufferWidth = this->_vf->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide;
const GLsizei newDstBufferHeight = this->_vf->GetSrcHeight() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide;
const GLsizei oldDstBufferWidth = (GLsizei)this->_vf->GetDstWidth();
const GLsizei oldDstBufferHeight = (GLsizei)this->_vf->GetDstHeight();
const GLsizei newDstBufferWidth = (GLsizei)(this->_vf->GetSrcWidth() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide);
const GLsizei newDstBufferHeight = (GLsizei)(this->_vf->GetSrcHeight() * newFilterAttr.scaleMultiply / newFilterAttr.scaleDivide);
if (oldDstBufferWidth != newDstBufferWidth || oldDstBufferHeight != newDstBufferHeight)
{
@ -6128,7 +6158,6 @@ void OGLImage::SetCPUPixelScalerOGL(const VideoFilterTypeID filterID)
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, newDstBufferWidth, newDstBufferHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, newMasterBuffer);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
_vfMasterDstBuffer = newMasterBuffer;
free_aligned(oldMasterBuffer);
@ -6141,7 +6170,6 @@ void OGLImage::LoadFrameOGL(const uint32_t *frameData, GLint x, GLint y, GLsizei
{
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataID);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, frameData);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
memcpy(this->_vf->GetSrcBufferPtr(), frameData, w * h * sizeof(uint32_t));
}
@ -6195,10 +6223,8 @@ void OGLImage::ProcessOGL()
// Output
this->_texVideoOutputID = this->_texVideoPixelScalerID;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboTexCoordID);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(this->_texCoordBuffer), this->_texCoordBuffer);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glBindBuffer(GL_ARRAY_BUFFER, this->_vboTexCoordID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(this->_texCoordBuffer), this->_texCoordBuffer);
}
void OGLImage::RenderOGL()
@ -6238,7 +6264,6 @@ void OGLImage::RenderOGL()
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
// Disable vertex attributes
glBindVertexArrayDESMUME(0);
@ -6305,22 +6330,22 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO)
_workingCharBufferList->reserve(16);
// Set up VBOs
glGenBuffersARB(1, &_vboPositionVertexID);
glGenBuffersARB(1, &_vboColorVertexID);
glGenBuffersARB(1, &_vboTexCoordID);
glGenBuffersARB(1, &_vboElementID);
glGenBuffers(1, &_vboPositionVertexID);
glGenBuffers(1, &_vboColorVertexID);
glGenBuffers(1, &_vboTexCoordID);
glGenBuffers(1, &_vboElementID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboPositionVertexID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboColorVertexID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_COLOR_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBuffer(GL_ARRAY_BUFFER, _vboPositionVertexID);
glBufferData(GL_ARRAY_BUFFER, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorVertexID);
glBufferData(GL_ARRAY_BUFFER, HUD_VERTEX_COLOR_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID);
glBufferData(GL_ARRAY_BUFFER, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _vboElementID);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(GLshort) * HUD_TOTAL_ELEMENTS * 6, NULL, GL_STATIC_DRAW_ARB);
GLshort *idxBufferPtr = (GLshort *)glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboElementID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLshort) * HUD_TOTAL_ELEMENTS * 6, NULL, GL_STATIC_DRAW);
GLshort *idxBufferPtr = (GLshort *)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
for (size_t i = 0, j = 0, k = 0; i < HUD_TOTAL_ELEMENTS; i++, j+=6, k+=4)
{
@ -6332,8 +6357,8 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO)
idxBufferPtr[j+5] = k+0;
}
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Set up VAO
glGenVertexArraysDESMUME(1, &_vaoMainStatesID);
@ -6341,13 +6366,13 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO)
if (oglVO->GetContextInfo()->IsShaderSupported())
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboPositionVertexID);
glBindBuffer(GL_ARRAY_BUFFER, _vboPositionVertexID);
glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboColorVertexID);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorVertexID);
glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID);
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _vboElementID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboElementID);
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_Color);
@ -6355,13 +6380,13 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO)
}
else
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboPositionVertexID);
glBindBuffer(GL_ARRAY_BUFFER, _vboPositionVertexID);
glVertexPointer(2, GL_FLOAT, 0, NULL);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboColorVertexID);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorVertexID);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, NULL);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID);
glTexCoordPointer(2, GL_FLOAT, 0, NULL);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _vboElementID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboElementID);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
@ -6380,10 +6405,10 @@ OGLHUDLayer::~OGLHUDLayer()
}
glDeleteVertexArraysDESMUME(1, &this->_vaoMainStatesID);
glDeleteBuffersARB(1, &this->_vboPositionVertexID);
glDeleteBuffersARB(1, &this->_vboColorVertexID);
glDeleteBuffersARB(1, &this->_vboTexCoordID);
glDeleteBuffersARB(1, &this->_vboElementID);
glDeleteBuffers(1, &this->_vboPositionVertexID);
glDeleteBuffers(1, &this->_vboColorVertexID);
glDeleteBuffers(1, &this->_vboTexCoordID);
glDeleteBuffers(1, &this->_vboElementID);
glDeleteTextures(1, &this->_texCharMap);
@ -6475,7 +6500,7 @@ void OGLHUDLayer::CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, c
}
}
glTexImage2D(GL_TEXTURE_2D, texLevel, GL_RGBA, texSize, texSize, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, charMapBuffer);
glTexImage2D(GL_TEXTURE_2D, texLevel, GL_RGBA, (GLsizei)texSize, (GLsizei)texSize, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, charMapBuffer);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
@ -6492,25 +6517,25 @@ void OGLHUDLayer::_UpdateVerticesOGL()
return;
}
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboPositionVertexID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
float *vtxPositionBufferPtr = (float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
glBindBuffer(GL_ARRAY_BUFFER, this->_vboPositionVertexID);
glBufferData(GL_ARRAY_BUFFER, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW);
float *vtxPositionBufferPtr = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
this->_output->SetHUDPositionVertices((float)this->_output->GetViewportWidth(), (float)this->_output->GetViewportHeight(), vtxPositionBufferPtr);
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboColorVertexID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_COLOR_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
uint32_t *vtxColorBufferPtr = (uint32_t *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
glBindBuffer(GL_ARRAY_BUFFER, this->_vboColorVertexID);
glBufferData(GL_ARRAY_BUFFER, HUD_VERTEX_COLOR_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW);
uint32_t *vtxColorBufferPtr = (uint32_t *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
this->_output->SetHUDColorVertices(vtxColorBufferPtr);
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboTexCoordID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW_ARB);
float *texCoordBufferPtr = (float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
glBindBuffer(GL_ARRAY_BUFFER, this->_vboTexCoordID);
glBufferData(GL_ARRAY_BUFFER, HUD_VERTEX_ATTRIBUTE_BUFFER_SIZE, NULL, GL_STREAM_DRAW);
float *texCoordBufferPtr = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
this->_output->SetHUDTextureCoordinates(texCoordBufferPtr);
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
this->_output->ClearHUDNeedsUpdate();
}
@ -6559,6 +6584,8 @@ void OGLHUDLayer::RenderOGL(bool isRenderingFlipped)
return;
}
glEnable(GL_BLEND);
if (this->_output->GetContextInfo()->IsShaderSupported())
{
glUseProgram(this->_program->GetProgramID());
@ -6570,6 +6597,26 @@ void OGLHUDLayer::RenderOGL(bool isRenderingFlipped)
this->_needUpdateViewport = false;
}
}
else
{
const GLdouble w = this->_output->GetViewportWidth();
const GLdouble h = this->_output->GetViewportHeight();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (isRenderingFlipped)
{
glOrtho(-w/2.0, -w/2.0 + w, -h/2.0 + h, -h/2.0, -1.0, 1.0);
}
else
{
glOrtho(-w/2.0, -w/2.0 + w, -h/2.0, -h/2.0 + h, -1.0, 1.0);
}
glDisable(GL_TEXTURE_RECTANGLE_ARB);
glEnable(GL_TEXTURE_2D);
}
if (this->_output->HUDNeedsUpdate())
{
@ -6584,6 +6631,7 @@ void OGLHUDLayer::RenderOGL(bool isRenderingFlipped)
{
const ClientDisplayPresenterProperties &cdp = this->_output->GetPresenterProperties();
// Draw the touch lines first.
if (this->_output->GetContextInfo()->IsShaderSupported())
{
glUniform1f(this->_uniformAngleDegrees, cdp.rotation);
@ -6599,8 +6647,9 @@ void OGLHUDLayer::RenderOGL(bool isRenderingFlipped)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glDrawElements(GL_TRIANGLES, hudTouchLineLength * 6, GL_UNSIGNED_SHORT, (GLvoid *)((this->_output->GetHUDString().length() + HUD_INPUT_ELEMENT_LENGTH) * 6 * sizeof(uint16_t)));
glDrawElements(GL_TRIANGLES, (GLsizei)(hudTouchLineLength * 6), GL_UNSIGNED_SHORT, (GLvoid *)((this->_output->GetHUDString().length() + HUD_INPUT_ELEMENT_LENGTH) * 6 * sizeof(uint16_t)));
// Then draw the input buttons overlay.
if (this->_output->GetContextInfo()->IsShaderSupported())
{
glUniform1f(this->_uniformAngleDegrees, 0.0f);
@ -6651,7 +6700,7 @@ void OGLHUDLayer::RenderOGL(bool isRenderingFlipped)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.50f);
}
glDrawElements(GL_TRIANGLES, (this->_output->GetHUDString().length() - 1) * 6, GL_UNSIGNED_SHORT, (GLvoid *)(6 * sizeof(GLshort)));
glDrawElements(GL_TRIANGLES, (GLsizei)((this->_output->GetHUDString().length() - 1) * 6), GL_UNSIGNED_SHORT, (GLvoid *)(6 * sizeof(GLshort)));
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArrayDESMUME(0);
@ -6676,14 +6725,14 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
pthread_rwlock_init(&_cpuFilterRWLock[NDSDisplayID_Touch][1], NULL);
// Set up VBOs
glGenBuffersARB(1, &_vboVertexID);
glGenBuffersARB(1, &_vboTexCoordID);
glGenBuffers(1, &_vboVertexID);
glGenBuffers(1, &_vboTexCoordID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboVertexID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(GLfloat) * (4 * 8), NULL, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(GLfloat) * (4 * 8), NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBuffer(GL_ARRAY_BUFFER, _vboVertexID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (4 * 8), NULL, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (4 * 8), NULL, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Set up VAO
glGenVertexArraysDESMUME(1, &_vaoMainStatesID);
@ -6691,9 +6740,9 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
if (this->_output->GetContextInfo()->IsShaderSupported())
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboVertexID);
glBindBuffer(GL_ARRAY_BUFFER, _vboVertexID);
glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID);
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
@ -6701,10 +6750,10 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
}
else
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboVertexID);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, _vboTexCoordID);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, _vboVertexID);
glVertexPointer(2, GL_FLOAT, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, _vboTexCoordID);
glTexCoordPointer(2, GL_FLOAT, 0, NULL);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -6767,8 +6816,8 @@ OGLDisplayLayer::~OGLDisplayLayer()
glDeleteVertexArraysDESMUME(1, &this->_vaoMainStatesID);
}
glDeleteBuffersARB(1, &this->_vboVertexID);
glDeleteBuffersARB(1, &this->_vboTexCoordID);
glDeleteBuffers(1, &this->_vboVertexID);
glDeleteBuffers(1, &this->_vboTexCoordID);
if (_output->GetContextInfo()->IsShaderSupported())
{
@ -6814,10 +6863,10 @@ void OGLDisplayLayer::_UpdateRotationScaleOGL()
void OGLDisplayLayer::_UpdateVerticesOGL()
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboVertexID);
float *vtxBufferPtr = (float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
glBindBuffer(GL_ARRAY_BUFFER, this->_vboVertexID);
float *vtxBufferPtr = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
this->_output->SetScreenVertices(vtxBufferPtr);
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glUnmapBuffer(GL_ARRAY_BUFFER);
this->_needUpdateVertices = false;
}
@ -7397,7 +7446,7 @@ void OGLDisplayLayer::ProcessOGL()
{
texMain = this->_output->GetTexCPUFilterDstID(NDSDisplayID_Main);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texMain);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, vfMain->GetDstWidth(), vfMain->GetDstHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, vfMain->GetDstBufferPtr());
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, (GLsizei)vfMain->GetDstWidth(), (GLsizei)vfMain->GetDstHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, vfMain->GetDstBufferPtr());
width[NDSDisplayID_Main] = (GLsizei)vfMain->GetDstWidth();
height[NDSDisplayID_Main] = (GLsizei)vfMain->GetDstHeight();
@ -7413,7 +7462,7 @@ void OGLDisplayLayer::ProcessOGL()
{
texTouch = this->_output->GetTexCPUFilterDstID(NDSDisplayID_Touch);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texTouch);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, vfTouch->GetDstWidth(), vfTouch->GetDstHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, vfTouch->GetDstBufferPtr());
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, (GLsizei)vfTouch->GetDstWidth(), (GLsizei)vfTouch->GetDstHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, vfTouch->GetDstBufferPtr());
width[NDSDisplayID_Touch] = (GLsizei)vfTouch->GetDstWidth();
height[NDSDisplayID_Touch] = (GLsizei)vfTouch->GetDstHeight();
@ -7431,15 +7480,15 @@ void OGLDisplayLayer::ProcessOGL()
}
// Update the texture coordinates
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->_vboTexCoordID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, (4 * 8) * sizeof(GLfloat), NULL, GL_STREAM_DRAW_ARB);
float *texCoordPtr = (float *)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
glBindBuffer(GL_ARRAY_BUFFER, this->_vboTexCoordID);
glBufferData(GL_ARRAY_BUFFER, (4 * 8) * sizeof(GLfloat), NULL, GL_STREAM_DRAW);
float *texCoordPtr = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
this->_output->SetScreenTextureCoordinates((float)width[NDSDisplayID_Main], (float)height[NDSDisplayID_Main],
(float)width[NDSDisplayID_Touch], (float)height[NDSDisplayID_Touch],
texCoordPtr);
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glUnmapBuffer(GL_ARRAY_BUFFER);
// OpenGL shader-based filters can modify the viewport, so it needs to be reset here.
glViewport(0, 0, this->_output->GetViewportWidth(), this->_output->GetViewportHeight());
@ -7460,6 +7509,8 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
{
const bool isShaderSupported = this->_output->GetContextInfo()->IsShaderSupported();
glDisable(GL_BLEND);
if (isShaderSupported)
{
glUseProgram(this->_finalOutputProgram->GetProgramID());
@ -7470,9 +7521,13 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
glUniform1i(this->_uniformRenderFlipped, (isRenderingFlipped) ? GL_TRUE : GL_FALSE);
this->_needUpdateViewport = false;
}
if (this->_needUpdateRotationScale)
{
this->_UpdateRotationScaleOGL();
}
}
if (this->_needUpdateViewport)
else
{
const GLdouble w = this->_output->GetViewportWidth();
const GLdouble h = this->_output->GetViewportHeight();
@ -7489,12 +7544,10 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
glOrtho(-w/2.0, -w/2.0 + w, -h/2.0, -h/2.0 + h, -1.0, 1.0);
}
this->_needUpdateViewport = false;
}
if (this->_needUpdateRotationScale)
{
this->_UpdateRotationScaleOGL();
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
}
if (this->_needUpdateVertices)
@ -7608,7 +7661,7 @@ void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, processedInfo.texID[majorDisplayID]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, this->_displayTexFilter[majorDisplayID]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, this->_displayTexFilter[majorDisplayID]);
glDrawArrays(GL_TRIANGLE_STRIP, majorDisplayVtx, 4);
glDrawArrays(GL_TRIANGLE_STRIP, (GLint)majorDisplayVtx, 4);
if (texFetchMajorNeedsLock)
{

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2014-2022 DeSmuME team
Copyright (C) 2014-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -18,16 +18,18 @@
#ifndef _OGLDISPLAYOUTPUT_H_
#define _OGLDISPLAYOUTPUT_H_
#ifndef _OGLDISPLAYOUTPUT_3_2_H_
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#ifdef _OGLDISPLAYOUTPUT_3_2_H_
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#else
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#endif
#include <OpenGL/OpenGL.h>
#endif
#endif // _OGLDISPLAYOUTPUT_3_2_H_
#include <set>
#include <string>
#include <pthread.h>
@ -47,7 +49,7 @@ enum ShaderSupportTier
ShaderSupport_MidTier = 3,
ShaderSupport_HighTier = 4,
ShaderSupport_TopTier = 5,
ShaderSupport_FutureTier = 6,
ShaderSupport_FutureTier = 6
};
struct OGLProcessedFrameInfo

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2015 DeSmuME team
Copyright (C) 2015-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -18,12 +18,6 @@
#ifndef _OGLDISPLAYOUTPUT_3_2_H_
#define _OGLDISPLAYOUTPUT_3_2_H_
#if defined(__APPLE__)
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#include <OpenGL/OpenGL.h>
#endif
#include "OGLDisplayOutput.h"
class OGLContextInfo_3_2 : public OGLContextInfo

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2013-2022 DeSmuME team
Copyright (C) 2013-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -238,6 +238,9 @@ public:
@property (assign) BOOL layerSubOBJ;
@property (assign) NSInteger render3DRenderingEngine;
@property (readonly) NSInteger render3DRenderingEngineApplied;
@property (readonly) NSInteger render3DRenderingEngineAppliedHostRendererID;
@property (readonly) NSString *render3DRenderingEngineAppliedHostRendererName;
@property (assign) BOOL render3DHighPrecisionColorInterpolation;
@property (assign) BOOL render3DEdgeMarking;
@property (assign) BOOL render3DFog;
@ -261,7 +264,6 @@ public:
#endif
- (BOOL) gpuStateByBit:(const UInt32)stateBit;
- (NSString *) render3DRenderingEngineString;
- (void) clearWithColor:(const uint16_t)colorBGRA5551;
- (void) respondToPauseState:(BOOL)isPaused;
@ -272,18 +274,14 @@ extern "C"
{
#endif
bool OSXOpenGLRendererInit();
bool OSXOpenGLRendererBegin();
void OSXOpenGLRendererEnd();
bool OSXOpenGLRendererFramebufferDidResize(const bool isFBOSupported, size_t w, size_t h);
bool cgl_initOpenGL_StandardAuto();
bool cgl_initOpenGL_LegacyAuto();
bool cgl_initOpenGL_3_2_CoreProfile();
bool CreateOpenGLRenderer();
void DestroyOpenGLRenderer();
void RequestOpenGLRenderer_3_2(bool request_3_2);
void SetOpenGLRendererFunctions(bool (*initFunction)(),
bool (*beginOGLFunction)(),
void (*endOGLFunction)(),
bool (*resizeOGLFunction)(const bool isFBOSupported, size_t w, size_t h));
void cgl_deinitOpenGL();
bool cgl_beginOpenGL();
void cgl_endOpenGL();
bool cgl_framebufferDidResizeCallback(const bool isFBOSupported, size_t w, size_t h);
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2013-2022 DeSmuME team
Copyright (C) 2013-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -16,6 +16,10 @@
*/
#import "cocoa_GPU.h"
#include <sys/types.h>
#include <sys/sysctl.h>
#import "cocoa_output.h"
#import "cocoa_globals.h"
#include "utilities.h"
@ -51,6 +55,9 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
NULL
};
int __hostRendererID = -1;
char __hostRendererString[256] = {0};
@implementation CocoaDSGPU
@dynamic gpuStateFlags;
@ -74,6 +81,9 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
@dynamic layerSubOBJ;
@dynamic render3DRenderingEngine;
@dynamic render3DRenderingEngineApplied;
@dynamic render3DRenderingEngineAppliedHostRendererID;
@dynamic render3DRenderingEngineAppliedHostRendererName;
@dynamic render3DHighPrecisionColorInterpolation;
@dynamic render3DEdgeMarking;
@dynamic render3DFog;
@ -118,11 +128,17 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
isCPUCoreCountAuto = NO;
_needRestoreRender3DLock = NO;
SetOpenGLRendererFunctions(&OSXOpenGLRendererInit,
&OSXOpenGLRendererBegin,
&OSXOpenGLRendererEnd,
&OSXOpenGLRendererFramebufferDidResize);
oglrender_init = &cgl_initOpenGL_StandardAuto;
oglrender_deinit = &cgl_deinitOpenGL;
oglrender_beginOpenGL = &cgl_beginOpenGL;
oglrender_endOpenGL = &cgl_endOpenGL;
oglrender_framebufferDidResizeCallback = &cgl_framebufferDidResizeCallback;
#ifdef OGLRENDER_3_2_H
OGLLoadEntryPoints_3_2_Func = &OGLLoadEntryPoints_3_2;
OGLCreateRenderer_3_2_Func = &OGLCreateRenderer_3_2;
#endif
#ifdef PORT_VERSION_OS_X_APP
gpuEvent = new GPUEventHandlerAsync;
@ -169,10 +185,10 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
openglDeviceMaxMultisamples = 0;
render3DMultisampleSizeString = @"Off";
bool isTempContextCreated = OSXOpenGLRendererInit();
bool isTempContextCreated = cgl_initOpenGL_StandardAuto();
if (isTempContextCreated)
{
OSXOpenGLRendererBegin();
cgl_beginOpenGL();
GLint maxSamplesOGL = 0;
@ -184,8 +200,8 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
openglDeviceMaxMultisamples = maxSamplesOGL;
OSXOpenGLRendererEnd();
DestroyOpenGLRenderer();
cgl_endOpenGL();
cgl_deinitOpenGL();
}
return self;
@ -193,7 +209,7 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
- (void)dealloc
{
DestroyOpenGLRenderer();
GPU->SetEventHandler(NULL); // Unassigned our event handler before we delete it.
delete fetchObject;
delete gpuEvent;
@ -371,17 +387,13 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
puts("DeSmuME: Invalid 3D renderer chosen; falling back to SoftRasterizer.");
rendererID = CORE3DLIST_SWRASTERIZE;
}
#if defined(__ppc__) || defined(__ppc64__)
if ( (rendererID != CORE3DLIST_NULL) && (rendererID != CORE3DLIST_SWRASTERIZE) )
else if (rendererID == CORE3DLIST_OPENGL)
{
puts("DeSmuME: PowerPC Macs only support SoftRasterizer; falling back to SoftRasterizer.");
rendererID = CORE3DLIST_SWRASTERIZE;
oglrender_init = &cgl_initOpenGL_StandardAuto;
}
#endif
gpuEvent->ApplyRender3DSettingsLock();
GPU->Set3DRendererByID(rendererID);
GPU->Set3DRendererByID((int)rendererID);
gpuEvent->ApplyRender3DSettingsUnlock();
}
@ -394,6 +406,88 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
return rendererID;
}
- (NSInteger) render3DRenderingEngineApplied
{
gpuEvent->ApplyRender3DSettingsLock();
if ( (gpu3D == NULL) || (CurrentRenderer == NULL) )
{
gpuEvent->ApplyRender3DSettingsUnlock();
return 0;
}
const NSInteger rendererID = (NSInteger)CurrentRenderer->GetRenderID();
gpuEvent->ApplyRender3DSettingsUnlock();
return rendererID;
}
- (NSInteger) render3DRenderingEngineAppliedHostRendererID
{
NSInteger hostID = 0;
gpuEvent->ApplyRender3DSettingsLock();
if ( (gpu3D == NULL) || (CurrentRenderer == NULL) )
{
gpuEvent->ApplyRender3DSettingsUnlock();
return hostID;
}
switch (CurrentRenderer->GetRenderID())
{
case RENDERID_OPENGL_AUTO:
case RENDERID_OPENGL_LEGACY:
case RENDERID_OPENGL_3_2:
hostID = (NSInteger)__hostRendererID;
break;
case RENDERID_NULL:
case RENDERID_SOFTRASTERIZER:
default:
break;
}
gpuEvent->ApplyRender3DSettingsUnlock();
return hostID;
}
- (NSString *) render3DRenderingEngineAppliedHostRendererName
{
NSString *theString = @"Uninitialized";
gpuEvent->ApplyRender3DSettingsLock();
if ( (gpu3D == NULL) || (CurrentRenderer == NULL) )
{
gpuEvent->ApplyRender3DSettingsUnlock();
return theString;
}
std::string theName;
switch (CurrentRenderer->GetRenderID())
{
case RENDERID_OPENGL_AUTO:
case RENDERID_OPENGL_LEGACY:
case RENDERID_OPENGL_3_2:
theName = std::string((const char *)__hostRendererString);
break;
case RENDERID_NULL:
case RENDERID_SOFTRASTERIZER:
default:
theName = CurrentRenderer->GetName();
break;
}
theString = [NSString stringWithCString:theName.c_str() encoding:NSUTF8StringEncoding];
gpuEvent->ApplyRender3DSettingsUnlock();
return theString;
}
- (void) setRender3DHighPrecisionColorInterpolation:(BOOL)state
{
gpuEvent->ApplyRender3DSettingsLock();
@ -484,7 +578,7 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
gpuEvent->ApplyRender3DSettingsLock();
CommonSettings.num_cores = numberCores;
CommonSettings.num_cores = (int)numberCores;
if (renderingEngineID == RENDERID_SOFTRASTERIZER)
{
@ -1018,26 +1112,6 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
return ([self gpuStateFlags] & (1 << stateBit)) ? YES : NO;
}
- (NSString *) render3DRenderingEngineString
{
NSString *theString = @"Uninitialized";
gpuEvent->ApplyRender3DSettingsLock();
if (gpu3D == NULL)
{
gpuEvent->ApplyRender3DSettingsUnlock();
return theString;
}
const char *theName = gpu3D->name;
theString = [NSString stringWithCString:theName encoding:NSUTF8StringEncoding];
gpuEvent->ApplyRender3DSettingsUnlock();
return theString;
}
- (void) clearWithColor:(const uint16_t)colorBGRA5551
{
gpuEvent->FramebufferLock();
@ -1819,22 +1893,494 @@ bool GPUEventHandlerAsync::GetRender3DNeedsFinish()
#pragma mark -
#if !defined(MAC_OS_X_VERSION_10_7)
#define kCGLPFAOpenGLProfile (CGLPixelFormatAttribute)99
#define kCGLOGLPVersion_Legacy 0x1000
#define kCGLOGLPVersion_3_2_Core 0x3200
#define kCGLOGLPVersion_GL3_Core 0x3200
#define kCGLRPVideoMemoryMegabytes (CGLRendererProperty)131
#define kCGLRPTextureMemoryMegabytes (CGLRendererProperty)132
#endif
#if !defined(MAC_OS_X_VERSION_10_9)
#define kCGLOGLPVersion_GL4_Core 0x4100
#endif
#if !defined(MAC_OS_X_VERSION_10_13)
#define kCGLRPRemovable (CGLRendererProperty)142
#endif
CGLContextObj OSXOpenGLRendererContext = NULL;
CGLContextObj OSXOpenGLRendererContextPrev = NULL;
SILENCE_DEPRECATION_MACOS_10_7( CGLPBufferObj OSXOpenGLRendererPBuffer = NULL );
bool OSXOpenGLRendererInit()
// Struct to hold renderer info
struct HostRendererInfo
{
bool isContextCreated = (OSXOpenGLRendererContext != NULL);
int32_t rendererID; // Renderer ID, used to associate a renderer with a display device or virtual screen
int32_t accelerated; // Hardware acceleration flag, 0 = Software only, 1 = Has hardware acceleration
int32_t displayID; // Display ID, used to associate a display device with a renderer
int32_t online; // Online flag, 0 = No display device associated, 1 = Display device associated
int32_t removable; // Removable flag, used to indicate if the renderer is removable (like an eGPU), 0 = Fixed, 1 = Removable
int32_t virtualScreen; // Virtual screen index, used to associate a virtual screen with a renderer
int32_t videoMemoryMB; // The total amount of VRAM available to this renderer
int32_t textureMemoryMB; // The amount of VRAM available to this renderer for texture usage
char vendor[256]; // C-string copy of the host renderer's vendor
char name[256]; // C-string copy of the host renderer's name
const void *vendorStr; // Pointer to host renderer's vendor string (parsing this is implementation dependent)
const void *nameStr; // Pointer to host renderer's name string (parsing this is implementation dependent)
};
typedef struct HostRendererInfo HostRendererInfo;
static bool __cgl_initOpenGL(const int requestedProfile)
{
bool result = false;
CACHE_ALIGN char ctxString[16] = {0};
if (requestedProfile == kCGLOGLPVersion_GL4_Core)
{
strncpy(ctxString, "CGL 4.1", sizeof(ctxString));
}
else if (requestedProfile == kCGLOGLPVersion_3_2_Core)
{
strncpy(ctxString, "CGL 3.2", sizeof(ctxString));
}
else
{
strncpy(ctxString, "CGL Legacy", sizeof(ctxString));
}
if (OSXOpenGLRendererContext != NULL)
{
result = true;
return result;
}
const bool isHighSierraSupported = IsOSXVersionSupported(10, 13, 0);
const bool isMavericksSupported = (isHighSierraSupported || IsOSXVersionSupported(10, 9, 0));
const bool isMountainLionSupported = (isMavericksSupported || IsOSXVersionSupported(10, 8, 0));
const bool isLionSupported = (isMountainLionSupported || IsOSXVersionSupported(10, 7, 0));
const bool isLeopardSupported = (isLionSupported || IsOSXVersionSupported(10, 5, 0));
CGLPixelFormatAttribute attrs[] = {
kCGLPFAColorSize, (CGLPixelFormatAttribute)24,
kCGLPFAAlphaSize, (CGLPixelFormatAttribute)8,
kCGLPFADepthSize, (CGLPixelFormatAttribute)24,
kCGLPFAStencilSize, (CGLPixelFormatAttribute)8,
kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)0,
kCGLPFAAllowOfflineRenderers,
kCGLPFAAccelerated,
kCGLPFANoRecovery,
(CGLPixelFormatAttribute)0
};
if (requestedProfile == kCGLOGLPVersion_GL4_Core)
{
if (isMavericksSupported)
{
attrs[5] = (CGLPixelFormatAttribute)0; // We'll be using FBOs instead of the default framebuffer.
attrs[7] = (CGLPixelFormatAttribute)0; // We'll be using FBOs instead of the default framebuffer.
attrs[9] = (CGLPixelFormatAttribute)requestedProfile;
}
else
{
fprintf(stderr, "%s: Your version of OS X is too old to support 4.1 Core Profile.\n", ctxString);
return result;
}
}
else if (requestedProfile == kCGLOGLPVersion_3_2_Core)
{
// As of 2021/09/03, testing has shown that macOS v10.7's OpenGL 3.2 shader
// compiler isn't very reliable, and so we're going to require macOS v10.8
// instead, which at least has a working shader compiler for OpenGL 3.2.
if (isMountainLionSupported)
{
attrs[5] = (CGLPixelFormatAttribute)0; // We'll be using FBOs instead of the default framebuffer.
attrs[7] = (CGLPixelFormatAttribute)0; // We'll be using FBOs instead of the default framebuffer.
attrs[9] = (CGLPixelFormatAttribute)requestedProfile;
}
else
{
fprintf(stderr, "%s: Your version of OS X is too old to support 3.2 Core Profile.\n", ctxString);
return result;
}
}
else if (isLionSupported)
{
attrs[9] = (CGLPixelFormatAttribute)kCGLOGLPVersion_Legacy;
}
else
{
attrs[8] = (CGLPixelFormatAttribute)kCGLPFAAccelerated;
attrs[9] = (CGLPixelFormatAttribute)kCGLPFANoRecovery;
attrs[11] = (CGLPixelFormatAttribute)0;
attrs[12] = (CGLPixelFormatAttribute)0;
}
CGLError error = kCGLNoError;
CGLPixelFormatObj cglPixFormat = NULL;
CGLContextObj newContext = NULL;
GLint virtualScreenCount = 0;
CGLChoosePixelFormat(attrs, &cglPixFormat, &virtualScreenCount);
if (cglPixFormat == NULL)
{
if (requestedProfile == kCGLOGLPVersion_GL4_Core)
{
// OpenGL 4.1 Core Profile requires hardware acceleration. Bail if we can't find a renderer that supports both.
fprintf(stderr, "%s: This system has no HW-accelerated renderers that support 4.1 Core Profile.\n", ctxString);
return result;
}
else if (requestedProfile == kCGLOGLPVersion_3_2_Core)
{
// OpenGL 3.2 Core Profile requires hardware acceleration. Bail if we can't find a renderer that supports both.
fprintf(stderr, "%s: This system has no HW-accelerated renderers that support 3.2 Core Profile.\n", ctxString);
return result;
}
// For Legacy OpenGL, we'll allow fallback to the Apple Software Renderer.
// However, doing this will result in a substantial performance loss.
if (attrs[8] == kCGLPFAAccelerated)
{
attrs[8] = (CGLPixelFormatAttribute)0;
attrs[9] = (CGLPixelFormatAttribute)0;
attrs[10] = (CGLPixelFormatAttribute)0;
}
else
{
attrs[10] = (CGLPixelFormatAttribute)0;
attrs[11] = (CGLPixelFormatAttribute)0;
attrs[12] = (CGLPixelFormatAttribute)0;
}
error = CGLChoosePixelFormat(attrs, &cglPixFormat, &virtualScreenCount);
if (error != kCGLNoError)
{
// We shouldn't fail at this point, but we're including this to account for all code paths.
fprintf(stderr, "%s: Failed to create the pixel format structure: %i\n", ctxString, (int)error);
return result;
}
else
{
printf("WARNING: No HW-accelerated renderers were found -- falling back to Apple Software Renderer.\n This will result in a substantial performance loss.");
}
}
// Create the OpenGL context using our pixel format, and then save the default assigned virtual screen.
error = CGLCreateContext(cglPixFormat, NULL, &newContext);
CGLReleasePixelFormat(cglPixFormat);
cglPixFormat = NULL;
if (error != kCGLNoError)
{
fprintf(stderr, "%s: Failed to create an OpenGL context: %i\n", ctxString, (int)error);
return result;
}
OSXOpenGLRendererContext = newContext;
GLint defaultVirtualScreen = 0;
CGLGetVirtualScreen(newContext, &defaultVirtualScreen);
// Retrieve the properties of every renderer available on the system.
CGLRendererInfoObj cglRendererInfo = NULL;
GLint rendererCount = 0;
CGLQueryRendererInfo(0xFFFFFFFF, &cglRendererInfo, &rendererCount);
HostRendererInfo *rendererInfo = (HostRendererInfo *)malloc(sizeof(HostRendererInfo) * rendererCount);
memset(rendererInfo, 0, sizeof(HostRendererInfo) * rendererCount);
if (isLeopardSupported)
{
for (GLint i = 0; i < rendererCount; i++)
{
HostRendererInfo &info = rendererInfo[i];
CGLDescribeRenderer(cglRendererInfo, i, kCGLRPOnline, &(info.online));
CGLDescribeRenderer(cglRendererInfo, i, kCGLRPDisplayMask, &(info.displayID));
info.displayID = (GLint)CGOpenGLDisplayMaskToDisplayID(info.displayID);
CGLDescribeRenderer(cglRendererInfo, i, kCGLRPAccelerated, &(info.accelerated));
CGLDescribeRenderer(cglRendererInfo, i, kCGLRPRendererID, &(info.rendererID));
if (isLionSupported)
{
CGLDescribeRenderer(cglRendererInfo, i, kCGLRPVideoMemoryMegabytes, &(info.videoMemoryMB));
CGLDescribeRenderer(cglRendererInfo, i, kCGLRPTextureMemoryMegabytes, &(info.textureMemoryMB));
}
else
{
CGLDescribeRenderer(cglRendererInfo, i, kCGLRPVideoMemory, &(info.videoMemoryMB));
info.videoMemoryMB = (GLint)(((uint32_t)info.videoMemoryMB + 1) >> 20);
CGLDescribeRenderer(cglRendererInfo, i, kCGLRPTextureMemory, &(info.textureMemoryMB));
info.textureMemoryMB = (GLint)(((uint32_t)info.textureMemoryMB + 1) >> 20);
}
if (isHighSierraSupported)
{
CGLDescribeRenderer(cglRendererInfo, i, kCGLRPRemovable, &(info.removable));
}
}
}
else
{
CGLDestroyRendererInfo(cglRendererInfo);
free(rendererInfo);
fprintf(stderr, "%s: Failed to retrieve renderer info - requires Mac OS X v10.5 or later.\n", ctxString);
return result;
}
CGLDestroyRendererInfo(cglRendererInfo);
cglRendererInfo = NULL;
// Retrieve the vendor and renderer info from OpenGL.
cgl_beginOpenGL();
for (GLint i = 0; i < virtualScreenCount; i++)
{
CGLSetVirtualScreen(newContext, i);
GLint r;
CGLGetParameter(newContext, kCGLCPCurrentRendererID, &r);
for (int j = 0; j < rendererCount; j++)
{
HostRendererInfo &info = rendererInfo[j];
if (r == info.rendererID)
{
info.virtualScreen = i;
info.vendorStr = (const char *)glGetString(GL_VENDOR);
if (info.vendorStr != NULL)
{
strncpy(info.vendor, (const char *)info.vendorStr, sizeof(info.vendor));
}
else if (info.accelerated == 0)
{
strncpy(info.vendor, "Apple Inc.", sizeof(info.vendor));
}
else
{
strncpy(info.vendor, "UNKNOWN", sizeof(info.vendor));
}
info.nameStr = (const char *)glGetString(GL_RENDERER);
if (info.nameStr != NULL)
{
strncpy(info.name, (const char *)info.nameStr, sizeof(info.name));
}
else if (info.accelerated == 0)
{
strncpy(info.name, "Apple Software Renderer", sizeof(info.name));
}
else
{
strncpy(info.name, "UNKNOWN", sizeof(info.name));
}
}
}
}
cgl_endOpenGL();
// Get the default virtual screen.
strncpy(__hostRendererString, "UNKNOWN", sizeof(__hostRendererString));
__hostRendererID = -1;
HostRendererInfo defaultRendererInfo = rendererInfo[0];
for (int i = 0; i < rendererCount; i++)
{
if (defaultVirtualScreen == rendererInfo[i].virtualScreen)
{
defaultRendererInfo = rendererInfo[i];
__hostRendererID = defaultRendererInfo.rendererID;
strncpy(__hostRendererString, (const char *)defaultRendererInfo.name, sizeof(__hostRendererString));
if ( (defaultRendererInfo.online == 1) && (defaultRendererInfo.vendorStr != NULL) && (defaultRendererInfo.nameStr != NULL) )
{
break;
}
}
}
printf("Default OpenGL Renderer: [0x%08X] %s\n", __hostRendererID, __hostRendererString);
/*
bool isDefaultRunningIntegratedGPU = false;
if ( (defaultRendererInfo.online == 1) && (defaultRendererInfo.vendorStr != NULL) && (defaultRendererInfo.nameStr != NULL) )
{
const HostRendererInfo &d = defaultRendererInfo;
isDefaultRunningIntegratedGPU = (strstr(d.name, "GMA 950") != NULL) ||
(strstr(d.name, "GMA X3100") != NULL) ||
(strstr(d.name, "GeForce 9400M") != NULL) ||
(strstr(d.name, "GeForce 320M") != NULL) ||
(strstr(d.name, "HD Graphics") != NULL) ||
(strstr(d.name, "Iris 5100") != NULL) ||
(strstr(d.name, "Iris Plus") != NULL) ||
(strstr(d.name, "Iris Pro") != NULL) ||
(strstr(d.name, "Iris Graphics") != NULL) ||
(strstr(d.name, "UHD Graphics") != NULL);
}
*/
#if defined(DEBUG) && (DEBUG == 1)
// Report information on every renderer.
if (!isLionSupported)
{
printf("WARNING: You are running a macOS version earlier than v10.7.\n Video Memory and Texture Memory reporting is capped\n at 2048 MB on older macOS.\n");
}
printf("CGL Renderer Count: %i\n", rendererCount);
printf(" Virtual Screen Count: %i\n\n", virtualScreenCount);
for (int i = 0; i < rendererCount; i++)
{
const HostRendererInfo &info = rendererInfo[i];
printf("Renderer Index: %i\n", i);
printf("Virtual Screen: %i\n", info.virtualScreen);
printf("Vendor: %s\n", info.vendor);
printf("Renderer: %s\n", info.name);
printf("Renderer ID: 0x%08X\n", info.rendererID);
printf("Accelerated: %s\n", (info.accelerated == 1) ? "YES" : "NO");
printf("Online: %s\n", (info.online == 1) ? "YES" : "NO");
if (isHighSierraSupported)
{
printf("Removable: %s\n", (info.removable == 1) ? "YES" : "NO");
}
else
{
printf("Removable: UNSUPPORTED, Requires High Sierra\n");
}
printf("Display ID: 0x%08X\n", info.displayID);
printf("Video Memory: %i MB\n", info.videoMemoryMB);
printf("Texture Memory: %i MB\n\n", info.textureMemoryMB);
}
#endif
// Search for a better virtual screen that will suit our offscreen rendering better.
//
// At the moment, we are not supporting removable renderers such as eGPUs. Attempting
// to support removable renderers would require a lot more code to handle dynamically
// changing display<-->renderer associations. - rogerman 2025/03/25
bool wasBetterVirtualScreenFound = false;
char *modelCString = NULL;
size_t modelStringLen = 0;
sysctlbyname("hw.model", NULL, &modelStringLen, NULL, 0);
if (modelStringLen > 0)
{
modelCString = (char *)malloc(modelStringLen * sizeof(char));
sysctlbyname("hw.model", modelCString, &modelStringLen, NULL, 0);
}
for (int i = 0; i < rendererCount; i++)
{
const HostRendererInfo &info = rendererInfo[i];
if ( (defaultRendererInfo.vendorStr == NULL) || (defaultRendererInfo.nameStr == NULL) || (info.vendorStr == NULL) || (info.nameStr == NULL) )
{
continue;
}
wasBetterVirtualScreenFound = (info.accelerated == 1) &&
( ( (modelCString != NULL) && (strstr((const char *)modelCString, "MacBookPro") != NULL) &&
( ( (strstr(defaultRendererInfo.name, "GeForce 9400M") != NULL) &&
(strstr(info.name, "GeForce 9600M GT") != NULL) ) ||
( (strstr(defaultRendererInfo.name, "HD Graphics") != NULL) &&
((strstr(info.name, "GeForce GT 330M") != NULL) ||
(strstr(info.name, "Radeon HD 6490M") != NULL) ||
(strstr(info.name, "Radeon HD 6750M") != NULL) ||
(strstr(info.name, "Radeon HD 6770M") != NULL) ||
(strstr(info.name, "GeForce GT 650M") != NULL) ||
(strstr(info.name, "Radeon Pro 450") != NULL) ||
(strstr(info.name, "Radeon Pro 455") != NULL) ||
(strstr(info.name, "Radeon Pro 555") != NULL) ||
(strstr(info.name, "Radeon Pro 560") != NULL)) ) ||
( (strstr(defaultRendererInfo.name, "Iris Pro") != NULL) &&
((strstr(info.name, "GeForce GT 750M") != NULL) ||
(strstr(info.name, "Radeon R9 M370X") != NULL)) ) ||
( (strstr(defaultRendererInfo.name, "UHD Graphics") != NULL) &&
((strstr(info.name, "Radeon Pro 555X") != NULL) ||
(strstr(info.name, "Radeon Pro 560X") != NULL) ||
(strstr(info.name, "Radeon Pro Vega 16") != NULL) ||
(strstr(info.name, "Radeon Pro Vega 20") != NULL) ||
(strstr(info.name, "Radeon Pro 5300M") != NULL) ||
(strstr(info.name, "Radeon Pro 5500M") != NULL) ||
(strstr(info.name, "Radeon Pro 5600M") != NULL)) ) ) ) ||
( (modelCString != NULL) && (strstr((const char *)modelCString, "MacPro6,1") != NULL) && (info.online == 0) &&
((strstr(info.name, "FirePro D300") != NULL) ||
(strstr(info.name, "FirePro D500") != NULL) ||
(strstr(info.name, "FirePro D700") != NULL)) ) );
if (wasBetterVirtualScreenFound)
{
CGLSetVirtualScreen(newContext, info.virtualScreen);
__hostRendererID = info.rendererID;
strncpy(__hostRendererString, (const char *)info.name, sizeof(__hostRendererString));
printf("Found Better OpenGL Renderer: [0x%08X] %s\n", __hostRendererID, __hostRendererString);
break;
}
}
// If we couldn't find a better virtual screen for our rendering, then just revert to the default one.
if (!wasBetterVirtualScreenFound)
{
CGLSetVirtualScreen(newContext, defaultVirtualScreen);
}
// We're done! Report success and return.
printf("%s: OpenGL context creation successful.\n\n", ctxString);
free(rendererInfo);
free(modelCString);
result = true;
return result;
}
bool cgl_initOpenGL_StandardAuto()
{
bool isContextCreated = __cgl_initOpenGL(kCGLOGLPVersion_GL4_Core);
if (!isContextCreated)
{
isContextCreated = CreateOpenGLRenderer();
isContextCreated = __cgl_initOpenGL(kCGLOGLPVersion_3_2_Core);
}
if (!isContextCreated)
{
isContextCreated = __cgl_initOpenGL(kCGLOGLPVersion_Legacy);
}
return isContextCreated;
}
bool OSXOpenGLRendererBegin()
bool cgl_initOpenGL_LegacyAuto()
{
return __cgl_initOpenGL(kCGLOGLPVersion_Legacy);
}
bool cgl_initOpenGL_3_2_CoreProfile()
{
return __cgl_initOpenGL(kCGLOGLPVersion_3_2_Core);
}
void cgl_deinitOpenGL()
{
if (OSXOpenGLRendererContext == NULL)
{
return;
}
CGLSetCurrentContext(NULL);
SILENCE_DEPRECATION_MACOS_10_7( CGLReleasePBuffer(OSXOpenGLRendererPBuffer) );
OSXOpenGLRendererPBuffer = NULL;
CGLReleaseContext(OSXOpenGLRendererContext);
OSXOpenGLRendererContext = NULL;
OSXOpenGLRendererContextPrev = NULL;
}
bool cgl_beginOpenGL()
{
OSXOpenGLRendererContextPrev = CGLGetCurrentContext();
CGLSetCurrentContext(OSXOpenGLRendererContext);
@ -1842,7 +2388,7 @@ bool OSXOpenGLRendererBegin()
return true;
}
void OSXOpenGLRendererEnd()
void cgl_endOpenGL()
{
#ifndef PORT_VERSION_OS_X_APP
// The OpenEmu plug-in needs the context reset after 3D rendering since OpenEmu's context
@ -1853,7 +2399,7 @@ void OSXOpenGLRendererEnd()
#endif
}
bool OSXOpenGLRendererFramebufferDidResize(const bool isFBOSupported, size_t w, size_t h)
bool cgl_framebufferDidResizeCallback(const bool isFBOSupported, size_t w, size_t h)
{
bool result = false;
@ -1871,7 +2417,7 @@ bool OSXOpenGLRendererFramebufferDidResize(const bool isFBOSupported, size_t w,
// Create a PBuffer if FBOs are not supported.
SILENCE_DEPRECATION_MACOS_10_7( CGLPBufferObj newPBuffer = NULL );
SILENCE_DEPRECATION_MACOS_10_7( CGLError error = CGLCreatePBuffer(w, h, GL_TEXTURE_2D, GL_RGBA, 0, &newPBuffer) );
SILENCE_DEPRECATION_MACOS_10_7( CGLError error = CGLCreatePBuffer((GLsizei)w, (GLsizei)h, GL_TEXTURE_2D, GL_RGBA, 0, &newPBuffer) );
if ( (newPBuffer == NULL) || (error != kCGLNoError) )
{
@ -1892,100 +2438,3 @@ bool OSXOpenGLRendererFramebufferDidResize(const bool isFBOSupported, size_t w,
result = true;
return result;
}
bool CreateOpenGLRenderer()
{
bool result = false;
bool useContext_3_2 = false;
CGLPixelFormatObj cglPixFormat = NULL;
CGLContextObj newContext = NULL;
GLint virtualScreenCount = 0;
CGLPixelFormatAttribute attrs[] = {
kCGLPFAColorSize, (CGLPixelFormatAttribute)24,
kCGLPFAAlphaSize, (CGLPixelFormatAttribute)8,
kCGLPFADepthSize, (CGLPixelFormatAttribute)24,
kCGLPFAStencilSize, (CGLPixelFormatAttribute)8,
kCGLPFAAccelerated,
(CGLPixelFormatAttribute)0, (CGLPixelFormatAttribute)0,
(CGLPixelFormatAttribute)0
};
// If we can support a 3.2 Core Profile context, then request that in our
// pixel format attributes.
#ifdef MAC_OS_X_VERSION_10_7
// As of 2021/09/03, testing has shown that macOS v10.7's OpenGL 3.2 shader
// compiler isn't very reliable, and so we're going to require macOS v10.8
// instead, which at least has a working shader compiler for OpenGL 3.2.
useContext_3_2 = IsOSXVersionSupported(10, 8, 0);
if (useContext_3_2)
{
attrs[9] = kCGLPFAOpenGLProfile;
attrs[10] = (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core;
}
#endif
CGLChoosePixelFormat(attrs, &cglPixFormat, &virtualScreenCount);
if (cglPixFormat == NULL)
{
// Remove the HW rendering requirement and try again. Note that this will
// result in SW rendering, which will cause a substantial speed hit.
attrs[8] = (CGLPixelFormatAttribute)0;
CGLChoosePixelFormat(attrs, &cglPixFormat, &virtualScreenCount);
if (cglPixFormat == NULL)
{
return result;
}
}
CGLCreateContext(cglPixFormat, NULL, &newContext);
CGLReleasePixelFormat(cglPixFormat);
RequestOpenGLRenderer_3_2(useContext_3_2);
OSXOpenGLRendererContext = newContext;
result = true;
return result;
}
void DestroyOpenGLRenderer()
{
if (OSXOpenGLRendererContext == NULL)
{
return;
}
OSXOpenGLRendererEnd();
SILENCE_DEPRECATION_MACOS_10_7( CGLReleasePBuffer(OSXOpenGLRendererPBuffer) );
OSXOpenGLRendererPBuffer = NULL;
CGLReleaseContext(OSXOpenGLRendererContext);
OSXOpenGLRendererContext = NULL;
OSXOpenGLRendererContextPrev = NULL;
}
void RequestOpenGLRenderer_3_2(bool request_3_2)
{
#ifdef OGLRENDER_3_2_H
if (request_3_2)
{
OGLLoadEntryPoints_3_2_Func = &OGLLoadEntryPoints_3_2;
OGLCreateRenderer_3_2_Func = &OGLCreateRenderer_3_2;
return;
}
#endif
OGLLoadEntryPoints_3_2_Func = NULL;
OGLCreateRenderer_3_2_Func = NULL;
}
void SetOpenGLRendererFunctions(bool (*initFunction)(),
bool (*beginOGLFunction)(),
void (*endOGLFunction)(),
bool (*resizeOGLFunction)(const bool isFBOSupported, size_t w, size_t h))
{
oglrender_init = initFunction;
oglrender_beginOpenGL = beginOGLFunction;
oglrender_endOpenGL = endOGLFunction;
oglrender_framebufferDidResizeCallback = resizeOGLFunction;
}

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2011-2015 DeSmuME team
Copyright (C) 2011-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -16,37 +16,305 @@
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#include <string>
#include <vector>
#include "../../cheatSystem.h"
#undef BOOL
#import <Cocoa/Cocoa.h>
class CHEATS;
class CHEATS_LIST;
class CHEATSEARCH;
class ClientCheatManager;
enum CheatType
{
CheatType_Internal = 0,
CheatType_ActionReplay = 1,
CheatType_CodeBreaker = 2
};
/********************************************************************************************
CocoaDSCheatItem - OBJECTIVE-C CLASS
enum CheatFreezeType
{
CheatFreezeType_Normal = 0,
CheatFreezeType_CanDecrease = 1,
CheatFreezeType_CanIncrease = 2
};
This is an Objective-C wrapper class for DeSmuME's cheat item struct.
The cheat item data is not freed upon release of this object. This is by design.
enum CheatSearchStyle
{
CheatSearchStyle_ExactValue = 0,
CheatSearchStyle_Comparative = 1
};
enum CheatSearchCompareStyle
{
CheatSearchCompareStyle_GreaterThan = 0,
CheatSearchCompareStyle_LesserThan = 1,
CheatSearchCompareStyle_Equals = 2,
CheatSearchCompareStyle_NotEquals = 3
};
union DesmumeCheatSearchItem
{
uint64_t data;
struct
{
uint32_t address;
uint32_t value;
};
};
typedef union DesmumeCheatSearchItem DesmumeCheatSearchItem;
typedef std::vector<DesmumeCheatSearchItem> DesmumeCheatSearchResultsList;
struct InternalCheatParam
{
uint32_t address;
uint32_t value;
uint8_t valueLength;
};
typedef struct InternalCheatParam InternalCheatParam;
class ClientCheatItem
{
protected:
ClientCheatManager *_cheatManager;
bool _isEnabled;
bool _willAddFromDB;
CheatType _cheatType;
std::string _nameString;
std::string _commentString;
// Internal cheat type parameters
CheatFreezeType _freezeType;
char _addressString[10+1];
uint32_t _address;
uint32_t _value;
uint8_t _valueLength;
// Action Replay parameters
uint32_t _codeCount;
std::string _rawCodeString;
std::string _cleanCodeString;
void _ConvertInternalToActionReplay();
void _ConvertActionReplayToInternal();
public:
ClientCheatItem();
~ClientCheatItem();
void Init(const CHEATS_LIST &inCheatItem);
void Init(const ClientCheatItem &inCheatItem);
void SetCheatManager(ClientCheatManager *cheatManager);
ClientCheatManager* GetCheatManager() const;
void SetEnabled(bool theState);
bool IsEnabled() const;
void SetWillAddFromDB(bool theState);
bool WillAddFromDB() const;
CheatType GetType() const;
void SetType(CheatType requestedType);
bool IsSupportedType() const;
const char* GetName() const;
void SetName(const char *nameString);
const char* GetComments() const;
void SetComments(const char *commentString);
CheatFreezeType GetFreezeType() const;
void SetFreezeType(CheatFreezeType theFreezeType);
uint32_t GetAddress() const;
void SetAddress(uint32_t theAddress);
const char* GetAddressString() const;
const char* GetAddressSixDigitString() const;
void SetAddressSixDigitString(const char *sixDigitString);
uint32_t GetValue() const;
void SetValue(uint32_t theValue);
uint8_t GetValueLength() const;
void SetValueLength(uint8_t byteLength);
void SetRawCodeString(const char *rawString, const bool willSaveValidatedRawString);
const char* GetRawCodeString() const;
const char* GetCleanCodeString() const;
const std::string& GetCleanCodeCppString() const;
uint32_t GetCodeCount() const;
void ClientToDesmumeCheatItem(CHEATS_LIST *outCheatItem) const;
};
class ClientCheatList
{
private:
ClientCheatItem* __AddItem(const ClientCheatItem *srcItem, const bool willCopy, const bool allowDuplicates);
protected:
std::vector<ClientCheatItem *> *_list;
public:
ClientCheatList();
~ClientCheatList();
CheatSystemError LoadFromFile(const char *filePath);
CheatSystemError SaveToFile(const char *filePath);
bool IsItemDuplicate(const ClientCheatItem *srcItem);
ClientCheatItem* AddNew();
ClientCheatItem* AddNewItemCopy(const ClientCheatItem *srcItem);
ClientCheatItem* AddNewItemCopyNoDuplicate(const ClientCheatItem *srcItem);
ClientCheatItem* AddExistingItemNoDuplicate(const ClientCheatItem *srcItem);
bool Remove(ClientCheatItem *targetItem);
bool RemoveAtIndex(size_t index);
void RemoveAll();
bool Update(const ClientCheatItem &srcItem, ClientCheatItem *targetItem);
bool UpdateAtIndex(const ClientCheatItem &srcItem, size_t index);
size_t GetTotalCheatCount() const;
size_t GetActiveCheatCount() const;
std::vector<ClientCheatItem *>* GetCheatList() const;
size_t GetIndexOfItem(const ClientCheatItem *cheatItem) const;
ClientCheatItem* GetItemAtIndex(size_t index) const;
void ReplaceFromEngine(const CHEATS *engineCheatList);
void CopyListToEngine(const bool willApplyOnlyEnabledItems, CHEATS *engineCheatList);
};
class ClientCheatSearcher
{
protected:
CHEATSEARCH *_desmumeSearcher;
uint8_t _searchValueLength;
size_t _resultsCount;
bool _didSearchStart;
DesmumeCheatSearchResultsList _resultsList;
public:
ClientCheatSearcher();
~ClientCheatSearcher();
bool DidStart() const;
void Reset();
size_t SearchExactValue(uint32_t value, uint8_t valueLength, bool performSignedSearch);
size_t SearchComparative(CheatSearchCompareStyle compareStyle, uint8_t valueLength, bool performSignedSearch);
const DesmumeCheatSearchResultsList& RefreshResults();
const DesmumeCheatSearchResultsList& GetResults();
size_t GetResultCount() const;
};
class ClientCheatDatabase
{
protected:
ClientCheatList *_list;
std::string _title;
std::string _description;
std::string _lastFilePath;
public:
ClientCheatDatabase();
~ClientCheatDatabase();
ClientCheatList* GetList() const;
ClientCheatList* LoadFromFile(const char *dbFilePath);
const char* GetTitle() const;
const char* GetDescription() const;
};
class ClientCheatManager
{
protected:
ClientCheatList *_currentSessionList;
ClientCheatDatabase *_currentDatabase;
ClientCheatSearcher *_currentSearcher;
ClientCheatItem *_selectedItem;
size_t _selectedItemIndex;
uint32_t _untitledCount;
std::string _currentSessionLastFilePath;
std::vector<InternalCheatParam> _pendingInternalCheatWriteList;
bool _masterNeedsUpdate;
public:
ClientCheatManager();
~ClientCheatManager();
static CHEATS* GetMaster();
static void SetMaster(const CHEATS *masterCheats);
ClientCheatList* GetSessionList() const;
const char* GetSessionListLastFilePath() const;
virtual CheatSystemError SessionListLoadFromFile(const char *filePath);
virtual CheatSystemError SessionListSaveToFile(const char *filePath);
ClientCheatItem* SetSelectedItemByIndex(size_t index);
ClientCheatItem* NewItem();
ClientCheatItem* AddExistingItemNoDuplicate(const ClientCheatItem *theItem);
void RemoveItem(ClientCheatItem *theItem);
void RemoveItemAtIndex(size_t index);
void RemoveSelectedItem();
void ModifyItem(const ClientCheatItem *srcItem, ClientCheatItem *targetItem);
void ModifyItemAtIndex(const ClientCheatItem *srcItem, size_t index);
size_t GetTotalCheatCount() const;
size_t GetActiveCheatCount() const;
void LoadFromMaster();
void ApplyToMaster();
void MasterNeedsUpdate();
ClientCheatList* GetDatabaseList() const;
ClientCheatList* DatabaseListLoadFromFile(const char *dbFilePath);
const char* GetDatabaseTitle() const;
const char* GetDatabaseDescription() const;
bool SearchDidStart() const;
void SearchReset();
size_t SearchExactValue(uint32_t value, uint8_t valueLength, bool performSignedSearch);
size_t SearchComparative(CheatSearchCompareStyle compareStyle, uint8_t valueLength, bool performSignedSearch);
const DesmumeCheatSearchResultsList& SearchResultsRefresh();
const DesmumeCheatSearchResultsList& GetSearchResults();
size_t GetSearchResultCount() const;
void DirectWriteInternalCheatAtIndex(size_t index);
void DirectWriteInternalCheatItem(const ClientCheatItem *cheatItem);
void DirectWriteInternalCheat(uint32_t targetAddress, uint32_t newValue32, size_t newValueLength);
void ApplyPendingInternalCheatWrites();
};
Thread Safety:
Assume that all methods are not thread-safe. This was done for performance
reasons. The caller of this class' methods is expected to handle thread safety.
********************************************************************************************/
@interface CocoaDSCheatItem : NSObject
{
CHEATS_LIST *data;
CHEATS_LIST *internalData;
ClientCheatItem *_internalData;
BOOL _didAllocateInternalData;
BOOL _disableWorkingCopyUpdate;
BOOL willAdd;
pthread_mutex_t mutexData;
CocoaDSCheatItem *workingCopy;
CocoaDSCheatItem *parent;
BOOL _isMemAddressAlreadyUpdating;
}
@property (assign) CHEATS_LIST *data;
@property (readonly, nonatomic, getter=clientData) ClientCheatItem *_internalData;
@property (assign) BOOL willAdd;
@property (assign, nonatomic) BOOL enabled;
@property (assign, nonatomic) NSInteger cheatType;
@ -64,17 +332,17 @@ class CHEATSEARCH;
@property (readonly) CocoaDSCheatItem *workingCopy;
@property (assign) CocoaDSCheatItem *parent;
- (id) initWithCheatData:(CHEATS_LIST *)cheatData;
- (BOOL) retainData;
- (id) initWithCocoaCheatItem:(CocoaDSCheatItem *)cdsCheatItem;
- (id) initWithCheatItem:(ClientCheatItem *)cheatItem;
- (id) initWithCheatData:(const CHEATS_LIST *)cheatData;
- (char *) descriptionCString;
- (void) update;
- (CocoaDSCheatItem *) createWorkingCopy;
- (void) destroyWorkingCopy;
- (void) mergeFromWorkingCopy;
- (void) mergeToParent;
- (void) setDataWithDictionary:(NSDictionary *)dataDict;
- (NSDictionary *) dataDictionary;
+ (void) setIconDirectory:(NSImage *)iconImage;
+ (NSImage *) iconDirectory;
+ (void) setIconInternalCheat:(NSImage *)iconImage;
+ (NSImage *) iconInternalCheat;
+ (void) setIconActionReplay:(NSImage *)iconImage;
@ -84,92 +352,116 @@ class CHEATSEARCH;
@end
/********************************************************************************************
CocoaDSCheatManager - OBJECTIVE-C CLASS
@interface CocoaDSCheatDBEntry : NSObject
{
CheatDBEntry *_dbEntry;
CocoaDSCheatDBEntry *parent;
NSMutableArray *child;
NSInteger willAdd;
NSString *codeString;
BOOL needSetMixedState;
}
This is an Objective-C wrapper class for DeSmuME's cheat list class.
@property (readonly, nonatomic) NSString *name;
@property (readonly, nonatomic) NSString *comment;
@property (readonly, nonatomic) NSImage *icon;
@property (readonly, nonatomic) NSInteger entryCount;
@property (readonly, nonatomic) NSString *codeString;
@property (readonly, nonatomic) BOOL isDirectory;
@property (readonly, nonatomic) BOOL isCheatItem;
@property (assign) NSInteger willAdd;
@property (assign) BOOL needSetMixedState;
@property (assign) CocoaDSCheatDBEntry *parent;
@property (readonly, nonatomic) NSMutableArray *child;
- (id) initWithDBEntry:(const CheatDBEntry *)dbEntry;
- (ClientCheatItem *) newClientItem;
@end
@interface CocoaDSCheatDBGame : NSObject
{
CheatDBGame *_dbGame;
CocoaDSCheatDBEntry *entryRoot;
NSUInteger index;
}
@property (assign) NSUInteger index;
@property (readonly, nonatomic) NSString *title;
@property (readonly, nonatomic) NSString *serial;
@property (readonly, nonatomic) NSUInteger crc;
@property (readonly, nonatomic) NSString *crcString;
@property (readonly, nonatomic) NSInteger dataSize;
@property (readonly, nonatomic) NSString *dataSizeString;
@property (readonly, nonatomic) BOOL isDataLoaded;
@property (readonly, nonatomic) NSInteger cheatItemCount;
@property (readonly, nonatomic) CocoaDSCheatDBEntry *entryRoot;
- (id) initWithGameEntry:(const CheatDBGame *)gameEntry;
- (CocoaDSCheatDBEntry *) loadEntryDataFromFilePtr:(FILE *)fp isEncrypted:(BOOL)isEncrypted;
@end
@interface CocoaDSCheatDatabase : NSObject
{
CheatDBFile *_dbFile;
CheatDBGameList *_dbGameList;
NSMutableArray *gameList;
NSURL *lastFileURL;
}
@property (readonly) NSURL *lastFileURL;
@property (readonly, nonatomic) NSString *description;
@property (readonly, nonatomic) NSString *formatString;
@property (readonly, nonatomic) BOOL isEncrypted;
@property (readonly) NSMutableArray *gameList;
- (id) initWithFileURL:(NSURL *)fileURL error:(CheatSystemError *)errorCode;
- (CocoaDSCheatDBGame *) getGameEntryUsingCode:(const char *)gameCode crc:(NSUInteger)crc;
- (CocoaDSCheatDBEntry *) loadGameEntry:(CocoaDSCheatDBGame *)dbGame;
@end
Thread Safety:
All methods are thread-safe.
********************************************************************************************/
@interface CocoaDSCheatManager : NSObject
{
CHEATS *listData;
NSMutableArray *list;
ClientCheatManager *_internalCheatManager;
NSMutableArray *sessionList;
NSMutableArray *searchResultsList;
pthread_rwlock_t *rwlockCoreExecute;
BOOL isUsingDummyRWlock;
NSUInteger untitledCount;
NSString *dbTitle;
NSString *dbDate;
}
@property (readonly) CHEATS *listData;
@property (readonly) NSMutableArray *list;
@property (assign) pthread_rwlock_t *rwlockCoreExecute;
@property (assign) NSUInteger untitledCount;
@property (copy) NSString *dbTitle;
@property (copy) NSString *dbDate;
@property (readonly, nonatomic, getter=internalManager) ClientCheatManager *_internalCheatManager;
@property (readonly) NSMutableArray *sessionList;
@property (readonly, nonatomic) NSString *currentGameCode;
@property (readonly, nonatomic) NSUInteger currentGameCRC;
@property (readonly, nonatomic) NSUInteger itemTotalCount;
@property (readonly, nonatomic) NSUInteger itemActiveCount;
@property (readonly) NSMutableArray *searchResultsList;
@property (readonly, nonatomic) BOOL searchDidStart;
@property (readonly, nonatomic) NSUInteger searchCount;
@property (assign, nonatomic) pthread_rwlock_t *rwlockCoreExecute;
- (id) initWithFileURL:(NSURL *)fileURL;
- (id) initWithListData:(CHEATS *)cheatList;
- (id) initWithFileURL:(NSURL *)fileURL listData:(CHEATS *)cheatList;
- (BOOL) add:(CocoaDSCheatItem *)cheatItem;
- (void) remove:(CocoaDSCheatItem *)cheatItem;
- (BOOL) update:(CocoaDSCheatItem *)cheatItem;
- (CocoaDSCheatItem *) newItem;
- (CocoaDSCheatItem *) addExistingItem:(ClientCheatItem *)cheatItem;
- (CocoaDSCheatItem *) addExistingCocoaItem:(CocoaDSCheatItem *)cocoaCheatItem;
- (void) remove:(CocoaDSCheatItem *)cocoaCheatItem;
- (void) removeAtIndex:(NSUInteger)itemIndex;
- (BOOL) update:(CocoaDSCheatItem *)cocoaCheatItem;
- (BOOL) save;
- (NSUInteger) activeCount;
- (NSMutableArray *) cheatListFromDatabase:(NSURL *)fileURL errorCode:(NSInteger *)error;
- (void) applyInternalCheat:(CocoaDSCheatItem *)cheatItem;
- (void) directWriteInternalCheat:(CocoaDSCheatItem *)cocoaCheatItem;
- (void) loadFromMaster;
- (void) applyToMaster;
+ (void) setMasterCheatList:(CocoaDSCheatManager *)cheatListManager;
+ (void) applyInternalCheatWithItem:(CocoaDSCheatItem *)cheatItem;
+ (void) applyInternalCheatWithAddress:(UInt32)address value:(UInt32)value bytes:(NSUInteger)bytes;
+ (NSMutableArray *) cheatListWithListObject:(CHEATS *)cheatList;
+ (NSMutableArray *) cheatListWithItemStructArray:(CHEATS_LIST *)cheatItemArray count:(NSUInteger)itemCount;
+ (NSMutableDictionary *) cheatItemWithType:(NSInteger)cheatTypeID description:(NSString *)description;
@end
@interface CocoaDSCheatSearch : NSObject
{
CHEATSEARCH *listData;
NSMutableArray *addressList;
pthread_rwlock_t *rwlockCoreExecute;
BOOL isUsingDummyRWlock;
NSUInteger searchCount;
}
@property (readonly) CHEATSEARCH *listData;
@property (readonly) NSMutableArray *addressList;
@property (assign) pthread_rwlock_t *rwlockCoreExecute;
@property (readonly) NSUInteger searchCount;
- (NSUInteger) databaseAddSelectedInEntry:(CocoaDSCheatDBEntry *)theEntry;
- (NSUInteger) runExactValueSearch:(NSInteger)value byteSize:(UInt8)byteSize signType:(NSInteger)signType;
- (void) runExactValueSearchOnThread:(id)object;
- (NSUInteger) runComparativeSearch:(NSInteger)typeID byteSize:(UInt8)byteSize signType:(NSInteger)signType;
- (void) runComparativeSearchOnThread:(id)object;
- (void) reset;
+ (NSMutableArray *) addressListWithListObject:(CHEATSEARCH *)addressList maxItems:(NSUInteger)maxItemCount;
@end
@interface CocoaDSCheatSearchParams : NSObject
{
NSInteger comparativeSearchType;
NSInteger value;
UInt8 byteSize;
NSInteger signType;
}
@property (assign) NSInteger comparativeSearchType;
@property (assign) NSInteger value;
@property (assign) UInt8 byteSize;
@property (assign) NSInteger signType;
- (void) searchReset;
@end

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@ class ClientExecutionControl;
@class CocoaDSFirmware;
@class CocoaDSGPU;
@class CocoaDSOutput;
@class CocoaDSCheatManager;
typedef struct
{
@ -48,6 +49,7 @@ typedef struct
CocoaDSController *cdsController;
CocoaDSFirmware *cdsFirmware;
CocoaDSGPU *cdsGPU;
CocoaDSCheatManager *cdsCheatManager;
NSMutableArray *cdsOutputList;
pthread_t coreThread;
@ -72,6 +74,7 @@ typedef struct
@property (retain) CocoaDSFirmware *cdsFirmware;
@property (readonly) CocoaDSController *cdsController;
@property (readonly) CocoaDSGPU *cdsGPU;
@property (readonly) CocoaDSCheatManager *cdsCheatManager;
@property (readonly) NSMutableArray *cdsOutputList;
@property (assign) BOOL masterExecute;

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2011-2022 DeSmuME team
Copyright (C) 2011-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -20,6 +20,7 @@
#import "cocoa_input.h"
#import "cocoa_firmware.h"
#import "cocoa_GPU.h"
#import "cocoa_cheat.h"
#import "cocoa_globals.h"
#import "cocoa_output.h"
#import "cocoa_rom.h"
@ -48,6 +49,7 @@ volatile bool execute = true;
@synthesize cdsFirmware;
@synthesize cdsController;
@synthesize cdsGPU;
@synthesize cdsCheatManager;
@synthesize cdsOutputList;
@dynamic masterExecute;
@ -122,6 +124,7 @@ volatile bool execute = true;
cdsFirmware = nil;
cdsController = [[CocoaDSController alloc] init];
cdsGPU = [[CocoaDSGPU alloc] init];
cdsCheatManager = [[CocoaDSCheatManager alloc] init];
cdsOutputList = [[NSMutableArray alloc] initWithCapacity:32];
ClientInputHandler *inputHandler = [cdsController inputHandler];
@ -164,10 +167,11 @@ volatile bool execute = true;
pthread_attr_destroy(&threadAttr);
[cdsGPU setOutputList:cdsOutputList rwlock:&threadParam.rwlockOutputList];
[cdsCheatManager setRwlockCoreExecute:&threadParam.rwlockCoreExecute];
macOS_driver *newDriver = new macOS_driver;
newDriver->SetCoreThreadMutexLock(&threadParam.mutexThreadExecute);
newDriver->SetCoreExecuteRWLock(self.rwlockCoreExecute);
newDriver->SetCoreExecuteRWLock(&threadParam.rwlockCoreExecute);
newDriver->SetExecutionControl(execControl);
driver = newDriver;
@ -603,7 +607,7 @@ volatile bool execute = true;
execControl->SetExecutionBehavior((ExecutionBehavior)coreState);
pthread_rwlock_rdlock(&threadParam.rwlockOutputList);
char frameStatusCStr[128] = {0};
char frameStatusCStr[64] = {0};
switch ((ExecutionBehavior)coreState)
{
@ -614,7 +618,7 @@ volatile bool execute = true;
[cdsOutput setIdle:YES];
}
sprintf(frameStatusCStr, "%llu", (unsigned long long)[self frameNumber]);
snprintf(frameStatusCStr, sizeof(frameStatusCStr), "%llu", (unsigned long long)[self frameNumber]);
[_fpsTimer invalidate];
_fpsTimer = nil;
@ -628,7 +632,7 @@ volatile bool execute = true;
[cdsOutput setIdle:NO];
}
sprintf(frameStatusCStr, "%llu", (unsigned long long)[self frameNumber]);
snprintf(frameStatusCStr, sizeof(frameStatusCStr), "%llu", (unsigned long long)[self frameNumber]);
[_fpsTimer invalidate];
_fpsTimer = nil;
@ -642,7 +646,7 @@ volatile bool execute = true;
[cdsOutput setIdle:NO];
}
sprintf(frameStatusCStr, "%s", "Executing...");
snprintf(frameStatusCStr, sizeof(frameStatusCStr), "%s", "Executing...");
if (_fpsTimer == nil)
{
@ -668,7 +672,7 @@ volatile bool execute = true;
}
}
sprintf(frameStatusCStr, "Jumping to frame %llu.", (unsigned long long)execControl->GetFrameJumpTarget());
snprintf(frameStatusCStr, sizeof(frameStatusCStr), "Jumping to frame %llu.", (unsigned long long)execControl->GetFrameJumpTarget());
[_fpsTimer invalidate];
_fpsTimer = nil;
@ -724,50 +728,42 @@ volatile bool execute = true;
- (void) setArm9ImageURL:(NSURL *)fileURL
{
const char *filePath = (fileURL != NULL) ? [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding] : NULL;
execControl->SetARM9ImagePath(filePath);
execControl->SetARM9ImagePath([CocoaDSUtil cPathFromFileURL:fileURL]);
}
- (NSURL *) arm9ImageURL
{
const char *filePath = execControl->GetARM9ImagePath();
return [NSURL fileURLWithPath:[NSString stringWithCString:filePath encoding:NSUTF8StringEncoding]];
return [CocoaDSUtil fileURLFromCPath:execControl->GetARM9ImagePath()];
}
- (void) setArm7ImageURL:(NSURL *)fileURL
{
const char *filePath = (fileURL != NULL) ? [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding] : NULL;
execControl->SetARM7ImagePath(filePath);
execControl->SetARM7ImagePath([CocoaDSUtil cPathFromFileURL:fileURL]);
}
- (NSURL *) arm7ImageURL
{
const char *filePath = execControl->GetARM7ImagePath();
return [NSURL fileURLWithPath:[NSString stringWithCString:filePath encoding:NSUTF8StringEncoding]];
return [CocoaDSUtil fileURLFromCPath:execControl->GetARM7ImagePath()];
}
- (void) setFirmwareImageURL:(NSURL *)fileURL
{
const char *filePath = (fileURL != NULL) ? [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding] : NULL;
execControl->SetFirmwareImagePath(filePath);
execControl->SetFirmwareImagePath([CocoaDSUtil cPathFromFileURL:fileURL]);
}
- (NSURL *) firmwareImageURL
{
const char *filePath = execControl->GetFirmwareImagePath();
return [NSURL fileURLWithPath:[NSString stringWithCString:filePath encoding:NSUTF8StringEncoding]];
return [CocoaDSUtil fileURLFromCPath:execControl->GetFirmwareImagePath()];
}
- (void) setSlot1R4URL:(NSURL *)fileURL
{
const char *filePath = (fileURL != NULL) ? [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding] : NULL;
execControl->SetSlot1R4Path(filePath);
execControl->SetSlot1R4Path([CocoaDSUtil cPathFromFileURL:fileURL]);
}
- (NSURL *) slot1R4URL
{
const char *filePath = execControl->GetSlot1R4Path();
return [NSURL fileURLWithPath:[NSString stringWithCString:filePath encoding:NSUTF8StringEncoding]];
return [CocoaDSUtil fileURLFromCPath:execControl->GetSlot1R4Path()];
}
- (void) updateFirmwareMACAddressString
@ -996,8 +992,9 @@ volatile bool execute = true;
return NO;
}
std::string sramPath = (sramURL != nil) ? [[sramURL path] cStringUsingEncoding:NSUTF8StringEncoding] : "";
const char *fileName = [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding];
const char *cSramPath = [CocoaDSUtil cPathFromFileURL:sramURL];
std::string sramPath = (cSramPath != NULL) ? std::string(cSramPath) : "";
const char *fileName = [CocoaDSUtil cPathFromFileURL:fileURL];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"Y M d H m s SSS"];
@ -1155,6 +1152,7 @@ static void* RunCoreThread(void *arg)
CoreThreadParam *param = (CoreThreadParam *)arg;
CocoaDSCore *cdsCore = (CocoaDSCore *)param->cdsCore;
CocoaDSGPU *cdsGPU = [cdsCore cdsGPU];
ClientCheatManager *cheatManager = [[cdsCore cdsCheatManager] internalManager];
ClientExecutionControl *execControl = [cdsCore execControl];
ClientInputHandler *inputHandler = execControl->GetClientInputHandler();
NSMutableArray *cdsOutputList = [cdsCore cdsOutputList];
@ -1235,6 +1233,8 @@ static void* RunCoreThread(void *arg)
// Execute the frame and increment the frame counter.
pthread_rwlock_wrlock(&param->rwlockCoreExecute);
cheatManager->ApplyToMaster();
cheatManager->ApplyPendingInternalCheatWrites();
NDS_exec<false>();
SPU_Emulate_user();
execControl->FetchOutputPostNDSExec();

View File

@ -142,7 +142,7 @@ static NSMutableDictionary *_gURLDictionary = nil;
return result;
}
const char *statePath = [[saveStateURL path] cStringUsingEncoding:NSUTF8StringEncoding];
const char *statePath = [CocoaDSUtil cPathFromFileURL:saveStateURL];
bool cResult = savestate_load(statePath);
if(cResult)
{
@ -161,7 +161,7 @@ static NSMutableDictionary *_gURLDictionary = nil;
return result;
}
const char *statePath = [[saveStateURL path] cStringUsingEncoding:NSUTF8StringEncoding];
const char *statePath = [CocoaDSUtil cPathFromFileURL:saveStateURL];
bool cResult = savestate_save(statePath);
if(cResult)
{
@ -180,7 +180,7 @@ static NSMutableDictionary *_gURLDictionary = nil;
return result;
}
const char *romPath = [[romURL path] cStringUsingEncoding:NSUTF8StringEncoding];
const char *romPath = [CocoaDSUtil cPathFromFileURL:romURL];
NSInteger resultCode = NDS_LoadROM(romPath, NULL, NULL);
if (resultCode > 0)
{
@ -199,7 +199,7 @@ static NSMutableDictionary *_gURLDictionary = nil;
return result;
}
const char *replayPath = [[replayURL path] cStringUsingEncoding:NSUTF8StringEncoding];
const char *replayPath = [CocoaDSUtil cPathFromFileURL:replayURL];
const char *resultCode = FCEUI_LoadMovie(replayPath, true, false, -1);
if (resultCode == NULL)
{
@ -212,7 +212,7 @@ static NSMutableDictionary *_gURLDictionary = nil;
+ (BOOL) importRomSave:(NSURL *)romSaveURL
{
BOOL result = NO;
const char *romSavePath = [[romSaveURL path] cStringUsingEncoding:NSUTF8StringEncoding];
const char *romSavePath = [CocoaDSUtil cPathFromFileURL:romSaveURL];
NSInteger resultCode = MMU_new.backupDevice.importData(romSavePath, 0);
if (resultCode == 0)
@ -243,7 +243,7 @@ static NSMutableDictionary *_gURLDictionary = nil;
#endif
case ROMSAVEFORMAT_NOGBA:
{
const char *destinationPath = [[[destinationURL path] stringByAppendingPathExtension:@FILE_EXT_ROM_SAVE_NOGBA] cStringUsingEncoding:NSUTF8StringEncoding];
const char *destinationPath = [CocoaDSUtil cPathFromFilePath:[[destinationURL path] stringByAppendingPathExtension:@FILE_EXT_ROM_SAVE_NOGBA]];
bool resultCode = MMU_new.backupDevice.exportData(destinationPath);
if (resultCode)
{
@ -254,7 +254,7 @@ static NSMutableDictionary *_gURLDictionary = nil;
case ROMSAVEFORMAT_RAW:
{
const char *destinationPath = [[[destinationURL path] stringByAppendingPathExtension:@FILE_EXT_ROM_SAVE_RAW] cStringUsingEncoding:NSUTF8StringEncoding];
const char *destinationPath = [CocoaDSUtil cPathFromFilePath:[[destinationURL path] stringByAppendingPathExtension:@FILE_EXT_ROM_SAVE_RAW]];
bool resultCode = MMU_new.backupDevice.exportData(destinationPath);
if (resultCode)
{
@ -358,55 +358,55 @@ static NSMutableDictionary *_gURLDictionary = nil;
NSURL *romURL = [CocoaDSFile directoryURLByKind:@"ROM" version:versionString port:portString];
if (romURL != nil)
{
strlcpy(path.pathToRoms, [[romURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToRoms, [CocoaDSUtil cPathFromFileURL:romURL], MAX_PATH);
}
NSURL *romSaveURL = [CocoaDSFile directoryURLByKind:@"ROM Save" version:versionString port:portString];
if (romSaveURL != nil)
{
strlcpy(path.pathToBattery, [[romSaveURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToBattery, [CocoaDSUtil cPathFromFileURL:romSaveURL], MAX_PATH);
}
NSURL *saveStateURL = [CocoaDSFile directoryURLByKind:@"Save State" version:versionString port:portString];
if (saveStateURL != nil)
{
strlcpy(path.pathToStates, [[saveStateURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToStates, [CocoaDSUtil cPathFromFileURL:saveStateURL], MAX_PATH);
}
NSURL *screenshotURL = [CocoaDSFile directoryURLByKind:@"Screenshot" version:versionString port:portString];
if (screenshotURL != nil)
{
strlcpy(path.pathToScreenshots, [[screenshotURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToScreenshots, [CocoaDSUtil cPathFromFileURL:screenshotURL], MAX_PATH);
}
NSURL *aviURL = [CocoaDSFile directoryURLByKind:@"Video" version:versionString port:portString];
if (aviURL != nil)
{
strlcpy(path.pathToAviFiles, [[aviURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToAviFiles, [CocoaDSUtil cPathFromFileURL:aviURL], MAX_PATH);
}
NSURL *cheatURL = [CocoaDSFile directoryURLByKind:@"Cheat" version:versionString port:portString];
if (cheatURL != nil)
{
strlcpy(path.pathToCheats, [[cheatURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToCheats, [CocoaDSUtil cPathFromFileURL:cheatURL], MAX_PATH);
}
NSURL *soundSamplesURL = [CocoaDSFile directoryURLByKind:@"Sound Sample" version:versionString port:portString];
if (soundSamplesURL != nil)
{
strlcpy(path.pathToSounds, [[soundSamplesURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToSounds, [CocoaDSUtil cPathFromFileURL:soundSamplesURL], MAX_PATH);
}
NSURL *firmwareURL = [CocoaDSFile directoryURLByKind:@"Firmware Configuration" version:versionString port:portString];
if (firmwareURL != nil)
{
strlcpy(path.pathToFirmware, [[firmwareURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToFirmware, [CocoaDSUtil cPathFromFileURL:firmwareURL], MAX_PATH);
}
NSURL *luaURL = [CocoaDSFile directoryURLByKind:@"Lua Script" version:versionString port:portString];
if (luaURL != nil)
{
strlcpy(path.pathToLua, [[luaURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToLua, [CocoaDSUtil cPathFromFileURL:luaURL], MAX_PATH);
}
}
@ -438,55 +438,55 @@ static NSMutableDictionary *_gURLDictionary = nil;
NSURL *romURL = (NSURL *)[URLDictionary valueForKey:@"ROM"];
if (romURL != nil)
{
strlcpy(path.pathToRoms, [[romURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToRoms, [CocoaDSUtil cPathFromFileURL:romURL], MAX_PATH);
}
NSURL *romSaveURL = (NSURL *)[URLDictionary valueForKey:@"ROM Save"];
if (romSaveURL != nil)
{
strlcpy(path.pathToBattery, [[romSaveURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToBattery, [CocoaDSUtil cPathFromFileURL:romSaveURL], MAX_PATH);
}
NSURL *saveStateURL = (NSURL *)[URLDictionary valueForKey:@"Save State"];
if (saveStateURL != nil)
{
strlcpy(path.pathToStates, [[saveStateURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToStates, [CocoaDSUtil cPathFromFileURL:saveStateURL], MAX_PATH);
}
NSURL *screenshotURL = (NSURL *)[URLDictionary valueForKey:@"Screenshot"];
if (screenshotURL != nil)
{
strlcpy(path.pathToScreenshots, [[screenshotURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToScreenshots, [CocoaDSUtil cPathFromFileURL:screenshotURL], MAX_PATH);
}
NSURL *aviURL = (NSURL *)[URLDictionary valueForKey:@"Video"];
if (aviURL != nil)
{
strlcpy(path.pathToAviFiles, [[aviURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToAviFiles, [CocoaDSUtil cPathFromFileURL:aviURL], MAX_PATH);
}
NSURL *cheatURL = (NSURL *)[URLDictionary valueForKey:@"Cheat"];
if (cheatURL != nil)
{
strlcpy(path.pathToCheats, [[cheatURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToCheats, [CocoaDSUtil cPathFromFileURL:cheatURL], MAX_PATH);
}
NSURL *soundSamplesURL = (NSURL *)[URLDictionary valueForKey:@"Sound Sample"];
if (soundSamplesURL != nil)
{
strlcpy(path.pathToSounds, [[soundSamplesURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToSounds, [CocoaDSUtil cPathFromFileURL:soundSamplesURL], MAX_PATH);
}
NSURL *firmwareURL = (NSURL *)[URLDictionary valueForKey:@"Firmware Configuration"];
if (firmwareURL != nil)
{
strlcpy(path.pathToFirmware, [[firmwareURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToFirmware, [CocoaDSUtil cPathFromFileURL:firmwareURL], MAX_PATH);
}
NSURL *luaURL = (NSURL *)[URLDictionary valueForKey:@"Lua Script"];
if (luaURL != nil)
{
strlcpy(path.pathToLua, [[luaURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
strlcpy(path.pathToLua, [CocoaDSUtil cPathFromFileURL:luaURL], MAX_PATH);
}
}
@ -738,6 +738,14 @@ static NSMutableDictionary *_gURLDictionary = nil;
portStr = @"Cocoa";
}
versionURL = [CocoaDSFile userAppSupportURL:nil version:@"0.9.14"];
versionPath = [versionURL path];
if (versionPath != nil && [[[filePath stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] isEqualToString:versionPath])
{
versionStr = @"0.9.14";
portStr = @"Cocoa";
}
fileVersion = [[versionStr stringByAppendingString:@" "] stringByAppendingString:portStr];
return fileVersion;

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2012-2022 DeSmuME team
Copyright (C) 2012-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -990,7 +990,7 @@ FirmwareConfigInterface::FirmwareConfigInterface()
_internalData = (FirmwareConfig *)malloc(sizeof(FirmwareConfig));
NDS_GetDefaultFirmwareConfig(*_internalData);
srand(time(NULL));
srand((uint32_t)time(NULL));
// Generate a random firmware MAC address and its associated string.
const uint32_t defaultFirmwareMACAddressValue = (uint32_t)_internalData->MACAddress[2] | ((uint32_t)_internalData->MACAddress[3] << 8) | ((uint32_t)_internalData->MACAddress[4] << 16) | ((uint32_t)_internalData->MACAddress[5] << 24);

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2012-2022 DeSmuME Team
Copyright (C) 2012-2023 DeSmuME Team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -30,7 +30,7 @@
#define NSSTRING_TITLE_EXPORT_ROM_SAVE_PANEL NSLocalizedString(@"Export ROM Save File", nil)
#define NSSTRING_TITLE_SELECT_ROM_PANEL NSLocalizedString(@"Select ROM", nil)
#define NSSTRING_TITLE_SELECT_ADVANSCENE_DB_PANEL NSLocalizedString(@"Select ADVANsCEne Database", nil)
#define NSSTRING_TITLE_SELECT_R4_CHEAT_DB_PANEL NSLocalizedString(@"Select R4 Cheat Database", nil)
#define NSSTRING_TITLE_OPEN_CHEAT_DB_PANEL NSLocalizedString(@"Open Cheat Database", nil)
#define NSSTRING_TITLE_SELECT_ARM7_IMAGE_PANEL NSLocalizedString(@"Select ARM7 BIOS Image", nil)
#define NSSTRING_TITLE_SELECT_ARM9_IMAGE_PANEL NSLocalizedString(@"Select ARM9 BIOS Image", nil)
#define NSSTRING_TITLE_SELECT_FIRMWARE_IMAGE_PANEL NSLocalizedString(@"Select Firmware Image", nil)
@ -46,8 +46,8 @@
#define NSSTRING_TITLE_ENABLE_SPEED_LIMIT NSLocalizedString(@"Enable Speed Limit", nil)
#define NSSTRING_TITLE_DISABLE_AUTO_FRAME_SKIP NSLocalizedString(@"Disable Auto Frame Skip", nil)
#define NSSTRING_TITLE_ENABLE_AUTO_FRAME_SKIP NSLocalizedString(@"Enable Auto Frame Skip", nil)
#define NSSTRING_TITLE_DISABLE_CHEATS NSLocalizedString(@"Disable Cheats", nil)
#define NSSTRING_TITLE_ENABLE_CHEATS NSLocalizedString(@"Enable Cheats", nil)
#define NSSTRING_TITLE_DISABLE_CHEATS NSLocalizedString(@"Disable Cheat System", nil)
#define NSSTRING_TITLE_ENABLE_CHEATS NSLocalizedString(@"Enable Cheat System", nil)
#define NSSTRING_TITLE_DISABLE_HUD NSLocalizedString(@"Disable HUD", nil)
#define NSSTRING_TITLE_ENABLE_HUD NSLocalizedString(@"Enable HUD", nil)
#define NSSTRING_TITLE_EXIT_FULL_SCREEN NSLocalizedString(@"Exit Full Screen", nil)
@ -303,41 +303,12 @@ enum
SPU_SYNC_METHOD_P = 2
};
enum
{
CHEAT_TYPE_INTERNAL = 0,
CHEAT_TYPE_ACTION_REPLAY = 1,
CHEAT_TYPE_CODE_BREAKER = 2
};
enum
{
CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE = 0,
CHEATSEARCH_SEARCHSTYLE_COMPARATIVE = 1
};
enum
{
CHEATSEARCH_COMPARETYPE_GREATER_THAN = 0,
CHEATSEARCH_COMPARETYPE_LESSER_THAN = 1,
CHEATSEARCH_COMPARETYPE_EQUALS_TO = 2,
CHEATSEARCH_COMPARETYPE_NOT_EQUALS_TO = 3
};
enum
{
CHEATSEARCH_UNSIGNED = 0,
CHEATSEARCH_SIGNED = 1
};
enum
{
CHEATEXPORT_ERROR_FILE_NOT_FOUND = 1,
CHEATEXPORT_ERROR_WRONG_FILE_FORMAT = 2,
CHEATEXPORT_ERROR_SERIAL_NOT_FOUND = 3,
CHEATEXPORT_ERROR_EXPORT_FAILED = 4
};
/*
PORT MESSAGES
*/

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2011-2022 DeSmuME team
Copyright (C) 2011-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -186,9 +186,9 @@ class ClientAVCaptureObject;
@property (assign) NSInteger outputFilter;
@property (assign) NSInteger pixelScaler;
- (void) commitPresenterProperties:(const ClientDisplayPresenterProperties &)viewProps;
- (void) commitPresenterProperties:(const ClientDisplayPresenterProperties &)viewProps needFlush:(BOOL)needFlush;
- (void) handleChangeViewProperties;
- (void) handleChangeViewPropertiesAndFlush:(BOOL)willFlush;
- (void) handleReceiveGPUFrame;
- (void) handleReloadReprocessRedraw;
- (void) handleReprocessRedraw;

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2011-2022 DeSmuME team
Copyright (C) 2011-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -295,7 +295,7 @@
if (methodID != SNDCORE_DUMMY)
{
result = SPU_ChangeSoundCore(methodID, (int)SPU_BUFFER_BYTES);
result = SPU_ChangeSoundCore((int)methodID, (int)SPU_BUFFER_BYTES);
}
if(result == -1)
@ -469,6 +469,10 @@
theString = @"Cosine";
break;
case SPUInterpolation_CatmullRom:
theString = @"Catmull-Rom";
break;
default:
break;
}
@ -717,13 +721,13 @@
[super dealloc];
}
- (void) commitPresenterProperties:(const ClientDisplayPresenterProperties &)viewProps
- (void) commitPresenterProperties:(const ClientDisplayPresenterProperties &)viewProps needFlush:(BOOL)needFlush
{
apple_unfairlock_lock(_unfairlockViewProperties);
_intermediateViewProps = viewProps;
apple_unfairlock_unlock(_unfairlockViewProperties);
[self handleChangeViewProperties];
[self handleChangeViewPropertiesAndFlush:needFlush];
}
- (BOOL) canFilterOnGPU
@ -1211,7 +1215,7 @@
switch (messageID)
{
case MESSAGE_CHANGE_VIEW_PROPERTIES:
[self handleChangeViewProperties];
[self handleChangeViewPropertiesAndFlush:YES];
break;
case MESSAGE_RELOAD_REPROCESS_REDRAW:
@ -1243,14 +1247,18 @@
_cdv->SetViewNeedsFlush();
}
- (void) handleChangeViewProperties
- (void) handleChangeViewPropertiesAndFlush:(BOOL)willFlush
{
apple_unfairlock_lock(_unfairlockViewProperties);
_cdv->Get3DPresenter()->CommitPresenterProperties(_intermediateViewProps);
apple_unfairlock_unlock(_unfairlockViewProperties);
_cdv->Get3DPresenter()->SetupPresenterProperties();
_cdv->SetViewNeedsFlush();
if (willFlush)
{
_cdv->SetViewNeedsFlush();
}
}
- (void) handleReceiveGPUFrame

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2011-2022 DeSmuME team
Copyright (C) 2011-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -674,7 +674,7 @@ void RomIconToRGBA8888(uint32_t *bitmapData)
// The first entry always represents the alpha, so just set it to 0.
const uint16_t *clut4 = (uint16_t *)ndsRomBanner.palette;
CACHE_ALIGN uint32_t clut32[16];
ColorspaceConvertBuffer555To8888Opaque<false, true, BESwapNone>(clut4, clut32, 16);
ColorspaceConvertBuffer555xTo8888Opaque<false, true, BESwapNone>(clut4, clut32, 16);
clut32[0] = 0x00000000;
// Load the image from the icon pixel data.

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2014-2018 DeSmuME Team
Copyright (C) 2014-2022 DeSmuME Team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -135,18 +135,18 @@
return currentDevice;
}
- (void) setMpcfFileSearchURL:(NSURL *)theURL
- (void) setMpcfFileSearchURL:(NSURL *)fileURL
{
if (theURL != nil)
if (fileURL != nil)
{
BOOL isDirectory = NO;
NSString *thePath = [theURL path];
NSString *filePath = [fileURL path];
NSFileManager *fileManager = [[NSFileManager alloc] init];
[fileManager fileExistsAtPath:thePath isDirectory:&isDirectory];
[fileManager fileExistsAtPath:[fileURL path] isDirectory:&isDirectory];
CFlash_Mode = (isDirectory) ? ADDON_CFLASH_MODE_Path : ADDON_CFLASH_MODE_File;
CFlash_Path = [thePath cStringUsingEncoding:NSUTF8StringEncoding];
CFlash_Path = [CocoaDSUtil cPathFromFileURL:fileURL];
[fileManager release];
}
@ -159,14 +159,14 @@
- (NSURL *) mpcfFileSearchURL
{
return [NSURL fileURLWithPath:[NSString stringWithCString:CFlash_Path.c_str() encoding:NSUTF8StringEncoding]];
return [CocoaDSUtil fileURLFromCPath:CFlash_Path.c_str()];
}
- (void) setGbaCartridgeURL:(NSURL *)fileURL
{
if (fileURL != nil)
{
GBACartridge_RomPath = [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding];
GBACartridge_RomPath = [CocoaDSUtil cPathFromFileURL:fileURL];
}
else
{
@ -176,14 +176,14 @@
- (NSURL *) gbaCartridgeURL
{
return [NSURL fileURLWithPath:[NSString stringWithCString:GBACartridge_RomPath.c_str() encoding:NSUTF8StringEncoding]];
return [CocoaDSUtil fileURLFromCPath:GBACartridge_RomPath.c_str()];
}
- (void) setGbaSRamURL:(NSURL *)fileURL
{
if (fileURL != nil)
{
GBACartridge_SRAMPath = [[fileURL path] cStringUsingEncoding:NSUTF8StringEncoding];
GBACartridge_SRAMPath = [CocoaDSUtil cPathFromFileURL:fileURL];
}
else
{
@ -193,7 +193,7 @@
- (NSURL *) gbaSRamURL;
{
return [NSURL fileURLWithPath:[NSString stringWithCString:GBACartridge_SRAMPath.c_str() encoding:NSUTF8StringEncoding]];
return [CocoaDSUtil fileURLFromCPath:GBACartridge_SRAMPath.c_str()];
}
- (BOOL) doesGbaCartridgeSaveExist

View File

@ -34,6 +34,11 @@
+ (NSColor *) NSColorFromRGBA8888:(uint32_t)theColor;
+ (uint32_t) RGBA8888FromNSColor:(NSColor *)theColor;
+ (NSString *) filePathFromCPath:(const char *)cPath;
+ (NSURL *) fileURLFromCPath:(const char *)cPath;
+ (const char *) cPathFromFilePath:(NSString *)filePath;
+ (const char *) cPathFromFileURL:(NSURL *)fileURL;
+ (NSInteger) appVersionNumeric;
+ (NSString *) appInternalVersionString;
+ (NSString *) appInternalNameAndVersionString;

View File

@ -136,6 +136,31 @@
#endif
}
+ (NSString *) filePathFromCPath:(const char *)cPath
{
if (cPath == NULL)
{
return nil;
}
return [[NSFileManager defaultManager] stringWithFileSystemRepresentation:cPath length:strlen(cPath)];
}
+ (NSURL *) fileURLFromCPath:(const char *)cPath
{
return [NSURL fileURLWithPath:[CocoaDSUtil filePathFromCPath:cPath]];
}
+ (const char *) cPathFromFilePath:(NSString *)filePath
{
return (filePath != nil) ? [filePath fileSystemRepresentation] : NULL;
}
+ (const char *) cPathFromFileURL:(NSURL *)fileURL
{
return (fileURL != nil) ? [CocoaDSUtil cPathFromFilePath:[fileURL path]] : NULL;
}
+ (NSInteger) appVersionNumeric
{
return (NSInteger)EMU_DESMUME_VERSION_NUMERIC();

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2013 DeSmuME team
Copyright (C) 2013-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -139,7 +139,7 @@
}
uint32_t *bitmapData = (uint32_t *)[imageRep bitmapData];
ColorspaceConvertBuffer888XTo8888Opaque<false, true>((const uint32_t *)[self runFilter], bitmapData, w * h);
ColorspaceConvertBuffer888xTo8888Opaque<false, true>((const uint32_t *)[self runFilter], bitmapData, w * h);
#ifdef MSB_FIRST
for (size_t i = 0; i < w * h; i++)

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2012-2022 DeSmuME team
Copyright (C) 2012-2024 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -21,7 +21,7 @@
#define HOST_DARWIN
#define DESMUME_COCOA
#define HAVE_OPENGL
#define ENABLE_OPENGL_STANDARD
#define HAVE_LIBZ
#define FT2_BUILD_LIBRARY

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>v0.9.13 (OpenEmu Plug-in)</string>
<string>v0.9.14 (OpenEmu Plug-in)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
@ -25,7 +25,7 @@
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>0.9.13</string>
<string>0.9.14</string>
<key>CSResourcesFileMapped</key>
<string>yes</string>
<key>NSHumanReadableCopyright</key>

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2012-2022 DeSmuME team
Copyright (C) 2012-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -195,7 +195,6 @@ volatile bool execute = true;
// Set up the cheat system
cdsCheats = [[CocoaDSCheatManager alloc] init];
[cdsCheats setRwlockCoreExecute:&rwlockCoreExecute];
addedCheatsDict = [[NSMutableDictionary alloc] initWithCapacity:128];
// Set up the DS firmware using the internal firmware
@ -371,7 +370,7 @@ volatile bool execute = true;
if (_cdp == NULL)
{
NSString *gameCoreFontPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"SourceSansPro-Bold" ofType:@"otf"];
const char *hudFontPath = [[NSFileManager defaultManager] fileSystemRepresentationWithPath:gameCoreFontPath];
const char *hudFontPath = [CocoaDSUtil cPathFromFilePath:gameCoreFontPath];
_cdp = new OE_OGLDisplayPresenter(fetchObj);
_cdp->Init();
@ -509,7 +508,7 @@ void UpdateDisplayPropertiesFromStates(uint64_t displayModeStates, ClientDisplay
// draw at 1x scaling, which starts looking uglier as the view size is increased.
if (!_canRespondToViewResize)
{
int legacyVersionScale = 1;
NSUInteger legacyVersionScale = 1;
_OEViewSize.width = (int)(transformNormalWidth + 0.0005);
_OEViewSize.height = (int)(transformNormalHeight + 0.0005);
@ -535,8 +534,8 @@ void UpdateDisplayPropertiesFromStates(uint64_t displayModeStates, ClientDisplay
}
// Multiply the normal size by our fixed scaling value.
_OEViewSize.width *= legacyVersionScale;
_OEViewSize.height *= legacyVersionScale;
_OEViewSize.width *= (int)legacyVersionScale;
_OEViewSize.height *= (int)legacyVersionScale;
}
apple_unfairlock_lock(unfairlockDisplayMode);
@ -719,8 +718,6 @@ void UpdateDisplayPropertiesFromStates(uint64_t displayModeStates, ClientDisplay
isRomLoaded = [CocoaDSFile loadRom:[NSURL fileURLWithPath:path]];
[CocoaDSCheatManager setMasterCheatList:cdsCheats];
// Set the default options.
// Have to do it now because displayModeInfo is only available now -- not at this object's init.
NSDictionary<NSString *, id> *userDefaultsDisplayMode = nil;
@ -1194,34 +1191,32 @@ void UpdateDisplayPropertiesFromStates(uint64_t displayModeStates, ClientDisplay
// state on an existing cheat, so be sure to account for both cases.
// First check if the cheat exists.
CocoaDSCheatItem *cheatItem = (CocoaDSCheatItem *)[addedCheatsDict objectForKey:code];
CocoaDSCheatItem *cocoaCheatItem = (CocoaDSCheatItem *)[addedCheatsDict objectForKey:code];
if (cheatItem == nil)
if (cocoaCheatItem == nil)
{
// If the cheat doesn't already exist, then create a new one and add it.
cheatItem = [[[CocoaDSCheatItem alloc] init] autorelease];
[cheatItem setCheatType:CHEAT_TYPE_ACTION_REPLAY]; // Default to Action Replay for now
[cheatItem setFreezeType:0];
[cheatItem setDescription:@""]; // OpenEmu takes care of this
[cheatItem setCode:code];
[cheatItem setMemAddress:0x00000000]; // UNUSED
[cheatItem setBytes:1]; // UNUSED
[cheatItem setValue:0]; // UNUSED
ClientCheatItem *newCheatItem = new ClientCheatItem;
newCheatItem->SetType(CheatType_ActionReplay); // Default to Action Replay for now
newCheatItem->SetFreezeType(CheatFreezeType_Normal);
newCheatItem->SetName(NULL); // OpenEmu takes care of this
newCheatItem->SetComments(NULL); // OpenEmu does not support cheat item comments
newCheatItem->SetRawCodeString([code cStringUsingEncoding:NSUTF8StringEncoding], true);
newCheatItem->SetEnabled((enabled) ? true : false);
[cheatItem setEnabled:enabled];
[[self cdsCheats] add:cheatItem];
cocoaCheatItem = [[self cdsCheats] addExistingItem:newCheatItem];
// OpenEmu doesn't currently save cheats per game, so assume that the
// cheat list is short and that code strings are unique. This allows
// us to get away with simply saving the cheat code string and hashing
// for it later.
[addedCheatsDict setObject:cheatItem forKey:code];
[addedCheatsDict setObject:cocoaCheatItem forKey:code];
}
else
{
// If the cheat does exist, then just set its enable state.
[cheatItem setEnabled:enabled];
[[self cdsCheats] update:cheatItem];
[cocoaCheatItem setEnabled:enabled];
[[self cdsCheats] update:cocoaCheatItem];
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,105 @@
/*
Copyright (C) 2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@class CocoaDSCheatDatabase;
@class CheatWindowDelegate;
@class CocoaDSCheatDBGame;
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
@interface CheatDatabaseWindowController : NSWindowController <NSWindowDelegate, NSTableViewDelegate>
#else
@interface CheatDatabaseWindowController : NSWindowController
#endif
{
NSObject *dummyObject;
NSWindow *errorSheet;
NSString *defaultWindowTitle;
NSArrayController *gameListController;
NSTreeController *entryListController;
NSSplitView *splitView;
NSTableView *gameTable;
NSOutlineView *entryOutline;
NSFont *codeViewerFont;
CheatWindowDelegate *cheatManagerDelegate;
CocoaDSCheatDatabase *database;
NSString *filePath;
BOOL isFileLoading;
BOOL isCurrentGameFound;
BOOL isSelectedGameTheCurrentGame;
NSInteger currentGameTableRowIndex;
NSString *currentGameIndexString;
NSString *currentGameSerial;
NSUInteger currentGameCRC;
BOOL isCompatibilityCheckIgnored;
BOOL isOptionWarningSilenced;
NSString *errorMajorString;
NSString *errorMinorString;
NSDictionary *initProperties;
}
@property (readonly) IBOutlet NSObject *dummyObject;
@property (readonly) IBOutlet NSWindow *errorSheet;
@property (readonly) IBOutlet NSArrayController *gameListController;
@property (readonly) IBOutlet NSTreeController *entryListController;
@property (readonly) IBOutlet NSSplitView *splitView;
@property (readonly) IBOutlet NSTableView *gameTable;
@property (readonly) IBOutlet NSOutlineView *entryOutline;
@property (retain) CheatWindowDelegate *cheatManagerDelegate;
@property (assign) NSFont *codeViewerFont;
@property (retain, nonatomic) CocoaDSCheatDatabase *database;
@property (readonly) NSString *filePath;
@property (readonly) NSString *databaseFormatString;
@property (readonly) NSInteger gameCount;
@property (readonly) NSString *isEncryptedString;
@property (assign) BOOL isFileLoading;
@property (assign) BOOL isCurrentGameFound;
@property (assign) BOOL isSelectedGameTheCurrentGame;
@property (retain, nonatomic) NSString *currentGameSerial;
@property (assign, nonatomic) NSUInteger currentGameCRC;
@property (readonly, nonatomic) NSString *currentGameCRCString;
@property (assign, nonatomic) BOOL isCompatibilityCheckIgnored;
@property (assign) BOOL isOptionWarningSilenced;
@property (assign) NSString *errorMajorString;
@property (assign) NSString *errorMinorString;
- (id) initWithWindowNibName:(NSString *)windowNibName delegate:(CheatWindowDelegate *)theDelegate;
- (void) loadFileStart:(NSURL *)theURL;
- (void) loadFileOnThread:(id)object;
- (void) loadFileDidFinish:(NSNotification *)aNotification;
- (void) updateWindow;
+ (void) setCurrentGameForAllWindowsSerial:(NSString *)serialString crc:(NSUInteger)crc;
- (void) validateGameTableFonts;
- (BOOL) validateWillAddColumn;
- (void) showErrorSheet:(NSInteger)errorCode;
- (void) didEndErrorSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
- (IBAction) openFile:(id)sender;
- (IBAction) selectAll:(id)sender;
- (IBAction) selectNone:(id)sender;
- (IBAction) addSelected:(id)sender;
- (IBAction) selectCurrentGame:(id)sender;
- (IBAction) closeErrorSheet:(id)sender;
@end

View File

@ -0,0 +1,818 @@
/*
Copyright (C) 2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#import "CheatDatabaseWindowController.h"
#import "cheatWindowDelegate.h"
#import "../cocoa_globals.h"
#import "../cocoa_cheat.h"
#import "../cocoa_util.h"
NSMutableArray *cheatDatabaseWindowList = nil;
@implementation CheatDatabaseWindowController
@synthesize dummyObject;
@synthesize errorSheet;
@synthesize gameListController;
@synthesize entryListController;
@synthesize splitView;
@synthesize gameTable;
@synthesize entryOutline;
@synthesize cheatManagerDelegate;
@synthesize codeViewerFont;
@dynamic database;
@dynamic filePath;
@dynamic databaseFormatString;
@dynamic gameCount;
@dynamic isEncryptedString;
@synthesize isFileLoading;
@synthesize isCurrentGameFound;
@synthesize isSelectedGameTheCurrentGame;
@dynamic currentGameSerial;
@synthesize currentGameCRC;
@dynamic currentGameCRCString;
@dynamic isCompatibilityCheckIgnored;
@synthesize isOptionWarningSilenced;
@synthesize errorMajorString;
@synthesize errorMinorString;
- (id) initWithWindowNibName:(NSString *)windowNibName delegate:(CheatWindowDelegate *)theDelegate
{
self = [super initWithWindowNibName:windowNibName];
if (self == nil)
{
return self;
}
cheatManagerDelegate = [theDelegate retain];
codeViewerFont = [NSFont fontWithName:@"Monaco" size:13.0];
dummyObject = nil;
defaultWindowTitle = [[NSString alloc] initWithString:@"Cheat Database Viewer"];
database = nil;
isFileLoading = NO;
isCurrentGameFound = NO;
isSelectedGameTheCurrentGame = NO;
currentGameIndexString = [[NSString alloc] initWithString:@"NSNotFound"];
currentGameTableRowIndex = NSNotFound;
currentGameSerial = nil;
currentGameCRC = 0;
isCompatibilityCheckIgnored = NO;
isOptionWarningSilenced = NO;
errorMajorString = @"No error has occurred!";
errorMinorString = @"This is just a placeholder message for initialization purposes.";
if (cheatDatabaseWindowList == nil)
{
cheatDatabaseWindowList = [[NSMutableArray alloc] initWithObjects:self, nil];
}
else
{
[cheatDatabaseWindowList addObject:self];
}
return self;
}
- (void)dealloc
{
[self setCheatManagerDelegate:nil];
[self setDatabase:nil];
[currentGameIndexString release];
[defaultWindowTitle release];
[super dealloc];
}
- (void) loadFileStart:(NSURL *)theURL
{
if (theURL == nil)
{
return;
}
// First check if another cheat database window has already opened the file at this URL.
CheatDatabaseWindowController *foundWindowController = nil;
for (CheatDatabaseWindowController *windowController in cheatDatabaseWindowList)
{
NSURL *databaseURL = [[windowController database] lastFileURL];
NSString *foundDatabaseFilePath = [databaseURL path];
if ( (foundDatabaseFilePath != nil) && ([foundDatabaseFilePath isEqualToString:[theURL path]]) )
{
foundWindowController = windowController;
break;
}
}
if (foundWindowController != nil)
{
// If the file is already open, then simply assign that database file to this window.
[self setDatabase:[foundWindowController database]];
[self updateWindow];
}
else
{
// If the file is not open, then we need to open it now. Let's do this on a separate
// thread so that we don't lock up the main thread.
[self setIsFileLoading:YES];
[self setDatabase:nil];
NSString *threadNamePrefix = @"org.desmume.DeSmuME.loadDatabaseDidFinish_";
NSString *fullThreadName = [threadNamePrefix stringByAppendingString:[theURL absoluteString]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loadFileDidFinish:)
name:fullThreadName
object:nil];
[theURL retain];
[NSThread detachNewThreadSelector:@selector(loadFileOnThread:) toTarget:self withObject:theURL];
}
}
- (void) loadFileOnThread:(id)object
{
NSAutoreleasePool *threadPool = [[NSAutoreleasePool alloc] init];
NSURL *workingURL = (NSURL *)object;
NSString *threadNamePrefix = @"org.desmume.DeSmuME.loadDatabaseDidFinish_";
NSString *fullThreadName = [threadNamePrefix stringByAppendingString:[workingURL absoluteString]];
CheatSystemError error = CheatSystemError_NoError;
CocoaDSCheatDatabase *newDatabase = [[CocoaDSCheatDatabase alloc] initWithFileURL:workingURL error:&error];
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:
workingURL, @"URL",
[NSNumber numberWithInteger:(NSInteger)error], @"ErrorCode",
nil];
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:fullThreadName object:newDatabase userInfo:userInfo];
[threadPool release];
}
- (void) loadFileDidFinish:(NSNotification *)aNotification
{
CocoaDSCheatDatabase *newDatabase = [aNotification object];
NSDictionary *userInfo = [aNotification userInfo];
NSURL *workingURL = (NSURL *)[userInfo valueForKey:@"URL"];
CheatSystemError errorCode = (CheatSystemError)[(NSNumber *)[userInfo valueForKey:@"ErrorCode"] integerValue];
NSString *threadNamePrefix = @"org.desmume.DeSmuME.loadDatabaseDidFinish_";
NSString *fullThreadName = [threadNamePrefix stringByAppendingString:[workingURL absoluteString]];
[[NSNotificationCenter defaultCenter] removeObserver:self name:fullThreadName object:nil];
[self setIsFileLoading:NO];
[self setDatabase:[newDatabase autorelease]];
[self updateWindow];
if (errorCode != CheatSystemError_NoError)
{
[self showErrorSheet:errorCode];
}
if (database == nil)
{
return;
}
// Begin the generation of the cheat database recents menu.
NSString *legacyFilePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
BOOL useLegacyFilePath = ( (legacyFilePath != nil) && ([legacyFilePath length] > 0) );
NSArray *dbRecentsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
NSMutableArray *newRecentsList = [NSMutableArray arrayWithCapacity:[dbRecentsList count] + 1];
if (useLegacyFilePath)
{
// We need to check if the legacy file path also exists in the recents list.
// If it does, then the recents list version takes priority.
for (NSDictionary *dbRecentItem in dbRecentsList)
{
NSString *dbRecentItemFilePath = (NSString *)[dbRecentItem valueForKey:@"FilePath"];
if ([dbRecentItemFilePath isEqualToString:legacyFilePath])
{
useLegacyFilePath = NO;
break;
}
}
}
if (useLegacyFilePath)
{
// The legacy file path must always be the first entry of the recents list.
NSDictionary *legacyRecentItem = [NSDictionary dictionaryWithObjectsAndKeys:legacyFilePath, @"FilePath",
[legacyFilePath lastPathComponent], @"FileName",
nil];
[newRecentsList addObject:legacyRecentItem];
}
// Next, we need to add back all of the recent items in the same order in which
// they appear in user defaults, with the exception of our newest item.
NSString *newFilePath = [[database lastFileURL] path];
for (NSDictionary *dbRecentItem in dbRecentsList)
{
NSString *dbRecentItemFilePath = (NSString *)[dbRecentItem valueForKey:@"FilePath"];
if ( ![newFilePath isEqualToString:dbRecentItemFilePath] )
{
[newRecentsList addObject:dbRecentItem];
}
}
// Create our new recent item...
NSDictionary *newRecentItem = [NSDictionary dictionaryWithObjectsAndKeys:newFilePath, @"FilePath",
[newFilePath lastPathComponent], @"FileName",
[NSDate date], @"AddedDate",
[[self window] stringWithSavedFrame], @"WindowFrame",
[NSNumber numberWithFloat:[[[splitView subviews] objectAtIndex:0] frame].size.height], @"WindowSplitViewDividerPosition",
[NSNumber numberWithBool:[self isCompatibilityCheckIgnored]], @"OptionIgnoreCompatibilityCheck",
nil];
// ...and then add the newest recent item, ensuring that it is always last in the list.
[newRecentsList addObject:newRecentItem];
// We're done generating the new recent items list, so write it back to user defaults, and then
// send a notification that UI elements needs to be updated.
[[NSUserDefaults standardUserDefaults] setObject:newRecentsList forKey:@"CheatDatabase_RecentFilePath"];
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"org.desmume.DeSmuME.updateCheatDatabaseRecentsMenu" object:[newRecentsList retain] userInfo:nil];
}
- (void) updateWindow
{
if ([self database] == nil)
{
[[self window] setTitle:defaultWindowTitle];
}
else
{
[[self window] setTitle:[database description]];
}
[[self window] setRepresentedURL:[database lastFileURL]];
[gameListController setContent:[database gameList]];
NSIndexSet *selectedRows = [gameTable selectedRowIndexes];
[gameTable deselectAll:nil];
[gameTable selectRowIndexes:selectedRows byExtendingSelection:NO];
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
[self setCurrentGameSerial:[cheatManager currentGameCode]];
[self setCurrentGameCRC:[cheatManager currentGameCRC]];
[self validateGameTableFonts];
[self selectCurrentGame:nil];
}
+ (void) setCurrentGameForAllWindowsSerial:(NSString *)serialString crc:(NSUInteger)crc
{
if (cheatDatabaseWindowList == nil)
{
return;
}
for (CheatDatabaseWindowController *windowController in cheatDatabaseWindowList)
{
[windowController setCurrentGameSerial:serialString];
[windowController setCurrentGameCRC:crc];
[windowController validateGameTableFonts];
[[windowController gameTable] setNeedsDisplay];
[windowController validateWillAddColumn];
}
}
- (void) validateGameTableFonts
{
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
if ( (delegate == nil) || (cheatManager == nil) )
{
currentGameTableRowIndex = NSNotFound;
[currentGameIndexString release];
currentGameIndexString = [[NSString alloc] initWithString:@"NSNotFound"];
[self setIsCurrentGameFound:NO];
return;
}
for (CocoaDSCheatDBGame *game in [gameListController content])
{
if ( ([game crc] == [self currentGameCRC]) && ([[game serial] isEqualToString:[self currentGameSerial]]) )
{
[currentGameIndexString release];
currentGameIndexString = [[NSString alloc] initWithFormat:@"%llu", (unsigned long long)[game index]];
[self setIsCurrentGameFound:YES];
break;
}
}
}
- (BOOL) validateWillAddColumn
{
BOOL showWillAddColumn = NO;
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
NSArray *selectedObjects = [gameListController selectedObjects];
if ( (selectedObjects == nil) || ([selectedObjects count] == 0) )
{
return showWillAddColumn;
}
CocoaDSCheatDBGame *selectedGame = [selectedObjects objectAtIndex:0];
if ( (delegate != nil) && (cheatManager != nil) && ([selectedGame serial] != nil) )
{
showWillAddColumn = ( [self isCompatibilityCheckIgnored] || (([[selectedGame serial] isEqualToString:currentGameSerial]) && ([selectedGame crc] == currentGameCRC)) );
}
NSTableColumn *willAddColumn = [entryOutline tableColumnWithIdentifier:@"willAdd"];
[willAddColumn setHidden:!showWillAddColumn];
[self setIsSelectedGameTheCurrentGame:showWillAddColumn];
return showWillAddColumn;
}
- (void) showErrorSheet:(NSInteger)errorCode
{
switch (errorCode)
{
case CheatSystemError_NoError:
[self setErrorMajorString:@"No error has occurred."];
[self setErrorMinorString:@"This message is a placeholder. You are seeing this error as a test for this app's error handling.\n\nError Code: %i"];
break;
case CheatSystemError_FileOpenFailed:
[self setErrorMajorString:@"Failed to open file."];
[self setErrorMinorString:[NSString stringWithFormat:@"The system could not open the cheat database file. This problem is usually because another app is using it, or because the file permissions disallow read access.\n\nError Code: %i", (int)errorCode]];
break;
case CheatSystemError_FileFormatInvalid:
[self setErrorMajorString:@"Invalid file format."];
[self setErrorMinorString:[NSString stringWithFormat:@"DeSmuME could not recognize the file format of the cheat database file. Currently, DeSmuME only recognizes the R4 file format. It is also possible that the file data is corrupted.\n\nError Code: %i", (int)errorCode]];
break;
case CheatSystemError_GameNotFound:
{
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
[self setErrorMajorString:@"Current game not found in database."];
[self setErrorMinorString:[NSString stringWithFormat:@"The current game (Serial='%@', CRC=%llu) could not be found in the cheat database.\n\nError Code: %i", [cheatManager currentGameCode], (unsigned long long)[cheatManager currentGameCRC], (int)errorCode]];
break;
}
case CheatSystemError_LoadEntryError:
[self setErrorMajorString:@"Could not read cheat entries."];
[self setErrorMinorString:[NSString stringWithFormat:@"The entry data for the selected game could not be read. This is usually due to file data corruption.\n\nError Code: %i", (int)errorCode]];
break;
case CheatSystemError_FileDoesNotExist:
[self setErrorMajorString:@"The file does not exist."];
[self setErrorMinorString:[NSString stringWithFormat:@"If this file was selected from the Recents Menu, then it has been removed.\n\nError Code: %i", (int)errorCode]];
break;
default:
[self setErrorMajorString:@"An unknown error has occurred."];
[self setErrorMinorString:[NSString stringWithFormat:@"Error Code: %i", (int)errorCode]];
break;
}
#if defined(MAC_OS_X_VERSION_10_9) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9)
if ([[self window] respondsToSelector:@selector(beginSheet:completionHandler:)])
{
[[self window] beginSheet:errorSheet
completionHandler:^(NSModalResponse response) {
[self didEndErrorSheet:nil returnCode:response contextInfo:nil];
} ];
}
else
#endif
{
SILENCE_DEPRECATION_MACOS_10_10( [NSApp beginSheet:errorSheet
modalForWindow:[self window]
modalDelegate:self
didEndSelector:@selector(didEndErrorSheet:returnCode:contextInfo:)
contextInfo:nil] );
}
}
- (void) didEndErrorSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
}
#pragma mark -
#pragma mark Dynamic Properties
- (void) setDatabase:(CocoaDSCheatDatabase *)theDatabase
{
[self willChangeValueForKey:@"filePath"];
[self willChangeValueForKey:@"databaseFormatString"];
[self willChangeValueForKey:@"gameCount"];
[self willChangeValueForKey:@"isEncryptedString"];
[theDatabase retain];
[database release];
database = theDatabase;
[self didChangeValueForKey:@"filePath"];
[self didChangeValueForKey:@"databaseFormatString"];
[self didChangeValueForKey:@"gameCount"];
[self didChangeValueForKey:@"isEncryptedString"];
}
- (CocoaDSCheatDatabase *) database
{
return database;
}
- (NSString *) filePath
{
if ( (database != nil) && ([database lastFileURL] != nil) )
{
return [[database lastFileURL] path];
}
else if ([self isFileLoading])
{
return @"Loading database file...";
}
return @"No database file loaded.";
}
- (NSString *) databaseFormatString
{
if (database != nil)
{
return [database formatString];
}
return @"---";
}
- (NSInteger) gameCount
{
if (database != nil)
{
return [[database gameList] count];
}
return 0;
}
- (NSString *) isEncryptedString
{
if (database != nil)
{
return [database isEncrypted] ? @"Yes" : @"No";
}
return @"---";
}
- (void) setCurrentGameSerial:(NSString *)newString
{
NSString *oldString = currentGameSerial;
currentGameSerial = [newString retain];
[oldString release];
}
- (NSString *) currentGameSerial
{
if ( (currentGameSerial != nil) && ([currentGameSerial length] > 0) )
{
return currentGameSerial;
}
return @"---";
}
- (void) setCurrentGameCRC:(NSUInteger)crc
{
[self willChangeValueForKey:@"currentGameCRCString"];
currentGameCRC = crc;
[self didChangeValueForKey:@"currentGameCRCString"];
}
- (NSUInteger) currentGameCRC
{
return currentGameCRC;
}
- (NSString *) currentGameCRCString
{
if (currentGameCRC != 0)
{
return [NSString stringWithFormat:@"%08lX", (unsigned long)currentGameCRC];
}
return @"---";
}
- (BOOL) isCompatibilityCheckIgnored
{
return isCompatibilityCheckIgnored;
}
- (void) setIsCompatibilityCheckIgnored:(BOOL)theState
{
isCompatibilityCheckIgnored = theState;
if (![self isOptionWarningSilenced] && theState)
{
NSAlert *criticalErrorAlert = [[[NSAlert alloc] init] autorelease];
[criticalErrorAlert setAlertStyle:ALERTSTYLE_CRITICAL];
[criticalErrorAlert setMessageText:@"Using an incompatible cheat may ruin your game."];
[criticalErrorAlert setInformativeText:@"Cheats are normally restricted to the current game \
for compatibility reasons. By choosing to ignore the compatibility check, you can add any cheat to \
any game that you want, but you must also assume the risk of an incompatible cheat ruining your game \
session or corrupting your game's save data."];
[criticalErrorAlert runModal];
}
[self validateWillAddColumn];
}
#pragma mark -
#pragma mark IBActions
- (IBAction) openFile:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSSTRING_TITLE_OPEN_CHEAT_DB_PANEL];
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_R4_CHEAT_DB, nil];
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
// is deprecated in Mac OS X v10.6.
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
if (IsOSXVersionSupported(10, 6, 0))
{
[panel setAllowedFileTypes:fileTypes];
[panel beginSheetModalForWindow:[self window]
completionHandler:^(NSInteger result) {
[self chooseCheatDatabaseDidEnd:panel returnCode:(int)result contextInfo:nil];
} ];
}
else
#endif
{
SILENCE_DEPRECATION_MACOS_10_6( [panel beginSheetForDirectory:nil
file:nil
types:fileTypes
modalForWindow:[self window]
modalDelegate:self
didEndSelector:@selector(chooseCheatDatabaseDidEnd:returnCode:contextInfo:)
contextInfo:nil] );
}
}
- (void) chooseCheatDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
if (returnCode == GUI_RESPONSE_CANCEL)
{
return;
}
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
[self loadFileStart:selectedFileURL];
}
- (IBAction) selectAll:(id)sender
{
NSMutableArray *entryTree = [entryListController content];
if (entryTree == nil)
{
return;
}
for (CocoaDSCheatDBEntry *entry in entryTree)
{
[entry setWillAdd:YES];
}
[entryOutline setNeedsDisplay];
}
- (IBAction) selectNone:(id)sender
{
NSMutableArray *entryTree = [entryListController content];
if (entryTree == nil)
{
return;
}
for (CocoaDSCheatDBEntry *entry in entryTree)
{
[entry setWillAdd:NO];
}
[entryOutline setNeedsDisplay];
}
- (IBAction) addSelected:(id)sender
{
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
if (delegate == nil)
{
return;
}
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
if (cheatManager == nil)
{
return;
}
NSMutableArray *entryTree = [entryListController content];
if (entryTree == nil)
{
return;
}
NSInteger selectedIndex = [gameTable selectedRow];
CocoaDSCheatDBGame *selectedGame = (CocoaDSCheatDBGame *)[[gameListController arrangedObjects] objectAtIndex:selectedIndex];
if ( ![self isCompatibilityCheckIgnored] && ((![[selectedGame serial] isEqualToString:[self currentGameSerial]]) || ([selectedGame crc] != [self currentGameCRC])) )
{
return;
}
CocoaDSCheatDBEntry *rootEntry = [selectedGame entryRoot];
if (rootEntry == nil)
{
return;
}
const NSInteger addedItemCount = [cheatManager databaseAddSelectedInEntry:[selectedGame entryRoot]];
if (addedItemCount > 0)
{
[[delegate cheatListController] setContent:[cheatManager sessionList]];
[cheatManager save];
}
}
- (IBAction) selectCurrentGame:(id)sender
{
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
if (delegate == nil)
{
return;
}
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
if (cheatManager == nil)
{
return;
}
if ( ([self currentGameSerial] == nil) || ([self currentGameCRC] == 0) )
{
return;
}
NSUInteger selectionIndex = NSNotFound;
NSArray *arrangedObjects = (NSArray *)[gameListController arrangedObjects];
for (CocoaDSCheatDBGame *game in arrangedObjects)
{
if ( ([game crc] == [self currentGameCRC]) && ([[game serial] isEqualToString:[self currentGameSerial]]) )
{
selectionIndex = [arrangedObjects indexOfObject:game];
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:selectionIndex];
[gameTable selectRowIndexes:indexSet byExtendingSelection:NO];
[gameTable scrollRowToVisible:selectionIndex];
break;
}
}
}
- (IBAction) closeErrorSheet:(id)sender
{
NSWindow *sheet = [(NSControl *)sender window];
const NSInteger code = [(NSControl *)sender tag];
[CocoaDSUtil endSheet:sheet returnCode:code];
}
#pragma mark -
#pragma mark NSWindowDelegate Protocol
- (void)windowDidLoad
{
// Save a copy of the default window title before we replace it
// with the database file's description.
NSString *oldDefaultWindowTitle = defaultWindowTitle;
defaultWindowTitle = [[[self window] title] copy];
[oldDefaultWindowTitle release];
}
- (void)windowWillClose:(NSNotification *)notification
{
NSArray *userDefaultsRecentsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
if ( (userDefaultsRecentsList != nil) && ([userDefaultsRecentsList count] > 0) )
{
NSMutableArray *dbRecentsList = [NSMutableArray arrayWithCapacity:[userDefaultsRecentsList count]];
for (NSDictionary *recentItem in userDefaultsRecentsList)
{
NSString *thisFilePath = [[database lastFileURL] path];
NSString *recentItemPath = (NSString *)[recentItem objectForKey:@"FilePath"];
if ( (thisFilePath != nil) && ([recentItemPath isEqualToString:thisFilePath]) )
{
NSMutableDictionary *newRecentItem = [NSMutableDictionary dictionaryWithDictionary:recentItem];
[newRecentItem setObject:[[self window] stringWithSavedFrame] forKey:@"WindowFrame"];
[newRecentItem setObject:[NSNumber numberWithFloat:[[[splitView subviews] objectAtIndex:0] frame].size.height] forKey:@"WindowSplitViewDividerPosition"];
[newRecentItem setObject:[NSNumber numberWithBool:[self isCompatibilityCheckIgnored]] forKey:@"OptionIgnoreCompatibilityCheck"];
[dbRecentsList addObject:newRecentItem];
}
else
{
[dbRecentsList addObject:recentItem];
}
}
[[NSUserDefaults standardUserDefaults] setObject:dbRecentsList forKey:@"CheatDatabase_RecentFilePath"];
}
[cheatDatabaseWindowList removeObject:self];
[self release];
}
#pragma mark -
#pragma mark NSTableViewDelegate Protocol
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
NSTableView *table = (NSTableView *)[aNotification object];
NSInteger rowIndex = [table selectedRow];
if (table == gameTable)
{
if (rowIndex >= 0)
{
NSArray *selectedObjects = [gameListController selectedObjects];
CocoaDSCheatDBGame *selectedGame = [selectedObjects objectAtIndex:0];
CocoaDSCheatDBEntry *entryRoot = [database loadGameEntry:selectedGame];
[self validateWillAddColumn];
[entryListController setContent:[entryRoot child]];
if (entryRoot == nil)
{
[self showErrorSheet:CheatSystemError_LoadEntryError];
}
}
else
{
[entryListController setContent:nil];
}
}
}
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NSString *cellString = [cell stringValue];
if ( (cellString != nil) && [cellString isEqualToString:currentGameIndexString] )
{
currentGameTableRowIndex = row;
}
if ( (cellString != nil) && (row == currentGameTableRowIndex) )
{
[cell setFont:[NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize] + 1.0f]];
}
else
{
[cell setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
currentGameTableRowIndex = NSNotFound;
}
}
@end

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2017 DeSmuME team
Copyright (C) 2017-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -72,6 +72,7 @@ class MacDisplayLayeredView;
@property (assign) NSInteger pixelScaler;
- (void) setupLayer;
- (void) updateLayerPresenterProperties:(ClientDisplayPresenterProperties &)props scaleFactor:(const double)scaleFactor needFlush:(BOOL)needFlush;
@end

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2013-2022 DeSmuME team
Copyright (C) 2013-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -184,7 +184,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
if ([self isFullScreen])
{
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps];
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps needFlush:YES];
}
else
{
@ -199,7 +199,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
// display view to update itself.
if (oldBounds.width == newBounds.width && oldBounds.height == newBounds.height)
{
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps];
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps needFlush:YES];
}
}
}
@ -224,7 +224,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
}
else
{
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps];
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps needFlush:YES];
}
}
@ -244,7 +244,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
{
if ([self isFullScreen])
{
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps];
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps needFlush:YES];
}
else
{
@ -261,7 +261,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void) setDisplayOrder:(NSInteger)theOrder
{
_localViewProps.order = (ClientDisplayOrder)theOrder;
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps];
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps needFlush:YES];
}
- (NSInteger) displayOrder
@ -288,7 +288,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
case ClientDisplayLayout_Hybrid_16_9:
case ClientDisplayLayout_Hybrid_16_10:
default:
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps];
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps needFlush:YES];
break;
}
}
@ -298,7 +298,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
{
case ClientDisplayLayout_Hybrid_16_9:
case ClientDisplayLayout_Hybrid_16_10:
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps];
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps needFlush:YES];
break;
case ClientDisplayLayout_Horizontal:
@ -450,7 +450,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
// window size changed or not.
if (oldBounds.width == newBounds.width && oldBounds.height == newBounds.height)
{
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps];
[[[self view] cdsVideoOutput] commitPresenterProperties:_localViewProps needFlush:YES];
}
}
@ -494,13 +494,13 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
[[self view] setIsHUDRealTimeClockVisible:[[NSUserDefaults standardUserDefaults] boolForKey:@"HUD_ShowRTC"]];
[[self view] setIsHUDInputVisible:[[NSUserDefaults standardUserDefaults] boolForKey:@"HUD_ShowInput"]];
[[self view] setHudColorExecutionSpeed:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32([[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_ExecutionSpeed"])]];
[[self view] setHudColorVideoFPS:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32([[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_VideoFPS"])]];
[[self view] setHudColorRender3DFPS:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32([[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_Render3DFPS"])]];
[[self view] setHudColorFrameIndex:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32([[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_FrameIndex"])]];
[[self view] setHudColorLagFrameCount:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32([[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_LagFrameCount"])]];
[[self view] setHudColorCPULoadAverage:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32([[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_CPULoadAverage"])]];
[[self view] setHudColorRTC:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32([[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_RTC"])]];
[[self view] setHudColorExecutionSpeed:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_ExecutionSpeed"])]];
[[self view] setHudColorVideoFPS:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_VideoFPS"])]];
[[self view] setHudColorRender3DFPS:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_Render3DFPS"])]];
[[self view] setHudColorFrameIndex:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_FrameIndex"])]];
[[self view] setHudColorLagFrameCount:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_LagFrameCount"])]];
[[self view] setHudColorCPULoadAverage:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_CPULoadAverage"])]];
[[self view] setHudColorRTC:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_RTC"])]];
}
- (BOOL) masterStatusBarState
@ -1141,7 +1141,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
bool isSupportingCPU = false;
bool isSupportingShader = false;
OGLFilter::GetSupport([theItem tag], &isSupportingCPU, &isSupportingShader);
OGLFilter::GetSupport((int)[theItem tag], &isSupportingCPU, &isSupportingShader);
enable = isSupportingCPU || (isSupportingShader && [[self view] canUseShaderBasedFilters]);
}
@ -1295,7 +1295,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
[newDisplayOutput setClientDisplay3DView:cdv];
NSString *fontPath = [[NSBundle mainBundle] pathForResource:@"SourceSansPro-Bold" ofType:@"otf"];
cdv->Get3DPresenter()->SetHUDFontPath([fontPath cStringUsingEncoding:NSUTF8StringEncoding]);
cdv->Get3DPresenter()->SetHUDFontPath([CocoaDSUtil cPathFromFilePath:fontPath]);
cdv->Get3DPresenter()->SetHUDRenderMipmapped(true);
if (scaleFactor != 1.0f)
@ -1465,6 +1465,40 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
- (void)windowDidChangeScreen:(NSNotification *)notification
{
[self updateDisplayID];
// We also need to check if the window's backing scale factor changes, which can
// occur when moving the window from a normal display to a HiDPI display (in
// other words, from a non-Retina display to a Retina display), or vice versa.
// We must update the display presenter properties now so that HUD element
// locations and NDS touch points remain consistent for both Retina and non-Retina
// displays. This feature requires Mac OS X v10.7 Lion or later.
#if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
MacDisplayLayeredView *cdv = [[self view] clientDisplayView];
CALayer<DisplayViewCALayer> *localLayer = cdv->GetCALayer();
if ([[self window] respondsToSelector:@selector(backingScaleFactor)])
{
const double oldScaleFactor = cdv->Get3DPresenter()->GetScaleFactor();
const double newScaleFactor = [[self window] backingScaleFactor];
if (newScaleFactor != oldScaleFactor)
{
ClientDisplayPresenterProperties &props = [self localViewProperties];
props.clientWidth *= newScaleFactor / oldScaleFactor;
props.clientHeight *= newScaleFactor / oldScaleFactor;
[[self view] updateLayerPresenterProperties:props scaleFactor:newScaleFactor needFlush:NO];
if ([localLayer isKindOfClass:[CAOpenGLLayer class]] && [localLayer respondsToSelector:@selector(setContentsScale:)])
{
[localLayer setContentsScale:newScaleFactor];
}
cdv->Get3DPresenter()->SetScaleFactor(newScaleFactor);
cdv->SetViewNeedsFlush();
}
}
#endif
}
#if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
@ -2159,6 +2193,31 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
}
}
- (void) updateLayerPresenterProperties:(ClientDisplayPresenterProperties &)props scaleFactor:(const double)scaleFactor needFlush:(BOOL)needFlush
{
double checkWidth = props.normalWidth;
double checkHeight = props.normalHeight;
ClientDisplayPresenter::ConvertNormalToTransformedBounds(1.0, props.rotation, checkWidth, checkHeight);
props.viewScale = ClientDisplayPresenter::GetMaxScalarWithinBounds(checkWidth, checkHeight, props.clientWidth, props.clientHeight);
if (localOGLContext != nil)
{
[localOGLContext update];
}
else if ([localLayer isKindOfClass:[CAOpenGLLayer class]])
{
[localLayer setBounds:CGRectMake(0.0f, 0.0f, props.clientWidth / scaleFactor, props.clientHeight / scaleFactor)];
}
#ifdef ENABLE_APPLE_METAL
else if ([localLayer isKindOfClass:[CAMetalLayer class]])
{
[(CAMetalLayer *)localLayer setDrawableSize:CGSizeMake(props.clientWidth, props.clientHeight)];
}
#endif
[[self cdsVideoOutput] commitPresenterProperties:props needFlush:needFlush];
}
#pragma mark InputHIDManagerTarget Protocol
- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue hidManager:(InputHIDManager *)hidManager
{
@ -2249,7 +2308,6 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
if (rect.size.width != oldFrame.size.width || rect.size.height != oldFrame.size.height)
{
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate];
ClientDisplayPresenterProperties &props = [windowController localViewProperties];
NSRect newViewportRect = rect;
#if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
@ -2260,31 +2318,12 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
#endif
// Calculate the view scale for the given client size.
double checkWidth = props.normalWidth;
double checkHeight = props.normalHeight;
ClientDisplayPresenter::ConvertNormalToTransformedBounds(1.0, props.rotation, checkWidth, checkHeight);
ClientDisplayPresenterProperties &props = [windowController localViewProperties];
props.clientWidth = newViewportRect.size.width;
props.clientHeight = newViewportRect.size.height;
props.viewScale = ClientDisplayPresenter::GetMaxScalarWithinBounds(checkWidth, checkHeight, props.clientWidth, props.clientHeight);
if (localOGLContext != nil)
{
[localOGLContext update];
}
else if ([localLayer isKindOfClass:[CAOpenGLLayer class]])
{
const double scaleFactor = [[self cdsVideoOutput] clientDisplay3DView]->Get3DPresenter()->GetScaleFactor();
[localLayer setBounds:CGRectMake(0.0f, 0.0f, props.clientWidth / scaleFactor, props.clientHeight / scaleFactor)];
}
#ifdef ENABLE_APPLE_METAL
else if ([localLayer isKindOfClass:[CAMetalLayer class]])
{
[(CAMetalLayer *)localLayer setDrawableSize:CGSizeMake(props.clientWidth, props.clientHeight)];
}
#endif
[[self cdsVideoOutput] commitPresenterProperties:props];
const double scaleFactor = [[self cdsVideoOutput] clientDisplay3DView]->Get3DPresenter()->GetScaleFactor();
[self updateLayerPresenterProperties:props scaleFactor:scaleFactor needFlush:YES];
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2013-2022 DeSmuME Team
Copyright (C) 2013-2023 DeSmuME Team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -42,8 +42,6 @@ class AudioSampleBlockGenerator;
CocoaDSRom *currentRom;
CocoaDSFirmware *cdsFirmware;
CocoaDSSpeaker *cdsSpeaker;
CocoaDSCheatManager *cdsCheats;
CocoaDSCheatManager *dummyCheatList;
CheatWindowDelegate *cheatWindowDelegate;
MacScreenshotCaptureToolDelegate *screenshotCaptureToolDelegate;
@ -56,8 +54,8 @@ class AudioSampleBlockGenerator;
NSObjectController *cheatWindowController;
NSObjectController *slot2WindowController;
NSArrayController *inputDeviceListController;
NSArrayController *cheatListController;
NSArrayController *cheatDatabaseController;
NSMenu *cheatDatabaseRecentsMenu;
RomInfoPanel *romInfoPanel;
@ -138,7 +136,6 @@ class AudioSampleBlockGenerator;
@property (assign) CocoaDSRom *currentRom; // Don't rely on autorelease since the emulator doesn't support concurrent unloading
@property (retain) CocoaDSFirmware *cdsFirmware;
@property (retain) CocoaDSSpeaker *cdsSpeaker;
@property (retain) CocoaDSCheatManager *cdsCheats;
@property (readonly) IBOutlet CheatWindowDelegate *cheatWindowDelegate;
@property (readonly) IBOutlet MacScreenshotCaptureToolDelegate *screenshotCaptureToolDelegate;
@ -151,8 +148,8 @@ class AudioSampleBlockGenerator;
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
@property (readonly) IBOutlet NSObjectController *slot2WindowController;
@property (readonly) IBOutlet NSArrayController *inputDeviceListController;
@property (readonly) IBOutlet NSArrayController *cheatListController;
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
@property (readonly) IBOutlet NSMenu *cheatDatabaseRecentsMenu;
@property (readonly) IBOutlet RomInfoPanel *romInfoPanel;
@ -217,6 +214,9 @@ class AudioSampleBlockGenerator;
- (IBAction) stopReplay:(id)sender;
- (IBAction) importRomSave:(id)sender;
- (IBAction) exportRomSave:(id)sender;
- (IBAction) openCheatDatabaseFile:(id)sender;
- (IBAction) clearCheatDatabaseRecents:(id)sender;
- (IBAction) openRecentCheatDatabase:(id)sender;
// Emulation Menu
- (IBAction) toggleSpeedLimiter:(id)sender;
@ -302,6 +302,7 @@ class AudioSampleBlockGenerator;
- (BOOL) loadRomByURL:(NSURL *)romURL asynchronous:(BOOL)willLoadAsync;
- (void) loadRomDidFinish:(NSNotification *)aNotification;
- (BOOL) unloadRom;
- (void) updateCheatDatabaseRecentsMenu:(NSNotification *)aNotification;
- (void) addOutputToCore:(CocoaDSOutput *)theOutput;
- (void) removeOutputFromCore:(CocoaDSOutput *)theOutput;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2013-2022 DeSmuME Team
Copyright (C) 2013-2023 DeSmuME Team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -19,6 +19,7 @@
#import "DisplayWindowController.h"
#import "InputManager.h"
#import "cheatWindowDelegate.h"
#import "CheatDatabaseWindowController.h"
#import "Slot2WindowDelegate.h"
#import "MacAVCaptureTool.h"
#import "MacScreenshotCaptureTool.h"
@ -46,7 +47,6 @@
@synthesize currentRom;
@dynamic cdsFirmware;
@dynamic cdsSpeaker;
@synthesize cdsCheats;
@synthesize cheatWindowDelegate;
@synthesize screenshotCaptureToolDelegate;
@ -57,11 +57,11 @@
@synthesize cdsCoreController;
@synthesize cdsSoundController;
@synthesize cheatWindowController;
@synthesize cheatListController;
@synthesize cheatDatabaseController;
@synthesize slot2WindowController;
@synthesize inputDeviceListController;
@synthesize cheatDatabaseRecentsMenu;
@synthesize romInfoPanel;
@synthesize displayRotationPanel;
@ -134,7 +134,6 @@
currentRom = nil;
cdsFirmware = nil;
cdsSpeaker = nil;
dummyCheatList = nil;
isSaveStateEdited = NO;
isShowingSaveStateDialog = NO;
@ -198,6 +197,11 @@
name:@"org.desmume.DeSmuME.handleEmulatorExecutionState"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateCheatDatabaseRecentsMenu:)
name:@"org.desmume.DeSmuME.updateCheatDatabaseRecentsMenu"
object:nil];
return self;
}
@ -231,7 +235,6 @@
[[self currentRom] release];
[self setCurrentRom:nil];
[self setCdsCheats:nil];
[self setCdsSpeaker:nil];
[self setIsWorking:NO];
@ -807,6 +810,104 @@
[self restoreCoreState];
}
- (IBAction) openCheatDatabaseFile:(id)sender
{
CheatDatabaseWindowController *newWindowController = [[CheatDatabaseWindowController alloc] initWithWindowNibName:@"CheatDatabaseViewer" delegate:cheatWindowDelegate];
[newWindowController window]; // Just reference the window to force the NSWindow object to load.
[[newWindowController window] makeKeyAndOrderFront:sender];
[[newWindowController window] makeMainWindow];
[newWindowController openFile:sender];
}
- (IBAction) clearCheatDatabaseRecents:(id)sender
{
NSArray *menuItemList = [cheatDatabaseRecentsMenu itemArray];
for (NSMenuItem *menuItem in menuItemList)
{
if ( ([menuItem action] == @selector(openRecentCheatDatabase:)) || [menuItem isSeparatorItem] )
{
[cheatDatabaseRecentsMenu removeItem:menuItem];
}
}
NSArray *emptyArray = [[[NSArray alloc] init] autorelease];
[[NSUserDefaults standardUserDefaults] setObject:emptyArray forKey:@"CheatDatabase_RecentFilePath"];
// Also remove the legacy setting.
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"R4Cheat_DatabasePath"];
}
- (IBAction) openRecentCheatDatabase:(id)sender
{
CheatDatabaseWindowController *newWindowController = [[CheatDatabaseWindowController alloc] initWithWindowNibName:@"CheatDatabaseViewer" delegate:cheatWindowDelegate];
[newWindowController window]; // Just reference the window to force the NSWindow object to load.
[[newWindowController window] makeKeyAndOrderFront:self];
[[newWindowController window] makeMainWindow];
NSArray *recentDBFilePathsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
NSInteger index = [CocoaDSUtil getIBActionSenderTag:sender];
NSDictionary *recentItem = (NSDictionary *)[recentDBFilePathsList objectAtIndex:index];
NSString *recentItemFilePath = nil;
if (recentItem != nil)
{
NSNumber *compatibilityCheckNumber = (NSNumber *)[recentItem objectForKey:@"OptionIgnoreCompatibilityCheck"];
if (compatibilityCheckNumber != nil)
{
[newWindowController setIsOptionWarningSilenced:YES];
[newWindowController setIsCompatibilityCheckIgnored:[compatibilityCheckNumber boolValue]];
[newWindowController setIsOptionWarningSilenced:NO];
}
// Set up the window properties.
NSString *windowFrameString = (NSString *)[recentItem objectForKey:@"WindowFrame"];
if (windowFrameString != nil)
{
[[newWindowController window] setFrameFromString:windowFrameString];
}
NSNumber *windowSplitViewDividerPositionNumber = (NSNumber *)[recentItem objectForKey:@"WindowSplitViewDividerPosition"];
if (windowSplitViewDividerPositionNumber != nil)
{
CGFloat dividerPosition = [windowSplitViewDividerPositionNumber floatValue];
[[newWindowController splitView] setPosition:dividerPosition ofDividerAtIndex:0];
}
// Check for the file's existence at its path, and then handle appropriately.
recentItemFilePath = (NSString *)[recentItem objectForKey:@"FilePath"];
NSFileManager *fileManager = [[NSFileManager alloc] init];
BOOL doesFileExist = [fileManager fileExistsAtPath:recentItemFilePath];
[fileManager release];
if (!doesFileExist)
{
// If the file does not exist, then report the error to the user, and the remove the
// nonexistent file from the recents menu.
[newWindowController showErrorSheet:CheatSystemError_FileDoesNotExist];
NSMutableArray *newRecentsList = [NSMutableArray arrayWithCapacity:[recentDBFilePathsList count]];
for (NSDictionary *theItem in recentDBFilePathsList)
{
if (theItem != recentItem)
{
[newRecentsList addObject:theItem];
}
}
[[NSUserDefaults standardUserDefaults] setObject:newRecentsList forKey:@"CheatDatabase_RecentFilePath"];
[self updateCheatDatabaseRecentsMenu:nil];
return;
}
}
NSURL *dbFileURL = [NSURL fileURLWithPath:recentItemFilePath];
[newWindowController loadFileStart:dbFileURL];
}
- (IBAction) toggleExecutePause:(id)sender
{
[inputManager dispatchCommandUsingIBAction:_cmd sender:sender];
@ -1022,7 +1123,7 @@
{
[panel beginSheetModalForWindow:slot1ManagerWindow
completionHandler:^(NSInteger result) {
[self didEndChooseSlot1R4Directory:panel returnCode:result contextInfo:nil];
[self didEndChooseSlot1R4Directory:panel returnCode:(int)result contextInfo:nil];
} ];
}
else
@ -1935,75 +2036,8 @@
[romInfoPanelController setContent:[theRom bindings]];
// If the ROM has an associated cheat file, load it now.
NSString *cheatsPath = [[CocoaDSFile fileURLFromRomURL:[theRom fileURL] toKind:@"Cheat"] path];
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
CocoaDSCheatManager *newCheatList = [[[CocoaDSCheatManager alloc] initWithFileURL:[NSURL fileURLWithPath:cheatsPath]] autorelease];
if (newCheatList != nil)
{
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
[CocoaDSCheatManager setMasterCheatList:newCheatList];
[cheatListController setContent:[newCheatList list]];
[self setCdsCheats:newCheatList];
[cheatWindowBindings setValue:newCheatList forKey:@"cheatList"];
NSString *filePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
if (filePath != nil)
{
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSInteger error = 0;
NSMutableArray *dbList = [[self cdsCheats] cheatListFromDatabase:fileURL errorCode:&error];
if (dbList != nil)
{
[cheatDatabaseController setContent:dbList];
NSString *titleString = [[self cdsCheats] dbTitle];
NSString *dateString = [[self cdsCheats] dbDate];
[cheatWindowBindings setValue:titleString forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:dateString forKey:@"cheatDBDate"];
[cheatWindowBindings setValue:[NSString stringWithFormat:@"%ld", (unsigned long)[dbList count]] forKey:@"cheatDBItemCount"];
}
else
{
[cheatWindowBindings setValue:@"---" forKey:@"cheatDBItemCount"];
switch (error)
{
case CHEATEXPORT_ERROR_FILE_NOT_FOUND:
NSLog(@"R4 Cheat Database read failed! Could not load the database file!");
[cheatWindowBindings setValue:@"Database not loaded." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"CANNOT LOAD FILE" forKey:@"cheatDBDate"];
break;
case CHEATEXPORT_ERROR_WRONG_FILE_FORMAT:
NSLog(@"R4 Cheat Database read failed! Wrong file format!");
[cheatWindowBindings setValue:@"Database load error." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"FAILED TO LOAD FILE" forKey:@"cheatDBDate"];
break;
case CHEATEXPORT_ERROR_SERIAL_NOT_FOUND:
NSLog(@"R4 Cheat Database read failed! Could not find the serial number for this game in the database!");
[cheatWindowBindings setValue:@"ROM not found in database." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"ROM not found." forKey:@"cheatDBDate"];
break;
case CHEATEXPORT_ERROR_EXPORT_FAILED:
NSLog(@"R4 Cheat Database read failed! Could not read the database file!");
[cheatWindowBindings setValue:@"Database read error." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"CANNOT READ FILE" forKey:@"cheatDBDate"];
break;
default:
break;
}
}
}
[cheatWindowDelegate setCdsCheats:newCheatList];
[[cheatWindowDelegate cdsCheatSearch] setRwlockCoreExecute:[cdsCore rwlockCoreExecute]];
[cheatWindowDelegate setCheatSearchViewByStyle:CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE];
}
[cheatWindowDelegate cheatSystemStart:[cdsCore cdsCheatManager]];
// Add the last loaded ROM to the Recent ROMs list.
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[theRom fileURL]];
@ -2057,22 +2091,11 @@
[[windowController window] displayIfNeeded];
}
// Save the ROM's cheat list before unloading.
[[self cdsCheats] save];
[cheatWindowDelegate cheatSystemEnd];
// Update the UI to indicate that the ROM has started the process of unloading.
[self setStatusText:NSSTRING_STATUS_ROM_UNLOADING];
[romInfoPanelController setContent:[CocoaDSRom romNotLoadedBindings]];
[cheatListController setContent:nil];
[cheatWindowDelegate resetSearch:nil];
[cheatWindowDelegate setCdsCheats:nil];
[cheatDatabaseController setContent:nil];
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
[cheatWindowBindings setValue:@"No ROM loaded." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"No ROM loaded." forKey:@"cheatDBDate"];
[cheatWindowBindings setValue:@"---" forKey:@"cheatDBItemCount"];
[cheatWindowBindings setValue:nil forKey:@"cheatList"];
// Unload the ROM.
if (![cdsCore emuFlagUseExternalBios] || ![cdsCore emuFlagUseExternalFirmware])
@ -2083,14 +2106,6 @@
[[self currentRom] release];
[self setCurrentRom:nil];
// Release the current cheat list and assign the empty list.
[self setCdsCheats:nil];
if (dummyCheatList == nil)
{
dummyCheatList = [[CocoaDSCheatManager alloc] init];
}
[CocoaDSCheatManager setMasterCheatList:dummyCheatList];
// Update the UI to indicate that the ROM has finished unloading.
[self updateAllWindowTitles];
[screenshotCaptureToolDelegate setRomName:[currentRom internalName]];
@ -2118,6 +2133,93 @@
return result;
}
- (void) updateCheatDatabaseRecentsMenu:(NSNotification *)aNotification
{
NSArray *dbRecentsList = (NSArray *)[aNotification object];
BOOL needReleaseObject = (dbRecentsList != nil);
if ( (dbRecentsList == nil) || ([dbRecentsList count] == 0) )
{
dbRecentsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
}
NSMutableArray *newRecentsList = [NSMutableArray arrayWithArray:dbRecentsList];
// Note that we're relying on the notification object to retain this prior to
// sending the notification.
if (needReleaseObject)
{
[dbRecentsList release];
}
NSString *legacyFilePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
BOOL useLegacyFilePath = ( (legacyFilePath != nil) && ([legacyFilePath length] > 0) );
if (useLegacyFilePath)
{
// We need to check if the legacy file path also exists in the recents list.
// If it does, then the recents list version takes priority.
for (NSDictionary *dbRecentItem in dbRecentsList)
{
NSString *dbRecentItemFilePath = (NSString *)[dbRecentItem valueForKey:@"FilePath"];
if ([dbRecentItemFilePath isEqualToString:legacyFilePath])
{
useLegacyFilePath = NO;
break;
}
}
}
if (useLegacyFilePath)
{
// The legacy file path must always be the first entry of the recents list.
NSDictionary *legacyRecentItem = [NSDictionary dictionaryWithObjectsAndKeys:legacyFilePath, @"FilePath",
[legacyFilePath lastPathComponent], @"FileName",
nil];
[newRecentsList insertObject:legacyRecentItem atIndex:0];
if ([newRecentsList count] == 1)
{
// If the legacy file path is the only item in the recents list, then we can write it
// back to user defaults right now.
[[NSUserDefaults standardUserDefaults] setObject:newRecentsList forKey:@"CheatDatabase_RecentFilePath"];
}
}
NSArray *recentsMenuItems = [cheatDatabaseRecentsMenu itemArray];
for (NSMenuItem *menuItem in recentsMenuItems)
{
if ( [menuItem action] == @selector(openRecentCheatDatabase:) )
{
[cheatDatabaseRecentsMenu removeItem:menuItem];
}
}
if ([newRecentsList count] > 0)
{
if ( ![[cheatDatabaseRecentsMenu itemAtIndex:0] isSeparatorItem] )
{
[cheatDatabaseRecentsMenu insertItem:[NSMenuItem separatorItem] atIndex:0];
}
}
// Recent files are added in reverse order, in which least recent files appear below
// more recent files in the menu. The most recent file should be at the top of the menu.
for (NSDictionary *recentItem in newRecentsList)
{
NSString *menuNameString = [recentItem objectForKey:@"FileName"];
if ( (menuNameString == nil) || ([menuNameString length] == 0) )
{
menuNameString = [recentItem objectForKey:@"FilePath"];
}
NSMenuItem *newMenuItem = [[[NSMenuItem alloc] initWithTitle:menuNameString action:@selector(openRecentCheatDatabase:) keyEquivalent:@""] autorelease];
[newMenuItem setTag:[newRecentsList indexOfObject:recentItem]];
[newMenuItem setTarget:self];
[cheatDatabaseRecentsMenu insertItem:newMenuItem atIndex:0];
}
}
- (void) handleNDSError:(NSNotification *)aNotification
{
[self setIsUserInterfaceBlockingExecution:YES];
@ -3069,6 +3171,13 @@
enable = NO;
}
}
else if (theAction == @selector(clearCheatDatabaseRecents:))
{
if ([cheatDatabaseRecentsMenu numberOfItems] < 2)
{
enable = NO;
}
}
else if (theAction == @selector(changeCoreSpeed:))
{
NSInteger speedScalar = (NSInteger)([cdsCore speedScalar] * 100.0);
@ -3172,7 +3281,7 @@
{
if ([(id)theItem isMemberOfClass:[NSMenuItem class]])
{
[(NSMenuItem*)theItem setState:([[cdsCore cdsGPU] gpuStateByBit:[theItem tag]]) ? GUI_STATE_ON : GUI_STATE_OFF];
[(NSMenuItem*)theItem setState:([[cdsCore cdsGPU] gpuStateByBit:(UInt32)[theItem tag]]) ? GUI_STATE_ON : GUI_STATE_OFF];
}
}

View File

@ -1170,7 +1170,7 @@ void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSen
ClientCommandAttributes cmdToggleSpeedLimiter = NewCommandAttributesWithFunction("Enable/Disable Speed Limiter", &ClientCommandToggleSpeedLimiter);
ClientCommandAttributes cmdToggleAutoFrameSkip = NewCommandAttributesWithFunction("Enable/Disable Auto Frame Skip", &ClientCommandToggleAutoFrameSkip);
ClientCommandAttributes cmdToggleCheats = NewCommandAttributesWithFunction("Enable/Disable Cheats", &ClientCommandToggleCheats);
ClientCommandAttributes cmdToggleCheats = NewCommandAttributesWithFunction("Enable/Disable Cheat System", &ClientCommandToggleCheats);
ClientCommandAttributes cmdCoreExecute = NewCommandAttributesWithFunction("Execute", &ClientCommandCoreExecute);
ClientCommandAttributes cmdCorePause = NewCommandAttributesWithFunction("Pause", &ClientCommandCorePause);
ClientCommandAttributes cmdToggleExecutePause = NewCommandAttributesWithFunction("Execute/Pause", &ClientCommandToggleExecutePause);
@ -1227,7 +1227,7 @@ void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSen
defaultCommandAttributes["Set Speed"] = cmdToggleSpeed;
defaultCommandAttributes["Enable/Disable Speed Limiter"] = cmdToggleSpeedLimiter;
defaultCommandAttributes["Enable/Disable Auto Frame Skip"] = cmdToggleAutoFrameSkip;
defaultCommandAttributes["Enable/Disable Cheats"] = cmdToggleCheats;
defaultCommandAttributes["Enable/Disable Cheat System"] = cmdToggleCheats;
defaultCommandAttributes["Execute"] = cmdCoreExecute;
defaultCommandAttributes["Pause"] = cmdCorePause;
defaultCommandAttributes["Execute/Pause"] = cmdToggleExecutePause;
@ -1802,7 +1802,7 @@ void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSen
}
// Check if the audio file is already loaded. If it is, don't load it again.
std::string filePathStr = std::string([filePath cStringUsingEncoding:NSUTF8StringEncoding]);
std::string filePathStr = std::string([CocoaDSUtil cPathFromFilePath:filePath]);
for (AudioFileSampleGeneratorMap::iterator it=audioFileGenerators.begin(); it!=audioFileGenerators.end(); ++it)
{
if (it->first.find(filePathStr) != std::string::npos)
@ -1905,7 +1905,7 @@ void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSen
return NULL;
}
std::string filePathStr = std::string([filePath cStringUsingEncoding:NSUTF8StringEncoding]);
std::string filePathStr = std::string([CocoaDSUtil cPathFromFilePath:filePath]);
for (AudioFileSampleGeneratorMap::iterator it=audioFileGenerators.begin(); it!=audioFileGenerators.end(); ++it)
{
if (it->first.find(filePathStr) != std::string::npos)

View File

@ -1350,8 +1350,8 @@ ClientAVCaptureError FFmpegFileStream::WriteOneFrame(const AVStreamWriteParam &p
param.refObject = newCaptureObject;
param.fetchObject = currentFetchObj;
param.formatID = [self formatID];
param.savePath = std::string([savePath cStringUsingEncoding:NSUTF8StringEncoding]);
param.romName = std::string([romName cStringUsingEncoding:NSUTF8StringEncoding]);
param.savePath = std::string([CocoaDSUtil cPathFromFilePath:savePath]);
param.romName = std::string([CocoaDSUtil cPathFromFilePath:romName]);
param.useDeposterize = [self useDeposterize] ? true : false;
param.outputFilterID = (OutputFilterTypeID)[self outputFilterID];
param.pixelScalerID = (VideoFilterTypeID)[self pixelScalerID];
@ -1383,7 +1383,8 @@ ClientAVCaptureError FFmpegFileStream::WriteOneFrame(const AVStreamWriteParam &p
NSString *fileNameNSString = [[dateFormatter stringFromDate:[NSDate date]] stringByAppendingString:[NSString stringWithCString:param.romName.c_str() encoding:NSUTF8StringEncoding]];
[dateFormatter release];
std::string fileName = param.savePath + "/" + std::string([fileNameNSString cStringUsingEncoding:NSUTF8StringEncoding]);
NSString *savePathNSString = [CocoaDSUtil filePathFromCPath:param.savePath.c_str()];
std::string fileName = std::string([CocoaDSUtil cPathFromFilePath:[savePathNSString stringByAppendingPathComponent:fileNameNSString]]);
// Create the output file stream.
ClientAVCaptureError error = ClientAVCaptureError_None;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018-2022 DeSmuME team
Copyright (C) 2018-2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -87,7 +87,7 @@
{
[panel beginSheetModalForWindow:[self window]
completionHandler:^(NSInteger result) {
[self chooseDirectoryPathDidEnd:panel returnCode:result contextInfo:nil];
[self chooseDirectoryPathDidEnd:panel returnCode:(int)result contextInfo:nil];
} ];
}
else

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2017-2022 DeSmuME team
Copyright (C) 2017-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -20,6 +20,11 @@
#endif
#include "MacMetalDisplayView.h"
#include <sys/types.h>
#include <sys/sysctl.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include "../cocoa_globals.h"
#include "../../../common.h"
@ -54,13 +59,118 @@
- (id)init
{
device = nil;
self = [super init];
if (self == nil)
{
return nil;
}
device = MTLCreateSystemDefaultDevice();
#if defined(DEBUG) && (DEBUG == 1)
// Report information on every renderer.
NSArray< id<MTLDevice> > *mtlDeviceList = MTLCopyAllDevices();
int rendererCount = (int)[mtlDeviceList count];
printf("Metal Renderer Count: %i\n\n", rendererCount);
for (int i = 0; i < rendererCount; i++)
{
id<MTLDevice> mtlDevice = [mtlDeviceList objectAtIndex:i];
printf("Renderer Index: %i\n", i);
printf("Renderer: %s\n", [[mtlDevice name] cStringUsingEncoding:NSUTF8StringEncoding]);
#if HAVE_OSAVAILABLE && defined(MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13)
if (@available(macOS 10.13, *))
{
printf("Renderer ID: 0x%08llX\n", [mtlDevice registryID]);
printf("Removable: %s\n", [mtlDevice isRemovable] ? "YES" : "NO");
}
else
#endif
{
printf("Renderer ID: UNSUPPORTED, Requires High Sierra\n");
printf("Removable: UNSUPPORTED, Requires High Sierra\n");
}
printf("Online: %s\n\n", [mtlDevice isHeadless] ? "NO" : "YES");
}
#endif
// Check if we're running on a MacBook Pro. If we are, then set our rendering device
// to whatever the built-in display is using in order to respect the user setting for
// Automatic Graphics Switching.
char *modelCString = NULL;
size_t modelStringLen = 0;
sysctlbyname("hw.model", NULL, &modelStringLen, NULL, 0);
if (modelStringLen > 0)
{
modelCString = (char *)malloc(modelStringLen * sizeof(char));
sysctlbyname("hw.model", modelCString, &modelStringLen, NULL, 0);
}
if (strstr(modelCString, "MacBookPro") != NULL)
{
bool isBuiltInDisplayFound = false;
NSArray<NSScreen *> *screenList = [NSScreen screens];
for (NSScreen *theScreen in screenList)
{
NSNumber *screenNumber = (NSNumber *)[[theScreen deviceDescription] objectForKey:@"NSScreenNumber"];
CGDirectDisplayID displayID = [screenNumber unsignedIntValue];
isBuiltInDisplayFound = CGDisplayIsBuiltin(displayID);
if (isBuiltInDisplayFound)
{
// If we're running on a MacBook Pro with dual GPUs, we need to set our rendering device to
// whatever the built-in display is running. This has a chance of choosing the integrated GPU,
// but only under the following conditions:
// - The user has Automatic Graphics Switching enabled in System Preferences
// - The MacBook Pro's built-in display is online and available (in other words, the
// MacBook Pro's lid is open, not closed)
// - There are no additional displays connected to the MacBook Pro
// - The app has "Prefer External GPU" unchecked in Finder Get Info
device = CGDirectDisplayCopyCurrentMetalDevice(displayID);
NSString *screenName = NULL;
// For debugging purposes, let's also report the name of the display that the rendering device
// is associated to.
#if HAVE_OSAVAILABLE && defined(MAC_OS_X_VERSION_10_15) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15)
if (@available(macOS 10.15, *))
{
screenName = [theScreen localizedName];
}
else
#endif
{
io_connect_t displayPort = SILENCE_DEPRECATION_MACOS_10_9( CGDisplayIOServicePort(displayID) );
NSDictionary *screenInfo = CFBridgingRelease( IODisplayCreateInfoDictionary(displayPort, kIODisplayOnlyPreferredName) );
NSDictionary *localizedNames = (NSDictionary *)[screenInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
if ([localizedNames count] > 0)
{
screenName = (NSString *)[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]];
}
}
printf("MacBook Pro Built-in Display: %s\n", [screenName cStringUsingEncoding:NSUTF8StringEncoding]);
break;
}
}
}
if (modelStringLen > 0)
{
free(modelCString);
modelCString = NULL;
}
// If no rendering device was set from beforehand, then just use the system default renderer.
// For MacBook Pro with dual GPUs, this will NEVER choose the integrated GPU.
if (device == nil)
{
device = MTLCreateSystemDefaultDevice();
}
if (device == nil)
{
NSLog(@"Metal: A Metal device could not be found.");
@ -77,23 +187,24 @@
}
[device retain];
printf("Selected Metal Renderer: %s\n\n\n", [[device name] cStringUsingEncoding:NSUTF8StringEncoding]);
NSString *tempVersionStr = @"Metal - Unknown GPU Family";
const BOOL isRWTexSupported = [device supportsFeatureSet:10002]; // MTLFeatureSet_macOS_ReadWriteTextureTier2
const BOOL isRWTexSupported = [device supportsFeatureSet:(MTLFeatureSet)10002]; // MTLFeatureSet_macOS_ReadWriteTextureTier2
if ([device supportsFeatureSet:10005]) // MTLFeatureSet_macOS_GPUFamily2_v1
if ([device supportsFeatureSet:(MTLFeatureSet)10005]) // MTLFeatureSet_macOS_GPUFamily2_v1
{
tempVersionStr = @"macOS Metal GPUFamily2_v1";
}
else if ([device supportsFeatureSet:10004]) // MTLFeatureSet_macOS_GPUFamily1_v4
else if ([device supportsFeatureSet:(MTLFeatureSet)10004]) // MTLFeatureSet_macOS_GPUFamily1_v4
{
tempVersionStr = (isRWTexSupported) ? @"macOS Metal GPUFamily1_v4 w/ Tier2 R/W Textures" : @"macOS Metal GPUFamily1_v4";
}
else if ([device supportsFeatureSet:10003]) // MTLFeatureSet_macOS_GPUFamily1_v3
else if ([device supportsFeatureSet:(MTLFeatureSet)10003]) // MTLFeatureSet_macOS_GPUFamily1_v3
{
tempVersionStr = (isRWTexSupported) ? @"macOS Metal GPUFamily1_v3 w/ Tier2 R/W Textures" : @"macOS Metal GPUFamily1_v3";
}
else if ([device supportsFeatureSet:10001]) // MTLFeatureSet_macOS_GPUFamily1_v2
else if ([device supportsFeatureSet:(MTLFeatureSet)10001]) // MTLFeatureSet_macOS_GPUFamily1_v2
{
tempVersionStr = (isRWTexSupported) ? @"macOS Metal GPUFamily1_v2 w/ Tier2 R/W Textures" : @"macOS Metal GPUFamily1_v2";
}
@ -2556,7 +2667,7 @@ void MacMetalFetchObject::_FetchNativeDisplayByID(const NDSDisplayID displayID,
GPU->PostprocessDisplay(displayID, this->_fetchDisplayInfo[bufferIndex]);
pthread_rwlock_wrlock(&this->_srcCloneRWLock[displayID][bufferIndex]);
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(this->_fetchDisplayInfo[bufferIndex].nativeBuffer16[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>(this->_fetchDisplayInfo[bufferIndex].nativeBuffer16[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
pthread_rwlock_unlock(&this->_srcCloneRWLock[displayID][bufferIndex]);
}
@ -2570,7 +2681,7 @@ void MacMetalFetchObject::_FetchCustomDisplayByID(const NDSDisplayID displayID,
GPU->PostprocessDisplay(displayID, this->_fetchDisplayInfo[bufferIndex]);
pthread_rwlock_wrlock(&this->_srcCloneRWLock[displayID][bufferIndex]);
ColorspaceConvertBuffer888XTo8888Opaque<false, false>((u32 *)this->_fetchDisplayInfo[bufferIndex].customBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
ColorspaceConvertBuffer888xTo8888Opaque<false, false>((u32 *)this->_fetchDisplayInfo[bufferIndex].customBuffer[displayID], this->_srcNativeClone[displayID][bufferIndex], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT);
pthread_rwlock_unlock(&this->_srcCloneRWLock[displayID][bufferIndex]);
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2017-2022 DeSmuME team
Copyright (C) 2017-2025 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -142,6 +142,14 @@ MacOGLClientFetchObject::MacOGLClientFetchObject()
(NSOpenGLPixelFormatAttribute)0
};
// Normally, supporting Automatic Graphics Switching and allowing the context
// to use the integrated GPU requires NSOpenGLPFAAllowOfflineRenderers in the
// pixel format attributes. However, GPUs that can't support Metal are also
// too slow to run most of the video filters on OpenGL, and also show poor
// performance when running multiple display windows with high GPU scaling
// factors. Therefore, we will NOT allow OpenGL to run contexts on the
// integrated GPU for performance reasons. -rogerman (2025/03/26)
#ifdef _OGLDISPLAYOUTPUT_3_2_H_
// If we can support a 3.2 Core Profile context, then request that in our
// pixel format attributes.
@ -335,6 +343,14 @@ void MacOGLDisplayPresenter::__InstanceInit(MacOGLClientFetchObject *fetchObject
(NSOpenGLPixelFormatAttribute)0
};
// Normally, supporting Automatic Graphics Switching and allowing the context
// to use the integrated GPU requires NSOpenGLPFAAllowOfflineRenderers in the
// pixel format attributes. However, GPUs that can't support Metal are also
// too slow to run most of the video filters on OpenGL, and also show poor
// performance when running multiple display windows with high GPU scaling
// factors. Therefore, we will NOT allow OpenGL to run contexts on the
// integrated GPU for performance reasons. -rogerman (2025/03/26)
#ifdef _OGLDISPLAYOUTPUT_3_2_H_
// If we can support a 3.2 Core Profile context, then request that in our
// pixel format attributes.

View File

@ -75,8 +75,8 @@
param->refObject = NULL;
param->fetchObject = [self fetchObject];
param->formatID = [self formatID];
param->savePath = std::string([savePath cStringUsingEncoding:NSUTF8StringEncoding]);
param->romName = std::string([romName cStringUsingEncoding:NSUTF8StringEncoding]);
param->savePath = std::string([CocoaDSUtil cPathFromFilePath:savePath]);
param->romName = std::string([CocoaDSUtil cPathFromFilePath:romName]);
param->useDeposterize = [self useDeposterize] ? true : false;
param->outputFilterID = (OutputFilterTypeID)[self outputFilterID];
param->pixelScalerID = (VideoFilterTypeID)[self pixelScalerID];
@ -291,7 +291,7 @@ static void* RunFileWriteThread(void *arg)
NSString *fileName = [[dateFormatter stringFromDate:[NSDate date]] stringByAppendingString:[NSString stringWithCString:param.romName.c_str() encoding:NSUTF8StringEncoding]];
[dateFormatter release];
NSString *savePath = [NSString stringWithCString:param.savePath.c_str() encoding:NSUTF8StringEncoding];
NSString *savePath = [CocoaDSUtil filePathFromCPath:param.savePath.c_str()];
NSURL *fileURL = [NSURL fileURLWithPath:[savePath stringByAppendingPathComponent:fileName]];
[CocoaDSFile saveScreenshot:fileURL bitmapData:newImageRep fileType:(NSBitmapImageFileType)param.formatID];

View File

@ -36,6 +36,8 @@
NSObjectController *emuControlController;
NSObjectController *prefWindowController;
NSObjectController *cdsCoreController;
NSObjectController *databaseFileController;
NSArrayController *gameListController;
FileMigrationDelegate *migrationDelegate;
MacAVCaptureToolDelegate *avCaptureToolDelegate;
WifiSettingsPanelDelegate *wifiSettingsPanelDelegate;
@ -63,6 +65,8 @@
@property (readonly) IBOutlet NSObjectController *emuControlController;
@property (readonly) IBOutlet NSObjectController *prefWindowController;
@property (readonly) IBOutlet NSObjectController *cdsCoreController;
@property (readonly) IBOutlet NSObjectController *databaseFileController;
@property (readonly) IBOutlet NSArrayController *gameListController;
@property (readonly) IBOutlet FileMigrationDelegate *migrationDelegate;
@property (readonly) IBOutlet MacAVCaptureToolDelegate *avCaptureToolDelegate;
@property (readonly) IBOutlet WifiSettingsPanelDelegate *wifiSettingsPanelDelegate;

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2011-2022 DeSmuME Team
Copyright (C) 2011-2023 DeSmuME Team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -28,6 +28,7 @@
#import "inputPrefsView.h"
#import "cocoa_core.h"
#import "cocoa_cheat.h"
#import "cocoa_GPU.h"
#import "cocoa_file.h"
#import "cocoa_firmware.h"
@ -50,6 +51,8 @@
@synthesize emuControlController;
@synthesize prefWindowController;
@synthesize cdsCoreController;
@synthesize databaseFileController;
@synthesize gameListController;
@synthesize avCaptureToolDelegate;
@synthesize wifiSettingsPanelDelegate;
@synthesize migrationDelegate;
@ -312,6 +315,7 @@
// Bring the application to the front
[NSApp activateIgnoringOtherApps:YES];
[emuControl restoreDisplayWindowStates];
[emuControl updateCheatDatabaseRecentsMenu:nil];
// Load a new ROM on launch per user preferences.
if ([[NSUserDefaults standardUserDefaults] objectForKey:@"General_AutoloadROMOnLaunch"] != nil)

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