Compare commits

...
191 Commits
Author SHA1 Message Date
remutro f533120df6 Add noise channel to save state serialization 2025-12-18 12:44:55 +00:00
remutro ec37caccfb [N64] Fix pak menu radio selection 2025-12-09 11:50:14 +00:00
remutro d0b9669c50 Update CC92 based on agreed ROM and No-Intro entry 2025-12-07 16:33:51 +00:00
Luke Usher dfb355495a pce: fix missing cd-da playback 2025-12-01 16:03:05 +00:00
invertego 0f618995f4 mia: remove line of dead code 2025-12-01 15:47:30 +00:00
User 35ead94515 gba: implement write protection for HALTCNT 2025-11-28 16:05:42 +00:00
remutro 6c8ccc1c7e Add support for Viewpoint 2064 master to the N62 DB 2025-11-27 13:51:47 +00:00
Giovanni Bajo 361fb49fd0 n64: fix VI bug causing spinloop
VI_H_TOTAL is defined as the number of cycles per scanline *minus 1*.
We forgot to add that 1 back. Besides the minor inaccuracy in timing,
we could hit a race condition during initial VI config: if the Ares
VI thread ran when the display was turned on (VI_CTRL configured) but
VI_H_TOTAL wasn't already configured (and thus defaulted to 0), the
thread would spinloop forever because it would step by 0 cycles.

While fixing this, I also noticed that I wasn't properly taking into
account leap timings because of a typo; this means that PAL timings
were very slightly off.

Fixes #2293
2025-11-27 12:05:29 +00:00
Max Bebök 90139d028d increase n64 serialize version 2025-11-23 19:19:57 +00:00
Max Bebök d03915bde9 n64: handle correct R/W to RDP spans in test mode 2025-11-23 19:19:57 +00:00
remutro 8a7549fb21 Remove the entry for a test build of PF94 (already done for CC92) 2025-11-12 13:03:27 +00:00
remutro 6003e6933b [SNES] add db entries for newly dumped competition carts 2025-11-12 13:03:27 +00:00
Roger Sanders 35671b2f8d ld: Fix some media info registers. Fixes JB Harold side changing. 2025-11-04 11:33:39 +00:00
ZengGengSen 43686810d2 fix fc_keyboard support 2025-10-31 13:12:19 +00:00
Adrian Siekierka 9bd2afee61 ws: implement Karnak mapper ADPCM decoder 2025-10-29 14:55:07 +00:00
jcm 7bcb9ae39f build: Run gersemi formatting pass 2025-10-29 14:37:17 +00:00
jcm f39eac9b87 build: Add missing sources to CMake file enumeration 2025-10-29 14:37:17 +00:00
jcm f370521a55 build: Disable Metal GPU capture by default due to Xcode memory issues 2025-10-28 11:34:33 +00:00
jcm c763218430 build: Add ARES_DEBUG_DEPENDENCIES build option 2025-10-28 11:34:33 +00:00
jcm 2df5b97e5e build: Account for multiple possible prefixes in slang-shaders finder 2025-10-28 11:34:33 +00:00
jcm 0a7e1c5e4c Update dependencies to 2025-10-27 release 2025-10-28 11:34:33 +00:00
Adrian Siekierka 2d80fca221 ws: add I/O port access tracer support 2025-10-28 11:33:58 +00:00
User 3b8baddfba fc: fix evaluation of sprites not aligned to 4-byte boundaries in OAM 2025-10-28 11:33:49 +00:00
Luke Usher 5319fe68f0 screen: prevent blowing out brightness when increasing saturation. 2025-10-16 16:17:59 +01:00
User 6b11b281c4 fc: improve handling of OAM accesses during rendering 2025-10-16 07:10:01 +01:00
Rupert Carmichael c79a73e88c myvision: Adjust audio frequency to match real hardware
The divider is still unconfirmed, but 21 produces the correct pitch.

References:
https://gitlab.com/jgemu/jollycv/-/blob/master/src/jcv_myvision.c
https://www.youtube.com/watch?v=UqKuNb1Z9Uc
https://www.youtube.com/watch?v=RsNxhfD7iJk
2025-10-16 07:06:52 +01:00
remutro 53a63d6ae2 Resize board vector so that there are 2 entries minimum 2025-10-15 10:10:44 +01:00
Luke Usher c95ddfe754 tms9918: simplify/clarify timing.
The real chip expects colorburst*3 as input, and then divides that by 2 internally to get the pixel clock.
2025-10-08 10:03:48 +01:00
Luke Usher bfed5a56f0 myvision: adjust audio frequency to match other hardware with the same PSG.
Real hardware value unknown.
Still just a guess, but a better? guess than we had.
2025-10-07 21:42:02 +01:00
Luke Usher 41275f4a8a ym2149: implement readIO/writeIO
currently unused, but noticed support was missing compared to ay38910
2025-10-07 21:34:54 +01:00
Luke Usher 9fcb4f93e4 myvision: fix vdp clock to 2x colorburst. 2025-10-07 21:20:49 +01:00
png183 11a7827eef fc: bump serialization 2025-10-06 10:39:23 +01:00
User b7de9976a6 fc: values in CGRAM are six bits in size 2025-10-05 21:54:37 +01:00
DirtBag Xon 9671ec7c3d Fix ambiguous overload on mouseCursor types. Always compare with matching string types.
Fixes:
widget.cpp:142:20: error: ambiguous overload for ‘operator==’ (operand types are ‘const hiro::MouseCursor’ and ‘const nall::string’)

 142 | if(mouseCursor == MouseCursor::Hand) name = "hand1";
  | ~~~~~~~~~~~ ^~ ~~~~~~~~~~~~~~~~~
  | |           |
  | const hiro::MouseCursor const nall::string
2025-10-04 09:41:42 +01:00
Luke Usher cb4aec479f ps1: properly fix color modulation this time 2025-10-03 18:49:01 +01:00
Luke Usher 44f34f9bb2 ps1: improve color modulation
Fixes excessive colour banding, without breaking Silent Hill's loading screen.
2025-10-02 20:49:24 +01:00
Giovanni Bajo 90b6c0902d stdc++: remove nall::shared_pointer, now unused 2025-10-02 14:19:44 +01:00
Giovanni Bajo 445cfacb10 stdc++: migrate nall to std::shared_ptr 2025-10-02 14:19:44 +01:00
Giovanni Bajo 7989498177 stdc++: convert hiro to std::shared_ptr 2025-10-02 14:19:44 +01:00
Giovanni Bajo b38cacbab8 stdc++: convert ares/node to std::shared_ptr 2025-10-02 14:19:44 +01:00
Giovanni Bajo 4b121c28d0 stdc++: continue migrating most uses of nall::shared_pointer 2025-10-02 14:19:44 +01:00
Giovanni Bajo 4e1b4b79ef stdc++: start migrating nall::shared_pointer to std::shared_ptr 2025-10-02 14:19:44 +01:00
Roger Sanders 18500e679b ld: Fixed a potential threading issue with frame prefetch 2025-10-01 10:07:17 +01:00
Roger Sanders 174eb5bcf2 ld: Update minimum macOS target from 10.15 to 11.0 2025-09-30 14:57:05 +01:00
Roger Sanders 8d32ab3f4f ld: Fixed some missing includes which triggered build errors on some platforms 2025-09-30 14:57:05 +01:00
Roger Sanders 5cc3a8118f ld: Added frame prefetch and video resampling coefficient precalculation 2025-09-30 14:57:05 +01:00
User 753ba2af6a fc: improve frame counter IRQ timing 2025-09-30 08:57:24 +01:00
User 757f326c33 fc: reading APU status register should not affect open bus 2025-09-30 08:57:24 +01:00
Giovanni Bajo fc36600a6a stdc++: convert nall::unique_pointer to std::unique_ptr 2025-09-29 14:24:14 +01:00
Giovanni Bajo 038bcb91c2 stdc++: migrate nall::function to std::function 2025-09-29 14:24:14 +01:00
Giovanni Bajo 0b1714c8f6 stdc++: remove merge-sort.hpp, use std::stable_sort instead 2025-09-29 14:24:14 +01:00
User 76141ba703 gba: fix addressing of 2D mapped sprites 2025-09-27 16:14:19 +01:00
Giovanni Bajo 064b2120e4 stdc++: simplify span constructors 2025-09-27 16:14:06 +01:00
Giovanni Bajo 732d03f3af stdc++: apply review suggestions 2025-09-27 16:14:06 +01:00
Giovanni Bajo 81d0f131c4 stdc++: drop unused functions from span-helpers.hpp 2025-09-27 16:14:06 +01:00
Giovanni Bajo 5d0ff02cb3 stdc++: remove nall::array_span/array_view 2025-09-27 16:14:06 +01:00
Giovanni Bajo ba41375179 stdc++: convert uses in nall to std::span 2025-09-27 16:14:06 +01:00
Giovanni Bajo fe7f05fc1e stdc++: nall: convert some uses to std::span 2025-09-27 16:14:06 +01:00
Giovanni Bajo cbe2b7be32 stdc++: migrate missing uses in ares to std::span 2025-09-27 16:14:06 +01:00
Giovanni Bajo 0d1152de1c stdc++: migrate missing uses in ares to std::span 2025-09-27 16:14:06 +01:00
Giovanni Bajo eaf5e06683 stdc++: migrate most uses in mia to std::span 2025-09-27 16:14:06 +01:00
Giovanni Bajo 0921eb8038 stdc++: migrate serializers to std::span 2025-09-27 16:14:06 +01:00
Giovanni Bajo 64c8354511 stdc++: migrate vfs functions to use std::span 2025-09-27 16:14:06 +01:00
Giovanni Bajo cd21ca7bf4 stdc++: nall: migrate some uses of array_view/span to std::span 2025-09-27 16:14:06 +01:00
Giovanni Bajo ded925451b stdc++: introduce span-helpers.hpp to aid migration to std::span 2025-09-27 16:14:06 +01:00
Giovanni Bajo b0d5be69d0 stdc++: remove unusued / seldom used methods of array_view/array_span 2025-09-27 16:14:06 +01:00
Roger Sanders 2f7fa79b07 ld: Fix a potential out of bounds memory access in some video modes 2025-09-23 10:18:30 +01:00
Roger Sanders 4fd5318e52 ld: Fix image hold forcing a new frame to be latched when one was already in the buffer 2025-09-23 10:18:30 +01:00
Giovanni Bajo 810c508489 n64: fix PIF HLE on RX flag clearing
When beginning to execute a joybus frame, PIF clears the RX flags before
the transaction begins, so that errors notified in previous transactions
don't accumulate.

This is only visible in the where an application performs multiple
transactions (SI DMA reads) on the same frame layout (sent via a single
SI DMA write), while controllers are being hotplugged. This is not very
common in Ares, which is probably why it was not noticed before.
2025-09-23 06:38:17 +01:00
jsgroth 383a0870f1 m68000: fix write ordering in MOVEM.L with indirect pre-decrement addressing
pre-decrement mode writes each longword in reverse-word order in addition to writing the registers in reverse order
2025-09-23 06:31:56 +01:00
Luke Usher 9e4a00b968 pc-engine-ld: detect and insert a bios hucard when a cd-rom is loaded that depends on it.
Currently non-working because mia rejects non-ld content for LaserActive right now, but it's here for when we fix that!
2025-09-22 13:37:55 +01:00
Luke Usher a57cce6b94 pc-engine-ld: use internal bios rather than incorrectly mountitng the LD bios in the HuCard slot. 2025-09-22 13:23:47 +01:00
Luke Usher 74a561f62e pc-engine-cd: clarify 'arcade card' and 'system card 3.0' are the same bios rom. 2025-09-22 10:46:42 +01:00
Roger Sanders 52acac2933 ld: Added hash for NEC PAC-N10 bios 2025-09-22 07:46:21 +01:00
Dragorn421 9830daef91 Review: waitGDB -> awaitGDBClient, rename "Launch Debugger" to "Launch Tracer" 2025-09-21 09:39:28 +01:00
Dragorn421 2f9f7670da Add "Wait GDB" boot option 2025-09-21 09:39:28 +01:00
Luke Usher 808aaaf053 Revert "ps1: use physical addresses as early as possible"
This reverts commit 325c0ed876.
2025-09-19 22:19:26 +01:00
Luke Usher 1044d0ad37 desktop-ui: fix settings.bml loading/saving
This was broken by the renaming of the laseractive cores, because () are not valid bml node name characters.
2025-09-19 22:14:50 +01:00
invertego 0ebd9e3bbe ps1: use constant random seed in homebrew mode 2025-09-19 21:37:43 +01:00
invertego 57d1a2ef9a ps1: randomly initialize memory on boot
Randomly initialize CPU RAM, CPU I-cache, CPU scratchpad, GPU VRAM, and
SPU RAM.
2025-09-19 21:37:43 +01:00
Luke Usher eeacac8749 pcd: fixing the build after #2220 2025-09-19 14:13:04 +01:00
Giovanni Bajo 9e1ff7b479 stdc++: reindent 2025-09-19 12:49:19 +01:00
Giovanni Bajo 32d2f3d2b2 stdc++: completely remove nall::vector, now unused 2025-09-19 12:49:19 +01:00
Giovanni Bajo c64aff5992 stdc++: nall: remove vector<string> specialization (not used anymore) 2025-09-19 12:49:19 +01:00
Giovanni Bajo 3390d66a7e stdc++: migrate tools/tests removing uses of nall::vector 2025-09-19 12:49:19 +01:00
Giovanni Bajo e388299f05 stdc++: nall: remove other nall::vector usages 2025-09-19 12:49:19 +01:00
Giovanni Bajo f31fa5c99f stdc++: nall: migrate more uses to std::vector 2025-09-19 12:49:19 +01:00
Giovanni Bajo fec8d9029c stdc++: nall: remove some uses of nall::vector 2025-09-19 12:49:19 +01:00
Giovanni Bajo c4bc76b219 stdc++: avoid nall::vector in implementation of split functions 2025-09-19 12:49:19 +01:00
jcm 7d91e5f38a CI: avoid Strawberry Perl Ccache installation 2025-09-19 12:49:00 +01:00
jcm 907ccf6494 build: Clarify when to build genius 2025-09-19 12:49:00 +01:00
jcm c7fabe82d6 build: Remove /permissive- (unneeded under C++20) 2025-09-19 12:49:00 +01:00
jcm 9f9ff6bf09 build: disable IPO for *nix CI builds 2025-09-19 12:49:00 +01:00
jcm f60c003826 build: Don't use unsupported option in Clang-CL 2025-09-19 12:49:00 +01:00
jcm 6a30f98145 build: move generated targets to work around Visual Studio 2025-09-19 12:49:00 +01:00
Luke Usher 7855c8b469 desktop-ui: group mega ld/pc-engine ld as Pioneer LaserActive 2025-09-19 12:29:00 +01:00
Roger Sanders ee85afd30c ld: Initial working version of NEC PAC support for the LaserActive 2025-09-19 10:35:55 +01:00
Roger Sanders 09932f11d5 ld: MegaLD emulation accuracy and speed improvements 2025-09-19 10:35:55 +01:00
Luke Usher 85afab5b36 mia: fix fds loading 2025-09-18 10:13:48 +01:00
Giovanni Bajoandjcm 75ef6810e2 stdc+: switch to nall::split_and_strip and apply review suggestions
Co-authored-by: jcm <[email protected]>
2025-09-16 06:42:29 +01:00
Giovanni Bajo 66db5eb88c stdc++: discard global namespace qualifier for nall everywhere 2025-09-16 06:42:29 +01:00
Giovanni Bajo d5c3a4805b stdc++: apply review suggestions 2025-09-16 06:42:29 +01:00
Giovanni Bajo 82c777e7c2 stdc++: hiro: fix qt backend build 2025-09-16 06:42:29 +01:00
Giovanni Bajo cdbc88f92e stdc++: ruby: fix freebsd build 2025-09-16 06:42:29 +01:00
Giovanni Bajo 970a019476 stdc++: nall::string remove non-const constructors to avoid problematic uses 2025-09-16 06:42:29 +01:00
Giovanni Bajo 9c9ba5d6f4 stdc++: nall: remove string::split and vector<string>::match 2025-09-16 06:42:29 +01:00
Giovanni Bajo 86790da2ec stdc++: nall: finish migrating string split/match methods to functions 2025-09-16 06:42:29 +01:00
Giovanni Bajo 7fff423649 stdc++:: add global nall::split/match functions, migrate part of the code 2025-09-16 06:42:29 +01:00
Giovanni Bajo d258228cc0 md: avoid including dc-removal.hpp within the ares::MegaDrive namespace 2025-09-16 06:42:29 +01:00
Giovanni Bajo 9bf3ffc3ae stdc++: finish mia migration 2025-09-16 06:42:29 +01:00
Giovanni Bajo 7168f2e411 stdc++: migrate part of mia to std::vector 2025-09-16 06:42:29 +01:00
Giovanni Bajo c75ad74ce0 stdc++: desktop-ui: migrate from nall::vector to std::vector
- Replace all nall::vector declarations with std::vector in desktop-ui
- Update API calls: .append() -> .push_back(), .reset() -> .clear()
- Replace .takeFirst()/.takeLast() with .front()/.back() + .erase()/.pop_back()
- Convert .find() to std::ranges::find() and std::ranges::find_if()
- Replace .sort() with std::ranges::sort()
- Fix boolean conversions: if(!vector) -> if(vector.empty())
- Migrate all emulator-specific files and core desktop-ui components
- Use direct assignments between std::vector instead of manual loops
- Maintain compatibility with nall::split() by using auto type deduction
2025-09-16 06:42:29 +01:00
Giovanni Bajo 7ed8d6feac cmake: disable build of optional targets in ubuntu-ci-qt
genius can't build with Qt as it uses ComboEdit, but it is currently
enabled in the ubuntu-ci-qt as it inherits the base ubuntu-ci (which is
GTK-based).
2025-09-16 06:42:29 +01:00
tykkiman e2bf15a6ce recompiler: remove static_assert(false) from a template
GCC evaluated the always failing assert before the constexprs leading
to it, resulting in a compilation failure. As a workaround, we can move
the 'imm64' case inside the else block and check for the type there,
which also catches unhandled types at compile time.
2025-09-15 18:55:06 +01:00
Jay Prewitt 29139b104c n64: Use ISV read pointer as a start address 2025-09-15 18:54:17 +01:00
tykkiman 0b2a85f803 n64: use faster host function calls in the recompiler
Uses the new 'callf' function instead of 'call' in generated code. In
the n64-systemtest ROM, this change shaves off 6% and 10% of the
respective VR4300 and RSP  median block sizes:

  VR4300 block size statistics

            min   max   mean     median
   before   113   6369  893.93   573
   after    104   5937  881.17   537

  RSP block size statistics

            min   max   mean     median
   before   97   19196  3941.95  5336
   after    88   17044  3414.06  4606

Also, on a benchmark with an RSP-intensive homebrew libdragon ROM, this
change gave about 1% actual runtime speedup.
2025-09-14 21:20:30 +01:00
tykkiman a55688a95d recompiler: optimized 64-bit System V function calls
When ares switched to SLJIT, some tiny overhead was introduced in every call
from guest to host code on 64-bit Linux. This was due to the argument register
mapping differing between SLJIT's own convention and the System V AMD64 ABI.
This commit makes the recompiler put function arguments directly in the correct
registers.

This commit introduces a new 'callf' template function that accepts recompiler's
'mem' and 'imm' argument types. It abstracts away the register setup so that
different host platforms can implement their optimized function calls. This also
results in slightly shorter code in the recompiler (see the followup commit).

The SLJIT_CALL_REG_ARG type of call is actually meant for SLJIT's own, optimized
calling convention, but since it assumes function arguments are placed in
correct registers, it works here. The only other option I could think would've
been emitting x64 machine code directly.
2025-09-14 21:20:30 +01:00
Jay Prewitt f39ca5e3a7 n64: Make MI repeat mode accurate for 1 and 2 byte writes 2025-09-12 11:30:05 +01:00
jcmandStefan Schlosser 1a2aedcf00 CI: Add FreeBSD runner
Co-authored-by: Stefan Schlosser <[email protected]>
2025-09-09 17:09:21 +01:00
jcm 05e9c3a6c9 CI: Add Qt build 2025-09-09 17:09:21 +01:00
Christopher Bonhage 0d9ce81d20 Implement N64 Bio Sensor accessory 2025-09-09 14:06:34 +01:00
Christopher Bonhage eed44e0012 Support for N64 accessory commands with non-standard data lengths 2025-09-09 14:06:34 +01:00
Christopher Bonhage 93073f2700 Implement N64 accessory DETECT controller status 2025-09-09 14:06:34 +01:00
jcm 53a08c9101 build: Fix framework bundle copies under non-Xcode generators on macOS 2025-09-09 12:11:23 +01:00
jcm 6540059a28 build: Don't use -fno-char8_t when compiling C 2025-09-09 12:11:23 +01:00
jcm 48c816f2f9 desktop-ui: Properly initialize rewind state on startup 2025-09-09 12:11:07 +01:00
User 1edb30d1ea gba: improve handling of MEMCNT register 2025-09-08 14:34:10 +01:00
Jay Prewitt 797c798787 n64: Implement basic MI repeat mode
A simple implementation that is only accurate for 4-byte or 8-byte
aligned writes. Smaller accesses will require a full implementation of
write masking to be accurate.
2025-09-08 14:33:59 +01:00
Giovanni Bajo 2c3341dfdf stdc++: finish migrating ares 2025-09-08 14:32:44 +01:00
Giovanni Bajo 31357eb4e5 stdc++: bulk migration of ares 2025-09-08 14:32:44 +01:00
Giovanni Bajo 3401322e6e stdc++: migrate node and debuggers 2025-09-08 14:32:44 +01:00
Giovanni Bajo 50ed2ba9bc stdc++: replace vector<string>.merge macros with nall::merge; keep nall::vector path ops; add initializer_list overload 2025-09-08 14:32:44 +01:00
Giovanni Bajo ff8bdbcdc6 stdc++: add vector-helpers merge/split; migrate includes; use merge() in N64 disassemblers; std::vector<string> split 2025-09-08 14:32:44 +01:00
Giovanni Bajo 935802da1a stdc++: migrate enumerate() to std::vector<string> 2025-09-08 14:32:44 +01:00
Roger Sanders 1dffa3d974 nall: Fix linux-only compilation issue with owning string_view removal 2025-09-05 06:47:30 +01:00
Roger Sanders 78144f5fab nall: fixed remaining string_view conversion cases from release builds 2025-09-05 06:47:30 +01:00
Roger Sanders 47aa5dc1df nall: string_view missing change fix no2 2025-09-05 06:47:30 +01:00
Roger Sanders bf7a1a205c nall: Fixed a missing change 2025-09-05 06:47:30 +01:00
Roger Sanders 96bd51471d nall: remove memory ownership from string_view again 2025-09-05 06:47:30 +01:00
Giovanni Bajo bbd9fcca0c hiro: fix undefined behavior converting negative coordinates to u32
ubsan on Mac caught an issue in this method: all geometry coordinates
are floats out and into Cocoa, but intermediate calculations were
being performed with u32 that caused undefined behavior when negative
numbers were involved.
2025-09-04 11:10:42 +01:00
Giovanni Bajo f263e89f06 nall: remove unused modules 2025-09-03 19:48:57 +01:00
User 698ea74132 gba: fix remaining C++20 deprecation warnings 2025-09-02 22:04:44 +01:00
Giovanni Bajo 766fc1ece2 stdc++: remove all instances of if statements with initializers 2025-09-02 22:04:32 +01:00
Giovanni Bajo 247dd180ce stdc++: fixes from review 2025-09-02 22:04:32 +01:00
Giovanni Bajo 23ed3de93c stdc++: hiro: revert changes to clear of subwidgets that were broken 2025-09-02 22:04:32 +01:00
Giovanni Bajo c0791baa3d stdc++: simplify some code via std::erase 2025-09-02 22:04:32 +01:00
Giovanni Bajo 9ad89d134e stdc++: use range syntax in more places 2025-09-02 22:04:32 +01:00
Giovanni Bajo 84ce0e3d9f stdc++: convert all sorts and reverse loops to ranges 2025-09-02 22:04:32 +01:00
Giovanni Bajo 92fe0d2e44 stdc++: Introduce range-helpers and nall::index_of. 2025-09-02 22:04:32 +01:00
Giovanni Bajo 864ca3d91e stdc++: C++20 compactness pass (branch-local):
- Use std::erase and ranges::find where shorter.
- Replace ranges::distance with iterator subtraction.
- Enable <ranges> in hiro core/extension; use views::reverse for reverse-destruction loops.
- Minor cleanups (array_view ctor from vector, build fixes).
2025-09-02 22:04:32 +01:00
Giovanni Bajo 8729c5f591 stdc++: array_view: remove redundant explicit constructions where implicit std::vector conversion works (Pak append callers, vfs cdrom, emulator firmware, BWT/LZSA). Keep explicit array_view only when required for string construction or subspan. 2025-09-02 22:04:32 +01:00
Giovanni Bajo 89be74aab5 stdc++: Apply changes from review 2025-09-02 22:04:32 +01:00
Giovanni Bajo 24c5e367cc stdc++: Fix CI: map remaining vector-only APIs to std::vector equivalents: gtk keyboard keycodes push_back; windows menu-bar use erase/push_back and clear; WASAPI/XAudio2/WaveOut: use std algorithms and front()/empty() instead of vector truthiness/first/find; compute indices explicitly. 2025-09-02 22:04:32 +01:00
Giovanni Bajo 5004ca4a33 stdc++: hiro gtk/qt: migrate remaining nall::vector usages to std::vector; map append/remove/reset; update keyboard polling and settings containers; fix window lists to use std::vector ops. 2025-09-02 22:04:32 +01:00
Giovanni Bajo 799d0ce726 stdc++: tests: minimal changes to make tests building 2025-09-02 22:04:32 +01:00
Giovanni Bajo 47348d9002 stdc++: hiro/windows: replace nall::vector with std::vector; map append/remove/reset; fix utilities/keyboards/timer APIs; guard DropPaths and pixel buffers accordingly. 2025-09-02 22:04:32 +01:00
Giovanni Bajo 3eeecf1cc2 stdc++: Fix CI: std::vector<bool> copy; BrowserDialog truthiness; replace remaining .append/remove/reset in joypad/combo/icon-view; GTK TabFrame tabs as std::vector; ALSA/OSS device selection via std algorithms; fix reverse iteration and setSelected signature. 2025-09-02 22:04:32 +01:00
Giovanni Bajo 31380a1976 stdc++: ruby: migrate nall::vector to std::vector; mechanical API alignment
- Replace nall::vector with std::vector across ruby (audio/input) and hiro glue; update overrides to std::vector.

- Map vector APIs: append/reset/remove/truthiness -> push_back/clear/erase/empty(); adjust DropPaths guards and BrowserDialog callers.

- Fix Windows/GTK fallout: DropPaths checks and Windows TableView indexing; Keyboard::poll returns std::vector<bool>.

- Source-only commit; excludes build outputs and submodules.
2025-09-02 22:04:32 +01:00
Giovanni Bajo 6974764393 stdc++: std::vector alignment across nall/ruby/hiro; remove nall::vector-only APIs
- nall/directory (Windows): return std::vector<string>; replace list.append with push_back; convert drive split to std::vector
- ruby audio/video/input: make virtual overrides return std::vector; replace .append with .push_back; poll() now uses std::vector for device lists
- hiro utilities (cocoa/gtk/qt/windows): DropPaths now returns std::vector<string>; replace .append with .push_back; guard empty paths on GTK
- hiro widgets: tab-frame reordering uses erase/insert instead of take(); console history uses std::vector ops; table-view selection uses std::vector<u32>
- string: add stringify<std::vector<string>> for toolchains that instantiate it indirectly

No semantic changes intended; local build verified with ninja.
2025-09-02 22:04:32 +01:00
Giovanni Bajo 0e73ba0cc1 stdc++: nall: std::vector compatibility across toolchains
- array-view/span: include <vector> so std::vector constructors are visible on stricter compilers
- directory (Windows): make ufolders/ufiles return std::vector<string>; update locals accordingly to match headers

Build verified locally with ninja.
2025-09-02 22:04:32 +01:00
Giovanni Bajo 5bb5a70b0c stdc++: std::vector migration and interop cleanup across mia/desktop-ui
- Add Pak::append(std::vector<u8>&, string) overload to accept std::vector without wrappers
- Convert remaining callers to pass std::vector directly; remove redundant array_view wrappers
- Replace nall::vector truthiness/foreach assumptions with std::vector equivalents (!empty(), range-for)
- Use std::vector APIs consistently (push_back; insert with begin()/end() when merging)
- Align medium analyze signatures/callers to std::vector where required; no semantic changes intended
- Keep explicit array_view only for subspans (pointer+length) where necessary

Build verified with ninja.
2025-09-02 22:04:32 +01:00
Giovanni Bajo 2830ab92f7 stdc++: nall: remove most uses of nall::vector from the library and adapt callers
- directory, zip, mmi, cue: switch public APIs to std::vector; fix sort/find/append
- vfs/cdrom: use std::vector buffers and wrap into array_view when needed
- hid: replace inheritance from nall::vector with std::vector-backed fields
- instruction-set: use std::vector for cpuid data blocks
- windows/registry: contents() returns std::vector<string>
- set: iterator internals use std::vector stack
- tcptext socket/server: move buffers and onData() to std::vector<u8>
- remove umbrella includes of <nall/vector.hpp>

Callers fixed accordingly (ares/mcd, mia, desktop-ui).
2025-09-02 22:04:32 +01:00
Giovanni Bajo 2eb0e677a8 stdc++: Migrate project off nall::vector (outside nall) to std::vector
Scope
- Replace nall::vector with std::vector across hiro, ruby, and desktop-ui.
- Remove external includes of <nall/vector.hpp>; keep nall/ self-includes unchanged.

API adaptations
- append/prepend -> push_back/insert(begin,...).
- remove/removeLeft/removeRight -> erase/erase(begin)/erase(end-1) as appropriate.
- take*/first/last/left/right -> front()/back() or index-based access.
- contains/find/findSorted/foreach -> std::find, std algorithms, or range loops.
- reverse(...) iterations -> rbegin()/rend() or explicit reverse-iterator loops.
- vector truthiness -> use empty()/size() checks.

Subsystem-specific changes
- Ares node registry: use std::vector for class lists and child nodes; replace find/append/remove usage.
- Debug facility: store notices in std::vector; dedup via std::find.
- Hiro widgets/layouts: convert container state to std::vector; update signatures (e.g., onDrop/doDrop to std::vector<string>);
  fix batch/selection helpers to build std::vector results; update menu/popup/combo/table/tree widgets accordingly.
- Cocoa/GTK integrations: adjust DropPaths usage and emptiness checks.
- Ruby backends (audio/video/input): change capability lists and device enumerations to std::vector; replace .first() with front()
  and .append() with push_back; fix OpenAL/SDL/driver helpers.
- Desktop UI: Program::screens/streams now std::vector; platform attach/detach uses erase+remove; message queue uses std::vector
  push_back + pop-front pattern; Presentation drop handler accepts std::vector<string>.
- Message/Browser dialogs: std::vector for button/options/filters; remove truthiness; use back()/empty().

Build
- Verified clean build for desktop-ui, hiro, and ruby after changes (ninja).

Notes
- Conservative migration: no changes inside nall/ itself (still ships its own vector for internal use).
- Follow-up work can progressively replace remaining nall containers/APIs as needed.
2025-09-02 22:04:32 +01:00
John Chadwick a5f5eccdbe hiro/qt: Add Qt 6 support
Basic functionality is tested and working great. Obviously, things do
not work in Wayland yet.
2025-09-01 20:33:41 +01:00
John Chadwick 82ff8dbf6b hiro/qt: QLayout::setMargin -> QLayout::setContentsMargins
setMargin has been obsolete since Qt 4.3!
2025-09-01 20:33:41 +01:00
John Chadwick c9d8fc525c hiro/qt: Use QScreen for Monitor
Qt 5 introduces QScreen, which can be used to implement most of the
functionality needed by Monitor, although some of it probably won't make
sense when using Wayland.
2025-09-01 20:33:41 +01:00
John Chadwick 3854a4561d hiro/qt: Remove pendingEvents, add timeout to processEvents
Qt 6 no longer allows us to poll for the status of the event loop.
However, Qt 6 does still have a processEvents function, and the version
with the timeout actually spins the event loop and returns as early as
there are no more events in it. That's basically what we want to do. We
could run this with a really huge timeout, but that would just make it
more likely that hiro freezes up, so instead let's mirror hiro/gtk3 and
use a 50ms timeout.
2025-09-01 20:33:41 +01:00
John Chadwick cf4afeb7f0 hiro/core: Remove Application::pendingEvents
This does not seem to be used anywhere in bsnes, higan or ares. It's not
really possible to implement with Qt 6, which has stop exposing this
detail of the event loop. It turns out this is actually OK, since we
don't *really* need it anyway, and in the case of hiro/qt, the
replacement should be more robust anyways.
2025-09-01 20:33:41 +01:00
John Chadwick 755e15c3e1 Use QScreen for Desktop::{size,workspace}
Qt 5.0 adds the QScreen API, which exposes enough information that
Desktop::{size,workspace} no longer needs to fall back to Win32/Xlib. I
manually tested that this seems to give the same exact answers as the
Xlib path (though it technically goes a different route for
Desktop::size.)
2025-09-01 15:51:27 +01:00
John Chadwick 7f0d020466 Remove Qt 4 support.
Qt 4.8 LTS was released on December 15th, 2011. It hit its official
end-of-life on December 31st, 2015. It has been dead for nearly 10
years. Qt 4 is now so old, that it has been removed from Debian long
enough that "qt4" doesn't show up in *any* of the indexed package suites
in Debian's online package search service.

The CMake build of ares never supported Qt 4 in the first place, so this
code should all be dead anyway.
2025-09-01 15:47:36 +01:00
User 5a2be88f41 gba: fix some warnings from C++20 deprecating bitwise operations between different enums 2025-08-31 11:42:24 +01:00
jcm be570117bb CI: overwrite built-in pinned CMake installation 2025-08-30 16:31:42 +01:00
User 640fe5722c gba: handle cartridge access sizes via CPU bus 2025-08-30 15:35:57 +01:00
jcm dff1ad01a6 build: Disable C++20 module scanning 2025-08-29 23:58:11 +01:00
jcm e7a00354dc build: Add -fno-char8_t and /Zc:char8_t- 2025-08-29 16:14:23 +01:00
jcm f042f7a51a build: Compile in C++20 mode 2025-08-29 16:14:23 +01:00
jcm 4d92a5b433 Do not rely on implicit capture of this in lambdas 2025-08-29 16:14:23 +01:00
User 4aed87bf45 fc: bit 5 of $4015 reads open bus 2025-08-29 13:58:01 +01:00
User a5e76e2e4e mos6502: fix JSR memory transactions 2025-08-29 13:58:01 +01:00
User c7277c964e mos6502: general cleanup 2025-08-29 13:58:01 +01:00
jcm 846b622c80 build: Run gersemi formatting pass 2025-08-29 13:57:23 +01:00
jcm abcdff3e60 build: Fix list/string conversion in component list 2025-08-29 13:57:23 +01:00
jcm 4fcfe3a485 build: Clean up miscellaneous target locations 2025-08-29 13:57:23 +01:00
jcm 76b0204d91 build: Clean up link relationships
mame2bml: Fix linking

mia-ui: Fix linking

dekstop-ui: Fix linking
2025-08-29 13:57:23 +01:00
jcm cac6f0534a Update CMake policy version 2025-08-29 13:57:23 +01:00
jcm f66bb568df build: Match libco source organization with other targets 2025-08-29 13:57:23 +01:00
jcm cc4556824e build: Update .gersemirc for newer gersemi version 2025-08-29 13:57:23 +01:00
jcm c6f7efb797 build: Remove/fix up various unused/extraneous build code 2025-08-29 13:57:23 +01:00
jcm 6a2fcb21dc hiro: Make backend definition public 2025-08-29 13:57:23 +01:00
jcm 2b347c65de build: Track project meta files in IDEs 2025-08-29 13:57:23 +01:00
jcm f1823630be build: Update dependencies
deps.windows: Update SDL to 3.2.20
Update slang-shaders to ref `c9303dc`
deps.macos: Update SDL to 3.2.20
deps.macos: Update MoltenVK to 1.4.0
2025-08-29 13:57:13 +01:00
972 changed files with 12309 additions and 10542 deletions

No files matched your search

-3
View File
@@ -1,11 +1,8 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/master/gersemi/configuration.schema.json
color: false
definitions: [ares/CMakeLists.txt]
line_length: 120
indent: 2
list_expansion: favour-inlining
quiet: false
unsafe: false
warn_about_unknown_commands: false
workers: 10
+31
View File
@@ -0,0 +1,31 @@
# dummy GitHub target used to enable editing of GitHub files within generated IDE projects
add_library(.github INTERFACE)
set(.github_sources
ISSUE_TEMPLATE/bug_report.md
ISSUE_TEMPLATE/feature_request.md
ISSUE_TEMPLATE/game-issue-report.md
scripts/build_macos.sh
scripts/build_ubuntu.sh
scripts/build_windows.sh
scripts/package_artifacts.sh
workflows/build-aux.yml
workflows/build.yml
workflows/pr.yml
workflows/push.yml
workflows/release.yml
)
target_sources(
.github
PRIVATE
${.github_sources}
../.gitignore
../.gitattributes
../README.md
../LICENSE
)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${.github_sources})
+23 -3
View File
@@ -56,6 +56,14 @@ jobs:
os: ubuntu-24.04-arm
shell: bash
target-cmake-preset: ubuntu-ci-clang
- name: ubuntu-gcc-arm64-qt
os: ubuntu-24.04-arm
shell: bash
target-cmake-preset: ubuntu-ci-qt
- name: freebsd
os: ubuntu-24.04
shell: bash
target-cmake-preset: ubuntu-ci-clang
name: ${{ matrix.program }}-${{ matrix.platform.name }}
runs-on: ${{ matrix.platform.os }}
defaults:
@@ -78,12 +86,12 @@ jobs:
run: |
git config core.autocrlf true
- name: Install Linux Dependencies
if: runner.os == 'Linux'
if: runner.os == 'Linux' && matrix.platform.name != 'freebsd'
run: |
sudo apt-get update -y -qq
sudo apt-get install cmake ccache ninja-build libsdl2-dev libgtk-3-dev libao-dev libopenal-dev
sudo apt-get install cmake ccache ninja-build libsdl2-dev libgtk-3-dev libao-dev libopenal-dev qt6-base-dev
- name: "Build: Linux"
if: runner.os == 'Linux'
if: runner.os == 'Linux' && matrix.platform.name != 'freebsd'
run: .github/scripts/build_ubuntu.sh
env:
TARGET_PRESET: ${{ matrix.platform.target-cmake-preset }}
@@ -95,6 +103,18 @@ jobs:
CROSS_COMPILE: ${{ matrix.platform.native-cmake-preset != '' }}
NATIVE_PRESET: ${{ matrix.platform.native-cmake-preset }}
TARGET_PRESET: ${{ matrix.platform.target-cmake-preset }}
- name: "Build: FreeBSD"
if: matrix.platform.name == 'freebsd'
uses: cross-platform-actions/action@e8a7b572196ff79ded1979dc2bb9ee67d1ddb252
env:
TARGET_PRESET: ${{ matrix.platform.target-cmake-preset }}
with:
operating_system: freebsd
version: 14.3
environment_variables: TARGET_PRESET
run: |
sudo pkg install -y cmake pkgconf ccache ninja gtk3 libX11 libXext libXrandr libXrender libglvnd alsa-lib libao libudev-devd librashader openal-soft pulseaudio sdl3 vulkan-loader
.github/scripts/build_ubuntu.sh
- name: "Compress Build Artifacts (Windows)"
if: runner.os != 'macOS' && runner.os != 'Linux'
run: |
+1
View File
@@ -77,6 +77,7 @@ jobs:
- name: Install macOS Dependencies
if: runner.os == 'macOS'
run: |
brew uninstall --ignore-dependencies cmake
brew install ${{ matrix.platform.install }}
- name: "Build: Windows"
if: runner.os != 'macOS' && runner.os != 'Linux'
+6 -5
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.28...4.0)
cmake_minimum_required(VERSION 3.28...4.1)
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/common/bootstrap.cmake" NO_POLICY_SCOPE)
@@ -8,8 +8,6 @@ include(compilerconfig)
include(defaults)
include(helpers)
add_subdirectory(cmake)
add_subdirectory(thirdparty)
add_subdirectory(nall/nall)
@@ -21,7 +19,7 @@ add_subdirectory(hiro)
set(
ARES_CORES
a26 fc sfc sg ms md ps1 pce ng msx cv myvision gb gba ws ngp spec n64
CACHE STRING LIST
CACHE STRING "List of systems to be built by the project"
)
# gersemi: on
@@ -35,7 +33,7 @@ if(ARES_BUILD_OPTIONAL_TARGETS)
add_subdirectory(tests/arm7tdmi)
add_subdirectory(tests/i8080)
add_subdirectory(tests/m68000)
if(NOT OS_WINDOWS AND NOT OS_MACOS)
if(HIRO_BACKEND STREQUAL "GTK3")
add_subdirectory(tools/genius)
else()
target_disable_subproject(genius "genius (database editor)")
@@ -52,4 +50,7 @@ endif()
add_subdirectory(tools/sourcery)
message_configuration()
add_subdirectory(.github)
add_subdirectory(cmake)
return()
+14 -2
View File
@@ -82,7 +82,7 @@
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_OSX_ARCHITECTURES": {"type": "STRING", "value": "x86_64;arm64"},
"CMAKE_OSX_DEPLOYMENT_TARGET": {"type": "STRING", "value": "10.15"},
"CMAKE_OSX_DEPLOYMENT_TARGET": {"type": "STRING", "value": "11.0"},
"ARES_CODESIGN_IDENTITY": {"type": "STRING", "value": "$penv{MACOS_CERTIFICATE_NAME}"},
"ARES_CODESIGN_TEAM": {"type": "STRING", "value": "$penv{MACOS_NOTARIZATION_TEAMID}"},
"ENABLE_CCACHE": true,
@@ -103,7 +103,8 @@
"ARES_BUILD_OPTIONAL_TARGETS": true,
"ARES_UNITY_CORES": true,
"ARES_PRECOMPILE_HEADERS": true,
"CMAKE_MSVC_RUNTIME_LIBRARY": {"type": "STRING", "value": "MultiThreaded"}
"CMAKE_MSVC_RUNTIME_LIBRARY": {"type": "STRING", "value": "MultiThreaded"},
"CMAKE_IGNORE_PATH": {"type": "STRING", "value": "C:/Strawberry/c/bin/"}
}
},
{
@@ -160,6 +161,7 @@
"cacheVariables": {
"CMAKE_BUILD_TYPE": {"type": "STRING", "value": "RelWithDebInfo"},
"ENABLE_CCACHE": true,
"ENABLE_IPO": false,
"ARES_BUILD_LOCAL": false,
"ARES_BUILD_OPTIONAL_TARGETS": true,
"ARES_PRECOMPILE_HEADERS": false
@@ -174,6 +176,16 @@
"CMAKE_C_COMPILER": "clang",
"CMAKE_CXX_COMPILER": "clang++"
}
},
{
"name": "ubuntu-ci-qt",
"displayName": "Ubuntu CI (arm64, gcc, Qt)",
"description": "Single-arch binary for building on Github Actions",
"inherits": ["ubuntu-ci"],
"cacheVariables": {
"USE_QT6": true,
"ARES_BUILD_OPTIONAL_TARGETS": false
}
}
],
"buildPresets": [
+1 -1
View File
@@ -21,7 +21,7 @@ if(ARES_PRECOMPILE_HEADERS)
target_precompile_headers(ares PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:ares/ares.hpp>")
endif()
target_link_libraries(ares PUBLIC libco sljit nall)
target_link_libraries(ares PRIVATE libco ares::nall::headers $<$<BOOL:${ARES_ENABLE_CHD}>:chdr-static> PUBLIC sljit)
if(ARES_PROFILE_ACCURACY)
target_compile_definitions(ares PUBLIC PROFILE_ACCURACY)
+2 -1
View File
@@ -1,12 +1,13 @@
#pragma once
#include <ares/ares.hpp>
#include <vector>
#include <component/processor/mos6502/mos6502.hpp>
namespace ares::Atari2600 {
#include <ares/inline.hpp>
auto enumerate() -> vector<string>;
auto enumerate() -> std::vector<string>;
auto load(Node::System& node, string name) -> bool;
struct Region {
+8 -8
View File
@@ -19,15 +19,15 @@ auto Cartridge::connect() -> void {
information.region = pak->attribute("region");
information.board = pak->attribute("board");
if(information.board == "Linear") board = new Board::Linear{*this};
if(information.board == "Atari8k") board = new Board::Atari8k{*this};
if(information.board == "Atari16k") board = new Board::Atari16k{*this};
if(information.board == "Atari32k") board = new Board::Atari32k{*this};
if(information.board == "Commavid") board = new Board::Commavid{*this};
if(information.board == "ParkerBros8k") board = new Board::ParkerBros{*this};
if(information.board == "Tigervision") board = new Board::Tigervision{*this};
if(information.board == "Linear") board = std::make_unique<Board::Linear>(*this);
if(information.board == "Atari8k") board = std::make_unique<Board::Atari8k>(*this);
if(information.board == "Atari16k") board = std::make_unique<Board::Atari16k>(*this);
if(information.board == "Atari32k") board = std::make_unique<Board::Atari32k>(*this);
if(information.board == "Commavid") board = std::make_unique<Board::Commavid>(*this);
if(information.board == "ParkerBros8k") board = std::make_unique<Board::ParkerBros>(*this);
if(information.board == "Tigervision") board = std::make_unique<Board::Tigervision>(*this);
if(!board) board = new Board::Interface{*this};
if(!board) board = std::make_unique<Board::Interface>(*this);
board->pak = pak;
board->load();
power();
+1 -1
View File
@@ -22,7 +22,7 @@ struct Cartridge {
//serialization.cpp
auto serialize(serializer&) -> void;
unique_pointer<Board::Interface> board;
std::unique_ptr<Board::Interface> board;
//private:
struct Information {
+1 -1
View File
@@ -20,7 +20,7 @@ auto ControllerPort::unload() -> void {
}
auto ControllerPort::allocate(string name) -> Node::Peripheral {
if(name == "Gamepad") device = new Gamepad(port);
if(name == "Gamepad") device = std::make_unique<Gamepad>(port);
if(device) return device->node;
return {};
}
+1 -1
View File
@@ -1,6 +1,6 @@
struct ControllerPort {
Node::Port port;
unique_pointer<Controller> device;
std::unique_ptr<Controller> device;
//port.cpp
ControllerPort(string name);
+1 -1
View File
@@ -32,7 +32,7 @@ auto CPU::step(u32 clocks) -> void {
auto CPU::power(bool reset) -> void {
MOS6502::BCD = 1;
MOS6502::power();
Thread::create(system.frequency() / 3, {&CPU::main, this});
Thread::create(system.frequency() / 3, std::bind_front(&CPU::main, this));
io = {};
}
+1 -1
View File
@@ -33,7 +33,7 @@ auto RIOT::step(u32 clocks) -> void {
}
auto RIOT::power(bool reset) -> void {
Thread::create(system.frequency() / 3, {&RIOT::main, this});
Thread::create(system.frequency() / 3, std::bind_front(&RIOT::main, this));
timer = {};
port[0] = {};
port[0].data = 0xff;
+12 -10
View File
@@ -1,8 +1,9 @@
#include <a26/a26.hpp>
#include <algorithm>
namespace ares::Atari2600 {
auto enumerate() -> vector<string> {
auto enumerate() -> std::vector<string> {
return {
"[Atari] Atari 2600 (NTSC)",
"[Atari] Atari 2600 (PAL)",
@@ -11,7 +12,8 @@ auto enumerate() -> vector<string> {
}
auto load(Node::System& node, string name) -> bool {
if(!enumerate().find(name)) return false;
auto list = enumerate();
if(std::find(list.begin(), list.end(), name) == list.end()) return false;
return system.load(node, name);
}
@@ -53,15 +55,15 @@ auto System::load(Node::System& root, string name) -> bool {
information.frequency = 3546894;
}
node = Node::System::create(information.name);
node = std::make_shared<Core::System>(information.name);
node->setAttribute("configuration", name);
node->setGame({&System::game, this});
node->setRun({&System::run, this});
node->setPower({&System::power, this});
node->setSave({&System::save, this});
node->setUnload({&System::unload, this});
node->setSerialize({&System::serialize, this});
node->setUnserialize({&System::unserialize, this});
node->setGame(std::bind_front(&System::game, this));
node->setRun(std::bind_front(&System::run, this));
node->setPower(std::bind_front(&System::power, this));
node->setSave(std::bind_front(&System::save, this));
node->setUnload(std::bind_front(&System::unload, this));
node->setSerialize([this](bool s){ return this->serialize(s); });
node->setUnserialize([this](serializer& s){ return this->unserialize(s); });
root = node;
scheduler.reset();
+2 -2
View File
@@ -18,7 +18,7 @@ auto TIA::load(Node::Object parent) -> void {
node = parent->append<Node::Object>("TIA");
screen = node->append<Node::Video::Screen>("Screen", 180, displayHeight());
screen->colors(1 << 7, {&TIA::color, this});
screen->colors(1 << 7, std::bind_front(&TIA::color, this));
screen->setSize(180, displayHeight());
screen->setScale(2.0, 1.0);
Region::PAL() ? screen->setAspect(38.0, 45.0) : screen->setAspect(4.0, 5.0);
@@ -123,7 +123,7 @@ auto TIA::step(u32 clocks) -> void {
}
auto TIA::power(bool reset) -> void {
Thread::create(system.frequency(), {&TIA::main, this});
Thread::create(system.frequency(), std::bind_front(&TIA::main, this));
screen->power();
io = {};
playfield = {};
+8 -5
View File
@@ -3,6 +3,10 @@
#include <libco/libco.h>
#include <sljit.h>
#include <vector>
#include <ranges>
#include <algorithm>
#include <nall/platform.hpp>
#include <nall/adaptive-array.hpp>
#include <nall/any.hpp>
@@ -22,14 +26,13 @@
#include <nall/random.hpp>
#include <nall/serializer.hpp>
#include <nall/set.hpp>
#include <nall/shared-pointer.hpp>
#include <nall/span-helpers.hpp>
#include <nall/string.hpp>
#include <nall/terminal.hpp>
#include <nall/thread.hpp>
#include <nall/traits.hpp>
#include <nall/unique-pointer.hpp>
#include <memory>
#include <nall/variant.hpp>
#include <nall/vector.hpp>
#include <nall/vfs.hpp>
#include <nall/cd.hpp>
#include <nall/dsp/iir/one-pole.hpp>
@@ -51,8 +54,8 @@ namespace ares {
extern const u32 SerializerSignature;
namespace VFS {
using Pak = shared_pointer<vfs::directory>;
using File = shared_pointer<vfs::file>;
using Pak = std::shared_ptr<vfs::directory>;
using File = std::shared_ptr<vfs::file>;
}
namespace Video {
+12 -12
View File
@@ -4,40 +4,40 @@ Debug _debug;
auto Debug::reset() -> void {
_totalNotices = 0;
_unhandledNotices.reset();
_unimplementedNotices.reset();
_unusualNotices.reset();
_unverifiedNotices.reset();
_unhandledNotices.clear();
_unimplementedNotices.clear();
_unusualNotices.clear();
_unverifiedNotices.clear();
}
auto Debug::_unhandled(const string& text) -> void {
if(_unhandledNotices.find(text)) return;
if(std::ranges::find(_unhandledNotices, text) != _unhandledNotices.end()) return;
if(_totalNotices++ > 256) return;
_unhandledNotices.append(text);
_unhandledNotices.push_back(text);
print(terminal::color::yellow("[unhandled] "), text, "\n");
}
auto Debug::_unimplemented(const string& text) -> void {
if(_unimplementedNotices.find(text)) return;
if(std::ranges::find(_unimplementedNotices, text) != _unimplementedNotices.end()) return;
if(_totalNotices++ > 256) return;
_unimplementedNotices.append(text);
_unimplementedNotices.push_back(text);
print(terminal::color::magenta("[unimplemented] "), text, "\n");
}
auto Debug::_unusual(const string& text) -> void {
if(_unusualNotices.find(text)) return;
if(std::ranges::find(_unusualNotices, text) != _unusualNotices.end()) return;
if(_totalNotices++ > 256) return;
_unusualNotices.append(text);
_unusualNotices.push_back(text);
print(terminal::color::cyan("[unusual] "), text, "\n");
}
auto Debug::_unverified(const string& text) -> void {
if(_unverifiedNotices.find(text)) return;
if(std::ranges::find(_unverifiedNotices, text) != _unverifiedNotices.end()) return;
if(_totalNotices++ > 256) return;
_unverifiedNotices.append(text);
_unverifiedNotices.push_back(text);
print(terminal::color::gray("[unverified] "), text, "\n");
}
+4 -4
View File
@@ -26,10 +26,10 @@ private:
auto _unverified(const string&) -> void;
u64 _totalNotices = 0;
vector<string> _unhandledNotices;
vector<string> _unimplementedNotices;
vector<string> _unusualNotices;
vector<string> _unverifiedNotices;
std::vector<string> _unhandledNotices;
std::vector<string> _unimplementedNotices;
std::vector<string> _unusualNotices;
std::vector<string> _unverifiedNotices;
};
extern Debug _debug;
+3 -2
View File
@@ -1,6 +1,7 @@
#pragma once
#include <ares/memory/memory.hpp>
#include <span>
namespace ares::Memory {
@@ -32,7 +33,7 @@ struct Readable {
auto load(VFS::File fp) -> void {
if(!self.size) allocate(fp->size());
fp->read({self.data, min(fp->size(), self.size * sizeof(T))});
fp->read({(u8*)self.data, min(fp->size(), self.size * sizeof(T))});
for(u32 address = self.size; address <= self.mask; address++) {
self.data[address] = self.data[mirror(address, self.size)];
}
@@ -59,7 +60,7 @@ struct Readable {
auto end() const -> const T* { return &self.data[self.size]; }
auto serialize(serializer& s) -> void {
s(array_span<T>{self.data, self.size});
s(std::span<T>{self.data, self.size});
}
//private:
+4 -3
View File
@@ -1,6 +1,7 @@
#pragma once
#include <ares/memory/memory.hpp>
#include <span>
namespace ares::Memory {
@@ -32,14 +33,14 @@ struct Writable {
auto load(VFS::File fp) -> void {
if(!self.size) allocate(fp->size());
fp->read({self.data, min(fp->size(), self.size * sizeof(T))});
fp->read({(u8*)self.data, min(fp->size(), self.size * sizeof(T))});
for(u32 address = self.size; address <= self.mask; address++) {
self.data[address] = self.data[mirror(address, self.size)];
}
}
auto save(VFS::File fp) -> void {
fp->write({self.data, min(fp->size(), self.size * sizeof(T))});
fp->write({(const u8*)self.data, min(fp->size(), self.size * sizeof(T))});
}
explicit operator bool() const { return (bool)self.data; }
@@ -61,7 +62,7 @@ struct Writable {
auto end() const -> const T* { return &self.data[self.size]; }
auto serialize(serializer& s) -> void {
s(array_span<T>{self.data, self.size});
s(std::span<T>{self.data, self.size});
}
private:
+12 -12
View File
@@ -1,5 +1,5 @@
auto Stream::setChannels(u32 channels) -> void {
_channels.reset();
_channels.clear();
_channels.resize(channels);
}
@@ -12,7 +12,7 @@ auto Stream::setResamplerFrequency(f64 resamplerFrequency) -> void {
_resamplerFrequency = resamplerFrequency;
for(auto& channel : _channels) {
channel.nyquist.reset();
channel.nyquist.clear();
channel.resampler.reset(_frequency, _resamplerFrequency);
}
@@ -25,7 +25,7 @@ auto Stream::setResamplerFrequency(f64 resamplerFrequency) -> void {
DSP::IIR::Biquad filter;
f64 q = DSP::IIR::Biquad::butterworth(passes * 2, pass);
filter.reset(DSP::IIR::Biquad::Type::LowPass, cutoffFrequency, _frequency, q);
channel.nyquist.append(filter);
channel.nyquist.push_back(filter);
}
}
}
@@ -37,7 +37,7 @@ auto Stream::setMuted(bool muted) -> void {
auto Stream::resetFilters() -> void {
for(auto& channel : _channels) {
channel.filters.reset();
channel.filters.clear();
}
}
@@ -47,13 +47,13 @@ auto Stream::addLowPassFilter(f64 cutoffFrequency, u32 order, u32 passes) -> voi
if(order == 1) {
Filter filter{Filter::Mode::OnePole, Filter::Type::LowPass, Filter::Order::First};
filter.onePole.reset(DSP::IIR::OnePole::Type::LowPass, cutoffFrequency, _frequency);
channel.filters.append(filter);
channel.filters.push_back(filter);
}
if(order == 2) {
Filter filter{Filter::Mode::Biquad, Filter::Type::LowPass, Filter::Order::Second};
f64 q = DSP::IIR::Biquad::butterworth(passes * 2, pass);
filter.biquad.reset(DSP::IIR::Biquad::Type::LowPass, cutoffFrequency, _frequency, q);
channel.filters.append(filter);
channel.filters.push_back(filter);
}
}
}
@@ -65,13 +65,13 @@ auto Stream::addHighPassFilter(f64 cutoffFrequency, u32 order, u32 passes) -> vo
if(order == 1) {
Filter filter{Filter::Mode::OnePole, Filter::Type::HighPass, Filter::Order::First};
filter.onePole.reset(DSP::IIR::OnePole::Type::HighPass, cutoffFrequency, _frequency);
channel.filters.append(filter);
channel.filters.push_back(filter);
}
if(order == 2) {
Filter filter{Filter::Mode::Biquad, Filter::Type::HighPass, Filter::Order::Second};
f64 q = DSP::IIR::Biquad::butterworth(passes * 2, pass);
filter.biquad.reset(DSP::IIR::Biquad::Type::HighPass, cutoffFrequency, _frequency, q);
channel.filters.append(filter);
channel.filters.push_back(filter);
}
}
}
@@ -83,7 +83,7 @@ auto Stream::addLowShelfFilter(f64 cutoffFrequency, u32 order, f64 gain, f64 slo
Filter filter{Filter::Mode::Biquad, Filter::Type::LowShelf, Filter::Order::Second};
f64 q = DSP::IIR::Biquad::shelf(gain, slope);
filter.biquad.reset(DSP::IIR::Biquad::Type::LowShelf, cutoffFrequency, _frequency, q);
channel.filters.append(filter);
channel.filters.push_back(filter);
}
}
}
@@ -94,13 +94,13 @@ auto Stream::addHighShelfFilter(f64 cutoffFrequency, u32 order, f64 gain, f64 sl
Filter filter{Filter::Mode::Biquad, Filter::Type::HighShelf, Filter::Order::Second};
f64 q = DSP::IIR::Biquad::shelf(gain, slope);
filter.biquad.reset(DSP::IIR::Biquad::Type::HighShelf, cutoffFrequency, _frequency, q);
channel.filters.append(filter);
channel.filters.push_back(filter);
}
}
}
auto Stream::pending() const -> bool {
return _channels && _channels[0].resampler.pending();
return !_channels.empty() && _channels[0].resampler.pending();
}
auto Stream::read(f64 samples[]) -> u32 {
@@ -127,5 +127,5 @@ auto Stream::write(const f64 samples[]) -> void {
//if there are samples pending, then alert the frontend to possibly process them.
//this will generally happen when every audio stream has pending samples to be mixed.
if(pending()) platform->audio(shared());
if(pending()) platform->audio(std::static_pointer_cast<Core::Audio::Stream>(shared_from_this()));
}
+3 -3
View File
@@ -38,11 +38,11 @@ protected:
DSP::IIR::Biquad biquad;
};
struct Channel {
vector<Filter> filters;
vector<DSP::IIR::Biquad> nyquist;
std::vector<Filter> filters;
std::vector<DSP::IIR::Biquad> nyquist;
DSP::Resampler::Cubic resampler;
};
vector<Channel> _channels;
std::vector<Channel> _channels;
f64 _frequency = 48000.0;
f64 _resamplerFrequency = 48000.0;
bool _muted = false;
+10 -8
View File
@@ -4,26 +4,28 @@
struct Class {
struct Instance {
const string identifier;
const function<Node::Object ()> create;
const std::function<Node::Object ()> create;
};
static auto classes() -> vector<Instance>& {
static vector<Instance> classes;
static auto classes() -> std::vector<Instance>& {
static std::vector<Instance> classes;
return classes;
}
template<typename T> static auto register() -> void {
if(!classes().find([&](auto instance) { return instance.identifier == T::identifier(); })) {
classes().append({T::identifier(), &T::create});
auto& cls = classes();
auto it = std::ranges::find_if(cls, [&](const Instance& instance) { return instance.identifier == T::identifier(); });
if(it == cls.end()) {
cls.push_back({T::identifier(), &T::create});
} else {
throw;
}
}
static auto create(string identifier) -> Node::Object {
if(auto index = classes().find([&](auto instance) { return instance.identifier == identifier; })) {
return classes()[*index].create();
}
auto& cls = classes();
auto it = std::ranges::find_if(cls, [&](const Instance& instance) { return instance.identifier == identifier; });
if(it != cls.end()) return it->create();
if(identifier == "Object") throw; //should never occur: detects unregistered classes
return create("Object");
}
+2 -2
View File
@@ -5,7 +5,7 @@ struct RealTimeClock : Component {
auto update() -> void { if(_update) return _update(); }
auto timestamp() const -> u64 { return _timestamp; }
auto setUpdate(function<void ()> update) -> void { _update = update; }
auto setUpdate(std::function<void ()> update) -> void { _update = update; }
auto setTimestamp(u64 timestamp) -> void { _timestamp = timestamp; }
auto synchronize(u64 timestamp = 0) -> void {
@@ -25,6 +25,6 @@ struct RealTimeClock : Component {
}
protected:
function<void ()> _update;
std::function<void ()> _update;
u64 _timestamp;
};
+3 -3
View File
@@ -6,10 +6,10 @@ struct Graphics : Debugger {
auto width() const -> u32 { return _width; }
auto height() const -> u32 { return _height; }
auto capture() const -> vector<u32> { if(_capture) return _capture(); return {}; }
auto capture() const -> std::vector<u32> { if(_capture) return _capture(); return {}; }
auto setSize(u32 width, u32 height) -> void { _width = width, _height = height; }
auto setCapture(function<vector<u32> ()> capture) -> void { _capture = capture; }
auto setCapture(std::function<std::vector<u32> ()> capture) -> void { _capture = capture; }
auto serialize(string& output, string depth) -> void override {
Debugger::serialize(output, depth);
@@ -22,5 +22,5 @@ struct Graphics : Debugger {
protected:
u32 _width = 0;
u32 _height = 0;
function<vector<u32> ()> _capture;
std::function<std::vector<u32> ()> _capture;
};
+4 -4
View File
@@ -9,8 +9,8 @@ struct Memory : Debugger {
auto write(u32 address, u8 data) const -> void { if(_write) return _write(address, data); }
auto setSize(u32 size) -> void { _size = size; }
auto setRead(function<u8 (u32)> read) -> void { _read = read; }
auto setWrite(function<void (u32, u8)> write) -> void { _write = write; }
auto setRead(std::function<u8 (u32)> read) -> void { _read = read; }
auto setWrite(std::function<void (u32, u8)> write) -> void { _write = write; }
auto serialize(string& output, string depth) -> void override {
Debugger::serialize(output, depth);
@@ -22,6 +22,6 @@ struct Memory : Debugger {
protected:
u32 _size = 0;
function<u8 (u32)> _read;
function<void (u32, u8)> _write;
std::function<u8 (u32)> _read;
std::function<void (u32, u8)> _write;
};
+2 -2
View File
@@ -6,7 +6,7 @@ struct Properties : Debugger {
auto query() const -> string { if(_query) return _query(); return {}; }
auto setQuery(function<string ()> query) -> void { _query = query; }
auto setQuery(std::function<string ()> query) -> void { _query = query; }
auto serialize(string& output, string depth) -> void override {
Debugger::serialize(output, depth);
@@ -17,5 +17,5 @@ struct Properties : Debugger {
}
protected:
function<string ()> _query;
std::function<string ()> _query;
};
@@ -23,7 +23,7 @@ struct Instruction : Tracer {
auto setDepth(u32 depth) -> void {
_depth = depth;
_history.reset();
_history.clear();
_history.resize(depth);
for(auto& history : _history) history = ~0ull;
}
@@ -49,7 +49,7 @@ struct Instruction : Tracer {
for(auto index : range(_depth - 1)) {
_history[index] = _history[index + 1];
}
_history.last() = _address;
_history.back() = _address;
}
return true;
@@ -71,7 +71,8 @@ struct Instruction : Tracer {
if(!enabled()) return;
if(_omitted) {
PlatformLog(shared(), {"[Omitted: ", _omitted, "]"});
auto message = string{ "[Omitted: ", _omitted, "]" };
PlatformLog(std::dynamic_pointer_cast<Tracer>(shared_from_this()), message);
_omitted = 0;
}
@@ -82,7 +83,7 @@ struct Instruction : Tracer {
context, " ",
extra
};
PlatformLog(shared(), {output.strip()});
PlatformLog(std::dynamic_pointer_cast<Tracer>(shared_from_this()), {output.strip()});
}
auto serialize(string& output, string depth) -> void override {
@@ -135,6 +136,6 @@ protected:
//unserialized:
n64 _address = 0;
n64 _omitted = 0;
vector<u64> _history;
std::vector<u64> _history;
hashset<VisitMask> _masks;
};
@@ -6,7 +6,7 @@ struct Notification : Tracer {
auto notify(const string& message = {}) -> void {
if(!enabled()) return;
PlatformLog(shared(), message);
PlatformLog(std::dynamic_pointer_cast<Tracer>(shared_from_this()), message);
}
protected:
+2 -2
View File
@@ -12,7 +12,7 @@ struct Tracer : Debugger {
auto file() const -> bool { return _file; }
auto autoLineBreak() const -> bool { return _autoLineBreak; }
auto setToggle(function<void ()> toggle) -> void { _toggle = toggle; }
auto setToggle(std::function<void ()> toggle) -> void { _toggle = toggle; }
auto setComponent(string component) -> void { _component = component; }
auto setPrefix(bool prefix) -> void { _prefix = prefix; }
auto setTerminal(bool terminal) -> void { _terminal = terminal; if(_toggle) _toggle(); }
@@ -36,7 +36,7 @@ struct Tracer : Debugger {
}
protected:
function<void ()> _toggle;
std::function<void ()> _toggle;
string _component;
bool _prefix = false;
bool _terminal = false;
+35 -34
View File
@@ -45,47 +45,47 @@ namespace ares::Core {
}
namespace ares::Node {
using Object = shared_pointer<Core::Object>;
using System = shared_pointer<Core::System>;
using Peripheral = shared_pointer<Core::Peripheral>;
using Port = shared_pointer<Core::Port>;
using Object = std::shared_ptr<Core::Object>;
using System = std::shared_ptr<Core::System>;
using Peripheral = std::shared_ptr<Core::Peripheral>;
using Port = std::shared_ptr<Core::Port>;
namespace Component {
using Component = shared_pointer<Core::Component::Component>;
using RealTimeClock = shared_pointer<Core::Component::RealTimeClock>;
using Component = std::shared_ptr<Core::Component::Component>;
using RealTimeClock = std::shared_ptr<Core::Component::RealTimeClock>;
}
namespace Video {
using Video = shared_pointer<Core::Video::Video>;
using Sprite = shared_pointer<Core::Video::Sprite>;
using Screen = shared_pointer<Core::Video::Screen>;
using Video = std::shared_ptr<Core::Video::Video>;
using Sprite = std::shared_ptr<Core::Video::Sprite>;
using Screen = std::shared_ptr<Core::Video::Screen>;
}
namespace Audio {
using Audio = shared_pointer<Core::Audio::Audio>;
using Stream = shared_pointer<Core::Audio::Stream>;
using Audio = std::shared_ptr<Core::Audio::Audio>;
using Stream = std::shared_ptr<Core::Audio::Stream>;
}
namespace Input {
using Input = shared_pointer<Core::Input::Input>;
using Button = shared_pointer<Core::Input::Button>;
using Axis = shared_pointer<Core::Input::Axis>;
using Trigger = shared_pointer<Core::Input::Trigger>;
using Rumble = shared_pointer<Core::Input::Rumble>;
using Input = std::shared_ptr<Core::Input::Input>;
using Button = std::shared_ptr<Core::Input::Button>;
using Axis = std::shared_ptr<Core::Input::Axis>;
using Trigger = std::shared_ptr<Core::Input::Trigger>;
using Rumble = std::shared_ptr<Core::Input::Rumble>;
}
namespace Setting {
using Setting = shared_pointer<Core::Setting::Setting>;
using Boolean = shared_pointer<Core::Setting::Boolean>;
using Natural = shared_pointer<Core::Setting::Natural>;
using Integer = shared_pointer<Core::Setting::Integer>;
using Real = shared_pointer<Core::Setting::Real>;
using String = shared_pointer<Core::Setting::String>;
using Setting = std::shared_ptr<Core::Setting::Setting>;
using Boolean = std::shared_ptr<Core::Setting::Boolean>;
using Natural = std::shared_ptr<Core::Setting::Natural>;
using Integer = std::shared_ptr<Core::Setting::Integer>;
using Real = std::shared_ptr<Core::Setting::Real>;
using String = std::shared_ptr<Core::Setting::String>;
}
namespace Debugger {
using Debugger = shared_pointer<Core::Debugger::Debugger>;
using Memory = shared_pointer<Core::Debugger::Memory>;
using Graphics = shared_pointer<Core::Debugger::Graphics>;
using Properties = shared_pointer<Core::Debugger::Properties>;
using Debugger = std::shared_ptr<Core::Debugger::Debugger>;
using Memory = std::shared_ptr<Core::Debugger::Memory>;
using Graphics = std::shared_ptr<Core::Debugger::Graphics>;
using Properties = std::shared_ptr<Core::Debugger::Properties>;
namespace Tracer {
using Tracer = shared_pointer<Core::Debugger::Tracer::Tracer>;
using Notification = shared_pointer<Core::Debugger::Tracer::Notification>;
using Instruction = shared_pointer<Core::Debugger::Tracer::Instruction>;
using Tracer = std::shared_ptr<Core::Debugger::Tracer::Tracer>;
using Notification = std::shared_ptr<Core::Debugger::Tracer::Notification>;
using Instruction = std::shared_ptr<Core::Debugger::Tracer::Instruction>;
}
}
}
@@ -164,9 +164,10 @@ namespace ares::Node {
}
static inline auto parent(Object child) -> Object {
if(!child || !child->parent()) return {};
if(auto parent = child->parent().acquire()) return parent;
return {};
if(!child) return {};
auto wp = child->parent();
if(wp.expired()) return {};
return wp.lock();
}
template<typename T>
@@ -177,8 +178,8 @@ namespace ares::Node {
}
template<typename T>
static inline auto enumerate(Object from) -> vector<T> {
vector<T> objects;
static inline auto enumerate(Object from) -> std::vector<T> {
std::vector<T> objects;
if(from) from->enumerate<T>(objects);
return objects;
}
+45 -38
View File
@@ -3,13 +3,13 @@
#define DeclareClass(Type, Name) \
static auto identifier() -> string { return Name; } \
static auto create() -> Node::Object { return new Type; } \
static auto create() -> Node::Object { return std::make_shared<Type>(); } \
auto identity() const -> string override { return Name; } \
private: static inline Class::Register<Type> register; public: \
struct Object : shared_pointer_this<Object> {
struct Object : std::enable_shared_from_this<Object> {
static auto identifier() -> string { return "Object"; }
static auto create() -> Node::Object { return new Object; }
static auto create() -> Node::Object { return std::make_shared<Object>(); }
virtual auto identity() const -> string { return "Object"; }
private: static inline Class::Register<Object> register; public:
//DeclareClass(Object, "object")
@@ -18,44 +18,47 @@ struct Object : shared_pointer_this<Object> {
virtual ~Object() = default;
auto name() const -> string { return _name; }
auto parent() const -> shared_pointer_weak<Object> { return _parent; }
auto parent() const -> std::weak_ptr<Object> { return _parent; }
auto setName(string_view name) -> void { _name = name; }
auto prepend(Node::Object node) -> Node::Object {
if(auto found = find(node)) return found;
_nodes.prepend(node);
node->_parent = shared();
_nodes.insert(_nodes.begin(), node);
node->_parent = shared_from_this();
PlatformAttach(node);
return node;
}
template<typename T, typename... P>
auto prepend(P&&... p) -> Node::Object {
using Type = typename T::type;
return prepend(shared_pointer<Type>::create(std::forward<P>(p)...));
auto prepend(P&&... p) -> std::shared_ptr<typename T::element_type> {
using Type = typename T::element_type;
auto node = std::make_shared<Type>(std::forward<P>(p)...);
prepend(node);
return node;
}
auto append(Node::Object node) -> Node::Object {
if(auto found = find(node)) return found;
_nodes.append(node);
node->_parent = shared();
_nodes.push_back(node);
node->_parent = shared_from_this();
PlatformAttach(node);
return node;
}
template<typename T, typename... P>
auto append(P&&... p) -> Node::Object {
using Type = typename T::type;
return append(shared_pointer<Type>::create(std::forward<P>(p)...));
auto append(P&&... p) -> std::shared_ptr<typename T::element_type> {
using Type = typename T::element_type;
auto node = std::make_shared<Type>(std::forward<P>(p)...);
append(node);
return node;
}
auto remove(Node::Object node) -> void {
if(auto index = _nodes.find(node)) {
if(std::erase(_nodes, node)) {
PlatformDetach(node);
node->reset();
node->_parent.reset();
_nodes.remove(*index);
}
}
@@ -65,13 +68,12 @@ struct Object : shared_pointer_this<Object> {
node->reset();
node->_parent.reset();
}
_nodes.reset();
_nodes.clear();
}
template<typename T>
auto cast() -> shared_pointer<typename T::type> {
if(dynamic_cast<typename T::type*>(this)) return shared();
return {};
auto cast() -> std::shared_ptr<typename T::element_type> {
return std::dynamic_pointer_cast<typename T::element_type>(shared_from_this());
}
template<typename T>
@@ -80,17 +82,20 @@ struct Object : shared_pointer_this<Object> {
}
template<typename T>
auto find() -> vector<shared_pointer<typename T::type>> {
vector<shared_pointer<typename T::type>> result;
if(dynamic_cast<typename T::type*>(this)) {
if(auto instance = shared()) result.append(instance);
auto find() -> std::vector<std::shared_ptr<typename T::element_type>> {
std::vector<std::shared_ptr<typename T::element_type>> result;
if(dynamic_cast<typename T::element_type*>(this)) {
if(auto instance = cast<T>()) result.push_back(instance);
}
for(auto& node : _nodes) {
auto sub = node->find<T>();
std::ranges::copy(sub, std::back_inserter(result));
}
for(auto& node : _nodes) result.append(node->find<T>());
return result;
}
template<typename T>
auto find(u32 index) -> shared_pointer<typename T::type> {
auto find(u32 index) -> std::shared_ptr<typename T::element_type> {
auto result = find<T>();
if(index < result.size()) return result[index];
return {};
@@ -106,31 +111,33 @@ struct Object : shared_pointer_this<Object> {
template<typename T = Node::Object>
auto find(string name) -> T {
using Type = typename T::type;
auto path = name.split("/");
name = path.takeFirst();
using Type = typename T::element_type;
auto path = nall::split(name, "/");
if(path.empty()) return {};
name = path.front();
path.erase(path.begin());
for(auto& node : _nodes) {
if(node->_name != name) continue;
if(path) return node->find<T>(path.merge("/"));
if(node->identity() == Type::identifier()) return node;
if(!path.empty()) return node->find<T>(nall::merge(path, "/"));
if(node->identity() == Type::identifier()) return node->template cast<T>();
}
return {};
}
template<typename T = Node::Object>
auto scan(string name) -> T {
using Type = typename T::type;
using Type = typename T::element_type;
for(auto& node : _nodes) {
if(node->identity() == Type::identifier() && node->_name == name) return node;
if(node->identity() == Type::identifier() && node->_name == name) return node->template cast<T>();
if(auto result = node->scan<T>(name)) return result;
}
return {};
}
template<typename T>
auto enumerate(vector<T>& objects) -> void {
using Type = typename T::type;
if(auto instance = cast<T>()) objects.append(instance);
auto enumerate(std::vector<T>& objects) -> void {
using Type = typename T::element_type;
if(auto instance = cast<T>()) objects.push_back(instance);
for(auto& node : _nodes) node->enumerate<T>(objects);
}
@@ -230,6 +237,6 @@ protected:
string _name;
VFS::Pak _pak;
set<Attribute> _attributes;
shared_pointer_weak<Object> _parent;
vector<Node::Object> _nodes;
std::weak_ptr<Object> _parent;
std::vector<Node::Object> _nodes;
};
+9 -9
View File
@@ -5,15 +5,15 @@ struct Port : Object {
auto type() const -> string { return _type; }
auto family() const -> string { return _family; }
auto hotSwappable() const -> bool { return _hotSwappable; }
auto supported() const -> vector<string> { return _supported; }
auto supported() const -> std::vector<string> { return _supported; }
auto setAllocate(function<Node::Peripheral (string)> allocate) -> void { _allocate = allocate; }
auto setConnect(function<void ()> connect) -> void { _connect = connect; }
auto setDisconnect(function<void ()> disconnect) -> void { _disconnect = disconnect; }
auto setAllocate(std::function<Node::Peripheral (string)> allocate) -> void { _allocate = allocate; }
auto setConnect(std::function<void ()> connect) -> void { _connect = connect; }
auto setDisconnect(std::function<void ()> disconnect) -> void { _disconnect = disconnect; }
auto setType(string type) -> void { _type = type; }
auto setFamily(string family) -> void { _family = family; }
auto setHotSwappable(bool hotSwappable) -> void { _hotSwappable = hotSwappable; }
auto setSupported(vector<string> supported) -> void { _supported = supported; }
auto setSupported(std::vector<string> supported) -> void { _supported = supported; }
auto connected() -> Node::Peripheral {
return find<Node::Peripheral>(0);
@@ -64,11 +64,11 @@ struct Port : Object {
}
protected:
function<Node::Peripheral (string)> _allocate;
function<void ()> _connect;
function<void ()> _disconnect;
std::function<Node::Peripheral (string)> _allocate;
std::function<void ()> _connect;
std::function<void ()> _disconnect;
string _type;
string _family;
bool _hotSwappable = false;
vector<string> _supported;
std::vector<string> _supported;
};
+4 -4
View File
@@ -1,7 +1,7 @@
struct Boolean : Setting {
DeclareClass(Boolean, "setting.boolean")
Boolean(string name = {}, bool value = {}, function<void (bool)> modify = {}) : Setting(name) {
Boolean(string name = {}, bool value = {}, std::function<void (bool)> modify = {}) : Setting(name) {
_currentValue = value;
_latchedValue = value;
_modify = modify;
@@ -11,7 +11,7 @@ struct Boolean : Setting {
auto value() const -> bool { return _currentValue; }
auto latch() const -> bool { return _latchedValue; }
auto setModify(function<void (bool)> modify) { _modify = modify; }
auto setModify(std::function<void (bool)> modify) { _modify = modify; }
auto setValue(bool value) -> void {
_currentValue = value;
@@ -26,11 +26,11 @@ struct Boolean : Setting {
auto readValue() const -> string override { return value(); }
auto readLatch() const -> string override { return latch(); }
auto readAllowedValues() const -> vector<string> override { return {"false", "true"}; }
auto readAllowedValues() const -> std::vector<string> override { return {"false", "true"}; }
auto writeValue(string value) -> void override { setValue(value.boolean()); }
protected:
function<void (bool)> _modify;
std::function<void (bool)> _modify;
bool _currentValue = {};
bool _latchedValue = {};
};
+10 -10
View File
@@ -1,7 +1,7 @@
struct Integer : Setting {
DeclareClass(Integer, "setting.integer")
Integer(string name = {}, s64 value = {}, function<void (s64)> modify = {}) : Setting(name) {
Integer(string name = {}, s64 value = {}, std::function<void (s64)> modify = {}) : Setting(name) {
_currentValue = value;
_latchedValue = value;
_modify = modify;
@@ -11,10 +11,10 @@ struct Integer : Setting {
auto value() const -> s64 { return _currentValue; }
auto latch() const -> s64 { return _latchedValue; }
auto setModify(function<void (s64)> modify) { _modify = modify; }
auto setModify(std::function<void (s64)> modify) { _modify = modify; }
auto setValue(s64 value) -> void {
if(_allowedValues && !_allowedValues.find(value)) return;
if(!_allowedValues.empty() && !std::ranges::count(_allowedValues, value)) return;
_currentValue = value;
if(_dynamic) setLatch();
}
@@ -25,23 +25,23 @@ struct Integer : Setting {
modify(_latchedValue);
}
auto setAllowedValues(vector<s64> allowedValues) -> void {
auto setAllowedValues(std::vector<s64> allowedValues) -> void {
_allowedValues = allowedValues;
if(_allowedValues && !_allowedValues.find(_currentValue)) setValue(_allowedValues.first());
if(!_allowedValues.empty() && !std::ranges::count(_allowedValues, _currentValue)) setValue(_allowedValues.front());
}
auto readValue() const -> string override { return value(); }
auto readLatch() const -> string override { return latch(); }
auto readAllowedValues() const -> vector<string> override {
vector<string> values;
for(auto value : _allowedValues) values.append(value);
auto readAllowedValues() const -> std::vector<string> override {
std::vector<string> values;
for(auto value : _allowedValues) values.push_back(value);
return values;
}
auto writeValue(string value) -> void override { setValue(value.integer()); }
protected:
function<void (s64)> _modify;
std::function<void (s64)> _modify;
s64 _currentValue = {};
s64 _latchedValue = {};
vector<s64> _allowedValues;
std::vector<s64> _allowedValues;
};
+10 -10
View File
@@ -1,7 +1,7 @@
struct Natural : Setting {
DeclareClass(Natural, "setting.natural")
Natural(string name = {}, u64 value = {}, function<void (u64)> modify = {}) : Setting(name) {
Natural(string name = {}, u64 value = {}, std::function<void (u64)> modify = {}) : Setting(name) {
_currentValue = value;
_latchedValue = value;
_modify = modify;
@@ -11,10 +11,10 @@ struct Natural : Setting {
auto value() const -> u64 { return _currentValue; }
auto latch() const -> u64 { return _latchedValue; }
auto setModify(function<void (u64)> modify) { _modify = modify; }
auto setModify(std::function<void (u64)> modify) { _modify = modify; }
auto setValue(u64 value) -> void {
if(_allowedValues && !_allowedValues.find(value)) return;
if(!_allowedValues.empty() && !std::ranges::count(_allowedValues, value)) return;
_currentValue = value;
if(_dynamic) setLatch();
}
@@ -25,23 +25,23 @@ struct Natural : Setting {
modify(_latchedValue);
}
auto setAllowedValues(vector<u64> allowedValues) -> void {
auto setAllowedValues(std::vector<u64> allowedValues) -> void {
_allowedValues = allowedValues;
if(_allowedValues && !_allowedValues.find(_currentValue)) setValue(_allowedValues.first());
if(!_allowedValues.empty() && !std::ranges::count(_allowedValues, _currentValue)) setValue(_allowedValues.front());
}
auto readValue() const -> string override { return value(); }
auto readLatch() const -> string override { return latch(); }
auto readAllowedValues() const -> vector<string> override {
vector<string> values;
for(auto value : _allowedValues) values.append(value);
auto readAllowedValues() const -> std::vector<string> override {
std::vector<string> values;
for(auto value : _allowedValues) values.push_back(value);
return values;
}
auto writeValue(string value) -> void override { setValue(value.natural()); }
protected:
function<void (u64)> _modify;
std::function<void (u64)> _modify;
u64 _currentValue = {};
u64 _latchedValue = {};
vector<u64> _allowedValues;
std::vector<u64> _allowedValues;
};
+10 -10
View File
@@ -1,7 +1,7 @@
struct Real : Setting {
DeclareClass(Real, "setting.real")
Real(string name = {}, f64 value = {}, function<void (f64)> modify = {}) : Setting(name) {
Real(string name = {}, f64 value = {}, std::function<void (f64)> modify = {}) : Setting(name) {
_currentValue = value;
_latchedValue = value;
_modify = modify;
@@ -11,10 +11,10 @@ struct Real : Setting {
auto value() const -> f64 { return _currentValue; }
auto latch() const -> f64 { return _latchedValue; }
auto setModify(function<void (f64)> modify) { _modify = modify; }
auto setModify(std::function<void (f64)> modify) { _modify = modify; }
auto setValue(f64 value) -> void {
if(_allowedValues && !_allowedValues.find(value)) return;
if(!_allowedValues.empty() && !std::ranges::count(_allowedValues, value)) return;
_currentValue = value;
if(_dynamic) setLatch();
}
@@ -25,23 +25,23 @@ struct Real : Setting {
modify(_latchedValue);
}
auto setAllowedValues(vector<f64> allowedValues) -> void {
auto setAllowedValues(std::vector<f64> allowedValues) -> void {
_allowedValues = allowedValues;
if(_allowedValues && !_allowedValues.find(_currentValue)) setValue(_allowedValues.first());
if(!_allowedValues.empty() && !std::ranges::count(_allowedValues, _currentValue)) setValue(_allowedValues.front());
}
auto readValue() const -> string override { return value(); }
auto readLatch() const -> string override { return latch(); }
auto readAllowedValues() const -> vector<string> override {
vector<string> values;
for(auto value : _allowedValues) values.append(value);
auto readAllowedValues() const -> std::vector<string> override {
std::vector<string> values;
for(auto value : _allowedValues) values.push_back(value);
return values;
}
auto writeValue(string value) -> void override { setValue(value.real()); }
protected:
function<void (f64)> _modify;
std::function<void (f64)> _modify;
f64 _currentValue = {};
f64 _latchedValue = {};
vector<f64> _allowedValues;
std::vector<f64> _allowedValues;
};
+2 -2
View File
@@ -12,12 +12,12 @@ struct Setting : Object {
virtual auto readValue() const -> string { return {}; }
virtual auto readLatch() const -> string { return {}; }
virtual auto readAllowedValues() const -> vector<string> { return {}; }
virtual auto readAllowedValues() const -> std::vector<string> { return {}; }
virtual auto writeValue(string value) -> void {}
auto load(Node::Object source) -> bool override {
if(!Object::load(source)) return false;
if(auto setting = source->cast<shared_pointer<Setting>>()) writeValue(setting->readValue());
if(auto setting = source->cast<Node::Setting::Setting>()) writeValue(setting->readValue());
return true;
}
+8 -8
View File
@@ -1,7 +1,7 @@
struct String : Setting {
DeclareClass(String, "setting.string")
String(string name = {}, string value = {}, function<void (string)> modify = {}) : Setting(name) {
String(string name = {}, string value = {}, std::function<void (string)> modify = {}) : Setting(name) {
_currentValue = value;
_latchedValue = value;
_modify = modify;
@@ -11,10 +11,10 @@ struct String : Setting {
auto value() const -> string { return _currentValue; }
auto latch() const -> string { return _latchedValue; }
auto setModify(function<void (string)> modify) { _modify = modify; }
auto setModify(std::function<void (string)> modify) { _modify = modify; }
auto setValue(string value) -> void {
if(_allowedValues && !_allowedValues.find(value)) return;
if(!_allowedValues.empty() && !std::ranges::count(_allowedValues, value)) return;
_currentValue = value;
if(_dynamic) setLatch();
}
@@ -25,19 +25,19 @@ struct String : Setting {
modify(_latchedValue);
}
auto setAllowedValues(vector<string> allowedValues) -> void {
auto setAllowedValues(std::vector<string> allowedValues) -> void {
_allowedValues = allowedValues;
if(_allowedValues && !_allowedValues.find(_currentValue)) setValue(_allowedValues.first());
if(!_allowedValues.empty() && !std::ranges::count(_allowedValues, _currentValue)) setValue(_allowedValues.front());
}
auto readValue() const -> string override { return value(); }
auto readLatch() const -> string override { return latch(); }
auto readAllowedValues() const -> vector<string> override { return _allowedValues; }
auto readAllowedValues() const -> std::vector<string> override { return _allowedValues; }
auto writeValue(string value) -> void override { setValue(value); }
protected:
function<void (string)> _modify;
std::function<void (string)> _modify;
string _currentValue = {};
string _latchedValue = {};
vector<string> _allowedValues;
std::vector<string> _allowedValues;
};
+14 -14
View File
@@ -10,20 +10,20 @@ struct System : Object {
auto serialize(bool synchronize = true) -> serializer { if(_serialize) return _serialize(synchronize); return {}; }
auto unserialize(serializer& s) -> bool { if(_unserialize) return _unserialize(s); return false; }
auto setGame(function<string ()> game) -> void { _game = game; }
auto setRun(function<void ()> run) -> void { _run = run; }
auto setPower(function<void (bool)> power) -> void { _power = power; }
auto setSave(function<void ()> save) -> void { _save = save; }
auto setUnload(function<void ()> unload) -> void { _unload = unload; }
auto setSerialize(function<serializer (bool)> serialize) -> void { _serialize = serialize; }
auto setUnserialize(function<bool (serializer&)> unserialize) -> void { _unserialize = unserialize; }
auto setGame(std::function<string ()> game) -> void { _game = game; }
auto setRun(std::function<void ()> run) -> void { _run = run; }
auto setPower(std::function<void (bool)> power) -> void { _power = power; }
auto setSave(std::function<void ()> save) -> void { _save = save; }
auto setUnload(std::function<void ()> unload) -> void { _unload = unload; }
auto setSerialize(std::function<serializer (bool)> serialize) -> void { _serialize = serialize; }
auto setUnserialize(std::function<bool (serializer&)> unserialize) -> void { _unserialize = unserialize; }
protected:
function<string ()> _game;
function<void ()> _run;
function<void (bool)> _power;
function<void ()> _save;
function<void ()> _unload;
function<serializer (bool)> _serialize;
function<bool (serializer&)> _unserialize;
std::function<string ()> _game;
std::function<void ()> _run;
std::function<void (bool)> _power;
std::function<void ()> _save;
std::function<void ()> _unload;
std::function<serializer (bool)> _serialize;
std::function<bool (serializer&)> _unserialize;
};
+35 -35
View File
@@ -1,17 +1,18 @@
#include <memory>
Screen::Screen(string name, u32 width, u32 height) : Video(name) {
_canvasWidth = width;
_canvasHeight = height;
if(width && height) {
_inputA = new u32[width * height]();
_inputB = new u32[width * height]();
_output = new u32[width * height]();
_rotate = new u32[width * height]();
_inputA = std::make_unique<u32[]>(width * height);
_inputB = std::make_unique<u32[]>(width * height);
_output = std::make_unique<u32[]>(width * height);
_rotate = std::make_unique<u32[]>(width * height);
_lineOverrideActive.resize(width * height, false);
_lineOverride.resize(width * height, nullptr);
if constexpr(ares::Video::Threaded) {
_thread = nall::thread::create({&Screen::main, this});
_thread = nall::thread::create(std::bind_front(&Screen::main, this));
}
}
}
@@ -43,22 +44,22 @@ auto Screen::main(uintptr_t) -> void {
auto Screen::quit() -> void {
_kill = true;
_thread.join();
_sprites.reset();
_sprites.clear();
}
auto Screen::power() -> void {
lock_guard<recursive_mutex> lock(_mutex);
memory::fill<u32>(_inputA.data(), _canvasWidth * _canvasHeight, _fillColor);
memory::fill<u32>(_inputB.data(), _canvasWidth * _canvasHeight, _fillColor);
memory::fill<u32>(_output.data(), _canvasWidth * _canvasHeight, _fillColor);
memory::fill<u32>(_rotate.data(), _canvasWidth * _canvasHeight, _fillColor);
memory::fill<u32>(_inputA.get(), _canvasWidth * _canvasHeight, _fillColor);
memory::fill<u32>(_inputB.get(), _canvasWidth * _canvasHeight, _fillColor);
memory::fill<u32>(_output.get(), _canvasWidth * _canvasHeight, _fillColor);
memory::fill<u32>(_rotate.get(), _canvasWidth * _canvasHeight, _fillColor);
memory::fill<n1>(_lineOverrideActive.data(), _canvasWidth * _canvasHeight, false);
memory::fill<const u32*>(_lineOverride.data(), _canvasWidth * _canvasHeight, nullptr);
}
auto Screen::pixels(bool frame) -> array_span<u32> {
if(frame == 0) return {_inputA.data(), _canvasWidth * _canvasHeight};
if(frame == 1) return {_inputB.data(), _canvasWidth * _canvasHeight};
auto Screen::pixels(bool frame) -> std::span<u32> {
if(frame == 0) return {_inputA.get(), _canvasWidth * _canvasHeight};
if(frame == 1) return {_inputB.get(), _canvasWidth * _canvasHeight};
return {};
}
@@ -70,10 +71,10 @@ auto Screen::resetPalette() -> void {
auto Screen::resetSprites() -> void {
lock_guard<recursive_mutex> lock(_mutex);
_sprites.reset();
_sprites.clear();
}
auto Screen::setRefresh(function<void ()> refresh) -> void {
auto Screen::setRefresh(std::function<void ()> refresh) -> void {
lock_guard<recursive_mutex> lock(_mutex);
_refresh = refresh;
}
@@ -180,17 +181,17 @@ auto Screen::setInterlace(bool interlaceField) -> void {
auto Screen::attach(Node::Video::Sprite sprite) -> void {
lock_guard<recursive_mutex> lock(_mutex);
if(_sprites.find(sprite)) return;
_sprites.append(sprite);
if(std::ranges::find(_sprites, sprite) != _sprites.end()) return;
_sprites.push_back(sprite);
}
auto Screen::detach(Node::Video::Sprite sprite) -> void {
lock_guard<recursive_mutex> lock(_mutex);
if(!_sprites.find(sprite)) return;
_sprites.removeByValue(sprite);
if(std::ranges::find(_sprites, sprite) == _sprites.end()) return;
std::erase(_sprites, sprite);
}
auto Screen::colors(u32 colors, function<n64 (n32)> color) -> void {
auto Screen::colors(u32 colors, std::function<n64 (n32)> color) -> void {
lock_guard<recursive_mutex> lock(_mutex);
_colors = colors;
_color = color;
@@ -228,8 +229,8 @@ auto Screen::refresh() -> void {
auto pitch = _canvasWidth;
auto width = _canvasWidth;
auto height = _canvasHeight;
auto input = _inputB.data();
auto output = _output.data();
auto input = _inputB.get();
auto output = _output.get();
for(u32 y : range(height)) {
auto source = input + y * pitch;
@@ -310,11 +311,11 @@ auto Screen::refresh() -> void {
for(u32 y : range(height)) {
auto source = output + y * width;
for(u32 x : range(width)) {
auto target = _rotate.data() + (width - 1 - x) * height + y;
auto target = _rotate.get() + (width - 1 - x) * height + y;
*target = *source++;
}
}
output = _rotate.data();
output = _rotate.get();
swap(width, height);
swap(viewWidth, viewHeight);
}
@@ -324,11 +325,11 @@ auto Screen::refresh() -> void {
for(u32 y : range(height)) {
auto source = output + y * width;
for(u32 x : range(width)) {
auto target = _rotate.data() + (height - 1 - y) * width + (width - 1 - x);
auto target = _rotate.get() + (height - 1 - y) * width + (width - 1 - x);
*target = *source++;
}
}
output = _rotate.data();
output = _rotate.get();
}
if(_rotation == 270) {
@@ -336,17 +337,17 @@ auto Screen::refresh() -> void {
for(u32 y : range(height)) {
auto source = output + y * width;
for(u32 x : range(width)) {
auto target = _rotate.data() + x * height + (height - 1 - y);
auto target = _rotate.get() + x * height + (height - 1 - y);
*target = *source++;
}
}
output = _rotate.data();
output = _rotate.get();
swap(width, height);
swap(viewWidth, viewHeight);
}
platform->video(shared(), output + viewX + viewY * width, width * sizeof(u32), viewWidth, viewHeight);
memory::fill<u32>(_inputB.data(), width * height, _fillColor);
platform->video(std::static_pointer_cast<Core::Video::Screen>(shared_from_this()), output + viewX + viewY * width, width * sizeof(u32), viewWidth, viewHeight);
memory::fill<u32>(_inputB.get(), width * height, _fillColor);
}
auto Screen::lookupPalette(u32 index) -> u32 {
@@ -368,7 +369,7 @@ auto Screen::refreshPalette() -> void {
if(_palette) return;
//generate the color lookup palettes to convert native colors to ARGB8888
_palette = new u32[_colors];
_palette = std::make_unique<u32[]>(_colors);
for(u32 index : range(_colors)) {
n64 color = _color(index);
n16 b = color.bit( 0,15);
@@ -378,10 +379,9 @@ auto Screen::refreshPalette() -> void {
if(_saturation != 1.0) {
n16 grayscale = uclamp<16>((r + g + b) / 3);
f64 inverse = max(0.0, 1.0 - _saturation);
r = uclamp<16>(r * _saturation + grayscale * inverse);
g = uclamp<16>(g * _saturation + grayscale * inverse);
b = uclamp<16>(b * _saturation + grayscale * inverse);
r = uclamp<16>(grayscale + (r - grayscale) * _saturation);
g = uclamp<16>(grayscale + (g - grayscale) * _saturation);
b = uclamp<16>(grayscale + (b - grayscale) * _saturation);
}
if(_gamma != 1.0) {
+13 -13
View File
@@ -18,7 +18,7 @@ struct Screen : Video {
auto aspectY() const -> f64 { return _aspectY; }
auto overscan() const -> bool { return _overscan; }
auto colors() const -> u32 { return _colors; }
auto pixels(bool frame = 0) -> array_span<u32>;
auto pixels(bool frame = 0) -> std::span<u32>;
auto saturation() const -> double { return _saturation; }
auto gamma() const -> double { return _gamma; }
@@ -32,7 +32,7 @@ struct Screen : Video {
auto resetPalette() -> void;
auto resetSprites() -> void;
auto setRefresh(function<void ()> refresh) -> void;
auto setRefresh(std::function<void ()> refresh) -> void;
auto setViewport(u32 x, u32 y, u32 width, u32 height) -> void;
auto refreshRateHint(double refreshRate) -> void;
auto refreshRateHint(double pixelFrequency, int dotsPerLine, int linesPerFrame) -> void;
@@ -58,7 +58,7 @@ struct Screen : Video {
auto attach(Node::Video::Sprite) -> void;
auto detach(Node::Video::Sprite) -> void;
auto colors(u32 colors, function<n64 (n32)> color) -> void;
auto colors(u32 colors, std::function<n64 (n32)> color) -> void;
auto frame() -> void;
auto refresh() -> void;
auto lookupPalette(u32 index) -> u32;
@@ -91,15 +91,15 @@ protected:
bool _overscan = true;
u32 _rotation = 0; //counter-clockwise (90 = left, 270 = right)
function<n64 (n32)> _color;
unique_pointer<u32[]> _inputA;
unique_pointer<u32[]> _inputB;
unique_pointer<u32[]> _output;
unique_pointer<u32[]> _rotate;
unique_pointer<u32[]> _palette;
vector<n1> _lineOverrideActive;
vector<const u32*> _lineOverride;
vector<Node::Video::Sprite> _sprites;
std::function<n64 (n32)> _color;
std::unique_ptr<u32[]> _inputA;
std::unique_ptr<u32[]> _inputB;
std::unique_ptr<u32[]> _output;
std::unique_ptr<u32[]> _rotate;
std::unique_ptr<u32[]> _palette;
std::vector<n1> _lineOverrideActive;
std::vector<const u32*> _lineOverride;
std::vector<Node::Video::Sprite> _sprites;
//unserialized:
nall::thread _thread;
@@ -108,7 +108,7 @@ protected:
condition_variable _frameCondition;
atomic<bool> _kill = false;
atomic<bool> _frame = false;
function<void ()> _refresh;
std::function<void ()> _refresh;
bool _progressive = false;
bool _progressiveDouble = false;
bool _interlace = false;
+3 -3
View File
@@ -10,13 +10,13 @@ auto Sprite::setPosition(u32 x, u32 y) -> void {
auto Sprite::setImage(nall::image image, bool invert) -> void {
_width = image.width();
_height = image.height();
_pixels = new u32[_width * _height];
_pixels = std::make_unique<u32[]>(_width * _height);
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
memory::copy(_pixels.data(), _width * _height * sizeof(u32), image.data(), image.size());
memory::copy(_pixels.get(), _width * _height * sizeof(u32), image.data(), image.size());
if(!invert) return;
for(u32 y : range(_height)) {
auto data = _pixels.data() + y * _width;
auto data = _pixels.get() + y * _width;
for(u32 x : range(_width)) {
auto pixel = data[x];
pixel ^= 0xffffff;
+2 -2
View File
@@ -7,7 +7,7 @@ struct Sprite : Video {
auto y() const -> u32 { return _y; }
auto width() const -> u32 { return _width; }
auto height() const -> u32 { return _height; }
auto image() const -> array_view<u32> { return {_pixels.data(), _width * _height}; }
auto image() const -> std::span<const u32> { return {_pixels.get(), _width * _height}; }
auto setVisible(bool visible) -> void;
auto setPosition(u32 x, u32 y) -> void;
@@ -19,5 +19,5 @@ protected:
u32 _y = 0;
u32 _width = 0;
u32 _height = 0;
unique_pointer<u32[]> _pixels;
std::unique_ptr<u32[]> _pixels;
};
+1 -1
View File
@@ -13,7 +13,7 @@ enum class Event : u32 {
struct Platform {
virtual auto attach(Node::Object) -> void {}
virtual auto detach(Node::Object) -> void {}
virtual auto pak(Node::Object) -> shared_pointer<vfs::directory> { return {}; }
virtual auto pak(Node::Object) -> std::shared_ptr<vfs::directory> { return {}; }
virtual auto event(Event) -> void {}
virtual auto log(Node::Debugger::Tracer::Tracer, string_view message) -> void {}
virtual auto status(string_view message) -> void {}
+13 -5
View File
@@ -4,6 +4,9 @@ namespace ares {
struct Random {
enum class Entropy : u32 { None, Low, High };
struct Init { u64 seed, sequence; };
static constexpr Init Default { 0x853c49e6748fea9b, 0xda3e39cb94b95bdb };
auto operator()() -> n64 {
return random();
@@ -14,8 +17,8 @@ struct Random {
seed();
}
auto seed(maybe<n32> seed = nothing, maybe<n32> sequence = nothing) -> void {
if(!seed) seed = (n32)clock();
auto seed(maybe<n64> seed = nothing, maybe<n64> sequence = nothing) -> void {
if(!seed) seed = (n64)clock();
if(!sequence) sequence = 0;
_state = 0;
@@ -25,6 +28,10 @@ struct Random {
step();
}
auto seed(Init init) -> void {
seed((n64)init.seed, (n64)init.sequence);
}
auto random() -> n64 {
if(_entropy == Entropy::None) return 0;
return (n64)step() << 32 | (n64)step() << 0;
@@ -43,15 +50,16 @@ struct Random {
}
}
auto array(array_span<n8> buffer) -> void {
auto array(std::span<u8> buffer) -> void {
if(_entropy == Entropy::None) {
memory::fill(buffer.data(), buffer.size());
return;
}
if(_entropy == Entropy::High) {
for(n32 address : range(buffer.size())) {
buffer[address] = random();
while(buffer.size()) {
u64 value = random();
nall::writel(buffer, value, min((u32)sizeof(value), (u32)buffer.size()));
}
return;
}
+4 -4
View File
@@ -1,5 +1,5 @@
inline auto Scheduler::reset() -> void {
_threads.reset();
_threads.clear();
}
inline auto Scheduler::threads() const -> u32 {
@@ -41,15 +41,15 @@ inline auto Scheduler::maximum() const -> u64 {
}
inline auto Scheduler::append(Thread& thread) -> bool {
if(_threads.find(&thread)) return false;
if(std::ranges::find(_threads, &thread) != _threads.end()) return false;
thread._uniqueID = uniqueID();
thread._clock = maximum() + thread._uniqueID;
_threads.append(&thread);
_threads.push_back(&thread);
return true;
}
inline auto Scheduler::remove(Thread& thread) -> void {
_threads.removeByValue(&thread);
std::erase(_threads, &thread);
}
//power cycle and soft reset events: assigns the primary thread and resets all thread clocks.
+1 -1
View File
@@ -38,7 +38,7 @@ private:
cothread_t _primary = nullptr; //primary thread (used to synchronize components)
Mode _mode = Mode::Run;
Event _event = Event::Step;
vector<Thread*> _threads;
std::vector<Thread*> _threads;
bool _synchronize = false;
friend struct Thread;
+7 -7
View File
@@ -1,5 +1,5 @@
inline auto Thread::EntryPoints() -> vector<EntryPoint>& {
static vector<EntryPoint> entryPoints;
inline auto Thread::EntryPoints() -> std::vector<EntryPoint>& {
static std::vector<EntryPoint> entryPoints;
return entryPoints;
}
@@ -7,7 +7,7 @@ inline auto Thread::Enter() -> void {
for(u32 index : range(EntryPoints().size())) {
if(co_active() == EntryPoints()[index].handle) {
auto entryPoint = EntryPoints()[index].entryPoint;
EntryPoints().remove(index);
EntryPoints().erase(EntryPoints().begin() + index);
while(true) {
scheduler.synchronize();
entryPoint();
@@ -45,22 +45,22 @@ inline auto Thread::setClock(u64 clock) -> void {
_clock = clock;
}
inline auto Thread::create(double frequency, function<void ()> entryPoint) -> void {
inline auto Thread::create(double frequency, std::function<void ()> entryPoint) -> void {
if(!_handle) {
_handle = co_create(Thread::Size, &Thread::Enter);
} else {
co_derive(_handle, Thread::Size, &Thread::Enter);
}
EntryPoints().append({_handle, entryPoint});
EntryPoints().push_back({_handle, entryPoint});
setFrequency(frequency);
setClock(0);
scheduler.append(*this);
}
//returns a thread to its entry point (eg for a reset), without resetting the clock value
inline auto Thread::restart(function<void()> entryPoint) -> void {
inline auto Thread::restart(std::function<void()> entryPoint) -> void {
co_derive(_handle, Thread::Size, &Thread::Enter);
EntryPoints().append({_handle, entryPoint});
EntryPoints().push_back({_handle, entryPoint});
}
inline auto Thread::destroy() -> void {
+4 -4
View File
@@ -6,10 +6,10 @@ struct Thread {
struct EntryPoint {
cothread_t handle = nullptr;
function<void ()> entryPoint;
std::function<void ()> entryPoint;
};
static auto EntryPoints() -> vector<EntryPoint>&;
static auto EntryPoints() -> std::vector<EntryPoint>&;
static auto Enter() -> void;
Thread() = default;
@@ -29,8 +29,8 @@ struct Thread {
auto setScalar(u64 scalar) -> void;
auto setClock(u64 clock) -> void;
auto create(double frequency, function<void ()> entryPoint) -> void;
auto restart(function<void ()> entryPoint) -> void;
auto create(double frequency, std::function<void ()> entryPoint) -> void;
auto restart(std::function<void ()> entryPoint) -> void;
auto destroy() -> void;
auto step(u32 clocks) -> void;
+2 -1
View File
@@ -1,6 +1,6 @@
list(REMOVE_DUPLICATES ares.components)
set(ARES_COMPONENTS_LIST "${ares.components}" CACHE LIST "Enabled shared hardware components" FORCE)
set(ARES_COMPONENTS_LIST "${ares.components}" CACHE STRING "Enabled shared hardware components" FORCE)
mark_as_advanced(ARES_COMPONENTS_LIST)
@@ -138,6 +138,7 @@ component_sources(
INCLUDED
processor/arm7tdmi/algorithms.cpp
processor/arm7tdmi/arm7tdmi.hpp
processor/arm7tdmi/coprocessor.cpp
processor/arm7tdmi/disassembler.cpp
processor/arm7tdmi/instruction.cpp
processor/arm7tdmi/instructions-arm.cpp
+4 -2
View File
@@ -135,10 +135,10 @@ auto YM2149::read() -> n8 {
data.bit(4,7) = envelope.unused;
break;
case 14:
data.bit(0,7) = portA.data;
data.bit(0,7) = readIO(0);
break;
case 15:
data.bit(0,7) = portB.data;
data.bit(0,7) = readIO(1);
break;
}
@@ -215,9 +215,11 @@ auto YM2149::write(n8 data) -> void {
break;
case 14:
portA.data = data;
writeIO(0, data);
break;
case 15:
portB.data = data;
writeIO(1, data);
break;
}
}
+3
View File
@@ -5,6 +5,9 @@ namespace ares {
//Yamaha YM2149 (General Instrument AY-3-8910 derivative)
struct YM2149 {
virtual auto readIO(n1 port) -> n8 { return 0xff; }
virtual auto writeIO(n1 port, n8 data) -> void {}
//ym2149.cpp
auto clock() -> array<n5[3]>;
auto read() -> n8;
+1 -1
View File
@@ -15,7 +15,7 @@ auto M24C::serialize(serializer& s) -> void {
s(output);
s(response);
s(writable);
s(array_span<u8>{memory, size()});
s(std::span<n8>{memory, size()});
if(type >= Type::M24C32) s(idpage);
s(locked);
}
+11 -11
View File
@@ -136,7 +136,7 @@ struct ARM7TDMI {
}
n32 data;
function<auto () -> void> modify;
std::function<auto () -> void> modify;
};
struct PSR {
@@ -248,17 +248,17 @@ struct ARM7TDMI {
b1 irq;
b1 nonsequential;
function<void (n32 opcode)> armInstruction[4096];
function<void ()> thumbInstruction[65536];
std::function<void (n32 opcode)> armInstruction[4096];
std::function<void ()> thumbInstruction[65536];
//coprocessor.cpp
auto bindCDP(n4 id, function<void (n4 cm, n3 op2, n4 cd, n4 cn, n4 op1)> handler) -> void;
auto bindMCR(n4 id, function<void (n32 data, n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void;
auto bindMRC(n4 id, function<n32 (n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void;
auto bindCDP(n4 id, std::function<void (n4 cm, n3 op2, n4 cd, n4 cn, n4 op1)> handler) -> void;
auto bindMCR(n4 id, std::function<void (n32 data, n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void;
auto bindMRC(n4 id, std::function<n32 (n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void;
function<void (n4 cm, n3 op2, n4 cd, n4 cn, n4 op1)> CDP[16];
function<void (n32 data, n4 cm, n3 op2, n4 cn, n3 op1)> MCR[16];
function<n32 (n4 cm, n3 op2, n4 cn, n3 op1)> MRC[16];
std::function<void (n4 cm, n3 op2, n4 cd, n4 cn, n4 op1)> CDP[16];
std::function<void (n32 data, n4 cm, n3 op2, n4 cn, n3 op1)> MCR[16];
std::function<n32 (n4 cm, n3 op2, n4 cn, n3 op1)> MRC[16];
//disassembler.cpp
auto armDisassembleBranch(i24, n1) -> string;
@@ -310,8 +310,8 @@ struct ARM7TDMI {
auto thumbDisassembleStackMultiple(n8, n1, n1) -> string;
auto thumbDisassembleUndefined() -> string;
function<string (n32 opcode)> armDisassemble[4096];
function<string ()> thumbDisassemble[65536];
std::function<string (n32 opcode)> armDisassemble[4096];
std::function<string ()> thumbDisassemble[65536];
n32 _pc;
string _c;
@@ -1,11 +1,11 @@
auto ARM7TDMI::bindCDP(n4 id, function<void (n4 cm, n3 op2, n4 cd, n4 cn, n4 op1)> handler) -> void {
auto ARM7TDMI::bindCDP(n4 id, std::function<void (n4 cm, n3 op2, n4 cd, n4 cn, n4 op1)> handler) -> void {
CDP[id] = handler;
}
auto ARM7TDMI::bindMCR(n4 id, function<void (n32 data, n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void {
auto ARM7TDMI::bindMCR(n4 id, std::function<void (n32 data, n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void {
MCR[id] = handler;
}
auto ARM7TDMI::bindMRC(n4 id, function<n32 (n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void {
auto ARM7TDMI::bindMRC(n4 id, std::function<n32 (n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void {
MRC[id] = handler;
}
@@ -442,8 +442,8 @@ auto ARM7TDMI::armInitialize() -> void {
auto ARM7TDMI::thumbInitialize() -> void {
#define bind(id, name, ...) { \
assert(!thumbInstruction[id]); \
thumbInstruction[id] = [=] { return thumbInstruction##name(__VA_ARGS__); }; \
thumbDisassemble[id] = [=] { return thumbDisassemble##name(__VA_ARGS__); }; \
thumbInstruction[id] = [=, this] { return thumbInstruction##name(__VA_ARGS__); }; \
thumbDisassemble[id] = [=, this] { return thumbDisassemble##name(__VA_ARGS__); }; \
}
#define pattern(s) \
+2 -2
View File
@@ -180,8 +180,8 @@ protected:
} io;
n23 stack[8];
function<void ()> instructionTable[65536];
function<string ()> disassembleTable[65536];
std::function<void ()> instructionTable[65536];
std::function<string ()> disassembleTable[65536];
auto disassembleADD(n7 reg, n5 shift) -> string;
auto disassembleADD(n8 imm, n5 shift) -> string;
@@ -1,8 +1,8 @@
HG51B::HG51B() {
#define bind(id, name, ...) { \
if(instructionTable[id]) throw; \
instructionTable[id] = [=] { return instruction##name(__VA_ARGS__); }; \
disassembleTable[id] = [=] { return disassemble##name(__VA_ARGS__); }; \
instructionTable[id] = [=, this] { return instruction##name(__VA_ARGS__); }; \
disassembleTable[id] = [=, this] { return disassemble##name(__VA_ARGS__); }; \
}
#define pattern(s) \
@@ -163,7 +163,7 @@ auto HuC6280::disassembleInstruction() -> string {
n8 opcode = readByte();
#define op(id, name, ...) case id: o = {name, " ", vector<string>{__VA_ARGS__}.merge(",")}; break;
#define op(id, name, ...) case id: o = {name, " ", nall::merge({__VA_ARGS__}, ",")}; break;
string o;
#define U
@@ -41,7 +41,7 @@ auto I8080::disassembleContext() -> string {
return s;
}
#define op(id, name, ...) case id: return {name, " ", vector<string>{__VA_ARGS__}.merge(",")};
#define op(id, name, ...) case id: return {name, " ", nall::merge({__VA_ARGS__}, ",")};
#define N string{"$", hex(byte(), 2L)}
#define IN string{"(", N, ")"}
@@ -10,13 +10,13 @@ auto M68000::instruction() -> void {
M68000::M68000() {
#define bind(id, name, ...) { \
assert(!instructionTable[id]); \
instructionTable[id] = [=] { return instruction##name(__VA_ARGS__); }; \
disassembleTable[id] = [=] { return disassemble##name(__VA_ARGS__); }; \
instructionTable[id] = [=, this] { return instruction##name(__VA_ARGS__); }; \
disassembleTable[id] = [=, this] { return disassemble##name(__VA_ARGS__); }; \
}
#define unbind(id) { \
instructionTable[id].reset(); \
disassembleTable[id].reset(); \
instructionTable[id] = {}; \
disassembleTable[id] = {}; \
}
#define pattern(s) \
@@ -752,7 +752,12 @@ template<u32 Size> auto M68000::instructionMOVEM_TO_MEM(EffectiveAddress to) ->
if(to.mode == AddressRegisterIndirectWithPreDecrement) addr -= bytes<Size>();
auto data = index < 8 ? read<Size>(DataRegister{index}) : read<Size>(AddressRegister{index});
write<Size>(addr, data);
if(to.mode == AddressRegisterIndirectWithPreDecrement) {
//pre-decrement mode writes longwords in reverse-word order (low word before high)
write<Size, Reverse>(addr, data);
} else {
write<Size>(addr, data);
}
if(to.mode != AddressRegisterIndirectWithPreDecrement) addr += bytes<Size>();
}
+2 -2
View File
@@ -300,7 +300,7 @@ struct M68000 {
bool reset;
} r;
function<void ()> instructionTable[65536];
std::function<void ()> instructionTable[65536];
private:
//disassembler.cpp
@@ -434,7 +434,7 @@ private:
auto _condition(n4 condition) -> string;
n32 _pc;
function<string ()> disassembleTable[65536];
std::function<string ()> disassembleTable[65536];
};
}
@@ -6,8 +6,8 @@ auto MOS6502::addressAbsolute() -> n16 {
auto MOS6502::addressAbsoluteJMP() -> n16 {
n16 absolute = operand();
// JMP Indirect last_cycle
L absolute |= operand() << 8;
// JMP Indirect last cycle
L absolute |= operand() << 8;
return absolute;
}
@@ -39,10 +39,6 @@ auto MOS6502::addressAbsoluteYWrite() -> n16 {
return absolute + Y;
}
auto MOS6502::addressAccumulator() -> n16 {
return PC;
}
auto MOS6502::addressImmediate() -> n16 {
return PC++;
}
@@ -56,8 +52,8 @@ auto MOS6502::addressIndirect() -> n16 {
absolute |= operand() << 8;
n16 indirect = read(absolute);
absolute.byte(0)++;
// JMP Indirect last_cycle
L indirect |= read(absolute) << 8;
// JMP Indirect last cycle
L indirect |= read(absolute) << 8;
return indirect;
}
@@ -210,10 +210,12 @@ auto MOS6502::algorithmJMP() -> void {
}
auto MOS6502::algorithmJSR() -> void {
PC--;
n16 target = operand();
MDR = read(0x0100 | S); // dummy stack read
push(PCH);
L push(PCL);
PC = MAR;
push(PCL);
L target |= operand() << 8;
PC = target;
}
auto MOS6502::algorithmLDA() -> void {
@@ -257,8 +259,8 @@ auto MOS6502::algorithmORA() -> void {
}
auto MOS6502::algorithmPHA() -> void {
read(MAR); // dummy implied read
L push(A);
read(MAR); // dummy implied read
L push(A);
}
auto MOS6502::algorithmPHP() -> void {
@@ -24,7 +24,7 @@ auto MOS6502::reset() -> void {
read(0x0100 | S--); // Dummy push (P)
I = 1;
PCL = read(vector++);
L PCH = read(vector++);
L PCH = read(vector++);
resetting = 0;
}
@@ -42,7 +42,7 @@ auto MOS6502::instruction() -> void {
op(0x07, Modify, addr(ZeroPage), fp(SLO))
op(0x08, None, addr(Implied), fp(PHP))
op(0x09, Load, addr(Immediate), fp(ORA))
op(0x0a, Load, addr(Accumulator), fp(ASLA))
op(0x0a, Load, addr(Implied), fp(ASLA))
op(0x0b, Load, addr(Immediate), fp(AAC))
op(0x0c, Load, addr(Absolute), fp(NOP))
op(0x0d, Load, addr(Absolute), fp(ORA))
@@ -64,7 +64,7 @@ auto MOS6502::instruction() -> void {
op(0x1d, Load, addr(AbsoluteXRead), fp(ORA))
op(0x1e, Modify, addr(AbsoluteXWrite), fp(ASLM))
op(0x1f, Modify, addr(AbsoluteXWrite), fp(SLO))
op(0x20, Load, addr(Absolute), fp(JSR))
op(0x20, None, addr(Implied), fp(JSR))
op(0x21, Load, addr(IndirectX), fp(AND))
op(0x22, None, addr(Implied), fp(JAM))
op(0x23, Modify, addr(IndirectX), fp(RLA))
@@ -40,7 +40,6 @@ struct MOS6502 {
auto addressAbsoluteXWrite() -> n16;
auto addressAbsoluteYRead() -> n16;
auto addressAbsoluteYWrite() -> n16;
auto addressAccumulator() -> n16;
auto addressImmediate() -> n16;
auto addressImplied() -> n16;
auto addressIndirect() -> n16;
@@ -6,7 +6,7 @@ auto SH2::hint(P&&... p) const -> string {
}
auto SH2::disassembleInstruction(u16 opcode) -> string {
vector<string> s;
std::vector<string> s;
auto registerName = [&](u32 r) -> string {
return {"r", r};
@@ -512,10 +512,10 @@ auto SH2::disassembleInstruction(u16 opcode) -> string {
break;
}
if(!s) s = {"illegal", {"0x", hex(opcode, 4L)}};
auto name = s.takeFirst();
if(s.empty()) s = {"illegal", {"0x", hex(opcode, 4L)}};
auto name = s.front(); s.erase(s.begin());
while(name.size() < 8) name.append(" ");
string r = {name, s.merge(",")};
string r = {name, nall::merge(s, ",")};
while(r.size() < 30) r.append(" ");
return r;
}
+13 -13
View File
@@ -705,7 +705,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//BRA disp
case range16(0xa0, 0xaf): {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
add32(PPC, PC, imm(4 + (i12)d12 * 2));
mov32(PPM, imm(Branch::Slot));
});
@@ -714,7 +714,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//BSR disp
case range16(0xb0, 0xbf): {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
mov32(reg(0), PC);
mov32(PR, reg(0));
add32(reg(0), reg(0), imm(4 + (i12)d12 * 2));
@@ -807,7 +807,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//BT disp
case 0x89: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
auto skip = cmp32_jump(T, imm(0), flag_eq);
add32(PPC, PC, imm(4 + (s8)d8 * 2));
mov32(PPM, imm(Branch::Take));
@@ -818,7 +818,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//BF disp
case 0x8b: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
auto skip = cmp32_jump(T, imm(0), flag_ne);
add32(PPC, PC, imm(4 + (s8)d8 * 2));
mov32(PPM, imm(Branch::Take));
@@ -829,7 +829,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//BT/S disp
case 0x8d: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
auto skip = cmp32_jump(T, imm(0), flag_eq);
add32(PPC, PC, imm(4 + (s8)d8 * 2));
mov32(PPM, imm(Branch::Slot));
@@ -840,7 +840,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//BF/S disp
case 0x8f: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
auto skip = cmp32_jump(T, imm(0), flag_ne);
add32(PPC, PC, imm(4 + (s8)d8 * 2));
mov32(PPM, imm(Branch::Slot));
@@ -875,7 +875,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//TRAPA #imm
case 0xc3: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
getSR(reg(2));
sub32(reg(1), R15, imm(4));
mov32(R15, reg(1));
@@ -1022,7 +1022,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//BSRF Rm
case 0x003: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
mov32(reg(0), PC);
mov32(PR, reg(0));
add32(reg(0), reg(0), Rm);
@@ -1059,7 +1059,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//BRAF Rm
case 0x023: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
add32(reg(0), PC, Rm);
add32(reg(0), reg(0), imm(4));
mov32(PPC, reg(0));
@@ -1168,7 +1168,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//JSR @Rm
case 0x40b: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
mov32(PR, PC);
add32(PPC, Rm, imm(4));
mov32(PPM, imm(Branch::Slot));
@@ -1370,7 +1370,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//JMP @Rm
case 0x42b: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
add32(PPC, Rm, imm(4));
mov32(PPM, imm(Branch::Slot));
});
@@ -1405,7 +1405,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//RTS
case 0x000b: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
add32(PPC, PR, imm(4));
mov32(PPM, imm(Branch::Slot));
});
@@ -1447,7 +1447,7 @@ auto SH2::Recompiler::emitInstruction(u16 opcode) -> u32 {
//RTE
case 0x002b: {
checkDelaySlot([=] {
checkDelaySlot([=, this] {
mov32(reg(1), R15);
add32(R15, reg(1), imm(4));
call(readL);
+3 -3
View File
@@ -283,8 +283,8 @@ struct SH2 {
auto reset() -> void {
generation = 0;
blocks.reset();
pools.reallocate(1 << 24);
pools.fill();
pools.resize(1 << 24);
std::ranges::fill(pools, nullptr);
}
auto invalidateCached() -> void {
@@ -312,7 +312,7 @@ struct SH2 {
bump_allocator allocator;
hashset<BlockHashPair> blocks;
u16 instructions[1 << 7];
vector<Pool*> pools;
std::vector<Pool*> pools;
} recompiler{*this};
#include "sh7604/sh7604.hpp"
@@ -17,7 +17,7 @@ auto V30MZ::disassembleInstruction(u16 ps, u16 pc) -> string {
return offset;
};
auto instruction = [&](string_view name) -> string {
auto instruction = [&](string name) -> string {
if(name.size() >= 7) return name;
return pad(name, -7);
};
@@ -150,7 +150,7 @@ auto V30MZ::disassembleInstruction(u16 ps, u16 pc) -> string {
};
#define op(id, name, ...) case id: \
output.append(instruction(name), vector<string>{__VA_ARGS__}.merge(",")); \
output.append(instruction(name), nall::merge({__VA_ARGS__}, ",")); \
break
auto opcode = read(0);
@@ -56,7 +56,7 @@ auto Z80::disassembleContext() -> string {
return s;
}
#define op(id, name, ...) case id: return {name, " ", vector<string>{__VA_ARGS__}.merge(",")};
#define op(id, name, ...) case id: return {name, " ", nall::merge({__VA_ARGS__}, ",")};
#define N string{"$", hex(byte(), 2L)}
#define IN string{"(", N, ")"}
+1 -1
View File
@@ -1,5 +1,5 @@
auto S3511A::serialize(serializer& s) -> void {
s(array_span<u8>{data, size});
s(std::span<n8>{data, size});
s(cs);
s(sio);
+3 -3
View File
@@ -27,11 +27,11 @@ auto TMS9918::main() -> void {
background.run(x, y);
sprite.run(x, y);
dac.run(x, y);
step(1);
step(2);
}
step(200);
step(172);
} else {
step(456);
step(684);
}
io.vcounter++;
+3 -3
View File
@@ -34,9 +34,9 @@ auto V9938::main() -> void {
tick(1);
}
tick(200);
tick(86);
} else {
tick(456);
tick(342);
}
io.hcounter = 0;
@@ -71,7 +71,7 @@ auto V9938::tick(u32 clocks) -> void {
io.hcounter += clocks;
while(clocks--) {
command();
step(1);
step(2);
}
}
+4 -4
View File
@@ -19,12 +19,12 @@ auto Cartridge::connect() -> void {
information.region = pak->attribute("region");
information.board = pak->attribute("board");
if(information.board == "xin1") board = new Board::xin1{*this};
if(information.board == "coleco") board = new Board::coleco{*this};
if(information.board == "megacart") board = new Board::megacart{*this};
if(information.board == "xin1") board = std::make_unique<Board::xin1>(*this);
if(information.board == "coleco") board = std::make_unique<Board::coleco>(*this);
if(information.board == "megacart") board = std::make_unique<Board::megacart>(*this);
if(!board) board = new Board::Interface{*this};
if(!board) board = std::make_unique<Board::Interface>(*this);
board->pak = pak;
board->load();
power();
+1 -1
View File
@@ -22,7 +22,7 @@ struct Cartridge {
//serialization.cpp
auto serialize(serializer&) -> void;
unique_pointer<Board::Interface> board;
std::unique_ptr<Board::Interface> board;
//private:
struct Information {
+1 -1
View File
@@ -20,7 +20,7 @@ auto ControllerPort::unload() -> void {
}
auto ControllerPort::allocate(string name) -> Node::Peripheral {
if(name == "Gamepad") device = new Gamepad(port);
if(name == "Gamepad") device = std::make_unique<Gamepad>(port);
if(device) return device->node;
return {};
}
+1 -1
View File
@@ -1,6 +1,6 @@
struct ControllerPort {
Node::Port port;
unique_pointer<Controller> device;
std::unique_ptr<Controller> device;
//port.cpp
ControllerPort(string name);
+1 -1
View File
@@ -57,7 +57,7 @@ auto CPU::setIRQ(bool value) -> void {
auto CPU::power() -> void {
Z80::bus = this;
Z80::power();
Thread::create(system.colorburst(), {&CPU::main, this});
Thread::create(system.colorburst(), std::bind_front(&CPU::main, this));
PC = 0x0000; //reset vector address
state = {};
+2 -1
View File
@@ -2,6 +2,7 @@
//started: 2019-02-19
#include <ares/ares.hpp>
#include <vector>
#include <component/processor/z80/z80.hpp>
#include <component/video/tms9918/tms9918.hpp>
@@ -9,7 +10,7 @@
namespace ares::ColecoVision {
#include <ares/inline.hpp>
auto enumerate() -> vector<string>;
auto enumerate() -> std::vector<string>;
auto load(Node::System& node, string name) -> bool;
struct Model {
+1 -1
View File
@@ -38,7 +38,7 @@ auto PSG::step(u32 clocks) -> void {
auto PSG::power() -> void {
SN76489::power();
Thread::create(system.colorburst() / 16.0, {&PSG::main, this});
Thread::create(system.colorburst() / 16.0, std::bind_front(&PSG::main, this));
for(u32 level : range(15)) {
volume[level] = pow(2, level * -2.0 / 6.0);
+13 -11
View File
@@ -1,8 +1,9 @@
#include <cv/cv.hpp>
#include <algorithm>
namespace ares::ColecoVision {
auto enumerate() -> vector<string> {
auto enumerate() -> std::vector<string> {
return {
"[Coleco] ColecoVision (NTSC)",
"[Coleco] ColecoVision (PAL)",
@@ -12,7 +13,8 @@ auto enumerate() -> vector<string> {
}
auto load(Node::System& node, string name) -> bool {
if(!enumerate().find(name)) return false;
auto list = enumerate();
if(std::find(list.begin(), list.end(), name) == list.end()) return false;
return system.load(node, name);
}
@@ -55,20 +57,20 @@ auto System::load(Node::System& root, string name) -> bool {
information.colorburst = Constants::Colorburst::PAL * 4.0 / 5.0;
}
node = Node::System::create(information.name);
node = std::make_shared<Core::System>(information.name);
node->setAttribute("configuration", name);
node->setGame({&System::game, this});
node->setRun({&System::run, this});
node->setPower({&System::power, this});
node->setSave({&System::save, this});
node->setUnload({&System::unload, this});
node->setSerialize({&System::serialize, this});
node->setUnserialize({&System::unserialize, this});
node->setGame(std::bind_front(&System::game, this));
node->setRun(std::bind_front(&System::run, this));
node->setPower(std::bind_front(&System::power, this));
node->setSave(std::bind_front(&System::save, this));
node->setUnload(std::bind_front(&System::unload, this));
node->setSerialize([this](bool save) -> serializer { return serialize(save); });
node->setUnserialize(std::bind_front(&System::unserialize, this));
root = node;
if(!node->setPak(pak = platform->pak(node))) return false;
if(auto fp = pak->read("bios.rom")) {
fp->read({bios, 0x2000});
fp->read(bios, 0x2000);
}
scheduler.reset();
+2 -2
View File
@@ -12,7 +12,7 @@ auto VDP::load(Node::Object parent) -> void {
node = parent->append<Node::Object>("VDP");
screen = node->append<Node::Video::Screen>("Screen", 284, 243);
screen->colors(1 << 4, {&VDP::color, this});
screen->colors(1 << 4, std::bind_front(&VDP::color, this));
screen->setSize(284, 243);
screen->setScale(1.0, 1.0);
screen->setAspect(8.0, 7.0);
@@ -59,7 +59,7 @@ auto VDP::frame() -> void {
auto VDP::power() -> void {
TMS9918::power();
Thread::create(system.colorburst() * 2, [&] { main(); });
Thread::create(system.colorburst() * 3, [&] { main(); });
screen->power();
}
+4 -5
View File
@@ -73,11 +73,11 @@ auto APU::tick() -> void {
}
auto APU::setIRQ() -> void {
cpu.apuLine(frame.irqPending | dmc.irqPending);
cpu.apuLine((frame.irqPending & ~frame.irqInhibit) | dmc.irqPending);
}
auto APU::power(bool reset) -> void {
Thread::create(system.frequency(), {&APU::main, this});
Thread::create(system.frequency(), std::bind_front(&APU::main, this));
pulse1.power(reset);
pulse2.power(reset);
@@ -100,11 +100,10 @@ auto APU::readIO(n16 address) -> n8 {
data.bit(2) = (bool)triangle.length.counter;
data.bit(3) = (bool)noise.length.counter;
data.bit(4) = (bool)dmc.lengthCounter;
data.bit(5) = 0;
//bit 5 is open bus
data.bit(6) = frame.irqPending;
data.bit(7) = dmc.irqPending;
frame.irqPending = false;
setIRQ();
frame.delayIRQ = true;
return data;
}
+2 -2
View File
@@ -199,8 +199,8 @@ struct APU : Thread {
n16 counter;
bool odd;
bool delay;
n3 delayCounter;
bool delayIRQ;
bool delayCounter[2];
constexpr static u16 periodNTSC[2][6] = {
{ 7457, 7456, 7458, 7457, 1, 1, },
+28 -25
View File
@@ -2,17 +2,25 @@ auto APU::FrameCounter::main() -> void {
--counter;
odd = !odd;
if (delay && --delayCounter == 0) {
delay = false;
step = 0;
counter = getPeriod() + 2;
if (mode == Freq48Hz) {
apu.clockHalfFrame();
if(!odd) {
//IRQ is reset on next GET cycle
if(delayIRQ) {
delayIRQ = false;
irqPending = 0;
apu.setIRQ();
}
//counter is reloaded on GET cycle after next
if(delayCounter[0]) {
step = 0;
counter = getPeriod();
if(mode == Freq48Hz) apu.clockHalfFrame();
}
delayCounter[0] = delayCounter[1];
delayCounter[1] = false;
}
if (counter != 0)
return;
if(counter != 0) return;
switch(step) {
case 0:
@@ -29,21 +37,22 @@ auto APU::FrameCounter::main() -> void {
break;
case 3:
step = 4;
if (mode == Freq60Hz && irqInhibit == 0)
irqPending = 1;
if(mode == Freq60Hz) irqPending = 1;
break;
case 4:
step = 5;
apu.clockHalfFrame();
if (mode == Freq60Hz && irqInhibit == 0) {
if(mode == Freq60Hz) {
irqPending = 1;
apu.setIRQ();
}
break;
case 5:
step = 0;
if (mode == Freq60Hz && irqInhibit == 0)
irqPending = 1;
if(mode == Freq60Hz) {
irqPending = ~irqInhibit;
apu.setIRQ();
}
break;
}
@@ -52,30 +61,24 @@ auto APU::FrameCounter::main() -> void {
auto APU::FrameCounter::power(bool reset) -> void {
irqInhibit = 0;
if (!reset) mode = Freq60Hz;
if(!reset) mode = Freq60Hz;
irqPending = 0;
step = 0;
counter = getPeriod();
odd = true;
delay = false;
delayCounter = 0;
delayIRQ = false;
delayCounter[0] = false;
delayCounter[1] = false;
}
auto APU::FrameCounter::write(n8 data) -> void {
mode = data.bit(7);
delay = true;
// If the write occurs during an APU cycle,
// the effects occur 3 CPU cycles after the
// $4017 write cycle, and if the write occurs
// between APU cycles, the effects occurs 4 CPU
// cycles after the write cycle.
delayCounter = odd ? 1 : 2;
delayCounter[1] = true;
irqInhibit = data.bit(6);
if (irqInhibit) {
if(irqInhibit) {
irqPending = 0;
apu.setIRQ();
}
+3 -2
View File
@@ -3,6 +3,7 @@ auto APU::serialize(serializer& s) -> void {
s(pulse1);
s(pulse2);
s(triangle);
s(noise);
s(dmc);
s(frame);
}
@@ -95,6 +96,6 @@ auto APU::FrameCounter::serialize(serializer& s) -> void {
s(counter);
s(odd);
s(delay);
s(delayCounter);
s(delayIRQ);
for(auto& delay : delayCounter) s(delay);
}
+2 -2
View File
@@ -18,7 +18,7 @@ struct BandaiLZ93D50 : Interface {
if(auto fp = pak->read("save.eeprom")) {
if(fp->size() == 128) eeprom.load(M24C::Type::X24C01);
if(fp->size() == 256) eeprom.load(M24C::Type::M24C02);
if(eeprom) fp->read({eeprom.memory, eeprom.size()});
if(eeprom) fp->read(eeprom.memory, eeprom.size());
}
}
@@ -26,7 +26,7 @@ struct BandaiLZ93D50 : Interface {
Interface::save(programRAM, "save.ram");
Interface::save(characterRAM, "character.ram");
if(auto fp = pak->write("save.eeprom")) {
if(eeprom) fp->write({eeprom.memory, eeprom.size()});
if(eeprom) fp->write(eeprom.memory, eeprom.size());
}
}
+2 -2
View File
@@ -18,7 +18,7 @@ auto Cartridge::connect() -> void {
information.title = pak->attribute("title");
information.region = pak->attribute("region");
board = Board::Interface::create(pak->attribute("board"));
board.reset(Board::Interface::create(pak->attribute("board")));
board->pak = pak;
board->load();
@@ -47,7 +47,7 @@ auto Cartridge::save() -> void {
}
auto Cartridge::power() -> void {
Thread::create(system.frequency(), {&Cartridge::main, this});
Thread::create(system.frequency(), std::bind_front(&Cartridge::main, this));
board->power();
}
+1 -1
View File
@@ -27,7 +27,7 @@ struct Cartridge : Thread {
} information;
//privileged:
unique_pointer<Board::Interface> board;
std::unique_ptr<Board::Interface> board;
auto readPRG(n32 address, n8 data) -> n8;
auto writePRG(n32 address, n8 data) -> void;
+2 -2
View File
@@ -20,8 +20,8 @@ auto ControllerPort::unload() -> void {
}
auto ControllerPort::allocate(string name) -> Node::Peripheral {
if(name == "Gamepad") device = new Gamepad(port);
if(name == "Zapper") device = new Zapper(port);
if(name == "Gamepad") device = std::make_unique<Gamepad>(port);
if(name == "Zapper") device = std::make_unique<Zapper>(port);
if(device) return device->node;
return {};
}
+1 -1
View File
@@ -1,6 +1,6 @@
struct ControllerPort {
Node::Port port;
unique_pointer<Controller> device;
std::unique_ptr<Controller> device;
ControllerPort(string name);
auto load(Node::Object) -> void;
+1 -1
View File
@@ -42,7 +42,7 @@ auto CPU::step(u32 clocks) -> void {
auto CPU::power(bool reset) -> void {
MOS6502::BCD = 0;
MOS6502::power(reset);
Thread::create(system.frequency(), {&CPU::main, this});
Thread::create(system.frequency(), std::bind_front(&CPU::main, this));
if(!reset) {
ram.fill(0xff);
+3 -2
View File
@@ -3,9 +3,10 @@ auto CPU::read(n16 address) -> n8 {
dma(address);
}
io.openBus = readBus(address);
n8 data = readBus(address);
if(address != 0x4015) io.openBus = data;
step(rate());
return io.openBus;
return data;
}
auto CPU::write(n16 address, n8 data) -> void {
+1 -1
View File
@@ -14,7 +14,7 @@ EPSM::EPSM(Node::Port parent) : ymf288(interface) {
ymf288.reset();
clocksPerSample = clocksPerSample = 8_MHz / ymf288.sample_rate(8_MHz);
Thread::create(8_MHz, {&EPSM::main, this});
Thread::create(8_MHz, std::bind_front(&EPSM::main, this));
}
EPSM::~EPSM() {
+2 -2
View File
@@ -19,8 +19,8 @@ auto ExpansionPort::unload() -> void {
}
auto ExpansionPort::allocate(string name) -> Node::Peripheral {
if(name == "EPSM") device = new EPSM(port);
if(name == "Family Keyboard") device = new FamilyKeyboard(port);
if(name == "EPSM") device = std::make_unique<EPSM>(port);
if(name == "Family Keyboard") device = std::make_unique<FamilyKeyboard>(port);
if(device) return device->node;
return {};
}
+1 -1
View File
@@ -1,6 +1,6 @@
struct ExpansionPort {
Node::Port port;
unique_pointer<Expansion> device;
std::unique_ptr<Expansion> device;
ExpansionPort(string name);
auto load(Node::Object) -> void;
Loaded 100 of 972 files, more files were not shown because too many files have changed in this diff. Show more