The previous formula was a decent approximation, but it looks like 6105
antipiracy protection requires a better one (in addition to better RSP
timings that already went in).
Fixes#129 (Jet Force Gemini and Mickey Speedway USA)
Implement pipeline stall conditions for the RSP's scalar unit (SU).
Tested against real hardware with a random instruction stream generator.
Vector unit (VU) timing, including dual issue with the SU, is not yet
implemented.
When an interlaced output is made by the game, an N64 emulator right now only allows "Bob" deinterlacing, this commit also adds a "Weave" deinterlace option
like all of these computers, loading cassette tape games is awkward,
requiring the user to know what format data the tape contains.
The following basic commands are used to load cassette tapes:
Binary Data: `BLOAD"CAS:",R`
Tokenized Basic: `CLOAD`
ASCII `RUN"CAS:"`
This introduces a faster version of tlb.Load which omits exception and debug checks in
instructionEpilogue; as it is assumed these checks are handled sufficiently by the recompiler
instruction fetch phase before execution.
Additionally, this also introduces a simple cache that caches the virtual to physical mapping
for a single 4k page; this prevents per-instruction lookups within recompiled block; and is
cleared when the TLB is written to, so should never become stale.
It is too slow to be usable with the rest of ares,
Now that macOS can run Parallel-RDP with MoltenVK, there is little reason
to keep this around.
We can just say that Vulkan is *required* for the N64 core going forward.
This reduces the total number of function calls made in each loop of system->run()
n64: add fast variant of devirtualize; fix remaining task from PR #1069
to scale according to cardinalMax, rename startCardinalMax and others for better clarity, and reformulate startCardinalMax based on new response equation.
54bfb871c Merge pull request #99 from scribam/dr_libs
5cd76b97e Revert "deps: add dr_libs as a header-only library"
903f2f5cc Merge pull request #93 from scribam/deps
1ccead153 deps: add dr_libs as a header-only library
3c6e0e47a deps: add zlib-1.2.13
8e04476eb deps: remove zlib 1.2.11 and zlib 1.2.12
468490000 Merge pull request #97 from scribam/github-workflows
b2996c832 Add basic GitHub Actions
688759416 Merge pull request #96 from scribam/malloc
10c340c5a Check mem alloc failures triggered by invalid chd
37a5c0f3c Merge pull request #94 from scribam/auxv
026969b6d Merge pull request #95 from scribam/division
179f02553 Avoid division by zero
5f3927dc3 Declare hardware capabilities for the Nintendo Switch and PlayStation Vita
fec8ab942 Merge pull request #89 from jpd002/huff_codec
4ddae00e5 Merge pull request #91 from flyinghead/master
de740535f Avoid huffman tree buffer overrun in huffman_import_tree_rle
571507743 Add support for 'huff' codec.
git-subtree-dir: thirdparty/libchdr
git-subtree-split: 54bfb871ccae31903b95a8feb7f2bf7121f304be
51538f102 documentation: refactor registers and function signatures (#169)
47ed75d0b Improve copy between float and general regs on x86-32
91798631a Fix uint to float conversion on x86, ppc, mips
6a8dc94e0 Implement unsigned to float conversion on ppc, mips
61736a11a Implement unsigned to float conversion on s390x
ec6d52516 Implement unsigned to float conversion on x86, arm, riscv
f368bb254 arm64: use MOV instead of ORR for readability (#166)
07a556181 arm64: implement atomics using CAS for CPUs with LSE (#164)
1a4d5f229 Improve atomic operation constraints (#165)
b7fed8e11 x86: correctly detect mode32 for atomic_store (#163)
a0e16b14f arm64: avoid undefined behaviour with signed shifts (#161)
7f2886127 Implement operations on s390x
c54325fee Improve atomic instructions
3499aba93 Set armv6 as the minimum arm version
53d5a2252 Implement set f32/f64 on x86, arm, riscv, ppc, mips
03bb5347f Improve atomic operations
b91921e24 Increase max stack to 1 Mbyte
af4ca5da5 Add atomic instructions (#157)
e37ec3253 macos: allow runtime detection if target is older than BigSur (#127)
5ed7e00a1 Remove functions for unsupported architecture
fa1881b57 Implement operations on s390x
cf5a17b77 Implement fselect operation on x86
e5c75cd73 Implement rev.u32 and rev.s32 on x86, arm, riscv, ppc, mips
d1f287bec Implement select, rev.u16 and rev.s16 on s390x
7efd60de8 Implement rev.u16 and rev.s16 on x86, arm, riscv, ppc, mips
63e307e4a Implement select operation on x86, arm, riscv, ppc, mips
3cc2b0fb2 Improve floating point comparison
git-subtree-dir: thirdparty/sljit
git-subtree-split: 51538f102dd342a6246e98acafc00ceebbab4618
Although Nintendo made many different cartridge circuit boards with different
memory mappings, ROMs do not indicate which specific board they are intended
to work with. Super Famicom emulators traditionally group mutually-compatible
mappings together and use heuristics to guess which family of mappings the
game expects.
There's one family of mappings that maps ROM data to the top half ($8000-$FFFF)
of memory banks in the Super Famicom address space. For historical reasons,
this family is called "LoROM" and has three main variants:
1. ROM only, mapped to the top half of every possible bank.
The boards database calls this "LOROM".
2. ROM mapped to the top half of every possible bank,
RAM mapped to the bottom half of banks 70-7d,f0-ff.
The boards database calls this "LOROM-RAM"
3. ROM mapped to the top half of low-numbered banks,
RAM mapped to both halves of banks 70-7d,f0-ff.
The boards database calls this "LOROM-RAM#A"
The largest official game that used variant 3 was 1MiB, so a common heuristic
is "if the ROM is 2MiB or less, use variant 3, otherwise use variant 2".
2MiB is used as the threshold instead of 1MiB, perhaps so somebody can expand a
commercial ROM that uses variant 3 without having to rework it to suit a
different mapping.
Since v107 or so, higan (and by extension, ares) has implemented variant 3 by
mapping ROM to banks 00-3f,80-bf, which exactly fits a 2MiB ROM. However,
other emulators like Mesen, snes9x and higan v106 implement it by mapping ROM
to banks 00-6f,80-ef, all the space that is left after the RAM is mapped.
This doesn't affect any verified games in the `Super Famicom.bml` database,
since those have specific, accurate memory maps. It also won't affect
well-written games that only read from memory addresses they have populated.
However, homebrew games and ROM hacks that have never existed on a real circuit
board depend on these heuristics across all devices that read Super Famicom
ROMs, including software emulators, flash-carts, and FPGA implementations, so
ares should match what other emulators do.
Adds support for patching ROMs on the fly with a corresponding IPS patch
file. Functions in a similar manner to the pre-existing BPS support. If
a *.ips file is found with the same name as the ROM, it attempts to
apply the patch. If both a BPS and IPS file are found, the BPS patch
takes priority. This patch implements the IPS format as described here:
https://zerosoft.zophar.net/ips.php
SWL/SWR do not raise address errors (it's their whole reason of
being), but they can still raise TLB misses if they access an unmapped
memory area. In that case, the COP0 BADVADDR register is expected to
contain *exactly* the address passed to them.
This happened to be true (by luck) for SWL but not for SWR: SWR in fact
needs to write *before* the address passed to it, so the opcode itself
was adjusting the address before calling the memory function.
Fixed by passing the misaligned address to CPU::write and telling it
to skip address errors. It's not pretty: the code in CPU::write/read is
a bit of a mess and it would require some refactoring but that's for
another day.
Verified on real hardware by adding a new test to n64-systemtest, which
is has been submitted upstream (https://github.com/lemmy-64/n64-systemtest/pull/50).
Interrupts are deferred when the CPU is in a branch delay slot. If the
recompiler repeatedly exits the code cache in a delay slot (much more
likely with "min cycles between syncs" optimization active) then
interrupts will be deferred indefinitely.
This is now avoided by resetting the "cycles until sync" count when
interrupts are deferred due to a branch delay slot.
An alternate and possibly more robust solution would be to single step
the next instruction with the interpreter. One side effect would be the
generation of more compiled blocks.
VR4300 icache/dcache use both the virtual address and the physical
address: the former one is used to select the cacheline (just like
the key to a hashtable), while the latter is used to check that the
cacheline contains the correct line of memory and not another one
that happens to have the same hash key.
So any access to the cache requires both addresses. This commit makes
this explicit, and make sure to call the functions correctly.
The only exception where we leave a FIXME is the icache.step call
in the recompiler, as we can't possibly devirtualize the PC for each
opcode. This will have to be fixed in another way.
With PC Engine, ares always emulates the presence of CD-ROM drive so
games can use its backup RAM for save data. However, it was not properly
loading the backup RAM file when loading a non-CD game, causing the file
to be subsequently filled with FFs on save.
The BIOS format procedure detects the size of backup RAM by sweeping
bank $f7 while writing zero and reading back the result. It stops when
the read back value is nonzero, proving that the 2 KiB backup RAM is not
intended to be mirrored across the 8 KiB address range. With this
corrected in ares the BIOS writes the correct header indicating the end
of the backup RAM is at 0x8800 rather than 0xA000.
This adds a hotkey that can be used to reset the active system.
Although this is similar to the existing "Reload Current Game" hotkey, it does have a functional difference, since a soft reset can result in the state of a system being slightly different than a cold boot. It also does not result in resizing the emulator window and is slightly faster due to not needing to reload various resources.
When using nall as a header-only library it was possible to opt out of
nall taking over main() by simply not including main.hpp. There was no
mechanism to opt out when building nall as a separate translation unit
because nall.cpp unconditionally pulled in main.cpp. Now, users of nall
must specifically opt in by including main.cpp in their build (though
header-only users still only need to include main.hpp).
- Update dirty bit field on invalidate so overlapping blocks can be lazily evicted
- Track "generation" to allow entire cached memory area to be lazily evicted
- Invalidate appropriate cache line/memory area on cache purge
Using lld is required to support advanced scenarios like incremental
ThinLTO and PDB symbol output. macOS has its own linker (ld64) and we
can continue to use that there.
If the iNES 2.0 header specifies NTSC timing, ares should not emulate a
PAL console even if the user region setting is "prefer Europe".
This change also embeds the iNES header in manifests to simplify user
bug reporting.
While I am happy we did the work to support this, having multiple
build systems does make it harder for contributions to be made
We can restore msbuild CI tests once (if) we eventually switch
to cmake.
Apply -march tuning for x86 (not just x86-64) and correctly pass
the ThinLTO cache path through the non-CL Clang frontend on Windows.
The move to CMake can't come soon enough.
With ThinLTO and an incremental LTO cache, incremental link time (with
LTO, of course) goes down from tens of seconds to less than a second.
For whatever reason, ThinLTO needs libco's co_swap_function to have
external linkage. Who am I to argue?
When booting the MD core from a CD a board is allocated on demand in
Cartridge::power(), and this is critical for Mega CD 32X games to
function. However, it also puts the cartridge into an inconsistent state
in which allocate() was never called and therefore catridge.node is
null, causing disconnect() and save() to be short-circuited. This means
the board never gets cleaned up, which also means it never gets
recreated in power() on subsequent loads. One consequence is that
loading a MCD game followed by a MCD 32X game will cause the 32X to not
actually be connected.
Given that all of these system configurations contain a cartridge slot,
it follows that one should always be allocated. This implies
cartridge.node will always be non-null so it cannot be used to determine
if a cartridge is actually connected. This change corrects one such
usage.
Avoid hard dependency on __int128 type suppport. For extended
multiplication, use MSVC intrinsics as an alternative when possible.
If neither are supported, fall back on the u128 type defined in
nall/arithmetic.hpp (which incidentally also works when building as
32-bit).
MSVC applies the same narrowing rules to these as it does to list
initializers, and while I don't know if that's justified by the standard
it's easy to avoid narrowing conversions. In this case, basically every
other core already defines System::frequency as a double so the a26 core
was the odd one out.
MSVC doesn't seem to support string literal concatenation in a
__declspec attribute, but that's fine because we only care about adding
to the .text section. It also requires an explicit pragma to define the
.text section before it can be referenced. Clang is fine with or without
these changes.
MSVC wants these to compile certain experessions, and while I'm not 100%
sure if it technically should require them, I see no reason for these
classes not to have any.
Narrowing conversions in initialization lists are disallowed by the
standard, but nall was supressing this diagnostic (which is actually
an error by default). MSVC doesn't let you supress errors so easily, so
we'd do well to abide by the standard and perform explicit casts as
needed. For nall::shared_pointer::create() we can simply avoid the
uniform initialization syntax to bypass these extra rules, which is the
same strategy taken by implementations of std::make_shared().
Variable length arrays are a C language feature (one of many, actually)
that does not exist in any version of the C++ standard. GCC supports
them in C++ with improvised semantics defined by no standards body, and
Clang follows suit for compatiblity with GCC.
Now a setting can be changed from command line using --setting.
The list of settings can be dumped with --dump-all-settings, so that
it is easy to find out how a certain setting is exactly spelled.
Previously, terminal (console) support on Windows required opting in at
compile time. Now, the runtime behavior is largely the same regardless
of how ares is compiled.
- ares will attach to the terminal of the parent process (if present) by
default and redirect any unset stdio streams.
- If the --terminal argument is provided, ares will always create a new
terminal window and stdio will be redirected to it.
- Otherwise, if stdio handles were already valid on launch they will be
left alone (to support redirection to/from files).
By default, builds are "local", meaning they are optimized specifically
for the host machine. For non-local builds such as our CI builds, we
enforce a minimum CPU spec to allow the compiler to use instructions
beyond the base AMD64 ISA. ares may also make use of SSE4 instructions
via intrinsics in the N64 core. On AMD64, the capabilities of the host
CPU are now checked at runtime and an error message will be displayed to
inform users if their machine does not meet the CPU requirements of that
build.
- Because clangarm64 is now a default enabled package source, there is
no need to edit pacman.conf.
- Because there is no need to edit pacman.conf, there is no need to sync
the package database.
- Because there is no need to sync the package database, there is no
need to update the initial set of installed packages to prevent
version mismatches.
- Install the "clang" package in favor of the "toolchain" package group
as none of the extra packages are needed by ares.
The other audio drivers in ares read exactly two samples from the buffer
passed to output(), but the WASAPI driver was reading the number of
channels supported by the device. ares only ever passes in two samples
so ruby was reading beyond the extent of the array. This caused garbage
to be piped through and resulted in silence on certain systems and build
configurations (likely because of NaNs).
This was only needed for parallel-rdp and that's been fixed upstream
which is now causing redefinition warnings. It's still defined by nall
headers so most of ares is unaffected either way.
When in a delay slot, instructions that modify PC should immediately
trigger an illegal slot instruction exception. This exception is not
predicated on the branch condition (in the case of BF/S or BT/S) of the
instruction in the slot. Furthermore, it should trigger before any side
effects of the instruction are observed.
Raise the timeout to make Start Wars: Shadows of the Empire boot again.
Also improve simulation of CPU halt; the real PIF does toggle the NMI
line but it does so extremely quickly. We don't emulate PIF that often,
so it's more accurate to simply keep the NMI line asserted forever,
as the final effect on the CPU is the same.
The multiplier scale settings are now radio buttons, allowing the
user to see which option is selected.
Available scale sizes are no longer bound by the current monitor
size, avoiding the situation where a selected option disappears
when moving a portable configuration to a different computer,
instead, the actual resizing code prevents the window from growing
larger than the display size.
The window resizing logic now avoids un-maximizing the window, if
the user has manually done so, even when adaptive sizing is
enabled.
Scale options have been renamed to better describe their function
and two new scaling modes have been added:
"Center" has been renamed to "Scale (Integer)"
"Scale" has been renamed to "Scale (Best Fit)"
New setting: "Pixel Perfect" which will always display a 1x scale
image in the center of the display, regardless of the window size
New setting: "Scale (Fixed)" which will always display an image
matching the users selected scale factor (1x, 2x, etc) regardless
of screen size.
This reverts pull-request #945 as it made ares rather frustrating
to use in non-1x situations for most users.
A more robust scaling solution will be worked on soon.
Allow Turok to boot again. This probably points to a problem in our
CPU timings, but the boot timeout number is made up anyway and doesn't
really help anyone to keep it short, so bump it.
Thanks to kev4cards for the analysis
Controller paks only accept writes in range 0-7FFF (without mirroring),
and return 0 when reading out of range.
Rumble paks return the ID only in range 0x8000-???? (TBC)
and accept writes only in range 0xC000-???? (TBC).
Fixes Milo's Astro Lanes saves, and Goldeneye initial rumbling.
Selecting "nothing" for a controller port from the UI only consistently
blocked input from the host, and it did not reliably do the extra work
required to actually disconnect the controller from the perspective of
the emulated device.
This was handled only by the MD and N64 cores, but now all cores are
standardized on the disconnection method originally implemented for MD.
4f7d8ec545 Improve code generation on x86
09cad66bc0 Change tmp1 to ebx on x86-32
2de5e04919 Allow negated comparison
5040a3caa1 Test84 fix
1811f1dcea Rework sljit_emit_shift_into on s390x
ba08667852 Rework sljit_emit_shift_into on x86, arm, ppc, riscv, mips
95d2d320ed Add define for masked shifts
dc79333621 Implement fcopy on ppc, mips
c9e58a4806 Implement fcopy on s390x
03f68fea46 Implement fcopy on x86, arm, riscv
ac6c7b307f Implement byte reverse on ppc
f4d1b06e9d Implement byte reverse on s390x
5ed842e093 Implement byte reverse on x68, arm, mips, riscv
fba2206b40 freebsd: implement system specific execallocator (#155)
0a0ab41d03 test: update test15 for 4 arguments (#149)
1942237bda config: really improve autodetection for arm (#153)
7de0fee9a7 Move allocators to separate files (#151)
7de1a4356d On x86_32, check for virtual registers in conversions to and from floating point (#152)
c2f9c138a6 riscv: disable FPU when using soft-float ABI (#147)
3b89155a25 config: improve autodetection for ARM (#145)
0a313731b9 Implement new features on s390x
26213dadc4 Introduce op_dst
faecd2b12f Implement sljit_get_return_address
8b491d0ade Replace not with xor
88e0dcf360 Add allocator data getters
git-subtree-dir: thirdparty/sljit
git-subtree-split: 4f7d8ec545f58ebe93a08f137fcb9a6dd2bb170f
This very boring commit should basically produce no changes. It just
make sure all devices can now step the CPU while the I/O is in
progress, if needed.
Numbers are based on this test ROM:
https://github.com/rasky/n64-systembench
There are still many other cases to handle but this should provide
the initial framework for further experimentation with PIF timings.
Fix a regression introduced by my last change. The pattern of checking
ready() at the top doesn't work for clear() because it's called from
iniatialize(). This was obscured by the fact that other code calls
clear() again after initialization *unless* you are loading a ROM
directly from the command line.
The WASAPI driver should now gracefully handle machines that don't have
any available output devices. The XAudio2 driver probably still won't,
but more importantly it won't crash machines that don't have a specific
DirectX redist from 2008 (!). It needs a rework but for now I'm leaving
it a little better than I found it.
The rom viewer debug window is a casualty of moving
to the board system, but as NES/Master System and
others with multiple board types don't have it,
it's not a big loss.
NOTE: This requires 'non merged' type roms, with all files related to
the game in a single zip file, ares does NOT resolve parent/child
relationships between roms.
This is a little bit hacky, because the debugging code in libdragon
is not compatible with actual IS-Viewer hardware, so we emulate
a 'quirky' version that satisfies both libraries.
This emulates the ZX Spectrum 48k and 128k models and should be fairly accurate
although imperfect; it is considered experimental for now. Save States are not
fully implemented, you may wish to avoid using them for this core.
No controller interface is currently exposed, meaning games must be played with
the keyboard at this time. It is planned to support the Kempston interface,
while supported by the underlying core, the UI interface for attaching expansion
port devices has not yet been implemented.
You must map a "Keyboard Capture" hotkey to allow ares to emulate the keyboard.
Ares maps most ZX Spectrum keys 1:1 with the same key on the host keyboard.
CAPS SHIFT is mapped to Left Shift, and Symbol shift is mapped to Left Control.
For special characters, it may be beneficial to look up the ZX Spectrum
keyboard layout. For the 48K it is necessary, as BASIC uses hot keys
rather than typed commands, for example, to load a game on the 48k,you must
type `J <symbol shift> PP` and then hit enter, which results in `LOAD ""`
being entered on the screen.
For the ZX Spectrum 128k, you can just use the Tape Loader menu option.
The emulator only implements support for raw WAV dumps right now; this is
because the TZX format is over-complicated, and I did wish to implement it at
this time.
There are many tools available for converting TZX to WAV, for all platforms,
so this isn't really seen as a blocking issue.
Enable these warnings in nall so they apply to all of ares and annotate
legitimate fallthrough with C++17 standard [[fallthrough]] attribute.
This type of mistake is just too easy to make.
Add support for American Video Entertainment's NINA-001 board which was
used only by the unlicensed NES port of Impossible Mission II developed
by Novotrade.
iNES mapper 34 is assigned to two unrelated boards, so detection must
rely on the NES 2.0 header or use the CHR ROM size as a heuristic.
The -mconsole and -mwindows flags don't seem to do much of anything when
Clang isn't targeting MinGW. On the other hand, directly overriding the
subsystem with a linker flag results in a bunch of unresolved symbols.
However, if the right entry point exists (either WinMain or main),
some apparent magic goes on under the hood to ensure that everything
links as expected, so we can just take advantage of that.
context.physMask is only used for TLBs. In directly-mapped memory
segments (either cached or uncached), the virtual-to-physical conversion
uses a hardcoded mask that depends on the exact address space segment,
and is not contextful. In 32-bit, segments only use 29 bits of the
virtual address. In 64-bit, some segments (xkphys*) use the full 32 bits.
Besides 64-bit direct-mapped segments correctness, this also fixes
the devirtualize function that is used as part of the CACHE/LL/SC
opcodes, which were misbehaving when used with a uncached segment
(0xa000'0000) in 32-bit mode. This might actually affect also games.
This change makes it possible to build ares using Clang without
MinGW-w64. All that is required is a copy of Visual Studio (or Build
Tools for Visual Studio) and Clang (also available through the VS
installer) along with GNU Make.
To build, just open an x64 Native Tools command prompt and run
`make compiler=clang++` as usual.
Begin the process of splitting nall into separate translation units.
It can now be used in two ways:
1) as a header-only library by defining NALL_HEADER_ONLY
2) by compiling nall/nall.cpp
sourcery has been updated to demonstrate the header-only use and
everything else now builds nall.cpp.
So far the only things moved into .cpp files are implementations that
call Windows APIs. This allows most of ares to build without including
windows.h and enables the removal of the abomination that was
windows/guard.hpp. The things that actually need windows.h (hiro, ruby)
must avoid using names reserved by Windows headers, but the rest of ares
is free to use names like "far", "boolean", and "interface" with
reckless abandon.
This work is done in preparation for building against MSVC and Windows
SDK headers/libraries an an alternative to MinGW-w64.
I know we play with this a lot; but it is the difference between barely scraping 50-55fps on 32x core to getting constant 60-70fps on my machine.
This does increase compilation time with GCC, clang fares a lot better.
This brings a significant performance increase to the NES/FC core with no accuracy or maintainability impact;
This is possible only because they share the same base clock, and always step at the same rate.
4b8798e4d2 config: simplify use of external allocator (#143)
d598b86d81 Add tcc to the list of compilers using AT&T syntax (#142)
c8e664c73b Fix x86 inline asm register clobbers (#141)
b65c854289 Add conditional exit for clz/ctz on riscv, mips
f55425dac8 riscv: typo in detect_jump_type (#140)
0148e65576 Implement ctz and improve clz on riscv, mips
e8eb434b2e Implement ctz on s390x
51d3c96183 arm: add missing check sljit_emit_mem_update in aarch64 (#139)
cd2a31e199 Implement ctz on x86, arm, and ppc
c0286016cf Improve rotate on mips, riscv
fded9f7823 Implement rotate on s390x
35764edc9e Implement rotate on mips, riscv
ea49b3f52e Implement rotate on x86, arm, and ppc
da180ae7e1 Implement sljit_emit_shift_into on s390x
05f5980620 Implement sljit_emit_shift_into on ppc, mips, riscv
84c0bc3614 Implement sljit_emit_shift_into on x86 and arm
8da3b39558 Label odd numbered tests (#134)
06e13ac7cc Label even numbered tests (#133)
1501371fad Split emit_mem to emit_mem and emit_mem_update
89965887cc Implement return_to on mips, ppc, riscv
e21f485cb4 Implement return_to on s390x
a122423a40 Implement return_to on x86, ARM
4672d4f6cb Improve cmov on s390x
06e9864247 Change SLJIT_32 flag passing to cmov
29af0267ce Update documentation
190313fcc2 Fix spelling of 'subtract' (#132)
4325440b0b Support floating point return
ba0f935c9a Implement recent features on s390x
12e6cb055b Implement always masked shift
f22f976060 Support memory moving of register pairs on riscv, mips, and ppc
git-subtree-dir: thirdparty/sljit
git-subtree-split: 4b8798e4d2fe8f8e8fb82b28e2dda9d71a00b27f
* The NEC V30MZ does not ignore the immediate operand in AAD/AAM calls.
This is contrary to NEC V20/V30 behaviour, as well as many existing
emulators. It is, broadly speaking, important to remember that the
V30MZ is much closer to "an 80186-compatible CPU with much better
opcode timings" than "a V20/V30 derivative". A test ROM is provided
for this.
* The sprite base location register's access to 0x4000-0x7FFF memory
is gated by the color mode bit, not by the 4bpp mode bit. A test
ROM is provided for this.
* The PPU can address 1024 tiles in 2bpp color mode, simply by
following the consecutive addresses (so 0x2000-0x5FFF total). This
has been verified independently.
* The planar(), packed(), depth() and grayscale() functions have been
reworked to accurately reflect what the hardware does. This has been
verified independently.
Currently, analog inputs are bound when crossing the threshold in either
direction halfway between zero and full positive/negative. This logic
doesn't work for triggers that are mapped to the full range of an axis
(as opposed to half the range) which makes them impossible to bind
correctly unless they are initially half pulled when pressing the assign
button. I'm not convinced there is much utility in binding any axis on
motion toward the center position, so this change triggers binding only
on motion away from the center.
Converting a negative floating-point value to an unsigned integer is
undefined behavior and just happens to do the desired thing when
compiling for x86-64. Convert to a signed integer first to avoid UB and
guarantee the expected result on arm64.
Using the host carry flag is a bit tricky because on ARM64 (and most
other non-x86 architectures) the meaning of the flag is inverted for
subtraction. There were some helpers in the recompiler to deal with this
but they performed explicit architecture checks which ran counter to the
goals of a generic recompiler.
Reading back the carry flag is now handled directly by sljit. This
feature had been removed from sljit but was recently added back. It
internally tracks whether the setting operation was an add or a subtract
so that x86 semantics are observed on all architectures.
Loading the carry flag is now handled with an explicit add or subtract
that matches the subsequent usage. This results in expected behavior on
all architectures.
Reinstate preprocessor guards for SSE code. Constexpr if statements
don't really work because the compiler still requires declarations for
the SSE types and intrinsics even if the body is ultimately discarded.
When building with clang for ARM64, the cmath round functions that
return floats compile to a single FRINT instruction. The ones that
return ints are provided by the C runtime, which is problematic on
Windows because the mingw implementations don't set the desired
status bits.
Two things are making this a bit more complicated than it ought to be:
- The msys2 clangarm64 package repository is not enabled by default
because it is still considered 'experimental'
- Cross-compiling requires that you manually override the runtime
library directory for the 'builtins' lib to be located
Both of these issues are known and should be addressed eventually.
There's a "hardware bug" in VI that hides 8 pixels on beginning/end
of each scanline if the scanout begins within the active area.
It is emulated by parallel-RDP but not by our VI implementation.
In a CRT, this is all within the border so it's not visible, and most
games will also respect an even smaller "safe area" anyway. It becomes
visible once the horizontal scanout start is pushed right into the
central area of the screen.
This is another regression introduced to mame RDP wrt upstream
angrylion and parallel-RDP. The color combiner slot "ONE" should use
the value 0x100 for the color components, not 0xff. Notice that
"ONE" in the blender is indeed 0xFF, instead.
- Fix copy assignment operator
- Prevent reserve() from reallocating/rehashing unless capacity is increasing
- Prevent insert() from inserting duplicate entries
- Disable remove() as needs some work and is currently unused
The "mask" feature in the instruction tracer broke when the N64 address
space was increased to 64 bits. This change fixes it by switching from a
vector to a hashset for tracking visited addresses.
The instruction tracer's default history depth (4) is much too low to
reliably filter out hot loops in processors clocked above a few
megahertz.
Assuming a correlation between processor speed and the path length of
code written for that processor, this change sets the history depth to
the processor's clock speed in megahertz rounded to the nearest power of
two.
This choice is arbitrary, but in practice I've nearly always had to
manually adjust the trace depth to values in the 16-64 range when
dealing with faster processors, so this seems like a good enough
heuristic.
- Detect RTC with MBC30 mapper (Pocket Monsters - Crystal Version)
- Read current time before saving it to disk, not after
- Don't clear RTC in power()
GDI's default mode of operation for downscaling is optimized for
monochrome images (!) and produces strange artifacts on color images.
This change selects the GDI mode that is essentially nearest-neighbor,
which is not great but is at parity with how it does upscaling.
e02b3d68eb Merge pull request #84 from scribam/dr_flac
146f076ca7 dr_flac: Version 0.12.39
9882eeaaa2 Bump dr_flac to latest, bump libchdr version to 0.2
44c91c96d4 Bump LZMA SDK to 22.01, need to implement asm optimizations
8cd08c0752 Upgrade to zlib 1.2.12
2781322c4a Merge pull request #78 from snickerbockers/virtual_core_file
40ec221c8a use virtual file i/o API which defaults to a stdio wrapper
git-subtree-dir: thirdparty/libchdr
git-subtree-split: e02b3d68eb759793ab8142376594c840c1194b3e
4de967acd0 Support memory moving of register pairs on x86 and arm.
git-subtree-dir: thirdparty/sljit
git-subtree-split: 4de967acd03499e7def404eab861e83a0689579b
The value of PC indicates the fourth byte (second instruction) after the
current instruction. The value stored when an exception raised does not
maintain this four byte offset. Consequently, the RTE instruction must
offset the value it reads back by four bytes.
ares was storing the offset value (and not applying one in RTE) and this
went unnoticed until an encounter with code that manually sets up an
exception frame (in an interrupt handler common to CD 32X games).
This change also fixes the PC stored in the event of an illegal slot
exception, which should be the delayed branch target.
The functional part of this change is just a few additional lines in
bus-external.cpp. The rest is refactoring to model the game cart as a
separate entity from the 32x, making it possible to delegate reads and
writes through the 0x900000... range to the cart implementation.
This fixes the corrupted menus and crashes in Golf Magazine: 36 Great
Holes Starring Fred Couples.
fc3121239 Update to 0f7cc6c3a13494a575dbbb977ff4424743b688d7.
d37cf0ed0 Update to 93dfb98643d0dd8094c5739300dfed818502304e.
d433bc4d2 Update to 93d77f713ba0fbcf6bb9e654924e89f808b04398.
22f03bb13 Update to 0f0f9446470f4d0aa018b88ff6280bbc4137b6f6.
482a41deb Update to 07c3d161dbeb78121be5eebdab7c810b72af822a
git-subtree-dir: ares/n64/vulkan/parallel-rdp
git-subtree-split: fc3121239716e3cd99ec63175c9ce5c9d088c033
* timing info based on Z80 netlist analysis by Floh
1. Corrected cycle counts for DDCB & FDCB prefixed opcode fetches (was 17, now 16). Instructions cycle counts were increased to compensate for the lost cycle, though this corrects wrong cycle counts for corresponding instructions without a DD or FD prefix (+1 cycle).
2. Removed redundant code for instructions fixed in 1.
3. Changed BIT instructions in DDCB & FDCB blocks to not modify registers (ref: "The Undocumented Z80 Documented").
* based on Z80 netlist analysis by Floh
1. Corrected cycle counts for EX (SP),rr (was 16, now 19) & IM n (was 12, now 8).
2. Reordered cycles for ADD/ADC/SBC HL,rr, RLD/RRD, & LD (rr),n.
3. Removed redundant code for CALL nn & IN (C).
While testing parallel-RDP on macOS via MoltenVK, I found out that
a special syntax used in the N64 Makefile to compile parallel-RDP
requires a version of GNU make which is newer than the one that comes
with macOS. To avoid confusion, just error out for now.
The presence of undefined behavior (in C++) revealed several
bugs in various shift and rotate instructions. These are
deceptively hard get right without resorting to iteration.
Rather than complicate the implementation further, a few more
are now implemented wtih loops like RCL/RCR.
The new code was completely wrong for interlaced resolutions, fix it
by changing into a simple filter on the current field.
Moreover, for some reason, the screen was only updated at 30fps.
Do it at 60fps, as both Vulkan and the native Ares screen knows how
to handle that.
There a handful of sequences of invalid commands that can
cause the RDP to crash (it will stop processing commands until hard
reboot). Mame RDP already knows about them and reacts by throwing an
exception, that currently kills Ares because it is not caught.
This commit lets Ares actually emulate the crashed RDP by basically
freezing its command processor. A log is also emitted on console.
This is useful to homebrew developers that can do mistakes while
coding.
from mooneye/acceptance/oam_dma_start
```
Expected timing (fresh DMA):
; M = 0: write to $FF46 happens
; M = 1: nothing (OAM still accessible)
; M = 2: new DMA starts, OAM reads will return $FF
```
The test still fails, likely due to bad restart behavior,
but it no longer hangs.
This should fix all games that had broken resolutions when not using
Vulkan. It also fix garbled graphics appearing on screen during scene
changes, usually at boot.
This pull request adds support for the Sega Mega Mouse. As the name implies,
this mouse was released for the MegaDrive, but as it is the case for 3/6 Button
controllers, the Mega Mouse can be safely connected to a Master System console and
even used, provided that the game software is programmed accordingly.
To my knowledge there are no official games on the SMS with mouse support, but there
is one demo I released (SMS-A-Sketch) which supports the Mega Mouse, and I have
an unreleased game that also supports it. I think it would be great to have ares
support the Mega Mouse on SMS as the only alternative at this point is to use
real hardware.
The VDPTEST still doesn't pass for any hcounter tests.
Inserting debug prints to print the hcounter value for every possible x coord shows correct output.
I suspect there are still some core timing issues in the z80...
At the moment, the game sees a controller in all ports, even after
the controller type is changed from Gamepad to Nothing. (the Gamepad
instance still lives and still gets called...)
I worked around this by making sure that port->allocate gets called,
even when the selection is "Nothing". The code in port.cpp simply
does not allocate anything in this case.
For most systems and in most practical cases this probably does
not matter. But now the raphnet N64 adapter manager ROM correctly
reports "Not conneted" in ports set to Nothing.
When the ->comm method returns with the invalid bit set, it means no
data was received. This happens for instance when sending invalid
or proprietary commands to a standard controller which does not answer.
When there is no answer, the PIF emulation code sets bit 7 of the receive
length byte to flag this error.
Since no data was received, the original (filler) bytes should be left
as-is in PIF RAM. This is what the hardware appears to do.
This fixes code that checks if the receive buffer got overwritten instead of
inspecting bit 7 for errors.
Ideally I think one should not need to read the source code to learn
that ares accepts command-line options and what those options are.
I wish I had known earlier that I could pass --system MSX when loading
a ROM directly, it would have saved me a lot of time. I had tried --help,
but it just opened the application window...
Many specializations of stringify store a reference to the wrapped
value. Therefore, passing arguments to make_string() by value can be
disastrous if the compiler does not perform copy elision and stringify
stores a reference to a variable that goes out of scope when
make_string() returns.
Detect build environments where 'g++' is just an alias for 'clang++'.
Example: MSYS2's Clang64 environment. This avoids the need to manually
override compiler detection.
Master system ports are compatible with megadrive controllers and
those can be used directly to play many original master system
games.
However MD controllers can be fully supported (i.e all buttons
working) if the game software is programmed to do so.
While really only useful on real hardware, there are game patches to
enable the Start button on MD controllers. But it's also possible
to make patches that use additional buttons or code full support
for Megadrive controllers in a homebrew title.
The N64 and PS1 cores set custom Screen:refresh() callbacks that run on
the video thread and have meaningful dependencies on core state. It's
not safe to unload components from beneath them, so the video thread
should be stopped before any unloading occurs.
ares uses nall::thread with the assumption that calling join() multiple
times on the same thread will have no harmful effects. This was true of
the Windows implementation but not of the POSIX one.
mia cannot save a file when the manifest size is zero.
instead, use the largest known eeprom size + 1 as a default.
The +1 signifies that we should auto-detect the real size of the eeprom
and the large size makes sure mia creates a file on disk large enough.
For games without a database entry, the eeprom size be larger on disk
than is actually used, but it's better than completely broken saves.
Note that even with this, some games will require database entries,
but most should work now.
This prevents slowdown in games that poll games multiple times per-frame.
5ms was chosen as ares already has a 5ms limit higher up the chain.
For me, Advanced Wars 2 (GBA) jumped from 50-55fps to 65-68 with this change
Following the precedent set by the SFC performance PPU, override the
timing of the PCE performance VDP for a handful of problematic games.
All of these games already work fine with the accuracy VDP (enabled with
the "pixel accuracy mode" video setting) which does not and never will
contain contain game specific logic.
Affected games:
- Kore ga Pro Yakyuu '89
- Kore ga Pro Yakyuu '90
- TV Sports Baseball
- TV Sports Football
- TV Sports Hockey
- Valkyrie no Densetsu
- Victory Run
- The primary lookup table is direct addressed
- The secondary lookup table is indexed by hash of code block contents
- IMEM invalidation is tracked at 64-byte granularity and used to
evict primary lookup table entries
- The secondary lookup table is only pruned on a full code cache flush
- Only executed instructions are hashed, so the code cache no longer
experiences unbounded growth
- Code blocks can now wrap around the end of IMEM
- generic::recompiler now supports aborting recompilation (required by
by an earlier version of this change)
On MSX, both joysticks are read through a common port (PSG port 14).
Which joystick is being accessed is selected through bit 6 in PSG
port 15. In other words, the ports inputs are multiplexed.
This pull request adds a simple concept of controller multiplexer
which the PSG IO code can call whenever port 14 is read.
PSG port 15 also controls the level and direction of some joystick
pins, but those are not multiplexed. This pull request corrects how
writes to port 15 are handled and organizes output bits in a predefined
order so controller implementation do not need to know which port they
are connected to. This paves the way for more advanced peripherals
controlled through those outputs, such as the Taito Arkanoid Vaus Paddle.
This adds support for the Sports Pad, a trackball controller for Master System. Input
is done using a Mouse or a trackball (best).
Tested with Sports Pad Soccer and a homebrew test ROM.
The write method is now actually called when TR/TH level and direction
IO port is written to. Also redefined the write method bit width (4) and
document which bit is used for what.
This will allow emulation of controllers which uses the TH line as a
control output. This includes the Export Paddle, the Sports Pad, and
Megadrive controllers.
When the mouse is grabbed, the current implementation hides the
pointer and centers it on the screen.
When the mouse is polled, its relative motion is determined by how far it
has moved from the center of the screen, then it is moved back to the
center by calling XWarpPointer().
XWarpPointer generates an event resulting in an additional poll, which then
sees no movement at all (since the pointer is now centered) and therefore
resets the relative motion values to zero.
If the above reset occurs before the controller code has had the chance to
access the relative motion values, the motion never reach the game. This
works around this issue using a flag to ignore the next event if the
mouse is still centered on the screen.
1. Nametable address is not a latched register, it takes effect immediately
2. Sprites should still be processed & overflow is still set during display disable
3. Hcounter -94 offset is incorrect for ares, as we already have clock 0 = pixel 0.
Despite the Game Gear having no physical controller ports, writes to the IO control register still need to be emulated, and thus the ports need to be present in ares, such that latching h-counter on 0-1 transition is still possible.
Internal Hcounter values (actually clock cycles) are larger than the range of a u8.
The actual Master System h-counter (0x00-0xff range) is calculated later.
1. ram is mirrored between 0xa000-0xbfff, not 0xa000-0xa1ff
2. ram & bank registers are mapped through 0x0000-0x3fff, using only bit.8 to select between them
1. Grouping systems by vendor in the system menu can no longer be disabled.
2. It is no longer possible to hide emulator cores from the menu
3. It is no longer possible to use the higan file select dialog; only the native OS file picker is available.
This makes games requiring a Paddle, such as Megumi Rescue,
playable with an analog stick, or using adapters USB adapters
supporting the HPD-200 Paddle.
"Prefer Japan" should be selected in tools->Boot Options before load
otherwise the game will expect the "Export Paddle" which is not
compatible.
Checking for libraries in /usr/lib does not work reliably, e.g.
on a x86-64 Gentoo the 64-bit libraries are located in /usr/lib64.
Use pkg-config to detect libraries, which should work much better
on any modern Linux distro and also covers Debian's multi-arch
setup.
Using a native data type significantly improves performance of ares::Nintendo64::RSP::instructionEpilogue, making it jump from ~9-10% of cpu time to 5-6% of cpu time during execution
045f2a7f2 Merge pull request #74 from 2weak2live/raw
e23f32f37 Add support for reading LZMA and FLAC hunks in non-CD CHDs.
git-subtree-dir: thirdparty/libchdr
git-subtree-split: 045f2a7f23f5ac10c0122f6f56e42023dfb71e2a
7c37b7ebc Rework x86-32 stack layout
09a58361f Improve sljit abi calling convention
58e36c06a Change skip checks to a macro
ac445a3ef Add sljit specific register argument calling convention
a6c8e5bf7 Remove fast call support on x86-32
a3785b330 Fix x86 mem address encoding
2f8e5c2f2 Implement ARM unaligned support
3e86c50e9 Fix PPC logical or/xor with flag set
d8af3f91b Remove sparc support
3055f116b Fix test50 alignment
41cb888d8 Start supporting unaligned memory access
git-subtree-dir: thirdparty/sljit
git-subtree-split: 7c37b7ebcf17a80f606100ae88e744dff22befe6
because Ubuntu 20.04 still has outdated GCC that doesn't support this flag;
people who get a performance hit from optimising for nehalem will just need to
self compile.
This reverts commit f7657dca4f.
The AI IRQ should be generated when a buffer starts playing, not when
it finishes playing, as verified by hardware tests.
Fixes the audio in Hey Pikachu and possibly other games.
This commit introduces preliminary Atari 2600 emulation.
In the current state, many games are working but with the following caveats
1. Only a small subset of mappers are supported
2. The TIA isn't cycle accurate yet; many games have rendering and/or collision issues.
There is currently little-to-no reason to use this over other Atari 2600 emulators at this time,
but the goal is to eventually have cycle-accurate atari emulation.
The exact behavior of the freeze bit hasn't been investigate yet, but
at the very least it stops the RDP command engine. This PR does a
basic approximation of it, pending more in-depth tests.
Fixes Banjo-Tooie.
It looks like address exceptions and TLB exceptions always set the
same registers (though some are marked as undefined in the manual), so
we unify the two implementations.
Fix several tests in n64-systemtest.
There's a big confusion in the CPU core between virtual and physical
addresses, and we have been fixing many bugs around this. Now that the
situation seems stable, do a big sweep and rename all "address" variables
to "vaddr" when they refer to a virtual address, to simplify reading
the code.
"address" is kept for physical addresses, which is consistent to the
rest of the code outside the CPU that only talks about physical
addresses anyway.
No functional changes.
This commit do further fixes 64-bit addressing. In 64-bit mode, the bus
addressable range is 2Gb (instead of 512Mb), so we need to mask
appropriately all physical addresses.
Fix several tests in n64-systemtest.
This begins improving the RDP status bits to more accurately reflect
what it can be seen on real hardware. It also undoes a hack for RDP
freeze that was allowing Banjo-Tooie to boot. Being a game-specific
hack, I think it is better to simply disable and wait until we find
out how to properly fix the game.
Fix a few new tests in n64-systemtest.
This one is the weirdest. The current implementation is unrolled, but
I can't find a pattern that works. Surely there must be one as the
hardware doesn't surely have a lookup table. Anyway for now this
implementation is completely accurate, albeit verbose.
Fix one test in n64-systemtest
On real hardware, LWL/LWR execute a SysAD 32-bit masked read. Ares
was emulating them with one or multiple shorter accesses, which is
not the correct behavior wrt RCP hardware registers and PI bus area,
where the RCP incorrectly ignores the access size causing several bugs.
After this commit, LWL/LWR always do a 32-bit access on the bus, which
makes sure that we replicate the exact behavior.
SWL/SWR have a similar problem but harder to fix, because the SysAD
bus can do 24-bit writes, which is not something that Ares memory
functions support. So that's for another day.
This fixes a bug in mame RDP with respect to scissoring: the upper X
bound is inclusive in copy and fill modes (and exclusives in the others).
This seems another bug in Mame's refactorings that doesn't appear
in upstream angrylion, given the fact that both cen64 and parallel-RDP
emulates this correctly.
Also adding in protection against another bad shift case. Can't use the same code here though... could avoid the branching if it can be safely assumed _addressBits is always at least 3
329a8c9 had a bug: it moved the queue.insert line *after* dmaWrite;
but dmaWrite updates the io.writeLength to its post-transfer status,
so the calculated timing was incorrect.
Fix the regression in Cruisin' Exotica and possibly others.
Luckily enough, n64-systemtest triggered an interesting bug in our
RSP recompiler: a hash collision of the IMEM contents. The used hash
is objectively very poor so a collision is well possible.
Switch to CRC32 that should be enough to our scope.
The idea of doing a full IMEM hash is probably a bit weak to begin with,
but that's for another time.
Fix a new test in n64-systemtest (that only failed because of this).
This change implements RSP DMA double buffering in a more faithful
way, so that reads from the registers always return the current values
(ongoing transfer or finished transfer) rather than the pending ones.
Moreover, this also makes Ares transfer bytes in background a row at
a time, rather than all of them at the end. It is a bit more accurate,
and it was also easier to implement in the new architecture.
This also fixes several tests in n64-systemtest.
Ares used to have full 64-bit TLB support but it was removed at some
point because of some wrong testing that apparently made us believe
that the CPU didn't support that mode. It will have to be restored from
the git history in the future, though it's not very urgent because
nobody is using 64-bit pointers on N64 (there is no toolchain with
64-bit pointers, nor it seems useful).
Luckily, at least the segment parsing was left in and just commented out.
This allows to pass the last two remaining tests in n64-systemtest.
761d48d2b Improve constant generation
1f32a9f23 Implement fpu operations for RISC-V
ad99f17a9 Improve x86 float compare
fb55788d0 Initial implementation of RISC-V port
7f08de6ff Improve jump code generator on MIPS
469c61db9 Improve mips code generator
a4e8e34ef Support unsaved registers on s390x
f404f3608 Support unsaved registers
88d4778b9 Add license file
160b6f99d windows: fix building in arm64 with clang (#126)
022482eeb wxexec: officially drop support for EOL NetBSD < 8 versions (#124)
beda74f07 Support reworked floating point compare on s390x
050215b22 Remove unnecessary checks
6b950049d Improve floating point compare.
6ace72c90 windows: allow building with MinGW64 gcc/clang (#125)
186b07064 mips: avoid sign conversion warnings with clang (#122)
e0b17f5a6 macos: fix recent regression breaking build in macos/arm64e (#121)
68d9b4bac misc: mostly to avoid warnings (#120)
76330309a Update s390x.
6807c7a8f Remove SLJIT_NEG.
ca530a4a7 Readd carry flag support.
5f60134b5 s390x: be explicit about cache coherence needs (#119)
75a555604 power: avoid bogus clear_cache builtin in gcc >= 10 (#118)
1448ef97c sparc: avoid NOP implementation for clear_cache with gcc (#117)
ad69ad87b sparc: build fixes (#116)
47646b943 Support incoming arguments in scratch registers for s390x.
4fbdd6953 Support incoming arguments in scratch registers.
86ebfbd50 Rework x86-32 function prologue/epilogue.
2f8cf7a08 Increase the number of floating point registers on ppc, mips, and sparc.
2737606ee Increase the number floating point registers on s390x.
03469c8e1 Rename tail call to call return and minor ARM improvements.
7cb8a5c24 Increase the number floating point registers on x86 and ARM.
b35ab5e7e Implement fpu support on s390x.
dcc8fc149 misc: fix -Wextra related errors (#114)
92fcb0fe5 Fix fallthrough errors.
d345a64b3 misc: build/documentation fixes from recent changes (#113)
ff6ec4f74 Implement tail call on MIPS.
eed28632f Implement tail call on ARM.
d7793570f Reduce signed comparison warnings.
30b2dcd83 Reduce value conversion warnings on s390x.
c783c1119 Reduce value conversion warnings on MIPS, PPC, SPARC.
335ee51f5 Reduce value conversion warnings on ARM.
8d0f668fa Improve value conversion warnings.
373163144 Implementing tail calls for x86.
9c8b6961b Improve argument sanity checks.
24c547b7e Swap f32 and f64 argument types.
7f0afb25e Rework function argument list descriptor macros.
585ac42bf Implement four argument support for emit enter.
b5e0b1234 Improve mov32 operation.
433294658 Fix incorrect function call (#112)
cf594d74d Change SLJIT_I32_OP and SLJIT_F32_OP to SLJIT_32.
ae5fff841 Improve arm code generator.
43538b877 Replace SLJIT_UNUSED with appropriate function calls.
git-subtree-dir: thirdparty/sljit
git-subtree-split: 761d48d2b89a048badbd9c5cf45da75336891cfe
When an exception happen in a delay slot, it behaves the same whether
the branch was taken or not. In Ares, instead, the state "delay slot"
only applied to taken branches.
Fix several tests in n64-systemtest
These timings actually depend on the PI registers, even though they
are almost always set to fixed default values. We will get there
eventually and provide a more accurate figure, but for now this
allows to pass timing tests in n64-systemtest so that it can't be
more wrong than before.
A last minute change in 741320e0be introduced a regression in controller
input.
Similar to what we did with PI DMA, SI DMA does not go through the main
bus (SysAD bus) but directly communicate with pif and rdram. This is not
just for the sake of correctness, but SysAD bus half-word writes are
now emulated with the same brokeness they have on real hardware, and
obviously DMA works instead. Moreover, since SI only reads/writes
32-bit words, also switch to word access.
Currently, Ares does not model the PIF chip on its own: it looks like
there was an original mistake that conflated the PI (peripheral
interface, one of the components of RCP) with the PIF-NUS (a separate
chip, connected to SI component of RCP via a serial bus).
This refactor introduces a PIF class and moves all the related code
into it. Since the class implements the Memory::IO protocol for memory
accesses, it also fixes memory accesses with non standard sizes, as
tested by n64-systemtest.
There is a bit confusion of virtual vs physical addresses in Ares,
so dcache/icache were sometimes using a virtual address, sometimes
a physical one. This is wrong: cache is based on physical addresses
only.
Moreover, the CACHE opcode was not even going through TLBs, while it
should. So a CACHE opcode on a TLB-mapped address wasn't working before.
This bug has always been there, but was hidden by the incorrect TLB
matching logic. After fixing the logic in 0bf24b3, this bug was
uncovered.
Fixes Goldeneye.
All writes through the PI bus are actually performed asynchronous by
the hardware, and the status is reflected in the PI IO busy bit.
This commit emulates this properly, and also emulates what happens while
the busy bit is set: further writes are ignored, and reads at any
address return the word being written.
This fixes A Bug's Life and Toy Story 2.
This is a revert of 56458d5b, while keeping b7f96b7109 which is the
real fix that should have been done all along. The former just papered
over the issue and actually introduced a regression (Goldeneye wouldn't
boot).
Co-Authored-By: remutro <[email protected]>
Also take the chance to remove the "hopefully accurate but then not
really" implementation which runs after every instruction in favor
of a real random.
Fix one test in n64-systemtest ROM.
PC register in VR4300 is 64-bit but there were many places where
the register was incorrectly treated as a 32-bit one, effectively
discarding the higher half.
Fix several tests in n64-systemtest ROM.
To get clean makefile targets working robustly under a Windows command
prompt, allow the entire contents of obj/out directories to be deleted.
They are now recreated by the build as needed.
Replace uses of Bourne shell commands (cp, mkdir) with shell-agnostic
versions that work from a Windows command prompt. Some Bourne shell
commands still remain in macOS and Linux specific makefile lines.
using `type` results in compiler warnings: `warning: result of comparison against a string literal is unspecified (use an explicit string comparison function instead)`
Was informed by merryhime that `typeStr` was probably intended.
The N64 core was forcing -msse4.2 for compilation of the whole Ares.
On host PCs without SSE 4.2, Ares would crash at startup with SIGILL
because GCC used SSE 4.2 instructions even in hiro, while building up
the UI.
RSP SIMD emulation requires SSE 4.1, but the solution here is to
fallback to SISD if SSE 4.1 is not supported. This can be checked
with a predefined macro, that will be set by GCC. We do compile with
-march=native, so this will reflect the host PC of the build process.
For non-local builds (eg: official CI builds), default to nehalem
(Core 2) which is the first architecture with SSE 4.1.
Since this is yet another compile-time flag that affects the N64 core
performance, add a status message warning if SIMD is disabled.
Fixes#193
This is because C-BIOS has significant compatibility issues, including
the ability to boot any software that uses BASIC.
The MSX2 emulation is still too preliminary to be able to boot the
official bios, so msx2 will continue to use C-BIOS for the time being.
Replace the large, inner circular dead-zone of the N64 control stick with a small, inner square dead-zone; separate the inner and outer dead-zones; attach the scaling equation to the outer dead-zone; fixes https://github.com/ares-emulator/ares/issues/86 .
Nintendo 64 homebrew community is standardizing on a convention to
declare the save memory type as a header flag. This convention has been
first introduced by EverDrive 64 as a way to handle games not present
in their DB, but it's been since adopted by libdragon as well.
With this commit, Ares will automatically configure the correct savetype
for homebrew ROMs using the special header flag.
This is implemented via a 'keyboard capture' hotkey; this ensures that
users can switch between keyboard & gamepad emulation, even if they have
no physical gamepad.
When keyboard capture is enabled:
- All non-hotkey key-presses are translated and dispatched to the guest
- Virtual GamePad Inputs that are mapped to Keyboard no longer trigger
- Virtual GamePad inputs that are mapped to Mouse or physical GamePads work normally.
Nearly all state is initialized to a fixed or random value during
power-on, though a few things are deliberately left alone on soft reset.
A handful of fields weren't being initialized at all, save for the zero
initialization that occurs during process creation. This state would be
persisted from one ROM load to the next.
This fix is intended to address 32x PWM audio eventually going silent
after switching between multiple roms.
- vtick() shifted; can't be any later w/o breaking due to render alignment
- vblank flag update moved to vtick(); also updated on v28/v30 switch (per ekeeke's note re: Kabuto's findings)
- corrected apu irq timing
- readded extra refresh slot when display is disabled (confirmed after latest timing fixes)
ares v127 brings significant improvements to Mega Drive and Nintendo 64
emulation, as well as improvements to NES / Famicom and SNES / Super Famicom.
Other than the usual emulation improvements, there have been the following notable
changes:
**Apple Silicon Support**
ares v127 fixes the recompiler for aarch64 architecture, meaning that it is now
possible to create Apple Silicon/M1 native builds, without relying on Rosetta
and without losing support for the high performance JIT recompilers.
In order to be Apple Silicon Native, it is currently required to compile ares
from source code as automated builds have not yet been configured, but users
who wish to do so will no longer lose functionality or suffer poor performance
as a result.
**MAME RDP**
ares's Nintendo 64 core uses paraLLEl-RDP by default; this brings fast and
accurate RDP emulation as long as Vulkan is present on the users machine; this
meant that Nintendo 64 emulation was completely broken for all configurations
without Vulkan support, including macOS.
ares v127 adds support for MAME's RDP implementation as a fallback, allowing
Nintendo 64 emulation to be used when Vulkan is not present. This is handled
automatically, however, a new option has been added to video settings to allow
Vulkan support to be toggled, giving all users the ability to test the MAME
RDP, if they wish to do so.
Although MAME RDP is now an option, paraLLEl-RDP is still the recommended
choice, for both performance and accuracy.
**Pixel Accuracy Mode**
ares has contains two implementations of some of our emulated hardware; one
optimised for performance, and another optimised for accuracy.
Historically, the choice of which path to use has never been exposed to the
user; higan *always* used the 'accurate' profiles, with ares always opting for
the 'performance' profiles; any user wishing to change this would be required
to compile ares themselves from source.
As of ares v127, we now provide a new option in the emulator settings: "Pixel
Accuracy"; when this is enabled, any emulator core that supports a pixel
accurate mode will use it.
For 99% of games, the default fast profiles will be sufficient, but enabling
"Pixel Accuracy" allows games that require mid-scanline effects, such as the
infamous "Air Strike Patrol" to function properly.
The following systems are currently support the Pixel Accuracy setting:
* NEC - PC-Engine / TurboGrafx
* Nintendo - Super Famicom / SNES
**Changelog:**
* desktop-ui: hook up pc-engine 6-button pads to virtual pads [Luke Usher]
* desktop-ui: implement frame advance [Luke Usher]
* fc: add bus conflicts to cnrom [encoded-byte]
* fc: check for ram on mmc1 [encoded-byte]
* fc: check if ram exists on mmc3 [encoded-byte]
* fc: clear oam address on each scanline [encoded-byte]
* fc: improve mmc3 irq behavior [encoded-byte]
* fc: improve ppu skipped clock timing [encoded-byte]
* fc: use hkrom for mmc6 [encoded-byte]
* m68000: allow recovery from zero divide [TascoDLX]
* m68000: reimplement DBcc instruction with correct timing[TascoDLX]
* md: A few fixes to SRAM save game [rasky]
* md: correct overscan / output when display is off [TascoDLX]
* md: correct reads of CRAM and VSRAM [rasky]
* md: detect region 'K' as NTSC-J [invertego]
* md: fix APU port in [rasky]
* md: fix debug register sprite masking [rasky]
* md: fix high bits in control port read [rasky]
* md: fix misaligned reads from VRAM [rasky]
* md: fix register masked write in mode5 [rasky]
* md: fix vblank bit toggling horizontal timing [rasky]
* md: fix VSRAM out of bound accesses [rasky]
* md: ignore erroneous device string used by Codemasters [invertego]
* md: implement undocumented VDP VRAM 8-bit reading mode [rasky]
* md: persist VDP state on reset [invertego]
* md: restore vdp free slot lost to refresh [TascoDLX]
* mia: Correct save type for Premier Manager 64 (N64) [sp1187]
* mia: Correct save type for Transformers: Beast Wars Transmetals (N64) [sp1187]
* mia: correct type for pak attribute [encoded-byte]
* mia: fix 32x sram [Luke Usher]
* mia: properly pass MD eeprom details to ares [Luke Usher]
* mia: updated famicom database [encoded-byte]
* mos6502: add illegal nops [encoded-byte]
* ms: correct overscan inc. dynamic screen resizing [TascoDLX]
* n64: add MAME RDP as a fallback for parallel-RDP [invertego]
* n64: allow vulkan to be disabled [Luke Usher]
* n64: change PI DMA to use 16 bit fetches [CasualPokePlayer]
* n64: fix mult/div opcode timings [rasky]
* n64: fix RSP halt condition to be more accurate [rasky]
* n64: fix several RDP regressions [invertego]
* n64: fix small bug in VMACQ [rasky]
* n64: fix SRA/SRAV opcodes [rasky]
* n64: fix vulkan detection [Luke Usher]
* n64: improve rsp recompiler pool allocation [invertego]
* n64: swap RSP/RDP order [CasualPokePlayer]
* n64: templatize rsp vpu [invertego]
* n64: vulkan tweaks [Luke Usher]
* nall: fix many compilation warnings on macOS [Luke Usher]
* nall: fix page protection on Apple silicon [invertego]
* nall: rewrite recompiler for machine-independence using sljit [invertego]
* pce: runtime pixel accurate VDP setting [invertego]
* sfc: fix horizontal off-screen test for sprites [jbo-85]
* sfc: fix missing sprite tile on Super Conflict title screen [jbo-85]
* sfc: fix missing sprites in Jurassic Park that are partly offscreen [jbo-85]
* sfc: runtime pixel accurate PPU setting [invertego]
* sh2: move registers into POD struct [invertego]
Some systems in ares contained two implementations of video hardware;
these systems were Mega Drive / Genesis, Super Famicom / SNES, and
PC-Engine / TurboGrafx 16.
For the Mega Drive, we switched to the accuracy core quite some time ago,
SNES and PC-Engine we were still using the performance core.
Going forward, we wish to only maintain the accuracy focused renderers.
VDP always writes transparent pixels to the internal sprite buffers,
overwriting previous transparent pixels; then the first non-transparent
pixel sticks and wins. This implementation detail only reveals itself
when sprite plane masking is activated using the VDP debug register:
in that case, the palette number of transparent pixels concurs in the
AND of the visible pixels, and thus the correct palette number should
be found in the buffer.
Fixes the logo effect of Overdrive 2 (ref #255)
After more analysis, it looks like the correct thing to do is to
check for vblank status on most of the raster line. Kabuto's doc says
that it is possibly to switch from V30 to V28 during line 224 and
still see the vblank triggered, which suggests that the hardware does
actually check it on most of the time.
This seems to fix#402 and does not seem to cause any immediate
regression in timing-sensitive ROMs.
Currently, the vblank bit is turned on/off at the same time vcounter
is incremented, which is a reasonable assumption, missing any real
data on this.
But it turns out this is responsible for most of the breakage of
Overdrive 1. I did some tests and it looks like anything in the
range >= 0xF0 (same line), or <= 0x80 (on next line) fixes those bugs.
I decided to bind it to vedge(), which means that vblank bit now is
triggered the same instant that VINT is raised, which also makes sense
when you think of it.
Updates #212
VRAM misaligned addresses were implemented with partial slot reads.
This seems to be wrong, as proven by vdpfifotesting: once the slot is
read, the whole word is invalidated.
VSRAM is actually made of 40 11-bit words, though the chip only accesses
the first 10 bits. The top bit on each word is still readable and writable
though, so they should be emulated.
Also, reading at addresses >= 40 returns a copy of the first word,
rather than 0.
Mode5 (SMS compatibility mode) is unsupported and mostly undocumented,
but the vdpfifotesting ROM at least checks one know behavior: non-SMS
registers can't be written.
Bits 10-15 in control port read (aka status register) are not fixed
as found in some online docs, but they are actually an open bus
that returns the instruction prefetched by m68k at that cycle.
* Allow MIA to declare address for mapping (typically from ROM header)
rather than hardcoding 0x200000.
* Autoenable SRAM if the ROM size is smaller. Also make the ramEnable
I/O conditional to the same layout.
* Add MIA entries for NBA Live 98, NHL 96 and NHL 98, which have a 8-bit
SRAM not declared in the header.
Using the read<Byte> currently in use breaks DMAs from Flash (breaking Paper Mario, probably others), which always return 0. I assume 8 bit reads are just not allowed for Flash, although I can't verify this myself.
Checking https://github.com/n64dev/cen64/commit/8367698e20cca7eb262779f19c8c7847ae31bb29, it seems that fetches should always be 16 bits anyways, so I presume this is the correct behavior, and fixes DMAs from Flash.
No regressions with the original testrom have occured.
- introduce a status api, so cores can report status messages to the UI
- avoid calling vulkan-related functions when vulkan is disabled
- show status messages so the user is aware of what RDP implementation is active
- Disabled 'loaded' status message, it prevented the Vulkan messages being shown
Update the stack base and limit in the thread information block. This is
required to support kernel stack unwinding, which is used for both C++
exception dispatch and setjmp/longjmp on Windows x64 and ARM64.
Add a cothread entry routine that consistently aborts when the user
supplied routine returns. Debugger stack backtraces now stop
consistently at this entry routine.
The Korean release of Tiny Toon Adventures specifies its region with a
'K' and, like several other Korean releases, is region locked to
Japanese consoles. It may be the only one with a 'K' specifier, though.
Taken from NEC VR4300 manual. These are easier than expected to
implement accurately as the CPU doesn't execute them in parallel but
stalls the entire pipeline while they are running.
Real hardware testing showed that VMACQ does not modify the accumulator
if it is exactly zero. Fix it.
Also remove two "unconfirmed" comments which I have personally verified.
* Fix usage of break opcode in a delay slot. After unhalt, the
RSP continues execution, taking the jump if needed. So the
branch state should not be affected by the break opcode.
* Reading from SP_PC produces garbage (open bus?) when the RSP is
running. This fix is unlikely to fix game but may help homebrew
developers.
* Writing to SP_PC resets the RSP MIPS pipeline, so any pending branch
is canceled.
The existing implementation was allocating pools in the code cache only
to copy them to the heap. This was wasteful on multiple counts: the
space in the cache would go unused until the next allocator flush and
the data copied to the heap consisted almost entirely of zeroes. Best of
all, writing the hash code to the code cache was triggering a page
protection fault on Apple M1.
A small data structure refactor avoids the heap allocations, the copies,
the wasted space in the code cache, and the page protection issue.
For systems that do not meet parallel-RDP's Vulkan requirements, use the
pure software RDP implementation from MAME as a fallback.
All of the source files taken from MAME are either BSD-3-Clause licensed
or public domain. Edits were kept to a minimum and guarded by ifdefs to
ease future integrations.
- when dynamically allocating executable memory, use VirtualAlloc/mmap()
for finer control over allocation flags (like MAP_JIT on macOS/arm64)
- toggle JIT memory protection around writes on macOS/arm64
- reduce recompiler code cache sizes to improve likelihood of dynamic
allocations being close to ares image (affects branch perf)
- remove arch x86_64 override on macOS non-local builds; native arm64
builds should now be at feature parity with x86_64
- sh2: prevent pollution of code cache with empty pools by invalidate()
Games tested so far. Two new not working games discovered:
- Aladdin (Europe): Hangs after starting game
- Wizards & Warriors (Europe): Graphicals glitches on HUD, severe slowdowns. PAL timing related?
For some users, this gives a dramatic performance boost, and finally
brings the Windows builds in-line with Linux/Mac builds in terms of
performance.
This technically goes against the Win64 ABI, which demands that SSE
registers are saved, however, in-practice, our testing has shown that
this has not caused any issues so far.
On Windows, track WM_SETFOCUS and WM_KILLFOCUS messages to determine
focused status rather than polling with GetForegroundWindow(). The
latter involves a syscall and causes noticeable slowdown when called
repeatedly, such as when GameBoy games poll joypad status in a loop.
Fix unloading systems with light gun peripherals active. The code
responsible for removing crosshair sprites was dereferencing a null
pointer. This cleanup now occurs in Screen::quit() when unloading.
Instead of just reading the first file from a zip archive, prefer files
that match known rom extensions. Extra files such as readmes should not
interfere with the loading of the game.
Fix several correctness bugs in SH2 instructions in both the interpreter and
recompiler and switch the default implementation from the cached interpreter to
the recompiler. This brings the 32x games BC Racers and Zaxxon's
Motherbase 2000 to playable status. Fixed instructions:
Interpreter
- ADDC Rm,Rn
- ADDV Rm,Rn
Recompiler
- MAC.W @Rm+,@Rn+
Both
- CMP/STR Rm,Rn
- MOV.B Rm,@-Rn
- MOV.W Rm,@-Rn
- MOV.L Rm,@-Rn
- NEGC Rm,Rn
Improves thread-switching performance using the following techniques:
- Interleave stores/loads
- Restore the stack pointer and link register as early as possible
The calling convention specifies that d8-d15 (the lower 64 bits of
vector registers q8-q15) are callee-saved. However, libco was
erroneously saving and restoring general-purpose registers x8-x15
instead.
Ares JIT recently started to require the data segment to be executable
(see https://github.com/ares-emulator/ares/pull/200 for details on why
this was done instead of allocating a new segment via mmap).
To do this, it uses mprotect() (bump_allocator::resize), but it also
needs to tell the linker that the data segment can be upgraded to
executable with -Wl,-segprot,__DATA,rwx,rw (nall/GNUmakefile).
Unfortunately, for quite some time, the clang LD had a bug and didn't
accept that option for the data segment.
The official CI has a newer linker without the bug, but for developers
compiling ares with an old toolchain, this small tool will patch the
binary to mark the data segment as potentially executable.
This change upgrades GCC from the version preinstalled by GitHub Actions
(8.1.0) to the latest MSYS2 version (10.3.0). It also adds a
Windows/Clang build configuration, though the release job still
grabs the GCC build.
ares v124 brings the compatibility rating for the Famicom and Nintendo 64 cores
up to three stars. This means that at least 80% of the game library is working.
There have been notable improvements to Game Boy, Mega Drive, Sega Mega CD,
Sega 32X and Nintendo 64 emulation, and the PC-Engine multi-tap is now supported.
Finally, the dynamic recompiler now generates slightly more efficient code. You
may notice a slight performance boost in Nintendo 64, Sega 32X and Sony
PlayStation.
**Changelog:**
* Famicom: Add support for Jaleco JF11/JF14 mapper [Shideravan]
* Game Boy: Bring fast-boot closer to normal boot; Fixes Dr. Fraken [invertego]
* Game Boy: Use stable sort for sprites; fixes speech bubbles in Crayon Shin-chan 3 [invertego]
* Game Boy: Remove limit on window width; fixes pause screen in Heiankyo Alien [invertego]
* Game Boy: Emulate serial transfers with no link; fixes input in Alleyway [invertego]
* Game Boy: Improve handling of LCD/BG enable for DMG; fixes Hyper Lode Runner [invertego]
* Game Boy: Resume from halt whenever (IE & IF) != 0; fies Amazing Penguin [invertego]
* Mega Drive: Fix DMA transfer rate and H-Int signalling; fixes Another World, 3 Ninja's Kick Back, Virtua Racing, Burning Force [TascoDLX]
* Mega Drive: Fix sprite masking and overflow; Fixes Mickey Mania [TascoDLX]
* Mega Drive: Fix DMA fill; Fixes Demons of Asteborg [TascoDLX]
* Mega Drive: Fix VRAM byte addressing; Fixes Contra Hard Corps, Musha [TascoDLX]
* Mega Drive: Fix VDP control port writes [TascoDLX]
* Mega Drive: Implement HV Counter Patching [TascoDLX]
* Mega Drive: Implement STOP instruction; fixes Thunder Force IV [TascoDLX]
* Mega Drive: Default to 3-button gamepad; fixes games that don't support 6-button pads [Shideravan]
* Mega Drive/Mega CD: Fix detection of device rom header; allows Mode-1 to work [Luke Usher]
* Mega CD: Fix word-ram 1M access pattern; Fixes Lethal Enforcers II [TascoDLX]
* Mega CD: Fix H-Int vectoring; Fixes Microcosm, Silpheed, Wing Commander, and others [TascoDLX]
* Mega CD: Implement full graphics/1M wordram translations; fixes Rebel Assault [TascoDLX]
* Mega 32X: Tighten M68k sync; Fixes Kolibri and Fifa 96 [TascoDLX]
* Neo Geo Pocket: Fix off-by-one error in LDAR instruction; fixes a crash in SNK Gals' Fighters [invertego]
* Nintendo 64: Support controller ports 3 & 4 [LukeUsher]
* Nintendo 64: Better Flash Ram support; Fixes Majora's Mask, Paper Mario, Derby Stallion 64 [jeltaqq]
* Nintendo 64: Add mempack/rumble status to database; eliminates controller pak/rumble pak warnings [remutro]
* Nintendo 64: Consume cycles to compensate for skipped RDRAM initialization; fixes Wave Race 64 Shindou Pak [invertego]
* Nintendo 64: Fix PIF RAM init on cold boot, preserve RDRAM on warm reset; fixes Perfect Dark boot [invertego]
* Nintendo 64: Default to 3 controllers for Jeopardy!, this game doesn't work with 4 controllers, even on hardware [invertego]
* Nintendo 64: Fix FPU compare and divide exceptions; Turok is now able to play the entire Acclaim logo animation [invertego]
* Nintendo 64: Decrease SI DMA delay; improves Turok, Donkey Kong 64, Forsaken 64, Hercules, Triple Play 2000 [invertego]
* Nintendo 64: Implement perfect PI DMA write [rasky]
* PC Engine: Support Multi-Tap [LukeUsher]
* TMS9918: Widen vcounter to 9-bits; improves ColecoVision, SG-1000, MSX [invertego]
* desktop-ui: Support up-to 5 virtual controllers (For PC-Engine) [LukeUsher]
* desktop-ui: Fix window background with GTK3 [ghisvail]
* desktop-ui: Install icons in freedesktop compliant locations [ghisvail]
* desktop-ui/hiro: Improved macOS user experience [LIJI32]
* ruby: Fix conflated keys on Windows; fixes some keyboard input issues [invertego]
* nall: Use XDG base directories on *nix systems [ghisvail]
* shaders: Include a selection of public-domain shaders [LukeUsher]
* ares: Fix address masking in instruction tracer [invertego]
* ares: Fix warnings reported by clang [invertego]
* ares: Fix static init in node subclasses [invertego]
* ares: Use 64-bit integers instead of 128-bit integers in the scheduler [invertego]
* ares: Use IP relative direct branches in the recompiler, where possible [invertego]
* ares: Emit only one epilog per block in the recompiler [invertego]
* ares: add label API to recompiler to simplify branches [invertego]
* ares: Use fixed BSS allocation for code cache; improves recompiler performance [invertego]
* ares: Fix instructionEpilogue test [invertego]
* ares: Directly emit code for target ABI; generates more efficient code in the recompiler [invertego]
* ares: Avoid encoding absolute data addresses in the recompiler [invertego]
* nall: allow mingw headers to define _MSVCRT_VERSION_ [invertego]
* nall: generate PDB when building with clang on windows [invertego]
* nall: allow generation of debug symbols with symbols=true [invertego]
* nall: link with lld wen building with clang on Windows [invertego]
* nall: Make thread movable but not copyable; fixes random UI hangs on Windows [invertego]
* mia: Fix MSU-1 rom loading [Luke Usher]
Reference data members via offsets from nonvolatile registers instead of
directly encoded absolute memory addresses. This is the last change
required for generated code to be fully position independent.
The reduction in code size is generally 5-7%, with the exception of the
N64 RSP, which sees a reduction of nearly 40%. This is mostly a result
of moving the clock increment to instructionEpilogue().
Previously, the recompilers in ares would assume the System V calling
convention, then emit extra moves on Windows to handle the differences
in register usage. Now, they directly populate the registers used by the
target system for passing parameters to functions. This is achieved
with register aliases set for the appropriate ABI at compile time.
Furthermore, registers that are nonvolatile only on Windows - rsi and
rdi - are no longer used as temporaries, removing the need to save and
restore them in recompiled code blocks.
This accounts for roughly a 10% reduction in recompiled code size on
Windows while making functionally no difference to other systems.
The thread class owns a resource and should have semantics akin to
std::unique_ptr. By allowing copying, the Windows implementation was
calling CloseHandle() when the original copy was destructed, meaning the
new copy would have no actual ownership of the handle. Once the thread
itself exited (dropping the last reference on the handle), later uses of
this handle in join() and ~thread() could end up operating on anything
or nothing depending on whether the handle value had been recycled.
This change modifies the POSIX implementation just enough to keep the
semantics the same as the Windows implementation for users of the class.
Otherwise, there is no functional change.
This fixes random UI hangs and other bad behavior on reset or unload.
instructionEpilogue() returns a bool, but all recompilers were
performing a 64-bit test on the return value. If sizeof(bool) == 1, only
the bottom 8 bits are guaranteed to be valid.
Place code caches in the bss section to guarantee proximity to the text
section in order to improve branch prediction and eventually so we can
reliably utilize IP-relative branch instructions.
There is now a fixed 1 GB buffer that is shared by all system cores with
recompilers (m32x, n64, ps1). Because the linker will place it in bss,
it will consume no space in the executable on disk, and operating
systems should be clever enough to avoid comitting physical pages until
it is actually in use. The buffer is defined in a separate translation
unit and only referenced from under compile-time recompiler checks, so
it should be left out by the linker when recompilers are disabled.
And defaulting it, as some older games depend on it to this kind of input to work properly.
eg.: Forgotten Worlds
https://youtu.be/ngHDIFQHFyQ
This also solves https://github.com/higan-emu/ares/issues/177
Fighting pad is still supported just need to be selected in Mega Drive->Controller Port
Currently ares is using 128-bit counters when the built-in __int128 type
is available. Near's notes on this topic conceded that it wasn't really
necessary, but defended it by stating there was no speed penalty on
64-bit architectures.
Unfortunately, LLVM's 128-bit integer support is buggy when compiling
for Windows targets. I've filed a bug report and am optimistic this will
eventually be fixed, but to prevent people from being burned when
compiling ares themselves, it would be safer to avoid the built-in
__int128 type entirely.
This change imposes 64-bit counters on all architectures for
consistency. It redefines the nall (u)intmax types to match the standard
(u)intmax_t types, though there is no longer anything in ares using them
at the moment.
This commit implement perfect PI DMA write. The PI DMA is normally used
for 8-byte aligned transfers, which is where it constantly works. The
hardware does contain a half-baked, buggy support for 2-byte aligned
transfers and odd-size lengths. I have extensively investigated the
behavior of every single quirk, and produced a test ROM that Ares
passes after this commit (timing is still off, but that's for another
day):
https://github.com/rasky/n64_pi_dma_test
The implementation is the same that I've previously submitted to cen64,
adapted for the ares codebase.
Whatever defining this manually was intended to fix, today it is only
breaking things. The mingw headers define this as 0x700 if you are
linking against MSVCRT and 0xE00 if you are linking against UCRT. This
is a mingw-internal macro, and there is currently no comparison in the
headers that evaluates differently for 0x601 than for 0x700. However,
always forcing it to 0x601 as nall does breaks linking against UCRT.
We should let mingw define this appropriately.
When building with clang, two static inline members of Node subclasses -
identifier and register - were not consistently initialized in that
order during application startup. Because the constructor of register
depends on identifier, this poses a problem.
I'm not sure if clang is on the wrong or if the initialization order is
actually unspecified by the language standard, but this situation can be
easily avoided, so I opted to do just that.
These warnings can often catch genuine bugs. The only tautological
compare warning I observed was reporting a real bug in the SFC core. The
shift count overflow warnings appeared to be for cases that were benign,
though only because I already fixed a significant one in the instruction
tracer. In general, such shifts are undefined behavior and require
surrendering to the whims of the compiler and the processor
architecture, so they are worth avoiding.
The large diff in ares/component/processor/tlcs900h/instruction.cpp is
mostly uninteresting. I had to make the control flow more explicit for
undefined instructions to stop the compiler from complaining about bad
template specializations. While I was at it, I enabled unused-value
warnings for that file, which only required adding a few void casts.
Most of the warnings are from Windows specific code, as the rest of the
codebase is already fairly clean. This change fixes a couple of (benign)
bugs discovered by these warnings.
In hiro/windows/action/menu.cpp, menu-item.cpp:
A function pointer was being passed in place of a bool argument to
nall::image::scale(). At one point the name Interpolation::Linear
referred to an enum. In any case, the argument in question defaults to
true - specifying linear interpolation - so it is unneeded.
In hiro/windows/widget/widget.hpp:
The function minimumSize() was being overloaded instead of overridden
due to a missing const qualifier. It doesn't appear to have had any
negative side effects in ares.
This change corrects masking for 32 bit addresses.
Per the C++ standard on shift operators: "The behavior is undefined if
the right operand is negative, or greater than or equal to the width of
the promoted left operand."
Reduce the (minimum) number of cycles between an SI DMA request and the
completion of said request from 131072 to 2304 cycles. This is the
duration used in other emulators, and it is in agreement with the
observed behavior of Turok, which can only tolerate a delay between 215
and 3888 cycles (subject to current timings in ares).
In addition to fixing input in Turok - Dinosaur Hunter, this change gets
the following games past the intro:
- Donkey Kong 64 (w/ major graphical issues)
- Forsaken 64
- Hercules - The Legendary Journeys
- Triple Play 2000
On compare to NaN:
- do not raise an exception if exceptions are disabled
- do not update the csr condition bit if exceptions are enabled
On divide by zero:
- do update the destination fpr if exceptions are disabled
For both of the above:
- do set the csr cause bit
- do set the csr flag bit if exceptions are disabled
Turok is now able to play out the entire Acclaim logo animation. It was
previously resetting due to erroneously raised invalid operation
exceptions.
Jeopardy! only supports up to 3 players, and if four controllers are
plugged in when the game starts, it performs an out of bounds array
access that breaks further input logic. The only workaround is to unplug
a controller and reset the system. To make this game work well in ares
out of the box, we should connect no more than 3 controllers by default.
I opted to put a check specifically in desktop-ui because this is
fundamentally a mismatch between a specific game and a design choice (to
default to 4 controllers) in the desktop-ui frontend. It didn't feel
right to add a dedicated attribute to mia that did not describe a
feature of the cartridge itself and would not be generally applicable
other games (unlike rumble and memory pak support).
This change also brings the rumble and memory pak attributes in line
with the implementation of boolean attributes for other systems. There
is no functional change, though it will affect generated manifests if
they are/were persisted to disk.
A recent workaround for BattleTanx caused a regression in Perfect Dark.
Essentially, it was always telling games that they had been started by a
warm reset rather than a cold boot. Perfect Dark expects data to be
preserved in RDRAM across resets and fails to get as far as drawing
something on the screen if it isn't there.
This change reverts the workaround so that Perfect Dark will perform the
full initialization required after a cold boot. Luckily, this will not
regress the BattleTanx games, as they were fixed by my last change
(making sure IPL3 consumes a sufficient number of cycles). This change
also skips clearing RDRAM on resets, which is again required by Perfect
Dark and possibly other games.
The RI_SELECT register is read by IPL3 to check if RDRAM initialization
should be skipped. If we are forcing it to be skipped, we should also
consume enough cycles to not inadvertently speed up the boot process.
Wave Race 64 Shindou Pak Taiou Version will freeze on the N64 logo if
the SCC count register, which increments at half the CPU clock rate, has
too small a value.
The idea of using RI_SELECT reads as a cue to consume extra cycles was
borrowed from MAME.
Thanks to Rasky for measuring the timing on real hardware.
The flags returned by the Raw Input API have distinct meanings. The
lowest bit reflects the state of the key and the next two bits indicate
scan code prefixes. An oversimplified interpretation of these flags was
causing ruby to conflate events for keys that differ only by prefix.
Reference:
https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawkeyboard
The full set of conflated key pairs:
Return Enter
Keypad0 Insert
Keypad1 End
Keypad2 Down
Keypad3 PageDown
Keypad4 Left
Keypad6 Right
Keypad7 Home
Keypad8 Up
Keypad9 PageUp
LeftAlt RightAlt
LeftControl RightControl
Multiply PrintScreen
Point Delete
Slash Divide
The TLCS-900 manual states the loaded address is relative to the start
of the instruction plus four bytes - in other words, one byte before the
end of the instruction.
This fixes crashes in SNK Gals' Fighters.
By using an 8 bit counter, the last 6 lines of every frame were being
skipped and the VDP was firing vblank interrupts ~2.3% faster than
intended in the ColecoVision, SG-1000, and MSX.
This also fixes the corrupted turtle graphics in Frogger for
ColecoVision, though this is mostly by chance. The game is buggy and
susceptible to graphics corruption if a vblank is raised between these
instructions:
1d09 out ($bf),a ; write low VRAM address byte
1d0b ld a,h
1d0c out ($bf),a ; write high VRAM address byte
It could easily be regressed by any future change that impacts timing.
Normally, breaking out of the halt state is handled by CPU::raise(), but
there is an edge case:
; preconditions: IME = 0, IE = 1, IF.0 = 1, LCDC.7 = 0
ei
halt
In other words, a vblank interrupt was requested with IME disabled, then
the display was disabled (so no more vblank interrupts will follow),
then interrupts were enabled while entering the halt state. Once halted,
there is no logic in ares to service the requested vblank interrupt.
A better long term approach would be to refactor the SM83 implementation
of halt to be more like the Z80 core - eliminating the loop within the
halt instruction itself - but in the meantime this change offers an
incremental improvement.
This fix prevents Amazing Penguin from freezing immediately on load.
On DMG, when the LCD is toggled from off to on, the screen remains blank
until one frame after the PPU becomes operational.
Furthermore, when the BG is disabled, the window is also no longer
drawn, though the other window logic (like the incrementing window line
counter) seems to remain operational.
This cleans up the visuals of Hyper Lode Runner on level start, but many
more games will be affected by blanking the first frame after the LCD is
toggled on.
This allows for all four n64 controllers to be used, while providing
capatbility to expand to five controllers for PC-Engine, once we
implement the multi/tubo-tap
When a serial transfer is started using the internal clock and no second
device is connected via link cable, 1 bits are shifted into the SB
register. This behavior must be emulated for the game Alleyway;
otherwise, it does not accept player input.
I couldn't find any research to support this limit, nor does it match
the behavior of other emulators. Everything I could find indicates that
the window should be drawn to the end of the line.
This fixes the right edge of the pause screen in Heiankyo Alien.
On DMG, sprites are sorted by x value then by OAM address. As the sprite
array begins in OAM order, a stable sort on x can achieve the desired
result. Conveniently, nall already contains a stable sort implementation
that is optimized for small arrays.
This fixes ordering issues with speech bubbles in Crayon Shin-chan 3.
The previous fast boot patch skipped the entire Nintendo logo animation
and sound. Unfortunately, this left a number of registers with different
values than they would otherwise have. The European release of the game
Dr. Franken does not initialize SCY, and fast boot was leaving it set to
100 instead of zero, causing the first logo to be shifted offscreen.
It would be easy enough to amend the patch to initialize SCY to 0, but
for most games this will cause the Nintendo logo to appear for a single
frame, which doesn't look so great.
This new patch skips the first ~4 seconds of the boot animation and
disables scrolling but otherwise leaves things alone. The result is a
a stationary Nintendo logo that appears centered on the screen,
accompanied by the usual sound, for ~1.5 seconds.
ares v123 includes significant improvements to the emulation of the ColecoVision,
SG-1000 and the Game Boy/Game Boy Color.
This release brings the compatibility rating for ColecoVision and SG-1000 to
four stars.
This means that we have 100% compatiiblity with both of those libraries, with
the only exception being the few games that require additional peripherals
(driving controllers; touchpads, etc).
The Game Boy improvements are significant, but not quite enough to increase
the compatibility rating at the present time, even so, Many more games are
playable than before.
Finally, a few tweaks to MegaDrive emulation have improved compatibility,
reduced the occurance of video corruption, and improved performance of
the Sega 32X emulation.
**Changelog:**
* ColecoVision: Initialize ram to 0; fixes a crash in The Heist [Luke Usher]
* ColecoVision: Disable cartridge rom mirroring; fixes Sammy Lightfoot [invertego]
* ColecoVision/MSX/SG-1000: Initialize VRAM to 0; fixes various games [invertego]
* Game Boy: Check window x-coord instead of only y-coord; improves the Acid2 test rom [Luke Usher]
* Game Boy: Only raise STAT interrupt when display is enabled; fixes Cool Hand [invertego]
* Game Boy: Implement HALT hardware bug [Meepster99]
* Game Boy: Fix relationship between LY and STAT interrupt; fixes Elite Soccer, Mouse Trap Hotel, Shantae [invertego]
* Game Boy: Only trigger STAT interrupts at the start of OAM search; fixes Mortal Kombat 3 [invertego]
* Game Boy Color: Fix HDMA5 bit.7 reads; improves a significant number of GBC games [invertego]
* Game Boy Advance: Simulate standard GBA instead of Game Boy Player; fixes GBA Video titles [Luke Usher]
* Mega Drive: Implement support for Sonic & Knuckles merged roms; fixes Sonic 2K, Sonic 3K [Luke Usher]
* Mega Drive: Implement support for SRAM/EEPROM when using the SEGA Mapper; fixes Demons of Asteborg [Luke Usher]
* Mega Drive: Default to 'accuracy' VDP; improves compatibility at the expense of performance [Luke Usher]
* Mega Drive: Optimize how often the emulator synchronises between components; offsets the cost of the previous change [Luke Usher]
* Nintendo 64: Maintain Parallel-RDP as a subtree; simplifies compilation [Luke Usher]
* SG-1000: Implement support for roms greater than 32KB [Luke Usher]
* SG-1000: Implement support for Taiwan Type-A/Type-B mappers; fixes unlicensed Taiwan releases [Luke Usher]
* SM83: Fix DAA instruction [Meepster99]
* TMS9918: Implement multicolor mode; fixes various SG-1000/ColecoVision games [invertego]
* TMS9918/Master System/MSX: Allow sprites to bleed off top/left screen edges [invertego]
* ares: Rename lucia to desktop-ui to better represent it's function [Luke Usher]
* mia: Improve N64 save-type database [jeltaqq]
* mia: Add support for UNF extension, alongside UNIF and NES [Shideravan]
* nall: Add macOS deployment target flags; fixes ares on macOS 10.14 [MerryMage]
* ruby: Give PulseAudio higher priority than ALSA on Linux Systems; ALSA was causing frame-rate issues [Luke Usher]
A refactor in v116r07 replaced the variable dmaCompleted with dmaActive
but failed to update its usage on HDMA5 register reads. Bit 7 should
read 0 if HDMA is active and 1 if completed.
This change will affect many (most?) GBC games.
STAT interrupts triggered by mode 2 (OAM search) should only occur at the
start of the line. Crucially, writes to STAT in the midst of mode 2 that
enable OAM interrupts should not trigger a STAT interrupt. This is
especially important on DMG because of the hardware bug that causes STAT
writes to briefly enable all STAT interrupts. Spurious STAT interrupts
that would not have occurred on real hardware can violate the
assumptions of games that aren't expecting them. Mortal Kombat 3 is one
such game, and it is now playable.
Previously, ares was emulating the coincidence flag in the the STAT
register with M-cycle accuracy but was much less accurate with the
timing of coincidence triggered STAT interrupts or with resetting the LY
register to 0 during vblank. This was breaking a pattern common to a
number of games that goes like this:
1) Write 0 to LYC and set the coincidence interrupt enable bit in STAT
2) In the STAT interrupt handler, read LY and increment by one
3) Loop until LY equals the incremented value
ares would trigger a STAT interrupt during line 153 but LY would
continue to read back as 153 instead of 0. A game incrementing this
value and waiting for it to appear in LY would become stuck in an
infinite loop, as there is no line 154.
This change brings M-cycle accuracy to the LY register and STAT
interrupts using "The Cycle-Accurate Game Boy Docs" by AntonioND as a
reference. It also stops resetting LY on write, as this erroneously
described behavior is not hardware accurate.
The following games should now be playable:
- Elite Soccer
- Mouse Trap Hotel
- Shantae
This significantly improves performance for md, cd, 32x and cd32x, with
minimal impact on accuracy.
Assuming 3420 cpu cycles per scanline, with a max horizontal resolution
of 320/342:
For MegaDrive/Mega-CD, we can sync every 10 cycles (approx 1 pixel),
since we're using a dot renderer, there is little point in synching more
often than that.
For 32X/CD32X, we sync once every 40 cycles (4 pixels), this provides
enough of a performance boost to make 32X emulation viable for modest
machines, but does not significantly impact compatibiltiy or accuracy;
it's still significantly better than with the scanline renderer we used
previously.
This improves compatibility with both MegaDrive and 32X titles at the
expense of performance.
On modest hardware, this still retains full-speed for MegaDrive titles, but 32X and MegaCD may struggle; this will be addressed in a later
commit.
This emulation bug, combined with the intentional emulation of the
hardware bug that causes spurious stat interrupts, was causing stat
interrupts to be raised when the display was disabled.
This stops the GB game Cool Hand from freezing after selecting cribbage.
This removes the special casing for Sonic & Knuckles, treating it as a standard rom.
While not strictly correct from an accuracy/real world point of view, all existing
emulators and rom dumps assume the emulator will treat it as a single cart.
The TMS9918 allows for sprites to, in the words of TI's VDP Programmer's
Guide, "bleed" off the top or left edge of the screen. Depending on the
edge, this is accomplished by different means.
Proper implementation of this behavior is known to affect the following
ColecoVision games:
- Frogger: some sprites should be hidden off the left edge of the screen
- The Heist: the player sprite crosses the left edge of the screen
- Bump 'N' Jump: car sprites cross the top edge of the screen
It looks as though the V9938 and SMS VDP will require similar fixes.
Initialize VRAM to zero on load for systems that use the TMS9918/V9938.
On real hardware this memory will be in a partially indeterminate state,
but as far as approximations go, 0x00 is much less problematic than
0xff. A sprite attribute table filled with 0xff is interpreted to have
valid entries for sprites in the top right corner of the screen. If the
pattern data is also filled with 0xff, a white square will be drawn in
the corner. On the other hand, a sprite entry of all 0x00 bytes will be
fully transparent (due to the color byte being zero) and therefore
invisible.
This is most noticeable in games that never get around to fully
initializing VRAM, such as the ColecoVision game Boulder Dash, which has
a permanent square in the corner.
SG-1000 games only seem to exhibit this problem briefly after booting,
and only for certain games, as they eventually get around to
initializing VRAM. Some homebrew is more seriously affected.
MSX compatibility is in too poor a state to test comprehensively, but a
survey of other emulators shows initializing VRAM to zero is the norm.
This change also allows VRAM to carry over across soft resets. This
should be closer to hardware behavior, though in reality it is possible
for some bits to be perturbed.
ColecoVision carts contain up to 4 separate 8 KiB banks, and there is no
mirroring when some banks are absent. The existing mirroring behavior
was causing Sammy Lightfoot to freeze on load.
This release primarily provides improved Neo Geo Pocket/Neo Geo Pocket Color and Sega 32X emulation.
The entire Neo Geo Pocket/Color library is now thought to be playable, with minor graphical issues in four titles.
A small number of SEGA 32X games are now playable, although most still experience graphical and/or audio issues.
Changelog:
ColecoVision: Clear top bit of controller port reads; fixes Defender [invertego]
Neo Geo Pocket: Allow BIOS to handle the boot process [invertego]
Neo Geo Pocket: Copy SNK logo from BIOS during fast boot; fixes Metal Slug: 2nd Mission [invertego]
Neo Geo Pocket: Fix address used to test ram initialization [invertego]
Neo Geo Pocket: Initialize Neo Geo Pocket port 1 to zero; fixes Dynamite Slugger [invertego]
Neo Geo Pocket: Many improvements to 'fast boot' [invertego]
Neo Geo Pocket: Re-enable savint ram to disk on unload [invertego]
Sega 32X: Implement FM/Framebuffer access bit; fixes Spiderman [Luke Usher]
Sega 32X: Implement RV bit [Luke Usher]
Sega 32X: Optimise SH7604 recompiler min-cycles for 32X; fixes Knuckles Choatix & Virtua Fighter [remutro]
Sega 32X: PWM DREQ and timer are different things; fixes PWM audio in many games [Luke Usher]
Sega 32X: Used cached interpreter instead of recompiler [Luke Usher]
TMS9918: Fix sprite size emulation; fixes many graphical issues in ColecoVision/MSX/SG-1000 [invertego]
TMS9918: fix interrupt behavior [invertego]
hiro: Fix browser dialog filters on macOS [Luke Usher]
hiro: Force GTK3 to use X11 backend; fixes a crash under Wayland [thrimbor]
lucia: Disable fast boot by default [Luke Usher]
lucia: Support digital presses from analog inputs [invertego]
mia: Add workaround for underdumped Delta Warp rom [Luke Usher]
mia: Improve Nintendo 64 save chip database; fixes saving in some titles [sp1187]
nall: Enable LTO by default on non-debug builds [Luke Usher]
nall: Speed up recompiler codegen [Luke Usher]
sh2: Allow cores to determine an ideal minimum recompiler block size [Luke Usher]
sh2: Optimised code-gen for the interpreter [Luke Usher]
sh2: Recompiler should invalidate single blocks, not entire pools [Luke Usher]
tlc2900h: Fix immediate mask in BIT #,r; fixes Pocket Tennis [invertego]
z80: Correct the effect of IE on the next instruction; fixes audio drop-out in Neo Geo Pocket games [invertego]
The existing implementation was very incorrect. Fortunately, this chip
is well documented and the correct behavior is quite easy to implement.
This fixes most of the remaining ColecoVision bugs that aren't related
to missing peripheral support.
The TMS9918 is also used by the SG-1000 and MSX cores. I don't have a
list of bugs for those platforms, so I couldn't do any targeted testing,
but I booted up a few games and did not see any new issues.
Commit 532aafe074 made some improvements
to sprite zoom (magnification) emulation. It also corrected sprite size
emulation in the SMS VDP in what is referred to as Mode 4 by most
sources ("graphics3" in ares). Unfortunately, it erroneously applied the
same changes to the TMS9918 and V9938 as well as the SMS VDP in TMS9918
compatible modes. This caused widespread regressions in ColecoVision,
SG-1000, MSX, and MSX2 emulation.
This commit reverts the changes made outside of SMS VDP Mode 4,
restoring the dimensions of double sized sprites from 8x16 to 16x16.
I couldn't find any references describing the expected value of the top
bit of controller port reads, but some games require it to be cleared.
Here is an example from Defender when it is waiting a 1/2 button press:
in a,($FC) ; read controller 1
cp $7D ; compare 1 button
jr z,$876D
cp $77 ; compare 2 button
jr z,$8773
Clearing it fixes input in games that depend on all the undefined bits.
The implementation of IE in the Z80 processor was incorrectly causing
nonmaskable interrupts raised before the next instruction to be dropped.
A correct implementation should do two things:
- set IFF1 and IFF2 to 1
- disable maskable interrupts until after the following instruction
This fixes the issue of audio dropping out of Neo Geo Pocket games
seemingly at random.
References:
Z80 CPU User Manual (http://www.zilog.com/docs/z80/UM0080.pdf)
Page 6: "NMI is always recognized at the end of the current instruction,
independent of the status of the interrupt enable flip-flop..."
Page 183: "During the execution of this instruction [EI] and the
following instruction, maskable interrupts are disabled."
Use three first letters of game ID for mapping.
Add more entries (mostly Japanese games) and fix a few incorrect ones.
Handle some special cases involving different save chips for different
revisions and regions of the same game.
Change manifest generation to use whole four-letter ID and also output
the revision.
modified: ares/md/m32x/sh7604.cpp
Change the cached interpreter's recompiler min_cycles value from 23 to 22.
It's just ever so slightly too agressive.
This addresses problems with the bonus levels in Knuckles Chaotix,
as well as the hang in Virtua Fighter after selecting your character.
This appears to be the optimal value through lots of additional testing.
There were no other problems observed in the 32X library by lowering this
value to 22. Additionally, there were no further gains to be made by going
any lower (all the way to zero) such as correcting the hang at the end of
the match in Brutal: Above the Claw or NBA Jam failing to go in-game. Both
of these currently require using the full interpreter, and not the cached
interpreter enabled by default to correct timing issues.
This fixes 5% of games in the 32X library. :-)
lucia maps the N64 C-buttons to the right thumbstick of the virtual pad.
These are analog inputs on the virtual pad, so sampled analog values are
not converted to digital. This means any nonzero value is treated as
button press, which is not ideal when mapped to an analog input device.
This change introduces a helper to convert raw input values to a binary
"pressed" state at time of use, currently only defined for digital and
analog input mappings - for relative and absolute inputs this concept
would not make much sense.
My last change indexed into the ram array by an absolute memory address,
but the array only covers a portion of the address space beginning at
0x4000. This was in fact indexing past the end of the array, but it
appeared to work as long as 1) something was mapped there and 2) that
something was nonzero. It's possible that booting from the shutdown
vector every time doesn't have any negative side effects, but booting
from the hardware reset vector the first time is still the more correct
thing to do from an accuracy perspective.
Neo Geo Pocket is an "always on" system. On first boot, it quickly
enters a low power state via a halt instruction. From there, the user
must press the power button to wake the sytem. At this point, the BIOS
setup is shown, requiring the user to pick a preferred language among
other choices. When power is pressed again, the system returns to a low
power state. This state is maintained by an internal battery should the
external batteries discharge or be removed. The hardware reset entry
point will not execute again until the internal battery fails.
The current design of ares appears to be motivated by a few goals:
- Avoid requiring the user to press the emulated power button
- Avoid showing the BIOS setup more times than necessary
- Enable "fast boot" mode to skip the boot animation
The required power button press is avoided by skipping the first boot
code entirely in CPU::power(). Emulation never begins at the hardware
reset vector, but rather at 0xFF1800, following MAME's lead. This entry
point appears to have been for development purposes only and is not
referenced by the BIOS itself. Crucially, it does not run some
bookkeeping logic that only occurs when entering a low power state
either after a cold boot, in response to a power button press, or after
a software requested shutdown. Skipping this logic can cause the BIOS
setup to be shown on next boot.
The BIOS setup is avoided by simulating the bookkeping done by the BIOS
in the emulator itself. This logic is located in CPU::load(), meaning
that it does not run between system resets. Therefore, resetting a game
can still cause the BIOS setup to be shown. The BIOS setup is also
skipped by fast boot mode.
Fast boot mode bypasses the BIOS entirely on boot, jumping straight to
the cartridge entry point. This means all of the many important side
effects of the boot process must be replicated by CPU::fastBoot().
Currently, it also gives the user no way to select Japanese as a
preferred language.
The existing solutions to these problems fall short of providing a
consistent user experience, tightly couple ares to the internals of the
BIOS rom, and (particularly with fast boot) have been a source of many
bugs. This change removes the existing solutions in favor of ones that
let the BIOS handle the entirety of the boot process.
The new code in this change does the following:
- Begin execution at the hardware reset vector on first boot
- Begin execution at the VECT_SHUTDOWN syscall on subsequent boots
- Simulate a power button press when entering a low power state
- Patch the BIOS to skip the boot animation in fast boot mode
Starting at the hardware reset vector ensures the BIOS setup will be
shown on first boot, affording the user the opportunity to pick a
preferred language. Subsequent boots will begin at the VECT_SHUTDOWN
system call. It may seem counterintuitive, but this allows the BIOS to
perform cleanup that would normally only occur when the user shuts off
the device before switching cartridges. In both of these cases, we can
avoid requiring the user to press the emulated power button by
simulating a button press on their behalf. It's a low tech solution to
be sure, but a reliable one.
Finally, the implementation of fast boot mode is replaced with a single
byte patch to the BIOS to immediately return from the routine that plays
the boot animation.
When this bit is set to 0, any framebuffer or VDP access from the sh2 has to be ignored and when this bit is set to 1, any framebuffer or VDP access from the m68k should be ignored.
This fixes the rendering issues in Spiderman, likely others too.
The fastboot option is a nice to have, but it has potential to introduce serious bugs/glitches into emulation, as seen with Neo Geo Pocket, so it is safer to default this option to disabled.
The game Metal Slug - 2nd Mission compares a region of character memory
to a copy of the SNK logo in the game rom. Normally this memory is
initialized for the boot animation played by the BIOS. If the logo isn't
an exact match, the game starts but you are unable to fire any weapons.
Conceptually, this is the reverse of what the Game Boy does on boot.
There, the boot rom validates a Nintendo logo on the cartridge.
Since we already have the BIOS loaded, we can copy the logo from there
during a fast boot, though some unpacking is required.
This code was commented out in commit
4e82321182 which otherwise only affected
TLCS900/H timing. I believe this was left in by mistake. Uncommenting
this code restores the ability to persist BIOS settings across play
sessions.
In the game Dynamite Slugger, when your batter strikes out it loads a
16-bit word from 0x0000 and resets the game if anything but zero comes
back. The second byte, at address 0x0001, is mapped to internal port 1,
and currently almost all port values are initialized to 1 at power on.
In a 2019 nesdev post [1], Near stated that port emulation was incomplete
and likely incorrect. Without hardware tests, I'd rather not touch this
code more than necessary, but at the very least it seems more correct to
initialize the latched value in port 1 to zero.
There is a chance that the null dereference in Dynamite Slugger is
itself the result of an emulation bug, but all I have to compare against
is MAME, and the game behaves the same there. I believe this is decent
evidence that we are seeing a real game bug and that reading back zero
is what would have occurred on actual hardware.
[1] http://forums.nesdev.com/viewtopic.php?f=23&t=18579#p236069
"I added ports 1, 2, A, and B. Although ports 1 (d8-d15) and 2 (a16-a23)
are ... strange. They're likely emulated very wrong. I don't even
understand how one can change the direction of the data bus. I'm ...
suspecting that ports have their own latch values, but the manual isn't
very clear on this."
Perform more initialization to match the side effects of booting from
the BIOS.
1) Initialize XIX register. Puyo Pop World relies on this (likely a game
bug).
2) Initialize interrupt vector table. SNK Gals' Fighters and the Pocket
Casino Series games rely on this.
3) Initialize interrupt request levels used by the VECT_INTLVSET system
call. The Pocket Casino Series games rely on this.
The BIT (imm, reg) instruction uses the low 4 bits of its immediate operand even
when the register operand is only 8 bits wide. When the register is 8 bits and
the immediate value is between 8 and 15, ZF will be always be set. ares was
erroneously using only the bottom 3 immediate bits in this case (so 15 would
behave the same as 7).
With this fix, sprites now render correctly in the Neo Geo Pocket game Pocket
Tennis.
This bug was discovered by comparing against an instruction trace from MAME.
This change is the functional equivalent of commit
57e42cda31430c75566403c5f27ec290dc123da3 in the MAME git repo.
Although mia doesn't use threads itself, it includes `ares/ares.hpp` and ares
*does* use threads, so we need to build with `-pthread` in order to link
successfully.
I've released ares v121. Because it is not fully complete or stable, it is
released as source code only.
The license is now once again ISC instead of CC-BY-NC-ND.
Master System, WonderSwan, and WonderSwan Color compatibility have increased to
100%, with no remaining known bugs.
The Neo Geo Pocket is very close to 100% now with one issue remaining, where
sound effects sometimes mute in games.
Nintendo 64 compatibility has increased to above 80% thanks to corrections to
controller pak handling.
Several NES and Mega CD fixes have been added. EEPROM support has been added for
the Mega Drive.
Memory cards and paks now pre-format themselves, so you don't have to do so in-
game or in BIOS settings.
The new Neo Geo emulation is slowly improving, but it's still very preliminary
with only seven games fully playable so far.
The Nintendo 64 SM5K and PlayStation HC05 processor cores have been emulated,
but not connected yet due to a lack of information.
Added mouse input support and connected peripheral selection to the GUI, so mice
and light gun games can now be used.
There is now per-system input mapping overlays, so you can map controllers based
on the original system button names.
And lastly as promised, the SNES core has gained optional widescreen support.
Changelog (since v120):
- Nintendo 64: added Windows ABI support to dynamic recompilers
- PlayStation: added Windows ABI support to dynamic recompiler
- Nintendo 64: temporarily disabled 64-bit addressing mode due to issues
- Nintendo 64: corrected analog stick ranges and emulated octagonal
boundaries
- Nintendo 64: code cleanups around memory access functions
- Nintendo 64: started to implement RDRAM broadcasting (very incomplete
still)
- Mega Drive: improved VDP scanline renderer timing
- M68K: corrected clipping bug in ADD,CMP,SUB instructions
- Nintendo 64: improved SI scanning of PIF RAM and emulated more flags
- Nintendo 64: added very accurate controller pak initialization code
- Nintendo 64: improved controller analog stick approximations [MerryMage]
- Nintendo 64: added priority queue to delay SI and PI DMA transfers
- Master System: added bit-perfect YM2413 instrument patch sets
- Mega Drive: fixed a bug with LINEA and LINEF instructions (should not
decrement PC)
- Mega Drive: added EEPROM emulation
- mia: added Mega Drive and Mega 32X EEPROM database entries
- nall: added priority_queue::remove(T) support
- Nintendo 64: reverted 64-bit TLB (not actually present)
- Neo Geo: initial implementation
- Neo Geo: many emulation improvements
- nall: add workaround for compilers that lack __has_builtin
- Nintendo 64: ignore A15 on controller pak reads and writes
- Master System: implemented Codemasters, Korea, MSX, Janggun mappers
- Master System: improved Sega mapper emulation
- Master System: added initial emulation of port $3e
- Master System: added support to load BIOSes
- Master System: initialize stack pointer to 0xfffd when no BIOS loaded
[Luke Usher]
- Game Boy Advance: emulated BIOS swap register [MerryMage]
- Mega Drive: cancel pending IRQs when they are disabled [Jonas Quinn]
- Mega Drive: fixed handling of VDP field flag [Jonas Quinn]
- Mega Drive: mask upper bit of VDP sprite Y value when in progressive
display mode [Jonas Quinn]
- X24C01, M24Cxx: improve emulation of EEPROM command sequences
- Famicom: added database entries for Jajamaru Gekimaden and Mazase Top
Pro PRG-RAM
- M24Cx: rewrote emulation to be more complete; though still not working
for Cxx/Cxxx sizes
- Nintendo 64: try stopping SI polling on recv=0xfe
- Mega Drive: improved EEPROM emulation
- Nintendo 64: fixed CPU SCC counter rate [simer]
- Nintendo 64: added initial emulation of the SM5K processor (not connected
yet)
- lucia: update frame rate from the main thread to prevent a race condition
with GTK
- Master System: emulated sprite zoom and fifth-sprite status flag
- Master System: corrected VDP background emulation for mode 4 [fixes
Codemasters games]
- Master System: latch VDP background nametable address and scroll registers
[fixes Desert Speedtrap]
- Master System: mask CRAM reads to 6-bit in Master System mode [fixes Mercs]
- Master System: refactored VDP code
- Z80: swapped IND/INI to post-decrement B, and OUTD/OUTI to pre-decrement B
- lucia: fixed a crash when loading Game Gear games due to stubbing out
the BIOS
- Nintendo 64: fixed cartridge flash memory support
- Master System: VDP line coincidence should be initialized to $ff [fixes
Shadow Dancer]
- Master System: VDP sprite overflow index defaults to $1f, not $00 [fixes
PGA Tour Golf]
- SN76489: corrected port latching behavior and noise volume writes [fixes
Micro Machines]
- TMS9918: greatly refactored code
- V9938: greatly refactored code
- Z80: disassembler fixes
- lucia: corrected mapping of Master System pause button [fixes Baku
Baku Panic]
- nall: disable -Wstringop-overflow for GCC due to compiler heuristics error
- M68HC05: initial core implementation added
- M68000: renamed core from M68K
- Super Famicom: clearing $4200.d0 stops active joypad polling for the rest
of the frame [Jonas Quinn]
- Master System: don't evaluate sprites past active display area [fixes
Rescue Mission]
- Mega Drive: don't acknowledge VDP IRQs until the CPU triggers them [fixes
Mega Lo Mania]
- lucia: begin refactoring input mapping to allow per-system mappings and
multiple controller types
- Game Gear: set CPU::in() unmapped return value to MDR; fixes RoboCop 3
[Jonas Quinn]
- WonderSwan Color: do not mask screen tilemap base address; fixes Sorobang
[FPGAzumSpass]
- Mega Drive: set supervisor mode and clear trace mode for all exceptions;
fixes Gouketsuji Ichizoku [Jonas Quinn]
- Mega CD: format BRAM instead of leaving it uninitialized; fixes Popful Mail
(US)
- WonderSwan: add patch for Meitantei Conan: Nishi no Meitantei Saidai
no Kiki!
- Game Boy: add MBC1#M mapper database entries; fixes Bomber Man Collection,
Genjin Collection, Momotarou Collection, and Mortal Kombat I & II
- Neo Geo Pocket: $8118 background register exists even in the K1GE GPU;
fixes Samurai Shodown
- Neo Geo Pocket Color: return 0xFF acknowledge byte after flash erase
command; fixes Puzzle Link 2 and Memories off: Pure
- Neo Geo Pocket: clear watchdog timer counter on trigger to prevent
infinite triggering; fixes Neo Baccarat, Neo Cherry Master Color, and
Neo Mystery Bonus
- TLCS900H: do not allow interrupts to run between CPDR, LDIR, LDDR
instructions; fixes Fantastic Night Dreams Cotton
- Neo Geo Pocket: add all remaining missing I/O registers (not emulated,
but registers are readable and writable now)
- Neo Geo Pocket Color: above changes also fixed in-game audio in Crush
Roller and Dynamite Slugger
- Mega CD: added 1M mode WRAM swap request flag; fxies AX-101, Earnest Evans,
and Might & Magic III [TascoDLX]
- lucia: added input mapping overlays for all remaining systems
- lucia: added two-player support to all remaining systems
- TLCS900H: refactored instruction decoder and disassembler using range-case
- TLCS900H: improved emulation of (PC+d16) addressing mode (LDAR)
- TMS9918, V9938, SMS VDP: corrected sprite zoom emulation [Jonas Quinn]
- Neo Geo Pocket: added new debugging modules (flash ROM, I/O accesses,
system calls)
- Neo Geo Pocket: improved CPU interrupt logger (prints name of interrupt
now)
- Neo Geo Pocket: fixed a critical issue with interrupt priority levels;
fixes many games
- Neo Geo Pocket: added stubs for all remaining TMP95C061F I/O registers
(not emulated yet)
- Neo Geo Pocket: set CPU I/O port $b1.d2 reads to return 1 (fixes SNK
Gals' Fighter)
- Neo Geo Pocket: added stubs for undocumented CPU I/O ports $b6 and $b7
- Super Famicom: PPU code restructuring
- Super Famicom: added widescreen (16:9 and 21:9) support to the scanline
renderer
- WonderSwan: refactored I/O handlers to use switch/case instead of if tests
- WonderSwan: rewrote PPU renderer to modularize each component (screen1,
screen2, sprite, dac, etc)
- WonderSwan: corrected timers to count down instead of up; fixes timing
in many games [FPGAzumSpass]
- WonderSwan: improved screen two window emulation [FPGAzumSpass]
- hiro: TableView::onContext() is now TableView::onContext(TableViewCell)
(not supported for Cocoa or Qt yet)
- lucia: merged code to handle input assignment overlays and controller
polling for each emulation core
- lucia: added virtual mouse emulation and added mouse capture support
- lucia: added support to change devices connected to controller ports
- Neo Geo Pocket: added database workaround for underdumped Prize Game:
PP-AA01 Pusher Program (Japan)
- Neo Geo Pocket: fixed fast boot mode for Neo Cherry Pocket
- nall/range: added new within() templates
- V30MZ: emulated instruction prefetch
- V30MZ: greatly improved instruction timings (thanks to FPGAzumSpass'
test ROM)
- WonderSwan: disabling an interrupt source does clear its pending status
(fixes Digimon Tamers)
- TLCS900H: improved prefetch handling and instruction timing (still
imperfect)
- TLCS900H: improved timing further (still imperfect)
- WonderSwan: disabling an interrupt source does clear its pending status
(fixes Digimon Tamers)
- TLCS900H: improved prefetch handling and instruction timing (still
imperfect)
This gets a 100% pass on FPGAzumSpass' WonderSwan instruction timing tests, and
emulates CPU prefetch as well, but it seems to make games less stable rather
than more =(
- TLCS900H: refactored instruction decoder and disassembler using range-case
- TLCS900H: improved emulation of (PC+d16) addressing mode (LDAR)
- TMS9918, V9938, SMS VDP: corrected sprite zoom emulation [Jonas Quinn]
- Neo Geo Pocket: added new debugging modules (flash ROM, I/O accesses,
system calls)
- Neo Geo Pocket: improved CPU interrupt logger (prints name of interrupt
now)
- Neo Geo Pocket: fixed a critical issue with interrupt priority levels;
fixes many games
- Neo Geo Pocket: added stubs for all remaining TMP95C061F I/O registers
(not emulated yet)
- Neo Geo Pocket: set CPU I/O port $b1.d2 reads to return 1 (fixes SNK
Gals' Fighter)
- Neo Geo Pocket: added stubs for undocumented CPU I/O ports $b6 and $b7
- Super Famicom: PPU code restructuring
- Super Famicom: added widescreen (16:9 and 21:9) support to the scanline
renderer
- WonderSwan: refactored I/O handlers to use switch/case instead of if tests
- WonderSwan: rewrote PPU renderer to modularize each component (screen1,
screen2, sprite, dac, etc)
- WonderSwan: corrected timers to count down instead of up; fixes timing
in many games [FPGAzumSpass]
- WonderSwan: improved screen two window emulation [FPGAzumSpass]
- hiro: TableView::onContext() is now TableView::onContext(TableViewCell)
(not supported for Cocoa or Qt yet)
- lucia: merged code to handle input assignment overlays and controller
polling for each emulation core
- lucia: added virtual mouse emulation and added mouse capture support
- lucia: added support to change devices connected to controller ports
- Neo Geo Pocket: added database workaround for underdumped Prize Game:
PP-AA01 Pusher Program (Japan)
- Neo Geo Pocket: fixed fast boot mode for Neo Cherry Pocket
- nall/range: added new within() templates
- Game Gear: set CPU::in() unmapped return value to MDR; fixes RoboCop 3
[Jonas Quinn]
- WonderSwan Color: do not mask screen tilemap base address; fixes Sorobang
[FPGAzumSpass]
- Mega Drive: set supervisor mode and clear trace mode for all exceptions;
fixes Gouketsuji Ichizoku [Jonas Quinn]
- Mega CD: format BRAM instead of leaving it uninitialized; fixes Popful Mail
(US)
- WonderSwan: add patch for Meitantei Conan: Nishi no Meitantei Saidai
no Kiki!
- Game Boy: add MBC1#M mapper database entries; fixes Bomber Man Collection,
Genjin Collection, Momotarou Collection, and Mortal Kombat I & II
- Neo Geo Pocket: $8118 background register exists even in the K1GE GPU;
fixes Samurai Shodown
- Neo Geo Pocket Color: return 0xFF acknowledge byte after flash erase
command; fixes Puzzle Link 2 and Memories off: Pure
- Neo Geo Pocket: clear watchdog timer counter on trigger to prevent
infinite triggering; fixes Neo Baccarat, Neo Cherry Master Color, and
Neo Mystery Bonus
- TLCS900H: do not allow interrupts to run between CPDR, LDIR, LDDR
instructions; fixes Fantastic Night Dreams Cotton
- Neo Geo Pocket: add all remaining missing I/O registers (not emulated,
but registers are readable and writable now)
- Neo Geo Pocket Color: above changes also fixed in-game audio in Crush
Roller and Dynamite Slugger
- Mega CD: added 1M mode WRAM swap request flag; fxies AX-101, Earnest Evans,
and Might & Magic III [TascoDLX]
- Nintendo 64: added ISViewer support
- lucia: added input mapping overlays for all remaining systems
- lucia: added two-player support to all remaining systems
- Game Gear: fix inputs
- Master System: don't evaluate sprites past active display area [fixes
Rescue Mission]
- Mega Drive: don't acknowledge VDP IRQs until the CPU triggers them [fixes
Mega Lo Mania]
- lucia: begin refactoring input mapping to allow per-system mappings and
multiple controller types
- M68HC05: initial core implementation added
- M68000: renamed core from M68K
- Super Famicom: clearing $4200.d0 stops active joypad polling for the rest
of the frame [Jonas Quinn]
- Nintendo 64: fixed cartridge flash memory support
- Master System: VDP line coincidence should be initialized to $ff [fixes
Shadow Dancer]
- Master System: VDP sprite overflow index defaults to $1f, not $00 [fixes
PGA Tour Golf]
- SN76489: corrected port latching behavior and noise volume writes [fixes
Micro Machines]
- TMS9918: greatly refactored code
- V9938: greatly refactored code
- Z80: disassembler fixes
- lucia: corrected mapping of Master System pause button [fixes Baku
Baku Panic]
- nall: disable -Wstringop-overflow for GCC due to compiler heuristics error
- Master System: emulated sprite zoom and fifth-sprite status flag
- Master System: corrected VDP background emulation for mode 4 [fixes
Codemasters games]
- Master System: latch VDP background nametable address and scroll registers
[fixes Desert Speedtrap]
- Master System: mask CRAM reads to 6-bit in Master System mode [fixes Mercs]
- Master System: refactored VDP code
- Z80: swapped IND/INI to post-decrement B, and OUTD/OUTI to pre-decrement B
- lucia: fixed a crash when loading Game Gear games due to stubbing out
the BIOS
- Mega Drive: improved EEPROM emulation
- Nintendo 64: fixed CPU SCC counter rate [simer]
- Nintendo 64: added initial emulation of the SM5K processor (not connected
yet)
- lucia: update frame rate from the main thread to prevent a race condition
with GTK
- Famicom: added database entries for Jajamaru Gekimaden and Mazase Top
Pro PRG-RAM
- M24Cx: rewrote emulation to be more complete; though still not working
for Cxx/Cxxx sizes
- Nintendo 64: try stopping SI polling on recv=0xfe
- Nintendo 64: ignore A15 on controller pak reads and writes
- Master System: implemented Codemasters, Korea, MSX, Janggun mappers
- Master System: improved Sega mapper emulation
- Master System: added initial emulation of port $3e
- Master System: added support to load BIOSes
- Master System: initialize stack pointer to 0xfffd when no BIOS loaded
[Luke Usher]
- Game Boy Advance: emulated BIOS swap register [MerryMage]
- Mega Drive: cancel pending IRQs when they are disabled [Jonas Quinn]
- Mega Drive: fixed handling of VDP field flag [Jonas Quinn]
- Mega Drive: mask upper bit of VDP sprite Y value when in progressive
display mode [Jonas Quinn]
- X24C01, M24Cxx: improve emulation of EEPROM command sequences
This one is an experiment to ignore A15 on memory pak reads+writes. If possible,
I'd like to know if any games with controller pak issues start working with this
change that didn't before ^-^;
- Mega Drive: fixed a bug with LINEA and LINEF instructions (should not
decrement PC)
- Mega Drive: added EEPROM emulation
- mia: added Mega Drive and Mega 32X EEPROM database entries
- nall: added priority_queue::remove(T) support
This doesn't justify a new WIP release yet, but it changes the PI DMA delay
timing which seems to make Aidyn Chronicles work again, so let's see how it
does.
- Nintendo 64: improved SI scanning of PIF RAM and emulated more flags
- Nintendo 64: added very accurate controller pak initialization code
- Nintendo 64: improved controller analog stick approximations [MerryMage]
- Nintendo 64: added priority queue to delay SI and PI DMA transfers
- Master System: added bit-perfect YM2413 instrument patch sets
This fixes a major issue with the 68K ADD,CMP,SUB instructions not clipping, and
improves the VDP scanline renderer timing somewhat.
This fixes Alien Solder, and I also moved the DMA run below the FIFO/prefetch to
fix Comix Zone's graphics. It regresses several Titan Overdrive 2 screens, but
oh well.
I'm trying to track down a bug in Popful Mail (US) where the CPU crashes right
after the title screen. It seems like the CPU is getting stuck in a loop that
keeps calling the same function, so the stack keeps decrementing until it ends
up overwriting the currently executing code with a bad instruction.
Without an I/O tracer it's really difficult to try and understand what the CPU
is stuck waiting on and looping on. I'll have to add an I/O tracer to the Mega
CD registers.
The CPU fixes sadly didn't improve anything in the 32X space. Metal Head gets in
a loop until it overwrites the stack frame return address with 0x1fff1fff that
causes a return to an unaligned address that crashes the SH2 master.
After Burner Complete doesn't boot at all. Amazing Spider-Man still has screwed
up graphics priority ordering for the 32X VDP.
Space Harrier still shows a bunch of junk lines at the top and bottom of the
screen.
The scanline VDP can now run Lemmings 1&2, Alien Soldier, etc. But it still does
horrifically bad with Titan Overdrive, especially 2.
This release provides improved Nintendo 64 and Mega Drive emulation, plus some
emulation speedups and new features like keyboard-mapping for all Nintendo 64
controls.
The infamous Titan Overdrive demos now run with the exception of one glitched
screen each, but you will need to compile with profile=accuracy to enable the
required cycle-based VDP renderer for this to work. I'll try in the future to
support as much of it as I can with the default scanline renderer as well.
Changelog (since v119):
- SH2: added support for Windows ABI to the recompiler
- SH2: MAC must increment R[n] before reading from R[m]; fixes Virtua
Fighter and Toughman Contest
- SH2: fixed dynarec MOV @Rm+,Rn to not increment when Rm==Rn
- SH2: fixed dynarec TST instruction
- SH2: improved dynarec accuracy by breaking blocks on delay slot branches
- SH2: improved dynarec accuracy by decreasing the underclocking amount
- Mega Drive: implemented undocumented VSRAM and CRAM DMA fill
- Mega Drive: simplified scanline VDP renderer; fixes TMNT: Tournament
Fighters graphics
- Mega Drive: improved region detection; correctly identifies Alien Soldier
region now
- Mega CD: fixed crash on game load
- Super Famicom: fixed direct color mode; fixes Secret of Mana world map
- WonderSwan Color: fixed initial state for new EEPROMs plus EEPROM size;
fixes missing sound
- lucia: fixed saving RAM files when a manual save path was specified
- ruby: fixed library dependency detection for Arch Linux and other
distributions
- SH2: additional correction for dynarec MOV @Rm+,Rn instructions
- hiro/GTK3: added CSS stylesheet overrides to improve appearance [Screwtape]
- N64: VMRG was not clearing VCO in C++ version [Rasky]
- N64: fixed "ctc2" in the disassembler
- Mega Drive: VDP address/command bits are set even for non-register writes
[Eke]
- Mega Drive: implemented VDP FIFO with approximated timings
- Mega Drive: implemented CPU bus arbitrator
- N64: fixed RSP vector unit register values in the disassembler
- Mega Drive: implemented proper VDP FIFO timings for both reads and writes
(hopefully)
- Mega Drive: enabled external and RAM refresh timing
- Mega Drive: added (Mega Drive | Mega 32X) + Mega CD mode 1 emulation
- Mega Drive: refactored dot-based VDP renderer
- ares: added Thread::restart() function to reset a thread without resetting
its clock
- Mega Drive: improved DRAM refresh timings
- Mega Drive: added VDP I/O logger
- Mega Drive: fixed VDP counter emulation (still inaccurate)
- Mega Drive: improved VDP DMA and FIFO emulation
- Nintendo 64: report 64DD as missing for now; fixes F-Zero X
- Nintendo 64: improved TLB emulation; fixes Conker's Bad Fur Day
- Nintendo 64: PI DMA from flash always reads data, never the status;
fixes Paper Mario
- Mega Drive: improved VDP FIFO emulation
- Mega Drive: improved VDP dot-renderer
- nall/bit-range: fixed bug with bit indexes >= 32
- Mega Drive: fixed VDP read buffer indexing for VSRAM and CRAM
- Mega Drive: fixed 68K to VDP DMA so that it instantly freezes the CPU
- Mega Drive: emulated VDP left window hardware glitch where hscroll&15!=0
- Mega Drive: improved CPU interrupt handling
- Mega Drive: added APU bus mirrorings
- Mega Drive: emulated the VDP debug register
- Mega Drive: fixed VDP VRAM DMA copy
- Mega Drive: improved 128KB VRAM mode support
- Mega Drive: mask sprite attribute table address in H40 mode [Sik]
- Mega Drive: VDP timing improvements
- Nintendo 64: improved EEPROM support; fixes Perfect Dark
- Nintendo 64: improved VI interrupt support; fixes Star Wars: Rogue Squadron
title screen [nodev]
- Nintendo 64: emulated CIC-NUS-6105 copy protection; fixes Banjo-Tooie
[XScale]
- Nintendo 64: added serrate (interlace) support and fixed bug when
supersampling in serrate mode
- Nintendo 64: emulated CPU instruction cache
- Nintendo 64: emulated CPU data cache
- Nintendo 64: emulated CPU CACHE instruction
- Nintendo 64: fixed CPU TLB bug; fixes GoldenEye
- Nintendo 64: began adapting CPU cached interpreter into a dynamic
recompiler
- Nintendo 64: began adapting RSP cached interpreter into a dynamic
recompiler
- Nintendo 64: added 64-bit addressing and TLB supporting
- Nintendo 64: added endian support to [LS][WD][LR] instructions
- Nintendo 64: improved dynamic recompiler
- PlayStation: began adapting CPU cached interpreter into a dynamic
recompiler
- lucia: allow mapping analog axes separately (allows mapping sticks to
the keyboard)
- Nintendo 64: corrected analog stick ranges
- Nintendo 64: emulate the analog stick as an octagon rather than a circle
[YetAnotherEmuDev]
[This is actually the second release of v120; the change since the first release
is the N64 analog stick ranges and the octagon gate. -Ed.]
- Mega Drive: VDP scanline renderer compiles once more
- Nintendo 64: improved dynamic recompiler
- PlayStation: began adapting CPU cached interpreter into a dynamic
recompiler
- lucia: allow mapping analog axes separately (allows mapping sticks to
the keyboard)
All that's left now is fixing the call() function in the N64/PS1 to support >3
(4) arguments on Windows and we can release v120
- Nintendo 64: began adapting CPU cached interpreter into a dynamic
recompiler
- Nintendo 64: began adapting RSP cached interpreter into a dynamic
recompiler
- Nintendo 64: added 64-bit addressing and TLB supporting
- Nintendo 64: added endian support to [LS][WD][LR] instructions
I could really use a hand with my CPU dynarec, n64/cpu/recompiler.cpp line 1335.
When calling an FPU instruction without SCC coprocessor 1 enabled, it throws an
exception.
If I call the exception function, the emulator crashes hard and I don't
understand why at all.
The stack is aligned, but it seems if I modify rbx/rbp/r13 as I do with the
RSP+SH2 just fine, it seems to die. Yet even if I make that code restore
rbx/rbp/r13 before calling the coprocessor exception function, it still dies.
Really at a loss >_>
Also, this will only work on Linux/BSD at the moment. The RSP vector functions
pass four parameters, and my Windows call wrapper can only handle 3 arguments
because after that the argument has to go on the stack. I'll fix that later.
Working Nintendo 64 data cache emulation (still don't know the memory access
timings for it) and improved Mega Drive VDP emulation (still can't run TO1&2)
GoldenEye 007 and Jet Force Gemini run now. Right now, known N64 bugs are:
Donkey Kong 64 hangs when the EEPROM support is enabled, Indiana Jones doesn't
boot (probably anti-emulator code?), Blast Corps blinks a lot (though less than
it did before.)
This WIP has CPU instruction and data cache emulation, though I had to disable
the data cache as it's not working yet.
Three N64 game fixes. Refactored Mega Drive profile=accuracy vdp more, still
can't pass Titan Overdrive 1 or 2 ._. Really getting demotivated on that one.
[Previously, Near said "Now to fix sprite fetching on Y=-1"]
Should be substantially better now.
Titan Overdrive 2 shows distorted graphics on the "Overdrive 2" logo screen
(after the ship crash and maze run), and the only way to get that working is to
double the VDP FIFO speed. It already runs twice as fast in 128K VRAM mode. The
same FIFO speed doubling is required to not crash after the Titancade screen.
Unless I'm really fundamentally misunderstanding something, I'm not sure what's
going on here.
This gets us a lot further with the Mega Drive, but still some major issues.
Lemmings 2 will sometimes crash when you load it (not threading related), and
Titan Overdrive 2 crashes after the arcade scene. Ran out of steam to work on
this more today though, 12 hours in already.
This has VDP debug register emulation, well one of the 16 debug registers anyway
I fixed sound in TO2, was mirroring like crazy in the APU space, also fixed
sprites not rendering all the way in the rain scene.
So what you'll see I'm doing is setting an irq.(vh)blank.pending=1 flag, and
then whenever you have hvirq enabled AND a pending flag, it sends an IRQ to the
CPU and clears the pending flag, and when the CPU triggers it, the CPU marks it
as acknowledged.
Apparently BlastEm links bit 7 of the control status register to the
vblank.pending flag, so I'm copying that.
[Near then posted a screenshot of Titan Overdrive 2 running inside ares. In
white text on a blue background, it says:
0D2 B50D
D0 00000001
D1 00FF2700
D2 93979301
D3 40000002
D4 0D12001C
D5 00000000
D6 00000001
D7 0000FFFF
A0 00C00004
A1 00C00000
A2 00000CBC
A3 00000DEC
A4 00FF1464
A5 00FF0C1A
A6 00FF0C1A
A7 00FFFFFE
-Ed.]
Crashes here if I don't lower the CPU H/VIRQ lines on Vblank/Hblank=0
Also I am faking the Vcounter incrementing early when reading the Vcounter,
easier that way.
Really substantial Mega Drive profile=accuracy timing improvements, but still
Titan Overdrive 2 performs much worse than the default performance profile, and
that fucking audio driver still won't play any sound.
- Nintendo 64: report 64DD as missing for now; fixes F-Zero X
- Nintendo 64: improved TLB emulation; fixes Conker's Bad Fur Day
- Mega Drive: improved VDP FIFO emulation
- ares: added Thread::restart() function to reset a thread without resetting
its clock
- Mega Drive: improved DRAM refresh timings
- Mega Drive: added VDP I/O logger
- Mega Drive: fixed VDP counter emulation (still inaccurate)
- Mega Drive: improved VDP DMA and FIFO emulation
- N64: fixed RSP vector unit register values in the disassembler
- Mega Drive: implemented proper VDP FIFO timings for both reads and writes
(hopefully)
- Mega Drive: enabled external and RAM refresh timing
- Mega Drive: added (Mega Drive | Mega 32X) + Mega CD mode 1 emulation
- Mega Drive: refactored dot-based VDP renderer
A working VDP FIFO implementation (write slots only), but probably wildly
inaccurate. Rough timing approximations for the slots.
This build fixes some issues in MD Sonic the Hedgehog (forgot to undo the
background color register bit twiddling when reverting some overly aggressive
VDP-performance optimizations) and also fixes MD Golden Axe II.
I spent a few hours trying to fix Lemmings 2 from locking up immediately. What
happens is I get a fourth Hblank IRQ before it clears a RAM value, whereas
Mednafen only gets three. And that desyncs something and it never gets out of a
loop.
Unfortunately a few critical issues crept in between v118 and v119, so here is a
bugfix release for all reported issues.
It also fixes some game bugs while I'm at it, and boosts 32X compatibility from
50% to a little over 60%.
Please do upgrade if you have v119, this one's important.
- SH2: MAC must increment R[n] before reading from R[m]; fixes Virtua
Fighter and Toughman Contest
- SH2: fixed dynarec MOV @Rm+,Rn to not increment when Rm==Rn
- SH2: fixed dynarec TST instruction
- SH2: improved dynarec accuracy by breaking blocks on delay slot branches
- SH2: improved dynarec accuracy by decreasing the underclocking amount
- Mega Drive: implemented undocumented VSRAM and CRAM DMA fill
- Mega Drive: simplified scanline VDP renderer; fixes TMNT: Tournament
Fighters graphics
- Mega Drive: improved region detection; correctly identifies Alien Soldier
region now
- Mega CD: fixed crash on game load
- Super Famicom: fixed direct color mode; fixes Secret of Mana world map
- WonderSwan Color: fixed initial state for new EEPROMs plus EEPROM size;
fixes missing sound
- lucia: fixed saving RAM files when a manual save path was specified
- ruby: fixed library dependency detection for Arch Linux and other
distributions
- hiro/GTK3: added CSS stylesheet overrides to improve appearance [Screwtape]
I'm releasing ares v119 today, which includes very preliminary Sega 32X
emulation support. Compatibility is currently at around 50% with the dynamic
recompiler, probably closer to 75% with the cached interpreter, and since the
system requirements were a bit too steep (on account of my Mega Drive core being
cycle/dot-accurate), I downclocked the SH2s a bit until I can speed up the
emulator more. You'll currently need about a Ryzen 5 2600 to hit 60fps reliably.
With the underclock, my Ryzen 7 5800X hits 120fps, and without it, 85fps.
Although the compatibility for the new 32X core is a bit low, this is mostly due
to pesky CPU bugs. The accuracy is quite high and I've emulated as much of the
32X and SH7604 peripheral functions as possible. I pass all 161 tests from the
Mars Check Program. It should not take much more work to reach 98% compatibility
in the future. Sega CD 32X emulation support is present, but is likely not
functional, as I haven't tested it yet.
Other major features in this release include Sega SVP support for Virtua Racing,
plus improved Nintendo 64, Mega Drive, and Mega CD emulation compatibility.
I'm going to start working on Sega Saturn emulation now, while Luke Usher works
on Neo Geo emulation. No promises as to when or if these cores will become
playable, I'm just giving you all a heads up since you'll see the skeletons for
these systems in the source code now.
Changelog:
- Nintendo 64: improved Expansion Pak detection
- Nintendo 64: fixed swapped L and R buttons [simer]
- Nintendo 64: emulated the RST bit for gamepads
- ruby: added library detection support for the Linux and BSD targets
- lucia: gained support for game paks (custom file dialog only)
- Super Famicom: added support for Super Game Boy, Sufami Turbo, and BS
Memory packs
- hiro: made SourceEdit optional for gtk2 and gtk3 targets (disabled
for ares)
- Nintendo 64: emulated 2048-byte EEPROM identifier and transfer protocol
- Super Famicom: corrected ppu-performance widths table indexing to consider
overscan
- Mega CD: fixed a bug in register $ff8003; allows Popful Mail to boot
[TascoDLX]
- Mega Drive: fixed a bug with 256-width video modes
- Mega Drive: improved VDP DMA emulation which should fix many games
- Mega Drive: added SVP emulation
- Mega Drive: added 32X emulation
- Mega CD: fixed a bit-masking bug in register $ff8004; fixes Radical Rex
[TascoDLX]
- Nintendo 64: fixed C implementation of RSP VMACU instruction
- Nintendo 64: use correct NTSC and PAL PIF ROM images based on the region
- Mega Drive: fixed reset logic, Z80 interrupt timing + prefix timing +
bus control [TascoDLX]
- Mega CD: fixed word RAM access and CDC DMA word RAM transfers [TascoDLX]
- Nintendo 64: improved RSP VMOV emulation [Rasky]
- Nintendo 64: fixed RSP DMEM DMA alignment (&~7, not &~3) [Rasky]
- Nintendo 64: upgraded to the latest version of ParaLLEl-RDP
- nall: greatly expanded recompiler/amd64's supported intrinsics
- mia: substantial refactoring around a new virtual filesystem implementation
from nall
[This release was posted to the ares Discord after r16. That version introduced
128KB VRAM mode for the Super Famicom core, and somebody requested the previous
version so they could see the changes involved in implementing that feature.
-Ed.]
That's as far as I can go with 32X support for now. I fully emulated the Sh2
cache but I still hang at Mars test 123. The Hblank (2) test fails because it
looks like I'm running a bit too fast. The DMA test fails because it expects
DREQ to become inactive when the DREQ length hits zero. If I do that, the test
hangs. If I don't do that, the test fails.
Virtua Fighter shows no graphics in-game, Virtua Racing shows no graphics
period.
Knuckles Chaotix is now fully playable at glorious 20fps, heh.
Still a whole ton of issues but I really went to town with this WIP. I
implemented read/write functionality for all the SH7804 internal
registers/functional units, and added basic simulation of the free-range timer,
DMA controller (very basic) and interrupt controller.
On the 32X side, it should be functionally complete save for bugs now. VDP and
PWM are fully implemented.
I am getting my ass kicked by SH-2 delay slots >_>
The basic idea of them is simple, but the PR register and when to do the +4 or
+2 or not is not intuitive.
SH-2 core finished, started connecting the 32X to it. It executes some
instructions and does some I/O register stuff before hanging. Still gotta
implement the 32X interrupts, PWM, and VDP stuff.
Here's the current build with working SVP support. Build with profile=accuracy
if you try it because my fast scanline renderer breaks soooo many games
including Virtua Racing ._.
This WIP has the new mia system. It's a pretty massive change ... I hope it will
go okay for you. Feel free to ping me and I'll walk you through it.
Essentially, we want to edit mia/system/neo-geo-(aes|mvs).cpp to load in the
necessary files from MAME's neogeo.zip that is given to it (I have a helper
Pak::read(zipfile, pattern) function to grab files out of the archive for you
into a vector<u8>), do endian conversion, add to the pak, then the Neo Geo core
can see it.
The Neo Geo cartridge support should be enough for Magician Lord and super early
games with no mappers or crypto, so we'll start there and work our way up.
My tracer was crashing in v118 for the Mega CD due to the trace address not
being masked and the value underflowing, so here's a pre-v118.4 WIP with that
fixed.
So, spoiler since you'll all see it: Luke and I are gonna be working on a
Neo*Geo core. Please keep that a secret for now until we can get some
screenshots to share with people.
Would appreciate feedack on the vfs redesign, still a work in progress. Right
now, the potential is there to have ares cores that don't use manifests at all.
So far, only the ColecoVision core actually does it. However, all cores are
ported to use the new Platform::pak() function instead of Platform::open() [now
removed.]
Lots of stuff is broken right now: N64/PS1 memory cards, PC Engine CD / Mega CD
internal save memory, Mega CD can't play any games, FDS and NGP don't save, etc.
I'm excited to launch ares v118 today, the first release featuring playable,
full-speed Nintendo 64 emulation!
The new Nintendo 64 emulation is made possible thanks to [Themaister] very
graciously porting his Vulkan-based ParaLLEl-RDP graphics renderer to ares. With
its default settings, it is nearly pixel-perfect to real hardware, and it
optionally supports upscaling to 2x or 4x the original Nintendo 64 resolution,
plus optional supersampling back down to the original resolution (for enhanced
anti-aliasing) if desired. The Vulkan support requires an appropriate graphics
card, and either Windows or Linux. At this time, Vulkan is not available for
macOS nor the BSDs.
Also new for the Nintendo 64 core in this release is Rumble Pak, Cartridge Pak,
SRAM, EEPROM, and Flash save support. Note that for right now, the Rumble Pak
will only be enabled for games which use internal saves (SRAM, EEPROM, and
Flash.) That does not cover all Rumble Pak-capable games. The option to choose
between Rumble Paks and Cartridge Paks will be added to a future release.
For the PlayStation core, [Luke Usher] provided two rendering fixes that allow
Final Fantasy VII and Tony Hawk's Pro Skater to be fully playable!
Right now, approximately 33% of the Nintendo 64 library is fully playable, and
about 67% of the PlayStation library is fully playable. Each core has only been
under active development for about one month each, so they both have a long way
to go. Please treat these early releases as tech samples, rather than finished
emulation cores.
Further, note that the Nintendo 64 and PlayStation cores employ cached
interpreters. This is a middle-ground between the accuracy of interpreters and
the performance of dynamic recompilers. As such, ares' system requirements will
be a bit higher than traditional emulators for these systems. Presuming no
background task interference or CPU throttling, generally speaking, a Ryzen 5
2600 or better CPU should get you to around ~120fps in the average case, and
~60fps in the worst case.
The source code has also been released under the terms of the Creative Commons
BY-NC-ND 4.0 license.
[Themaister]: http://github.com/Themaister/
[Luke Usher]: https://twitter.com/LukeUsher1
Ridge Racer now boots and gets in-game, but likely GTE errors prevent it
from being very playable yet.
- PlayStation: added DMA IRQ support
- PlayStation: added more GTE instructions
- ares: started on a new Debug class for notifications (unimplemented
features, etc.)
- PlayStation: improved timer support
- PlayStation: added more GPU GP0 rendering commands
- lucia: split the emulator list and emulator options into separate
settings panels
- lucia: added fast boot option for PlayStation and Neo Geo Pocket
cores
- PlayStation: fixed masking bug in LWL and LWR instructions
- PlayStation: improved timer support
- PlayStation: added EXE side-loading support
- PlayStation: added fast boot support
- PlayStation: added libc putchar logging support
- PlayStation: started implementing controller support
- PlayStation: improved texture semi-transparency support
- PlayStation: fixed a bug in render clipping
- Super Famicom: mosaic fix wasn't exactly right before; now it should
be
- PlayStation: started implementing CD interface
- PlayStation: started implementing GTE coprocessor
- Super Famicom: fixed bugs in hires + interlaced mosaic rendering
- PlayStation: started implementing the SPU (no DMA, CD-DA, reverb, or
sweep support yet)
I've started on a Sony PlayStation emulation core with this WIP. The
goal is to work on the MIPS CPU core while I am still well-versed with
the MIPS ISA. The Nintendo 64 core will remain my primary focus,
however.
- PlayStation: implemented initial driver skeleton (no emulation code
yet)
- lucia: added option to group the load menu options into submenus by
manufacturer
- lucia: connected Cocoa-specific application menu options to their
appropriate callbacks
- hiro/Cocoa: fixed compilation issues for HexEdit (the widget is not
implemented, however)
- hiro/Cocoa: fixed a subpixel precision rendering issue causing
blurry fonts [LIJI]
This WIP adds non-SIMD implementations of all RSP vector unit
functionality. This allows compiling without SSE, but was mainly added
for debugging SSE issues. It's also useful for documenting in code what
the SSE instructions are doing in C++ code.
- Nintendo 64: added non-SSE implementation of RSP vector unit
The new recompilers increase the framerate in Namco Museum from 60fps to
160fps, and in Zelda: Ocarina of Time from 55fps to 135fps (presuming no
RDP renderer.)
- Nintendo 64: completed basic CPU dynamic recompiler
- Nintendo 64: completed basic RSP dynamic recompiler
- N64: redesigned the bus handler
- N64: execute eight CPU instructions per synchronization event
- N64: range test the CPU Compare register
- N64: decode more RDP display list commands
Many N64 games are now playable.
- N64: VSUB should clear VCO
- N64: corrected VRCP(L) and VRSQ(L) instructions
- N64: many other smaller various fixes
- N64: added missing BLTZAL, BGEZAL instructions
- N64: added missing SLT, SLTI instructions (they were erroneously
aliased to SLTU, SLTIU)
- N64: mask low two bits of PC when writing to SP_PC_REG
- N64: refactored RSP DMA; only mask the low two bits SP_PBUS_ADDRESS
- N64: RSP DMA seemingly updates SP_PBUS_ADDRESS and SP_DRAM_ADDRESS
- N64: added PIF boot ROM emulation
- N64: detected NUS-CIC revision based on ROM bootcode checksum
- N64: added skeleton I/O reading and writing for all VI and PI
registers
This WIP separates the RSP SCC registers so that RDP rendering commands
are not processed inside of the RSP. The register interface is shared
between the SCC and the CPU bus, so there is no technically correct
location for these handlers.
- N64: moved RSP SCC registers to outer RSP and RDP I/O handlers
- N64: improved audio playback (AI_LENGTH &=~ 7, not (AI_LENGTH | 7) +
1)
- N64: improved exception handling (ERL bit isn't set on standard
exceptions)
- N64: added very incomplete, inital TLB emulation
- N64: various improvements to the disasssembler (including FPU
instruction support)
- N64: improved SI emulation (Namco Museum input now works)
This WIP boots the first official Nintendo 64 title, Namco Museum. It
remains to be playable, however.
- N64: improved interrupt handling
- N64: implemented basic state machine handling for PI serial data
transfers
- N64: resume previously executed instruction after ERET for non-
interrupt exceptions
- N64: various other improvements
- N64: removed libco completely, using direct cycle counters now
instead
- N64: emulated RSP DMA between IRAM/DRAM and RDRAM
- N64: emulated RSP core R4000 instructions
- N64: started working on RSP COP2 vector instructions
Emulation is now far enough along to complete the boot loading code and
begin executing game code. The "hello world" CPU rendering demo now runs
correctly in both 15bpp and 24bpp output modes.
- N64: implemented skeleton interfaces (MI, VI, AI, PI, RI, SI)
- N64: implemented PI DMA
- N64: added basic frame buffer rendering (320x240 only)
- VR4300: implemented register-immediate instructions
- VR4300: implemented half of the general instructions
- ares: added Port::supported() -> vector<string> API
- nall: improve checks in directory::exists() and directory::create()
- PC Engine CD: fixed Arcade Card emulation bug in register I/O
address decoding
- PC Engine CD: fixed a bug with ADPCM DMA
- Super Famicom: implemented more of the HG51B disassembler (still
very incomplete)
- PC Engine: added support for Populous save RAM
- PC Engine: attached debugging Node::Memory objects to HuCards with
RAM
- PC Engine: split System Card and Super System Card emulation into
separate classes
- PC Engine: added Arcade Card Duo and Arcade Card Pro emulation
(though it isn't working yet)
- PC Engine Duo: added emulation support (as a separate interface;
requires SSC 3.0 BIOS)
- lucia: display warning message when loading games if the save
directory is unwritable
- lucia: display error status message when capturing a screenshot to
an unwritable directory
- nall: added nall/encode/png.hpp (uses optipng or pngcrush for
optional compression)
- luna: capture screenshots in PNG format instead of in BMP format
- lucia: capture screenshots in PNG format instead of in BMP format
- PC Engine CD: emulated drive seek delays
- PC Engine CD: emulated CD-DA and ADPCM audio volume fader
- PC Engine CD: corrected ADPCM $180d flags (fixes many ADPCM playback
issues)
- PC Engine CD: use live playing flag for $180d.d5 (fixes Popful Mail
hanging bug)
- PC Engine CD: supported SCSI command 0xd9 CDDA playback mode (loop,
notify, stop)
- mia: use nall/vfs/cdrom to convert images on import (more complete;
shares code)
- mia: added identify(filename) function to detect what system a given
game image is for
- mia: added medium(name) to locate a Media object to use
- lucia: replaced Emulator::extensions with Emulator::medium
This WIP has started on a stream manager, which for now only allows you
to mute individual streams, but in the future it could be nice to expand
this tool to selectively configure bandpass filters and more.
- ares: added Node::Stream::setMuted(bool) function
- lucia: added audio stream manager to selectively mute individual
streams (for debugging purposes)
- lucia: include system name in recent games entries, to disambiguate
Mega CD and PC Engine CD games
The first officially licensed PC Engine CD games are now playable:
Bomberman '94 Taikenban and Deden no Den.
- ares: emulated the OKI MSM5025 ADPCM chip
- PC Engine CD: added ADPCM playback support (incomplete)
- PC Engine CD: various emulation improvements
- nall/vfs/cdrom: build image in-memory (required to support the below
features more easily)
- nall/vfs/cdrom: support multiple files per CUE sheet
- nall/vfs/cdrom: support WAV audio files
This release implements enough of the PC Engine CD to boot its first
software title, Chris Covell's Screen Dimension Test. There's a large
amount of work that remains before commercial titles will be playable,
however.
- PC Engine CD: started implementing SCSI commands
- nall/decode/cue: new decoder for parsing CD-ROM CUE sheets
- nall/vfs/cdrom: support ISO images
The base tree initialization rewrite is completed, however there remains
work to be done with attaching peripherals not unserializing properly.
But it's a solid start.
- ares: ported all cores to the new simplified tree construction
This WIP marks the start of an effort to simplify the process of
initializing system trees in ares. Before, all load functions had to
take both a parent Object, and a shadow source Object. During the
construction of every Object, the attributes and values of the shadow
Object would be copied in.
The goal here is to instead construct system trees only from parent
Objects, and then once the system tree has been constructed, copy a
serialized tree into the actual system tree. What makes this difficult
is that the serialized tree will have peripherals connected to ports,
resulting in a much larger tree. So the copy function has to specialize
on ports to create and attach said peripherals to the actual system
tree, and then continue unserializing the shadow tree to the actual
system tree.
In any case, so far this new approach is working, thankfully. This
reduces a substantial amount of boilerplate that was previously needed
inside every single emulation cores in ares. But it will take many WIPs
to slowly convert all twelve emulation cores to the new design. I made
this change in a way that the other cores will continue to function as
expected, so both designs are currently fully functional. Once every
core has been ported, I will start removing the boilerplate
functionality that was needed for the old design.
- ares: created Object::copy(Node::Object)
- Famicom: started simplifying tree construction
- Famicom: renamed NES-* boards to HVC-*
- Famicom, Super Famicom, Mega Drive, PC Engine: restructured
cartridge slot and expansion port handling
- hiro/Qt: fix crash on exit by destructing all UI objects first
[baraclese]
- ruby: removed Input::onHotplug(); luna and lucia handle hot-plugging
automatically
- Famicom: refactored SxROM and MMC1 into a single class
- Famicom: converted generic class variable types (bool, uint) to
uint# types
- Game Boy Advance: fixed a bug with keypad interrupt handling (keypad
array was erroneously marked static)
- all: moved inline designators from function designators to function
declarations
- ColecoVision: added memory editing support (CPU only; no VDP support
yet)
- Famicom: added memory editing support
- Game Boy + Game Boy Color: added memory editing support
- Game Boy Advance: added memory editing support
- Master System + Game Gear: added memory editing support
- MSX: added memory editing support (CPU only; no VDP support yet)
- SG-1000 + SC-3000: added memory editing support (CPU only; no VDP
support yet)
- SG-1000 + SC-3000: $c000-ffff maps to system RAM, not cartridge RAM
- Neo Geo Pocket + Neo Geo Pocket Color: added memory editing support
- WonderSwan + WonderSwan Color: added memory editing support
- ruby: added joypad hotplugging support to the SDL 2.0 driver
- ruby: added workaround for FreeBSD's SDL 2.0 port not supporting
SDL_JOYDEVICE(ADDED|REMOVED)
- lucia: support new ruby::Input::onHotplug() callback to
automatically refresh input mappings
- Mega Drive + Mega CD: added memory editing support
- lucia: implemented graphics viewer and export tool
- Super Famicom: added graphics viewing support to the accurate
renderer
- all: Makefile improvements (obj and out paths are no longer hard-
coded)
- all: renamed Screen::Region<String> to Screen::Overscan<Boolean>
- lucia: implemented bsnes' multiple-mappings per input system
- lucia: implemented memory editor and export tool
- Super Famicom: added memory editing support
- PC Engine: added overscan setting to the dot-based renderer (256 ->
272 width)
- restructured project layout by moving targets (luna and lucia) out
of ares
- added ares logo to lucia, luna, and mia's about dialog
- lucia: added screenshot capture tool (captures the *next* frame
rendered)
Initial release; fork of **higan** v110.
- the project and core library is now called **ares**
- the simplified user interface is now called **lucia**
- the advanced user interface is now called **luna**
- the game analyzer is now called **mia**
- removed the database editor **genius** from the project
- PC Engine: adjusted rendering viewport for the scanline renderer
from Y=18 to Y=21
* PC Engine: emulate MPR latch used by TMA and TAM instructions
* PC Engine: randomize various registers and memory at power-on
* PC Engine: do not allow block moves to read from $ff:0800-17ff
* PC Engine: always set P.B flag (except when pushing P during BRK)
* PC Engine: clean up and improve CPU IRQ handling
* PC Engine: delay PSG synchronization when not needed (~8% speedup for accuracy core)
* PC Engine: emulate 4-color background and sprite modes (partial; fixes Fighting Run sprites)
* PC Engine: emulate grayscale VCE mode
* PC Engine: emulate extra scanline VCE mode
* PC Engine: improve burst-mode emulation (including VRAM->VRAM early termination)
* PC Engine: fixed VRAM->VRAM DMA transfers (was transferring one byte less than it should)
* PC Engine: reposition background and sprite scanline latching slightly (for Toy Shop Boys flickering)
* PC Engine: improve Vblank handling when vertical timing registers exceed 261 scanlines
* PC Engine: added vertical timing latching to scanline renderer as well
* Mega Drive: fix crash when loading Sonic & Knuckles or Game Genie without a daughter cartridge
* all cores: add unload() to all cartridge and controller ports
* byuu: focus the viewport after loading games
* icarus: fix typo in save RAM portion of the manifest (was marked as ROM by mistake)
* PC Engine: improved IRQ handling significantly, fixes many games
* PC Engine: improved VDP penalty cycle timing
* PC Engine: emulated all T=1 mode instructions, not just immediate mode
* PC Engine: fixed T-Memory instructions (fixes Gai Flame and Dragon Spirit)
* PC Engine: run VDS first instead of VDW at the start of new frames (fixes Davis Cup Tennis)
* PC Engine: disassembler improvements
* PC Engine: add support for Street Fighter II CE's custom mapper
* higan: fix System menu option enabling when "Create New System" is selected
* byuu: don't show the program icon in the main window briefly when switching games
* Sega CD: mask CDC DMA d0-d2 bits on address register set [EkeEke]
* Sega CD: merge CDC PCM DMA fix verbatim [EkeEke]
* Sega CD: reset all state on power cycle
* disable context menu on "Create New System" list item
* PC Engine: disassembler improvements
* PC Engine: CPU instruction timing improvements
* PC Engine: fix VDC DCR writes (fixes Gaia no Monshou, Magical Chase, etc)
* PC Engine: added Avenue Pad 6 emulation (higan only for now)
* Mega CD: CDC PCM DMA can only write to current bank [EkeEke]
* PC Engine: trigger VDC coincidence IRQs at start of scanline
** (fixes Bomberman '94, Air Zonk start screen rendering issues)
* added higan::Node::enumerate() to find all nodes of a given type
* Famicom: emulated the X24C01 EEPROM for Bandai-FGC boards
** (no X24C02 support yet)
* nall: fixed a subtle yet critical issue with Natural/Integer::bit()
** (values out of range were not being masked out upon assignment)
* add support for deterministic serialization (save states)
* add support for run-ahead (has issues on GBA and MSX cores, however)
* SFC/Performance: do not render scanline 0
* SFC/Performance: fix rendering of mixed-resolution screens
* SFC/Performance: add raster override for Air Strike Patrol
* PCE/Performance: complete VDP serialization support
* SFC: scanline renderer - fixed an issue where the backdrop color was showing while the screen was disabled
* SFC: scanline renderer - fixed an off-by-one issue with the vertical sprite positions
* SFC: scanline renderer - added known scanline render position overrides from bsnes
* SFC: dot renderer - fixed an issue with scrolling in hires mode
* MS: fixed the pause button mapping (also, it binds to the start button now)
byuu v1:
* SNES: fixed hires and interlace rendering with new scanline-based renderer
* Mega Drive and Neo Geo Pocket (Color): default to English/NTSC-U for multi-region games
* Windows: fix an occasional crash when unloading games
* Windows: fix beeping sound when assigning inputs and hotkeys
* Neo Geo Pocket: added flash ROM save support
* Super Famicom: improved appended firmware size detection [devinacker]
* ruby: added dynamic rate control support to Linux/ALSA driver [RedDwarf]
* ruby: added dynamic rate control support to Linux/PulseAudio driver [RedDwarf]
byuu v0.14:
* PC Engine: fixed sprite rendering issue
* PC Engine: nearly doubled performance via audio decimation
* Game Boy Advance: 20% performance increase via lower-precision CPU synchronization
* added auto-save memory option
* added optional native file dialog support
* added warning when trying to map inputs with no input driver active
* abort input mapping attempts after closing settings window
* added 50ms delay for input mapping so that pressing enter won't automap said key
byuu v0.12:
* capture keyboard during input and hotkey assignments
** (prevents bell sound on Windows)
* support Trigger.Hi input mapping
** (will make mapping triggers harder, unfortunately)
* Mega Drive: added scanline renderer (~85fps to ~210fps average)
* Super Famicom: renamed "Cartridge Port" to "Cartridge Slot"
* Game Boy Advance: renamed "Screen" to "DAC"
SFC: fixed PAL region detection (for higan and byuu)
SFC: added scanline-based renderer (for byuu)
SFC: improved Super Game Boy MLT_REQ emulation [devinacker]
byuu v0.10
* fixed initial bindings for gamepad axes and hats
* allow multi-selection clear on input mappings
* added path searching to higan::Node::find()
* added higan::Node::scan() to locate relative tree nodes
* exposed settings for color bleed/emulation, interframe blending, overscan
* default to Path::desktop() instead of Path::user() for loading games
* started on scanline-based renderer for the SNES
byuu v0.9
* update driver settings when changing audio and input drivers
* correct sound output when not outputting at 48KHz
* correct sound output when changing frequency after game is loaded
* show program icon when game is not loaded
* move from native status bar to higan/bsnes-style status bar
* fix a bug with WonderSwan internal EEPROM data
* fix hotkey polling in fullscreen mode
* added joypad support
I've started on a new multi-system emulator, byuu.
It will share all cores with higan, and as such will be focused on accuracy and self-documenting code foremost.
But unlike higan, I will do everything possible to make the program featureful and easy to use.
The way I'm doing this is through a translation layer to abstract higan's tree-view into a list-view.
The list-view is similar to higan v106 and earlier. I'm also going to add more ease-of-use improvements from bsnes.
The list-view will sacrifice support for extreme edge cases, but should more than make up for it in ease of use.
bsnes' success greatly exceeded my expectations, and resulted in many improvements to higan's SNES core as well.
But unfortunately, bsnes is for the SNES only, and I just don't have the bandwidth to maintain 24 emulator projects.
As such, the goal of this project is to try and create an easy-to-use alternative for *all* of my emulator cores.
Right now, I'm maintaining this as an alternate user interface target inside the higan source tree.
Long-term, the intention is that higan and byuu will be equal emulators, rather than one being a superset of the other.
I don't know how that final form will look just yet, but for now, this will at least allow me to keep the history in Git.
I do ask that binaries not be distributed of byuu until the software is ready for release.
I wouldn't even recommend using it. It's not really functional at all yet. But it'll get there over time.
Fixed NES manifest lookups (mirroring, VRC pinouts, etc)
Corrected Game Boy CPU name strings
Updated databases to use SM83 instead of LR35902 for GB CPU naming
Sorry, I pasted the v107.1 changelog by mistake. The changelog for v107.3 is:
removed usleep() from main() during Application::modal()
* allows smooth window movement and resizing on Windows
Windows: added WS_CLIPCHILDREN to Window class
* prevents flickering of the viewport when moving the vertical resize grip
Windows: added WS_EX_TRANSPARENT to Frame class
* prevents drawing issues caused by WS_CLIPCHILDREN (which is why it was left off previously)
ASIO: ensure the minimum, maximum, and preferred buffer latencies are available in the latency list
ASIO: defer IASIO::start() until audio starts playing
* prevents bad ASIO drivers from segfaulting at application startup
ASIO: re-enabled the option for ASIO now that it can be enabled safely
* there is still an issue that many drivers (including Steinberg's) crash after music starts playing
Windows: added workaround for the audio settings panel not displaying properly on first-launch
GTK: added gtk_widget_queue_redraw() call after Widget::setGeometry() calls
* prevents minor redraw issues with higan's status bar when resizing the window
don't show "Disconnect" button when "Nothing" is selected if nothing is currently connected to a port
select the currently connected peripheral (or "Nothing" if disconnected) when selecting a port from the node manager
GTK: fix focus behavior to always work when changing which peripheral is connected to a port
disable any action on connecting an already-connected peripheral (was previously losing focus on the port connection panel)
hide events from the node manager (use the event manager instead)
added Node::Peripheral::manifest() API and connected it for all emulated cartridges, floppy disks, and CD-ROMs
added peripheral overview to see game manifests
removed Settings -> Advance Mode (failed concept; it didn't do anything)
removed v107 beta release warning message
removed video and audio driver activation (auto-activates at launch now)
add remove, rename, launch buttons to system overview panel
show system creation panel controls as disabled instead of hiding them when nothing is selected
added "Create New System" option to the top of the system manager panel list
added "Launch" option to system manager context and system menus
refresh the port connector list and select the newly created peripheral after creating new peripherals
fix an issue with showing "Import ..." button on port connector at inappropriate times
don't show "Disconnect" button when "Nothing" is selected if nothing is currently connected to a port
select the currently connected peripheral (or "Nothing" if disconnected) when selecting a port from the node manager
GTK: fix focus behavior to always work when changing which peripheral is connected to a port
disable any action on connecting an already-connected peripheral (was previously losing focus on the port connection panel)
hide events from the node manager (use the event manager instead)
added Node::Peripheral::manifest() API and connected it for all emulated cartridges, floppy disks, and CD-ROMs
added peripheral overview to see game manifests
removed Settings -> Advance Mode (failed concept; it didn't do anything)
removed v107 beta release warning message
SFC: disable math color bleed for first pixel
(fixes green line on the left-edge of Jurassic Park)
SFC/GG: attach Screen settings to Screen node, not PPU/VDP node
(fixes remembering Screen settings)
SFC: disable math color bleed for first pixel
(fixes green line on the left-edge of Jurassic Park)
SFC/GG: attach Screen settings to Screen node, not PPU/VDP node
(fixes remembering Screen settings)
Fixed focus issue with hotkeys.
Added sprite zoom emulation to TMS9918 and V9938 cores.
Improved clarity of ABCD and SBCD M68K instructions.
Fixes to ruby IOkit driver.
Added save state file size validation to all cores.
Added simple capture screenshot function.
Fixed macOS monitor name detection on multi-monitor systems.
Replaced the higan::Logger { Tracer, Notification } system.
Now uses Node::Event { Instruction, Notification } instead.
That is to say, loggable event sources are now part of the system tree.
The intention is do the same for higan::Video and higan::Audio soon.
* moved Screen, Sprite, Stream back to shared pointers
* fixed two SNES SA1 regressions
* added trace logging support to the GB and SNES cores
** (HG51BS169 not supported yet; uPD96050 and GSU are buggy still)
* WonderSwan: improve 1024-tile mode (fixes WSC IPLROM menu)
* WonderSwan: import boot ROMs from system template folders on first run
* WonderSwan: added automatic screen rotation support
* WS: added status icon emulation [icons by furrtek]
* WS: added option to use monaural speaker instead of stereo speakers
* WS,GBA: corrected screen rotation support
* WS: added proper keypad mappings for the Pocket Challenge V2
* WS: initialize EEPROMs as they would be from the factory
* added WonderSwan + WonderSwan Color IPLROM support [thanks furrtek!]
* split Microchip 93LCx6 emulation to shared component/eeprom class
* Game Boy MBC7 and WonderSwan EEPROMs now use 93LCx6 base class
* various WonderSwan emulation improvements
* provide actual display device names in ruby::Video::hasMonitors()
* macOS: fixed LineEdit::onChange (fixes state manager state naming)
* macOS: fixed RadioLabel height to not clip off bottom of radio icons
* macOS: fixed RadioLabel initial check states (fixed input settings
focus mode options)
* macOS: fixed TableViewItem::setSelected (fixes initial selection on
settings/tools windows)
* macOS: fixed TextEdit geometry (fixed manifest viewer)
* macOS: don't allow multiple TableViewItems to be selected in
single-selection mode
** (fixes settings/tools windows selecting multiple items via menubar
options)
The existing ppc implementation in libco only supports
the ELFv1 ABI on PowerPC 64 and therefore can't be used on
Little Endian systems and Big Endian systems running ELFv2
distros.
This commit introduces a new implementation of the libco
API for ppc64 elfv2. It has been tested with bsnes and higan.
The original ppc implementation is maintained for non-ELFv2
targets.
byuu says:
Moved operator() to .range() and operator[] to .field() for Natural/Integer
types. Also improved Super Game Boy emulation speed by ~16%, and removed the
need for two callbacks (but adding one new one). Joypad interrupts should now
work during CPU HALT and STOP as they're supposed to.
byuu says:
- higan: reset all thread clocks on power cycle
- higan: fix minor regression from WDC65816 CPU rewrite
- higan: fix nall::Integer casting regression
- higan: removed nall/bit-field.hpp and nall/bit-vector.hpp
byuu says:
- higan: don't create manifest.bml for peripherals created from
templates
- higan: fix binding of inputs when changing connected peripherals
- higan: fixed a Game Boy regression with an edge case in writes to
VRAM being blocked errantly
- higan: removed cheat code support (which was not working for most
systems; nor implemented in the new GUI)
- higan: corrected loading of BS Memory cassettes
- higan: added adaptive sizing option (changes the size of the program
window to fit the active system's video output size)
byuu says:
- ruby: fullscreen support for Windows OpenGL 3.2, DirectDraw 7.0, GDI drivers
- ruby: output(width, height) support for all drivers on all platforms
- hiro: improve focus capture for Canvas and Viewport widgets
- hiro: added two hotfixes for the macOS Cocoa target [Sintendo]
- higan, bsnes: focus the viewport after leaving fullscreen exclusive mode
- freebsd: moved from GCC 8.2.0 to Clang 6.0.1
- higan: added video display emulation option to Famicom and Mega Drive cores
The reason I moved to Clang was because GCC keeps deadlocking my FreeBSD system.
I don't know if it's GCC's fault, or suddenly running 32 copies of any high-CPU
usage program, heh. But at any rate, it's worth a try. The performance is the
same, but compilation takes a tiny bit longer with Clang.
byuu says:
- ruby: fullscreen exclusive support for XVideo and XShm video drivers
- ruby: support for 30-bit RGB under Xorg with OpenGL 3.2 and OpenGL 2.0
drivers
- bsnes: update libco, nall, ruby, hiro, sourcery
- bsnes: use new ruby::Video API for viewport sizing
- higan, bsnes: added EXLOROM, EXLOROM-RAM, EXHIROM mappings
- higan: added video display emulation option (NTSC 448p / PAL 480p output
selection)
- higan: reverted metadata.bml to manifest.bml
byuu says:
I merged the concepts of fullscreen and exclusive mode. There's no non-exclusive
mode anymore. I added support to the Linux/BSD OpenGL 2.0 and OpenGL 32 drivers
for the new fullscreen mode, which allows Gsync to work. I still have to add it
to the Windows OpenGL 3.2 driver. After that, I fixed a nasty issue with audio
breaking after loading save states. I redesigned the Audio, Video classes to use
regular pointers instead of shared pointers to function like the Scheduler. Also
threw in a few more GUI refinements.
byuu says:
some GUI work. better initial autosizing of tableview columns in gtk (removes a
bunch of 'todo hacks' in higan). added a status bar and menu toggles for that
and the panels. need to hook them both properly to hotkeys, that isn't working
right now.
byuu says:
I finally pass blargg's dmg-sound and cgb-sound tests, but at quite a cost.
Reads and writes can't happen on an exact T-cycle (clock cycle) point within an
M-cycle (opcode cycle) for the DMG. Writes to trigger take effect two clocks
after writes to wave RAM, for instance. Probably going to be a lot more of this
in low-level PPU emulation, so I'm biting the bullet and slowly converting the
Game Boy bus handler to this new format, which I'll use as a test bench for
doing this later to other systems with, since Game Boy performance isn't as
critical (it's a drop from 220fps to 200fps to have to poll the bus four times
per memory access and synchronize the CPU four times as often, so a lot less bad
than I'd feared at least.)
byuu says:
Game Boy: latch WY and don't increment when WX>=127 or window is disabled. Fixes
Donkey Kong level complete bottom status screen.
Mega Drive: add Z80 stall on 68K bus access during VDP DMA. Allow Z80 to
read 68K version register. Map $c0001c-c0001f (and its mirrors) to the CPU
prefetch IR register. Add work RAM refresh and cartridge/expansion /RAS refresh
emulation.
Fixed compilation bugs on Windows. Fixed DIrect3D driver. Disabled the mouse
capture trick for custom cursors on Windows because it was having bad side
effects. Disabled the multi-select activate on GTK workaround because it was
sometimes breaking input navigation in list boxes. Fixed a major issues in the
last WIP with GTK controls becoming unfocusable. Other stuff as well.
byuu says:
added viewport input capturing for windows. updated ruby (opengl 2.0, opengl
3.2, direct3d 9.0 only so far) to support width,height on the output() call,
which lets me center video inside a viewport widget. added center,scale,stretch
video output modes. added aspect correction setting. hotkey bindings are now
saved between runs. added fast forward hotkey. replaced alternating row colors
with column colors for input mappings. added batched mapping assignments to
inputs and hotkeys. fixed the video output not being black on startup with
windows and gtk3. added mouse cursor changing support to hiro for windows, gtk
and qt. the resize grips and about dialog hyperlink get appropriate cursors now.
the input driver now fully runs [as of] startup for the sake of hotkeys.
activating menu items that display panels will reshow a hidden panel bar now.
resored the ability to get game titles from every higan/icarus core. restored
the framerate counter. fixed a bug with nall::Location::pathname() returning a
blank string when there was no suffix on a filename. added video shader support
(needs testing with the new output(width, height) support.) lots of other
polishing work.
byuu says:
some more game boy improvements and a quick regression in legend of zerd
(already fixed but i'll spare you another one-line wip ^-^;;), also started on a
much larger GUI redesign to merge the video output with the panels.
needless to say, it's incredibly, incredibly broken. so, don't use it unless you
want to explore. but some major issues: hotkeys don't work before starting a
game. windows video output isn't working for some reason?? only GTK supports the
new Viewport::setFocusable() API needed to let the video output act as a sink
for keyboard input. on and on.
byuu says:
you can now unload a loaded system, allowing you to switch to another emulation
core without a restart (finally.) Fixed a couple of gekkio's Game Boy test ROMs,
but there's a lot of work left to do there.
byuu says:
150 KiB diff this time around. Rewrote almost all of the Node::Object tree
construction and unserializing functionality, so that everything's consistent
now instead of there being 3-4 different ways of doing it based on what type
of object we were working with. Certainly more to do there of course. I made
the Video::Screen stuff spawn at load time rather than power cycle time, which
fixes the SNES light guns form crashing or not working. However, I still haven't
connected mouse support to the new higan GUI. A minor thing that was bugging me
before: when powering on the system, if a settings page is open, it will refresh
to update the latched value text. I added a missing interframe blending option
to the Game Gear. There was also an issue before with certain settings not being
saved between runs, which should be fixed now. I moved all the system controls
under their own node, so it's System->Controls now instead of appearing in the
root System node. It adds another node to the system tree for each system, but
it should make it more obvious where the system controls are to remap them.
byuu says:
fixes a sprite rendering issue in Neo Geo Pocket affecting Magical Drop. Also
added NGP fast boot option that's pretty spiffy. Emulated 68K prefetch much
better than it was before, not that it's likely to affect any software -- except
there was a slight regression, so...
byuu says:
Scheduler/Thread redesign completed. Only about a ~1% performance hit, and fixes
the previous flaw completely. I also implemented region priorities (fancier
auto-detection) for all console-based systems. I need to remove the region node
from Game Gear still, though.
byuu says:
I made the Thread class aware of the Scheduler class, which removes the need
for every emulator core to inherit from higan::Thread. But I do have to
duplicate them via #include magic because of the Super Game Boy needing separate
schedulers for the SNES and GB. I improved some of the performance loss in the
last WIP, but 161 should do better still.
byuu says:
improved Mega Drive 128K mode (still far from complete, it's not well
documented), renamed Scheduler::synchronize() to Scheduler::resume(), and now
Scheduler::synchronize() is a version of synchronize(Thread&) that synchronizes
to all threads instead of just the specified one. It's much slower, but
unfortunately needed when two threads both sync to the same third thread plus
each other (long story, see Twitter.)
[byuu is referring to a thread starting at
https://twitter.com/byuu_san/status/1138436552634249217 reproduced below for
posterity:
Well heck, higan's about to take a speed hit it can't afford. Here's my
current scheduler design. It has a critical flaw, can you spot it?
CPU::step(uint clocks) {
Thread::step(clocks);
synchronize(apu);
synchronize(ym2612);
}
APU::step(uint clocks) {
Thread::step(clocks);
synchronize(cpu);
synchronize(ym2612);
}
YM2612::step(uint clocks) {
Thread::step(clocks);
synchronize(cpu);
synchronize(apu);
}
Thread::synchronize(Thread& thread) {
if(clock >= thread.clock) resume(thread);
}
Say the APU consumes some time, but it's not yet ahead of the CPU, but it
*is* ahead of the YM2612, so it switches to the YM2612 thread. The YM2612
isn't cycle accurate yet and consumes 144 clocks per sample. It's now way
ahead of the CPU, and so it resumes the CPU thread.
The problem is that the CPU may still be ahead of the APU, and so we just
broke synchronization between the CPU and APU. The solution will be painful:
we have to evaluate all available threads, find the one furthest behind in
time, and switch to that.
I'm probably going to need something like a binary min-heap array to allow
O(1) to find min(objects...), but for the immediate present, it'll have to
be a for-loop.
- Ed.]
byuu says:
completed all the cycle timings as per yacht.txt, with the exception of ...
exceptions. They have really weird cycle counts for some reason. I think he's
counting the opcodes in with the exceptions. Well whatever. I also implemented
128K VRAM mode, but without the 128K VRAM existing (since this isn't the Sega
Teradrive.) I may make 128K VRAM an option as with the SNES though.
byuu says:
added 68k prefetching, also reordered all of the 68k instructions in the C++
code to their opcode mnemonic ordering, improved cycle timings more, fixed a
crashing bug when a genesis game would enable TMSS but TMSS wasn't enabled in
the GUI so the ROM data wasn't there
byuu says:
r154 had a regression so let's skip to r155.
This greatly improves timing emulation on the 68K CPU (still far from complete),
including proper MUL(S,U)/DIV(S,U) cycle timing. The latter of which is ...
unbelievably nuanced. I also fixed a masking bug that snuck into r139 which
broke the loops in Sonic The Hedgehog.
Sadly, none of this has had any impact on the Sega CD issues: Sonic CD's intro
still has some gibberish, the US BIOS' music doesn't stop in the CD player, the
JP BIOS' music doesn't play, Lunar's Game Arts splash screen runs way too fast,
Popful Mail hangs ... sigh.
byuu says:
added Mega CD deemphasis emulation (with help on the high shelf feature from
MerryMage) and seek latencies that take the physical structure of the disc into
account (thanks to code from JosJuice). Added 2-cycle latencies to the 68K core
for -(An) and indirect indexed modes. None of this improved the emulation of
anything, sadly.
Oh yeah, r152 emulated the CDD DAC's attenuator, which is used for audio
fade-outs.
byuu says:
lots of cleanups to the subcode generation/parsing. Also emulated sega cd's cdc
dma, though it doesn't seem to get popful mail ingame, and sonic cd is pretty
weird with the audio on the title screen.
Oh wow I stand corrected, it's really just like that. The title screen plays
Sonic Boom much louder than the FMV that starts a few seconds later.
byuu says:
a quick regression slipped in trying to do a dma.io.length-- in the VDP DMA from
MCD WRAM, but with that reverted, Lunar: The Silver Star is now fully playable.
Only the "Game Arts" intro screen runs a bit too fast, but otherwise there's no
observable issues.
byuu says:
adds CD-DA audio and multi-track support + CUE parsing to Mega CD. Posted it
just a bit too soon before a freeze fix for Lunar: Silver Star, but that game
will be playable (with some glitches in FMV sequences) in the next release.
byuu says:
further along. The first sector is loaded by the BIOS, the BIOS confirms it's a
Sega CD game from it, goes to "press start button". That loads the first sector
again for some reason, and then ... nothing =( So close, so terribly close ...
byuu says:
not dead yet. full reed solomon implementation courtesy of merrymage's help
(still no C1/C2 CIRC, but P/Q RSPC is completed). implemented more CDD commands,
far enough along now to get the drive to seek to the start of the data track and
then .............. nothing. But ... progress?
byuu says:
emulated mega cd word ram -> vdp vram dma latency cycle penalty, fixes asic
graphics. bit of improvements to CDD, but it's still 99% unimplemented. hooked
up the ability to connect a game folder node representing a CD to the mega cd
hardware node, but no actual disc reading yet.
byuu says:
rewrote 68K memory handling, added a modest amount of CDC emulation, a bit of
CDD emulation, and full PSG emulation (though it doesn't work.)
byuu says:
added a whole lot of Sega CD stuff, got the secondary CPU booting and running
code, firing interrupts, etc. But unfortunately, ... nothing. Still seems to
just hang in a loop forever.
byuu says:
rewrote most of icarus to act like higan wherein you add a media class instance
to an array, and every other part of the program gains the ability to work with
the new system, emulated most of SA1 RAM write protections, added superfx backup
RAM even though nothing uses it, added genesis expansion port and enough to
get a frozen boot screen from the sega cd bios. icarus is missing some of the
niceties it had before, but they'll be re-added in time.
Last Blade broke on NGPC at some point... that's very depressing.
I removed MSX2+ stub support. There's only five exclusive games for it, and all
five are floppy disk games. There's 30+ floppy drive controllers, and C-BIOS
only has a non-working stub for it. So even if I pick a floppy drive, it'll
require a disk BIOS that is not legal to distribute with higan. So given both of
those, I'm just going to call it a day on MSX2+ support for now.
byuu says:
MSX2 V9938 support is in. I implemented graphics modes 1-4, sprite modes 1-2,
all hardware accelerated commands, some other stuff. still need graphics modes
5-7, text modes 1-2, multicolor mode, interlace, mouse, light pen, couple
hundred hours of bugfixing. then onto the MSX2+ V9958. "yay".
byuu says:
Got a better handle on understanding MSX primary, secondary, memory slots and
cartridge memory mappers. I knew this system would be a rabbit hole, yet somehow
it's still surprising me with just how much work there is to do here. I don't
know how far along my MSX support is going to get at this rate.
byuu says:
- improved waveOut DRC handling to match bsnes v107.1
- removed Famicom::APU::setSample() and replaced with Emulator::Stream
objects
- updated genius, map-analyzer, board-editor to new version of hiro
- updated genius, map-analyzer, board-editor to use nall::Instance
hiro objects
- removed Emulator::Game (failed experiment at code reuse which was
never used consistently)
- resynced Super Famicom/boards.bml to include 1CB5B-01 and 1K1X-10
PCBs
- Super Famicom: hard-forked bsnes; removed ppu-fast and speed hacks
from higan
- UI: removed "Show Hacks" from the settings menu
- Super Famicom: minor cleanups on PPU variable types (nothing
important)
- fix carry flag calculation bug in uPD7725/uPD96050 core
- don't render the screen during overscan area if overscan is
disabled; fixes Top Gear 3000 sprites
- note: I don't know if overscan can be enabled mid-scanline, but
it's somewhat likely ...
- added code to validate all peripheral locations on system load to
remove renamed/deleted peripherals from the tree
- remove FDS disk slot on cartridge disconnect rather than cartridge
unload
- all cores: scheduler.reset() called inside load() rather than
power(); as peripherals often create threads prior to power()
- removed binary=library rules from Makefile; since higan doesn't have
any use for it (it remains an option in bsnes)
- added icarus support for MSX2 and MSX2+
- added higan stubs for future MSX2 and MSX2+ support
- added MSX keyboard skeleton class (need to decide how to name the
keys before implementing the actual key bindings)
byuu says:
I improved FDS emulation a good deal. Timer IRQs were running too fast because
I was stepping at 21MHz instead of 21MHz/CPU rate (12 or 16 based on NTSC or
PAL), that fixes Zelda scrolling. I also emulate the CRC16 error check bit now.
I added a really simple emulation of the Famicom controller port 2 microphone,
where I just send random noise to the port when a Famicom/Microphone hotkey is
held down. Proper emulation would require ruby to support microphones. Next,
Molive wrote an SNES PPU test surrounding sprites and force blank, which showed
that a) sprite evaluations happen during Hblank instead of during active display
(which means the double-buffering system for OAM items/tiles can be eliminated),
and b) when force blank is enabled, it just skips updating the buffer entirely
(which is really strange ... I would've expected it'd zero out the sprites and
show nothing). So I emulate that test correctly now, but ... as always, exact
PPU timings are unknown so this is just playing whack-a-mole, but at least
it's more correct now than it was before. Finally, I added a dumb hack to the
scanline PPU to run Uniracers 2-player correctly, because why not?
byuu says:
I completed the initial emulation of the Famicom Disk System. Reading and
writing to disks work, plus the FM synthesis audio channel is now supported.
It's going to be far from perfect, but ... it mostly works.
A horrifying amount of additional work will be needed on the GUI to be able to
handle save states for FDS games cleanly.
byuu says:
fixed the pitch/speed of the VRC7, and added a 2280hz lowpass filter to match
hardware a bit more (it's kind of hacked in, but it works.) forgot to set the
echo buffer disable flag on the SNES DSP, which was breaking SNES games, so
that's fixed. started emulating the famicom disk system. so far just the icarus
BIOS + FDS disk imports (won't handle multi-disk merged ROMs yet), the basic PCB
mapping of PRG-ROM+RAM and CHR-RAM, some MMIO registers, FDS timer IRQs, and the
GUI connections to connect a disk (marked hot swappable.) I need more info on
the low-level details of how the ram adaper talks to the disk drive to proceed
further. But it's a start.
byuu says:
this release adds Talarubi's YM2413 emulation, VRC7 emulation, and NukeYKT's
dumped VRC7 patchset. It also adds MSX gamepad support (still no keyboard
support, though.)
byuu says:
now that it seems we're finally going to get some real alternative choices in
SNES emulation, I felt a bit emboldened to start performing some more radical
changes I put off for a long time. This WIP rewrites huge swaths of the SNES
DSP core to separate internal registers from underlying RAM. This allows me to
emulate the randomized memory registers at power-on, while not breaking games
due to also randomizing the actual DSP registers. This is part of Jonas Quinn's
findings about a year and a half ago, which is aimed at improving the chances
Magical Drop doesn't crash, as on real hardware.
byuu says:
substantially improved the Z80 emulation core. We now have sound in MSX games,
compatibility should be way up for MSX+ColecoVision, zexall passes, and I
even emulate new SCF/CCF flag findings that haven't made it into MAME yet.
Still needs a good review of all the cycle timings, though. I don't have full
confidence in those.
byuu says:
Nymp works fully now, need to initialize RAM to 0x00. It seems like my Z80
core is running twice as fast as it should, but if I halve it, audio starts
breaking up in other games... sigh. I finally committed the Megalomania SNES
intro scanline fix. I also emulated the MSX AY-3-8910, but unfortunately the
game I'm testing with isn't writing anything useful to the PSG registers yet, so
it's untested.
byuu says:
massively improved NGP timing emulation. Turns out I was running the CPU about
twice as fast as I was supposed to (Mednafen runs it about 2.5x too fast, MAME
can't run the bus timing test ROM for some reason, acts like there's no game
when loaded.) The actual cycle counts and specifics of the prefetch emulation
are still going to be extremely wrong, but ... it's already enough to run the
first minute of Nymp perfectly. Then the audio distorts for about 20 seconds,
and recovers for 40 seconds. Then it loops. So ... I have not had any luck
finding what's wrong here yet =( Neither Mednafen nor MAME have this distortion,
so it's obviously a CPU bug, but nothing at all jumps out at me in the trace
log. Comparing to the nymp source code, it's something to do with channel B /
phase B getting calculated incorrectly... in any case, I also emulated the LDAR
instruction, that one was well hidden, heh. I fixed several disassembler issues,
and another issue with writing to the upper word of XSP.
byuu says:
lots of improvements. Fixed the power on/off toggle, and fixed a bunch of neo
geo pocket bugs and improved things more. This is as good as I can get it
without hardware tests, though. So unless someone else comes along to help, or I
get my hands on a flash cart and figure out how to write tests on my own, this
is the end of the line.
If there's glaring bugs in games, but not in MAME, then I can probably create
CPU traces and figure out what's going wrong from that.
But as a whole, the CPU is likely running twice as fast as it's supposed to, and
even more than that, there's no penalty for using the CPU+Z80 at the same time
on APU RAM.
byuu says:
I didn't even notice that sound on the right channel was busted. Fixed now.
Also fixed a major issue where decw/l #3,r doesn't update flags, but
decw #3,(mem) DOES. It didn't help anything, but I updated LDIR/LDDR/CPIR/CPDR
so that interrupts can fire during them. Fixed the V flag with BS1B/BS1F, and
improved the carry assignment function to clear/set to undefined (eg clear for
now) other flags as they should. didn't help anything either. At this point, a
majority of games run okay. A few more key fixes (eg Puyo Puyo 2 not booting)
and then I'll start implementing proper reset and serialization, and then I
think that'll be a good neutral point to shift focus to other tasks for a while.
byuu says:
fixed a bug in ld reg,(reg+) instructions, which allows Card Fighters to run
properly. Rewrote the interrupt handling to vastly reduce the amount of polling
needed per instruction and ... it resulted in no difference to speed. Wonderful.
Spent hours trying to figure out the issue with Sonic Pocket skipping the title
screen and Rockman Fighters not accepting input on the character select screen.
Really heroic lengths like tracking every branch the code takes and inverting
the branches, one by one. Firing each interrupt sequentially based on a bound
debugger key. On and on. I have absolutely no idea what's wrong here ...
byuu says:
I added proper cycle timings for every instruction, including all of the various
penalty cycles that the dev manual lists. Also improved HDMA a bit. I can run
the FM synthesis demo ROM now, but the audio still appears to be playing about
twice as fast as it should, although with correct pitch. Any attempts I make to
halve the speed results in the pitch being halved. I have no idea what's wrong,
but we should be really close, hopefully, to running that demo ...
byuu says:
- added watchdog timer emulation,
- improved interrupt handling,
- implemented the GPIO modes of all port registers,
- completely revamped how ports, timer pins, and interrupt pins all
interoperate,
- updated the VPU to render sprite priorities correctly,
- added HDMA emulation,
- fixed a bug in the ZCF instruction that was preventing the time from being
set in the BIOS,
- accidentally stumbled across a crude RAM patching hack so that subsequent
boots don't keep dumping you into the BIOS setup (hopefully I can track down
where the RAM variable is supposed to get set, and determine why higan's not
setting it normally.)
byuu says:
some fixes to unmapped register bits, flash memory write commands, and some
other things ... a couple of NGP games are now playable, but the Z80 is
definitely not talking to the PSG correctly, still only DAC sound output.
byuu says:
I've added a waveOut audio driver for Windows (no DRC), and hooked up a lot more
neo geo pocket stuff (gamepad polling, APU/Z80 enable/disable, APU->CPU IRQs,
VPU I/O registers, etc.) still not enough to get any further than we already
were, sigh.
byuu says:
I made it default to the safe drivers so no more ASIO crash out of the box,
and full driver configuration is now in place, plus a skeleton Hotkeys
implementation (it won't save hotkey bindings to disk yet though...)
The way the driver stuff works is pretty spiffy...but also not complete. So when
you start the program, I don't initialize any drivers, because sucky vendor
drivers can crash higan and you get stuck in a crash loop. So instead, you
have to "activate" the driver before the driver settings are editable. For
instance, until XAudio2 is initialized, it can't query XAudio2 for all available
playback devices. So you go to audio settings, activate your driver, and now
you can change devices. whenever you change any driver setting, it updates all
driver settings again and refreshes the entire settings panel again. Because
for instance, if you change a WASAPI device, the new device may not support the
currently assigned frequency. Aren't computers fun?
Starting a system initializes the input and audio drivers, so that
auto-activates those drivers and you can immediately edit their settings. Video
is more difficult ... you have to have a visible window that has been realized
on the screen before you can initialize a video driver. So to get it to auto
activate, you have to actually power on the system. Otherwise, when you hit
activate, I flash a 1x1 pixel viewport at the bottom left of the video settings
panel, populate the settings, and then destroy it.
The downside to all of this is input ... if you try and bind hotkeys immediately
after starting higan, then no input driver will be bound. So, yeah, I gotta
figure out what I'm going to do there.
Like bsnes v107, higan now lets you change drivers on the fly, but of course
that's risky, so ... you know. you probably shouldn't. "activate" becomes
"change" once a driver is activated for the first time.
byuu says:
The sliders/checks are implemented on the audio/input settings panels, but
there's still the problem that I can't poll the video/audio properties
until after a device is initialized, which happens only after powering on a
system......... I added an import button to the port connector to shell an
icarus single-game import dialog, so you don't have to run icarus separately
now. i fixed a bug in nall/arguments .. off by TWO error, yikes. i removed the
name text box at the bottom of the port connector for templates, and changed the
icon from a white folder to a + icon. double clicking one pops open a create
name dialog box now. i forgot again about the nall/integer fix, so i just fixed
it now and it'll be in r112.
oh yeah, i changed it from centering the video and bumping the program window to
the left ... to centering both the program window + video window now. it means
the program window moves less drastically, and the program window won't get
placed offscreen unless the program window + video window exceed the width of
the entire window
still not ideal to be moving windows around but......... for now, this is more
tolerable.
[This WIP was made after byuu's forum closed, so byuu only gave a one-line
description -Ed.]
byuu says:
It improves windows hidpi support and removes the old, broken higan/bsnes legacy
ports since they'll never compile anyway.
[This WIP was made after byuu's forum closed, so byuu only gave a one-line
description -Ed.]
byuu says:
lots more Windows port improvements; adds high DPI support to Windows (icons
don't scale, but it still looks okay)
[This WIP was made after byuu's forum closed, so byuu only gave a one-line
description -Ed.]
byuu says:
This redesigned icarus; lots of improvements to build and run on Windows
[This WIP was made after byuu's forum closed, so byuu only gave a one-line
description -Ed.]
byuu says:
This splits ColecoVision, SG-1000/SC-3000 away from Master System/Game Gear.
Was getting too crowded in there.
byuu says:
Okay, all ten cores (and all 21 interfaces) have been ported to the new API.
Everything is of course super unstable, but ... it'll just take time.
byuu says:
8.5 hours today. I took too long to get on the PC after waking up, so I
wore out a bit sooner than I wanted.
I ported the Game Boy+Game Boy Color+Super Game Boy and Mega Drive cores
over to the new API. The Super Game Boy support is very unstable, and
will die horribly if you have no cartridge connected, or if you try
disconnecting a cartridge after the system is powered on. Lots of work
to do there. I didn't test Mega Drive cartridge chaining.
The Game Gear gained smarter up+down and left+right masking.
I added removeWhere() and findWhere() to nall::vector.
There's also been a lot of cleanups to various things.
There's four cores left to go, and two are skeletons so they shouldn't
be too terribly difficult.
byuu says:
Ten hours today.
identity.bml is now metadata.bml. I did not yet rename node.bml to
settings.bml, nor did I merge manifest.bml to metadata.bml.
I added a setting editor, which is fairly fancy. It'll show you the
latched value on static settings (eg CPU version#, which can't change
dynamically), and in the tree it'll show you "name: currentValue
(latchedValue)". Powering the system on latches the current settings,
and refreshes the tree (but not yet the Latched: value in the setting
editor ... polish work is needed.)
The node manager can refresh without losing its place now, which means
you can connect/disconnect peripherals without the port connector
disappearing.
I ported the Master System (and its five systems) and the Game Boy
Advance to the new Node API. I also separated out the Game Boy Advance
core into two models: Game Boy Advance and Game Boy Player, since
they're different physical devices. I skipped over the Game Gear Up+Down
/ Left+Right improved handling, so I'll need to get back to that.
I created Video::Screen, which acts a lot like Audio::Stream insofar as
allowing you to have different screens with different color counts and
color conversion functions. The big use case for multiple screens will
probably be if we emulate a peripheral that has its own screen (think
Dreamcast VMU but something more modest ... maybe one of those weird
peripherals Shonumi has been researching has a little status LCD screen
or something.)
I still need to update Audio::Stream to take a Node::Audio object on
construction.
I hooked up really, really rough save state support via a new tools
menu. Now, unfortunately I am so far unable to reproduce Tala's crashing
behavior with the Master System core's save states. If I can find a
reproducable case, I'll fix it.
So at this point we have three of nine cores converted. Once they are
all converted, I need to split off ColecoVision and SG-1000+SC-3000 to
their own separate cores. That's still going to be a ton of extra code
to write and compile, but the overall workload should be lessened with
the new higan/component/(video,audio) abstraction layer.
byuu says:
Only five hours today (maybe more later ...), but ... a fairly
productive day still.
The SNES is completely migrated to the new structure and seems to be
working ... quite well! (okay, the SGB support is still busted and ...
oh gods that one's gonna be tough as nails.)
I tweeted the new Interface and Platform APIs, and they're a real dream.
Lots more to do internally of course, like abstract higan::Video to use
shared_pointer<Screen> objects, so that each screen can get its own
dimensions and palettes. I also want to hook up the Node::RealTimeClock
stuff better. We can serialize the timestamp outside of the RTC RAM
now, so yay more faithful rtc.ram files. Should help with Satellaview
emulation when we can jump the time ahead seven minutes for the "wait
for the broadcast" titles.
I think it makes sense to build out CartridgePort, BSMemoryPort,
SufamiTurboPort classes as well, instead of merging the port +
peripheral into one.
There's gonna be tons of bugs, and I'd greatly favor fixes over reports
right now.
Hmm ... and of course, the pending bikeshedpocalypse coming up for
serialization of the tree and peripherals. I'd like to simplify the way
we save and load input mappings. Instead of
pathID+vendorID+productID+groupID+inputID, we could reduce it to
id+name, and print out string values for the group+input IDs.
On and on.
byuu says:
Only eleven hours today ...
So, I redesigned the Justifier/s support, added NTT Data Keypad and Twin
Tap emulation to the SNES core, and I improved the handling of up+down
and left+right to use the last key pressed instead of canceling each
other out when held simultaneously.
I started to port the Master System core to the new Node system, but
quickly grew displeased with the nested spaghetti code required to
unserialize the system. I wanted a design where the core runs alongside
creating new nodes, and copying in node values from a parallel tree next
to it. With every step along the way, the true tree should have the
equivalent level from the unserialized tree, so we can copy in exactly
what we want, and ignore what we don't want. Anything less than this,
and we're going to risk stagnant elements from previous versions
sticking around in new trees and causing issues. Further, this redesign
allows me to merge the peripheral node setup and device node binding
together.
It required a huge amount of rewriting, but the idea works. So far only
the SNES cartridge and controller port gamepads work. And even then,
they just barely work. Lots of annoying issues like losing input
mappings when unloading and reloading the gamepad, not displaying the
folder names in the system tree view, etc.
I wanted to get further along, but I'm getting too tired to think, so
it's best to stop here. It looks like I'll get one more day at this
tomorrow due to it being some kind of Japanese holiday. I'm hoping I can
repair the SNES core completely (well, sans SGB), and with any luck ...
it'd be great to get the Master System core up and running. I'll try my
best.
byuu says:
Sixteen hours of work today. This is getting ridiculous ...
I basically rewrote the GUI to merge the configuration and system
managers into one program window. I did all of this basically to save a
quick blinking when the configuration manager went away and the system
manager appeared. The menus have been broken out to their own classes,
so that we can share the settings and help menus between the two modes.
Renaming systems/peripherals on top of existing names now just errors
instead of letting you optionally delete the old item and rename it
anyway. Laziness, I may readd it later. Renaming peripherals that are
already connected to ports works much better now. Renaming systems is
still very broken.
There were a few other changes to things here and there, like the path
the port selection windows scan in is more obvious, with a button at the
bottom-left to select an alternate port.
This new design should let us do some more interesting things, like have
the settings and tools activate in the right-hand pane instead of
generating another window.
I regretfully went ahead and wrote the GUI using ListView widgets this
time instead of TreeView widgets. So, I'm sure this won't compile on
other platforms due to missing new functions to hiro, but ... let me
know what they are and then I can add them, I guess.
For some reason, I got distracted for about half an hour and started on
a nall/image64 class ... I don't know what I want that to be just yet,
but I'm kind of annoyed with how cumbersome everything is with
nall::image on account of having to support every possible ARGB image
format. I think this is because I added a somewhat subtle logo to the
empty panes in the main window, and doing so was kind of annoying.
There's a very strange bug in hiro/GTK's Frame control. For some reason
when you have a widget directly attached to it, it shows up just fine.
But attach a layout to it, and then put a widget inside that, and the
widget won't show up. I added a hack to call setVisible() on the layout
inside the pFrame::setGeometry call, but I have no idea why that works
or why that's necessary. If anyone's willing to take a stab at that,
you'd be a real life saver.
I updated the SNES mouse, super scope, and justifier code to compile
once again. Although the justifier code is completely broken. I am
struggling with how to design it to support dual justifiers more like
real hardware would. I think what I need is to bind the controller port
IO bit read/write functions to callbacks, so that the second justifier
can send the iobit strobe back up to the first justifier, which can then
propagate it to controller port 2. The second justifier really needs to
be its own class as well, as it's not simply just another justifier.
Overall I'm really disappointed. It took way, way too much work to merge
those two panels. I thought it'd be a relatively quick copy-paste affair
with a few tweaks, but it ended up being a huge mess that was easier to
just redo. But, damn. I wasted a critical day and a half on ...
something trifling. Sigh.
byuu says:
Another thirteen hours ... Concerta is a hell of a drug.
Okay, so this is a partial merging of Screwtape and bun's suggestions
for a multi-pane layout.
The configuration manager shows the list of systems on the left, and you
can choose to create a new system in the right pane, or to see
(read-only) the current connections of a given system entry. For right
now, there's just a simple logo display on the right when no systems are
selected and you're not in create mode. I imagine it will make more
sense to list the systems on the right when not showing a specific
system connections list, but ... I wanted to put the icon there for now.
To do that, I wrote a new nall::image function, shrink(), which detects
all entirely blank/transparent rows/columns on all four sides of an
image, and then crops them out. I could have just used Imagemagick on
the icon.png file, but ... overkill is more fun.
My thoughts were, maybe in the future, we can populate it as a kind of
"home" screen with some more things. Have to think about it.
The system manager window shows the connections on the left, and you can
edit either port↔peripheral connections or input mappings on the
right. And in the future, settings and other such things as well. The
system manager also has a "blank" panel, but this time it's just a
disabled, empty TreeView (so that the frame matches the other panels.)
We could put anything here as well in the future ...
There's new hiro classes, HorizontalResizeGrip and VerticalResizeGrip.
The former is used to let you resize the two panels.
I burned a lot of time reimplementing the horizontal scroll bar display
in GtkTreeView, because GTK's implementation was busted, ignored icon
indentations, and showed the scrollbar way too early.
The tree views now render little L bracket things to help show
indentation a bit better. Unfortunately my GTK themes can't do this even
with the extenders visible, so this is the best I can do in a
cross-platform manner for now ...
If we decide to give up on tree views ... we will have to lose the icons
(and the chance of any nicer node-specific icons in the future), because
the TableViewItem icons always appear at the far left. I might consider
it anyway because I really don't want to port TreeView to Windows, Qt,
and MacOS.
I turned back on the GTK alternating row colors for a bit, to make the
input mapping panel a bit easier to read.
I cleaned up a lot of the SNES core code as well. The Super Multitap is
back, and functions like a real Super Multitap for the first time ever.
There is the possibility of a controller that passes through the iobit
lines to PIO d6/d7, but for now, the only controller we emulate with
extra ports (save for maybe the dual Justifier) is the Multitap, and it
doesn't pass through the iobits to its connected children, so for now
I'm just having anything other than controller ports 1&2 return 0 from
iobit reads, and ignore iobit writes. The ControllerPorts implement
wrappers for the Controller functions (iobit, data, latch) so that the
Controller* device object can be a nullptr.
Expansions are connectable again. There's a new Thread::destroy() to
both release a cothread_t and remove it from the scheduler threads
list. I still regrettably have to also remove the threads from the
cpu.coprocessors/cpu.peripherals vectors (speaking of, I should
double-check that the peripherals do this right.) All of the
coprocessors have been updated to properly do all of this, and handle
thread attach/detach inside their own unload/power functions, instead of
in System/Cartridge::power,unload.
The Satellaview maps data onto and off the SNES bus, but ultimately this
should be okay because the expansion port isn't hot-swappable. If you
forcefully do it anyway, it should still work since nothing else maps to
those ranges except for the 21fx.
I updated hiro's setAlignment functions to replace the newer
setPlacement with something even more flexible. Love it or hate it,
higan now places the system manager window in the center of the screen,
and when you power on a system, it centers the video, and then moves the
system manager to the left of the video output. When you close the video
output, it acts like an unload event and moves the system manager back.
If the system manager is either minimized or maximized, it won't move it
on power on (though currently you can't power the system on with the
system manager minimized, but maybe later with a hotkey ...) When you
close the video window, it'll unminimize the system manager if you did
that, and then center it ... unless it was maximized.
Unserializing node.bml tables got a lot more strict. Now only Setting
values and Property values can be unserialized into the root tree, and
only when both the type (identity) and name of the node matches up. This
should hopefully help to prevent incompatibilities as the node.bml
structure changes.
If you right-click on a port, you can change the path it looks for
things in. This is a bit hidden, and the port connection panel should
really tell you where it's looking as well. We'll get there.
I'm sure there's a lot more, but that's all I can remember right now.
byuu says:
Fuck it, what's another few hours, right?
So remapping the SNES bus on power-on wasn't going to work, if we wanted
to also support hot-swappable cartridges (which would only work on real
hardware if you disabled the CIC, easy to do but breaks SA-1 and S-DD1
games ...). Plus, it's a lot of extra work. So instead, I'm reloading
the bus on every cartridge load and unload event. The CPU and PPU bus
mappings were broken out to CPU::map() and PPU::map().
An extremely long-overdue change ... I improved higan::Thread to let you
pass nall::function objects to create threads, so all of the static void
Enter(); methods are now deprecated. This was essential for Multitap
support to be able to connect peripherals to it that would then need
their own threads. Multitap support still isn't ready yet, but ... it's
getting closer now.
Ports gained a hotSwappable flag. When false and you try to disconnect a
peripheral (the flag can be set per-peripheral if you want too), it'll
warn you with options to forcefully disconnect the peripheral (and
possibly connect a new one), to power off the system first (safest), or
to cancel the port change attempt.
I may move this prompt to when you double-click on a port, but I held
off for now because that may not work well if we go with Screwtape's
multi-panel layout.
byuu says:
Another thirteen hours of work put in ... things are starting to shape
up.
I fixed the issue with relasing all the shared pointers properly, and
higan always exits cleanly now. I even went back to Application::quit()
instead of kill/exit().
The templates directory is now "fixed" to ~/.local/share/higan, which
holds all of the system folders. The configuration directory is now
fixed to ~/.config/higan, which holds the template and data paths, and
eventually program settings as well.
I removed as much of the old Emulator::Interface and Emulator::Platform
cruft as possible. I had to disable all but Gamepads for now, which is
fine since they were the only inputs that actually worekd anyway. It's
going to require a lot of reworking to get all the peripherals up and
running again ... sigh.
I killed off the properties/options support, and with it,
nall/settings.hpp, in favor of just using Nodes to represent things.
My trickery with trying to get us to have Node, Node::Input,
Node::Input::Button, etc was backfiring. I had to make Node::Input a
member of a Node struct, which inherited from
shared_pointer<Core::Node>, and so forth. This was leading to all kinds
of overloads and using statements necessary, and eventually things just
weren't converting properly to the derived types, so I scrapped it all
and now every Node::Object is just a shared_pointer<Core::Object> and
nothing more. Not crazy about this, but ... oh well. Ten-page compiler
errors on typos was clearly a sign I was pushing things.
<Platform::attach> and detach work properly now, which kills off the
GUI's Emulator::load,save hacks. You can attach and detach controllers
and have all the state saved properly now.
I sped up input polling by creating an intermediate shared_pointer
object that holds decoded group/input IDs. Probably doesn't matter much
in practice, but why not?
I have an initial fix for the annoying ipl.rom error ... it'll try to
import missing files from the templates folder for a given system. Won't
work for the GBA BIOS, but it's a start.
The next major thing I need to work on is SNES cartridge loading ... I
need it to just load for now, and do the mapping stuff at power-on.
I guess I'm going to get this as far as I can by the end of this
weekend, and then I'm going back to NGPC.
byuu says:
Very, very slow going ... sigh. Aforementioned changes to the Property
system in hiro and higan. string::from/to removed.
Input mappings now serialize the path/vendor/product IDs, and input
binding events were added to connect inputs back to devices on load and
on ruby device attach/detach events. (Speaking of ... a good tangent
would be a notification callback when adding/remove HID::Device objects
from ruby::Input. Neither hard nor expensive to scan the result of
Input::poll() to detect this, but still.)
The actual tree of each peripheral is loaded and saved now, and there's
an initial attempt at importing this data into the actual root tree on
load. I'm going to have to do this same thing in the port selection
manager when attaching/detaching peripherals.
There's code in place now to detect when you try to connect the same
peripheral to multiple ports, and it'll stop you. It won't attempt to
validate this if you give Interface::initialize a root.bml file that has
the same peripheral in two ports, however. Maybe later we can detect
that as well somehow ... it won't crash or anything even if you do this
anyway.
There's new <Platform::attach>, detach callbacks to send notifications
to the GUI whenever the emulator tree changes in any way.
And it's about here that I'm running into problems again. When closing
the emulator, I'm seemingly unable to get the tree to actually destruct
properly.
If we have ~Node::Port call disconnect(), it works, but then segfaults
after the application terminates in the global destructors. I was
thinking, the Peripheral is inside of the Port, so maybe catch
~Node::Peripheral instead, see if it's attached to a parent Node::Port
via the weak_pointer it holds, but no matter what that painfully
segfaults on startup.
I was pretty sure I wiped out all of the copies of the shared_pointers
to the ports before calling Application::exit(), but it seems not. I
guess that's the one downside to using shared pointers and holding
copies of them everywhere. It quickly becomes overwhelming to keep it
all in your head. Best I can think is to just slowly work on destructing
everything as cleanly as possible. Eg closing the input mapping window
should erase the list to clear the Node handles cached in the
TableViewItem entries, reset its holding of the Node::Port for said
mapping, etc.
There's another problem with the <Platform::attach,detach> ... it's
getting called with a bunch of nameless items. Nodes without names
should never be attached to the emulator tree, so there's some spurious
copies somewhere ... I'll need to update the static create() functions
to take variadic template parameter lists, and make the name parameter a
constant for the construction of Node objects. That should allow me to
find where nameless Nodes are being spawned, and stop that from
happening.
A lot more work needs to go into serializing and unserializing
Node::Peripherals to their respective folders. I feel like Node::clone
is asking for too much trouble, and we should instead rely more heavily
on <Platform::attach> during the load process to then connect
peripherals for us from our shadow tree instance. The GUI should only
ever call a function that copies all of the properties from the shadow
unserializing tree to the actual emulation core, and never act
recursively.
I really don't know what to do about the serialized root tree holding
all of the peripheral metadata. We have to do it in the case of
peripherals having their own ports that may be connected to things, but
... a lot of the information in the tree isn't necessary at all. It
would probably make sense to write some code to filter the serialized
tree, like stripping all Input nodes from it before saving.
Well whatever ... I *really* have to hurry up with this, but there's
just so much work to do ... sigh.
byuu says:
Templates now import to the user data folders, so you can create
multiple gamepads with distinct mappings ... or at least, you will be
able to. Things have progressed enough that you can map keyboard inputs
to play Zelda 3 a bit now. But if you close the emulator, the assignment
device will be lost. Right now, it's serializing things to the root.bml
document instead of to individual peripherals, and it's also not
properly serializing/unserializing the HID object from ruby.
The old naming of program, emulator, emulators didn't match the new
design where Program wasn't the center of higan anymore (the
configuration manager precedes it), and Emulator has become higan, so
that's been renamed to emulator, interface, interfaces.
Some new work on hiro and nall:
MessageDialog
- when dismissing, set the response to the last button
- add dismissed() function
NameDialog
- new class for create / rename file/folder dialog boxes
BrowserDialog
- add create (folder), rename, and delete support
directory:
- add copy() function
- fix sorting of folders to ignore trailing /
string:
- added string::from<T> and string.to<T> for object binding
- requires string::operator bool() to return true when capacity() == 0
...
The last one is going to be really contentious, but ... oh my gods I am
in love with it already. So for an example:
auto x = shared_pointer_make<Foo>();
node->setProperty("id", string::from(x));
if(auto y = node->property("id")) y.to<shared_pointer<Foo>>()->bar();
The idea is to add another special case in nall::string, where when the
capacity is zero, the new _hold pointer holds a type-erasing object.
This object is set via string::from<T>(), and extracted via
string.to<T>(). The capacity is always >= 23 normally, due to SSO, so
it's okay to special-case zero. _hold doesn't make the string take any
more space ... with SSO of 24 and two pointers before, we're just using
up the rest of the space we already had. The total size of strings is
still 32. Although at some point I'll probably make it 40 for 64-bit
size/capacity, but that's not super pressing right now.
Anyway ... why in the hell would I do this? Well, hiro has the
Object::property/setProperty system for keeping a set (red-black tree)
of name:value mappings. And higan adopted the same system for its Node
objects. The name is obviously a string, but the value is also a string.
Why a string? Because it's the easiest to serialize, and can be
converted to and from any data type: booleans, integers, floats,
strings, pointers ... and all of those implicitly convert into strings
for you, so you setProperty("name", 3.7) is just fine. But it can't hold
objects. Even if you allocate a new pointer and store it in the string,
it'll end up leaking if you don't make sure to extract the pointer and
delete it before the string goes away.
I really didn't want to move the property system to any<T> types because
they are such a massive pain in the ass to use in every case. It would
make serializing/unserializing Property structures in Node elements way
more painful, too. And any<T> basically requires heap allocation for
absolutely any value. nall::string will only allocate memory when the
string size is > 24 (or now, if you use the new string::from support.)
Now obviously, string::from has a caveat: you can't serialize it. You
can copy a string holding a T object to another safely, but once you try
and print it into a text document, the string value will be empty, and
when you try and read a string back from the text file, it's gonna also
be empty. Even if we extracted the pointer from the string to store,
restarting your program would invalidate the pointer anyway.
This is a pretty significant win ... for my tree structure in higan's
system manager, I can just hold shared_pointer copies of each Node
inside each TreeViewItem, and retrieve them directly. No crazy path
traversal up and down the tree with lots of string parsing involved. No
possibilities for bizarre bugs because the two get out of sync, or the
tree paths change in higan, or whatever else. The worst thing that could
possibly happen is the shared_pointers between higan::Interface::root()
and SystemManager get broken, and SystemManager just stabs at perfectly
valid but detached Node objects. No big deal. No problem. In practice
that's not going to happen anyway.
In implementing this new feature, I realized that my
template<typename... P> string(P&&...) constructor was matching
instead of string(const string&), so I added a string(string&)
constructor, which should in general help the performance of building
strings a whole hell of a lot, presumably much more than the tiny tiny
hit for the extra checks for the new string::from mode.
There's only one thing about string::from that kind of worries me ...
explicit string::operator bool() const must necessarily return true when
holding a T object, even though the size and capacity are both zero. If
we don't do this, the values will be lost in eg setProperty erasing
nall::set entries when the assigned value is a blank string. I don't
know if this will have unfortunate side effects in other string
processing code, but ... in general, I've never used nall::from in any
other code, so if there's an issue, we'll find it as we are using
nall::from objects. The change should not impact any existing code as
such.
Lastly, the MessageDialog change ... in way too many places, I do tests
like if(MessageDialog() .... question() == "Yes") or (... question() ==
"No"), but I don't test both Yes and No. So whichever I tested with ==,
it'd be false when the MessageDialog were dismissed, and the inverse for
!=. Not good. Sometimes it's the difference between deleting a
directory recursively or cancelling the operation. I don't think in the
history of using hiro I've ever bothered to actually test for
.question()=="", so I think this change is really imporant. If the
dismissal case is really needed, MessageDialog::dismissed() can be
checked now instead.
So the next big thing is going to be more advanced tree parsing: it
doesn't really matter whether the root tree gets serialized with all the
peripheral input values, but we absolutely must serialize each
peripheral to its respective folder. And when unserializing the root, we
have to go through and unserialize all of the peripherals.
Also for input mapping, I have to serialize the hardware HID path +
deviceID + vendorID, and then create a binding function that'll scan the
root tree for all Input devices and rebind the shared_pointers to the
new shared_pointer<HID::Device> instances.
But, hopefully, hopefully ... I can get that done in the next WIP.
byuu says:
Another eleven hours in ... I think we're finally starting to see some
hope.
Unserialization of the tree works now. An absolutely heroic effort. The
design challenges were thus:
- given a text document, reproduce a tree of shared pointer objects
- the text document may have extra or bad node names (perhaps it's
from an older version) -- ignore these so they don't appear in the
actual tree
- the text document may be missing some node names (again, maybe an
older version) -- populate the actual tree nodes with default values
in this case
- any peripherals connected in text document nodes won't be in the
actual tree, so we have to connect them
- upon the creation of a new actual tree peripheral, we must populate
it with the metadata from the text document recursively, with the
above rules in effect
- we also need to allow the GUI to attach new peripherals, where it
would not know about the child nodes each peripheral contains (eg
the buttons on a gamepad)
- lastly, even though the tree is small, try not to take an absolute
eternity to import a document into the tree
There's a hell of a lot of restructuring that needs doing, in the SNES
core far more than anywhere else. We have to split bus mapping to occur
at power-on time, and manifest generation + slot attachments to happen
during load / system configuration. GBA also should move to detecting
save types at run-time. And honestly, that scan is pretty painfully slow
... it may make sense to suffix array it ... 13*4MiB isn't that much
memory. That or just write a smarter substring scanner. Sigh.
So now that things can be serialized, the next step is going to be
writing an input manager. It's going to be a radical departure from the
old way of doing things. Now, when the core wants input state, it'll
call inputPoll with a Node::Input object that we can directly write the
value to (well, after we `dynamic_cast` it to its specialized type. It'd
sure be nice if there were a `dynamic_multicast` switch construct, so we
didn't have to keep doing repeated `dynamic_cast` calls for each input
type. I digress.) I guess we can cache things ...
Thus, input polling will be more like this:
- produce a map of Node::Input to
`shared_pointer<InputManager::Binding>` objects
- maybe even do a multitap as a lazier way of handling multiple
input bindings
- have the InputManager::Binding hold a `shared_pointer<nall::HID>`
object, the group ID, and the input ID
- polling will thus be a map (or multitap) lookup; copying the
nall::HID value over to the Node::Input value
- it should be fine to just store `shared_pointers` here, to save
the overhead of constantly converting `weak_pointers`
And of course, we have to write a GUI for this. Oh, and before I can
even do the above ... I have to implement template importing, and
implement serialization support when attaching / detaching peripherals.
Hmm, what else ... I got rid of the Port specializations, as Port ends
up needing a lot of glue code and any special handling can be done
inside the emulation cores anyway. So now, a Port is a Port. It's just a
Node with the special property that it may contain either zero or one
Peripheral nodes. In addition to nodes of other types, of course.
I'm thinking we should probably also enforce a tree rule that no parent
node shall have two child nodes that have both the same type and the
same name. If we stick to that rule, we can simplify path traversal, and
allow the append function to be used as a "create if not exists"
function.
Also, we're really going to need a system to pick sensible default
peripheral and template paths for ports, including for dynamic ports.
Having to manually assign these, and having the values on dynamically
generated ports lost easily, is very annoying.
byuu says:
This is starting to get ridiculous ... thirteen and a half hours today
of non-stop coding, and I barely made a dent.
So, the main change with this release was building out an introspection
layer for higan::Node objects. You can now construct a Node from a
string that represents its identifier.
There's now a templates system for things connected to ports. The idea
here is controllers will let you pick a template (Gamepad, Mouse,
Multitap, ...) which will (in the future) import a folder by the name
you gave it to the path you set the port to. This system will also be
used for creating eg blank BS Memory cassettes. Connecting something to
a port shows the templates first, and then the folders found in the
path. If you pick a template, you need to give it a name, although it'll
fill in by default to the name of the template. In the future, it may be
nice to produce a "#n" suffix, by counting the number of existing
matches in the path folder for said port.
The UI is currently erroneously collapsing the Display settings, because
it's a Port::Video, and the code tries to do that on all ports. This is
the same problem as with the Game Genie that I talked about previously.
Basically, what I need to do is have Node::Port hold its own separate
Node connected instance, and that will be the thing that gets condensed
in the system manager. It's still going to end up looking weird if a
connected Peripheral/Cartridge exposes its own child Nodes, while the
Port::Peripheral/Port::Cartridge also has its own child Nodes. They'd
end up getting merged into the same parent TreeViewItem.
So as such, I think we're gonna have to say it was a nice try, but
overloading two different things (Node connected + vetor<Node> children)
into one parent (Node::Port) isn't going to work well. If you connect a
to a port, it'll just have to create a child peripheral/cartridge node.
The Node::id field is gone. There's a new path/find API that generates a
string of tree indexes, eg "2/7/4" to represent root[2][7][4].
Nodes hold weak pointers to their parents now to do the reverse
traversal. Unlike hiro, I didn't bother keeping the offsets in the
children, I just do a scan of the parent Nodes list instead. Speaking of
... this traversal requirement is another dead-end for overloading Port
with a Node connected child. Too much extra work added on here.
Hmm, let's see ... there was also a failed initial attempt at actually
unserializing a loaded cartridge, but so far that isn't working. That's
a "fun" problem ... the serialized tree that we try and load in will
have the child Cartridge node, whereas the actual root tree will only
have the Port::Cartridge node. I added a virtual overload to grab the
child type, so a Port::Cartridge will attach a Cartridge instead of a
Node, so that's a start ...
What I'll need to do is, when unserializing a document, if the
Markup::Node has a child Cartridge, I'll have to attach it there and
invoke a callback bound in eg the SuperFamicom::Cartridge core, to go
ahead and do the cartridge load after we've populated the
Port::Cartridge properties (which holds where the game is located), and
before returning, so that the parent unserialize function will now see
that our Port::Cartridge node has a child Cartridge node, and begin to
unserialize that in turn.
The Super Famicom core is going to need a reworked bus mapping system:
we can't be calling bus.map and risking bus.read calls during
initialization. It's also a problem if we unload a cart and all of these
bus map entries still exist on the bus for the cartridge. So bus mapping
is going to have to be done at power-on for the entire system, and the
manifest parsing + slot creation stuff will have to happen during
initialization. Fun.
Once all of that is done, I'll then need to hook up input mapping, which
is going to be completely different. Hooray.
... I really didn't anticipate this being so much work. This is really
bad ... I am going to have to start triaging features. I think the goal
is gonna be getting just higan with just the SFC core working on just
GTK with the bare minimum of features. Work on the new GUI will have to
be a weekend thing while my day job comes first.
byuu says:
Things are slowly coming along. I keep making everything more and more
flexible though, not wanting to ever have to do this again, so it's
taking a lot of time to plan everything out.
Node now has subclassing, and can hold shared pointers to itself,
resulting in much more powerful run-time introspection of the tree.
The main window is now the connection manager (which I'm going to rename
the system manager.) The tree is scanned and a viewport is spawned for
each video port the system exposes. So that'll let us support eg
dual-screen Nintendo DS or whatever later. It also kills the
Interface::display(s) function. And by detaching displays from the main
menu and status, we open up a future possibility of spawning a
fullscreen exclusive viewport as a top-level window, without ruby having
to very hackishly attempt to do that per-driver (though it's only going
to be useful for maybe Direct 3D and OpenGL.)
Inputs are going underneath peripherals now. In the Node object system,
this means we can have any kind of values bound to any kind of inputs,
so we aren't limited to just int16 values anymore. Photoresistors,
microphones, etc become possible, presuming the GUI can handle them, of
course.
Properties and Options are going to be folded back into the tree as
well. We can attach options exactly where they're used this way. Slowly
but surely, the Interface specializations for each core are being
reduced in complexity. Lots of hard-coded IDs are going away, too. The
tree is going to assimilate as much as possible.
Nodes do still have IDs for the sole purpose of the connection manager
mapping a tree item back to a Node. But we can probably eliminate this
by writing wrappers to store weak pointers to nodes inside tree item
properties.
byuu says:
Things are further along ... good luck using it in its current state ...
A rather large change was removing Edge as a separate type to Node. Edge
conveys quite useful information (that it's connecting two nodes, and
thus will only have either zero children or one child Node), but forces
us to do twice the work in every tree parsing recursion. I added an edge
flag to Node for now, but it may be nicer to derive Edge from Node.
It's looking like Node unique IDs aren't really useful, when we can just
pass around the Node objects instead. So I will probably start doing
that.
I also added a property system, which was directly inspired from hiro's
property system. Each Node contains a set<Property>, where each Property
holds {string name, value;}. This lets any GUI set any metadata it wants
directly into the tree, so we don't have to keep parallel structures in
the GUI to link the two together.
The tree can be serialized, including its properties now. But it can't
yet be unserialized.
While I *can* allow configuration of the connections from the
configuration window, I'm thinking it's better if we don't allow that.
It might possibly start to end up in a weird state with the SNES hooking
directly into the GB core for SGB support. I won't be entirely opposed
to reverting this change and allowing the connections dialog inside the
configurations window, though.
The main window viewport is back when you start a system, but once again
this release has hard-coded OpenGL 3.2 / OSS / SDL drivers.
I think that I want to build out the tree far more in-depth than before:
a Gamepad should add child Nodes for all of its buttons, and the
connection manager can ignore anything that's marked as permanently
attached as a child so the list doesn't get cluttered.
This whole tree structure is making me rethink a lot of things as well
... why have each class call each subclass when doing things like saving
save RAM to disk, or unloading games, or serializing state, etc? If we
iterate over the tree, we can find everything that needs these things
done and do from the higan::Interface base class instead.
[Since r91 was not posted to the WIP thread, this changelog describes
changes made in that WIP. -Ed.]
[r91 was not posted to the WIP thread, but linked to later without a changelog.
This commit also incorporates some .gitignore files missing previously. -Ed.]
byuu says:
This WIP has another higan GUI rewrite. Since this one is far more
ambitious, it's much less further along.
For the first time in its history, higan won't start at the familiar
black window. Instead, you start at the configuration manager. Here, you
can create a tree of folders and system configurations. There's full
support for creation, renaming, and deleting of both. With lots of
safeguard messages for when things go wrong. Since this is based around
the filesystem, things are sorted alphabetically. The easy solution to
force sorting is to prefix things with numbers.
There's a very raw properties editor for systems in place. This is meant
for extremely advanced users, and it may even make sense to hide this by
default.
Then there's the connections manager. The emulator interface can return
a hierarchy now, which is an Object representing the system. Inside each
object is a list of connectors that are present. A cartridge port,
controller ports, an expansion port, etc. These may or may not be
connected to another Object. When they are, you thus have formed an
infinitely recursive chain, that should be able to do anything other
than literally form a circular dependency.
This model lets us emulate things at a far greater granularity than ever
before: multi-taps can expose four generic controller ports each, which
can have any device you want connected to them. So four mice? Sure, I
don't think the multitap protocol will really work with it, but why not?
The second-player Justifier? You can literally daisy-chain it off the
first Justifier now. Although it will have to be a slightly different
device that won't itself contain its own connector. The Voicer-kun can
let you pick a CD-ROM to use for playback. And so on.
The connections manager marks an ideal place to control user input
mappings. And for good reason: you can have different mappings for each
created device. So instead of just attaching the generic "Gamepad" to
port 1, you could have it generate a folder, assign it a label, and have
your inputs stored there.
When you go to connect an object to a connector, it'll inspect what
you're trying to connect, and adapt it to what it shows you. Cartridges
get you a folder selection dialog. Controllers get you a peripherals
list. And so forth.
Currently, the connection manager doesn't do anything but recursively
show you the tree of objects and their connectors. There's no assignment
support yet.
I need a couple of critical pieces now: since we can't delete Interface
objects and respawn them, emulator-\>initialize() needs to completely
reset the emulated core, detach all of the inputs, reset the system
properties and options, etc.
After that, I'll need a system of serializing and unserializing the
object hierarchy, so that we can save the configuration from the
configuration manager to a "defaults.bml".
Once I have that, then I can implementing launching a system. When this
happens, the connection manager will go away, and the selected
configuration will load on the selected system.
I want to give us lots of cool options, like an "auto power-on system
after launch". Then combine that with a command-line "--configuration
name", and you could create a shortcut that literally starts playing
Zelda: Link's Awakening on the Super Game Boy, with the SGB Commander
connected and configured for your Xbox 360 gamepad. Running with the CRT
Royale shader. In fullscreen mode. Set to close higan when you close the
launched system, rather than return to the configuration manager.
Yeah, the system I built is that flexible: you can have per-game
configurations now.
I need to think through the specifics of where to create these folders.
\~/.local/share/higan is getting kind of old.
The real question will be, where do we import games to? There's pros and
cons of importing them to a generic folder (\~/Emulation/Super Famicom),
as well as to importing them to the Configuration we just made (you
could create categories of games. Your main window can be "RPGs",
"Fighters", etc, that launches you into an emulation core that will only
show you the relevant games.) Probably ... it needs to be a
configuration option on the connector item.
byuu says:
This WIP starts on a new higan GUI, and it's extremely new. To the point
where you have to edit the settings file to assign your own ruby drivers
by name. No input support, only systems configuration. Only the GBA core
just barely compiles with target=higan, and nothing else works.
There's substantial changes to the higan Interface API that is going to
take time to work through.
So, the gist of it is: emulator->load() now basically just initializes
the emulation core and nothing else. After that, the GUI can call
emulator->load(id), where id comes from emulator->slots(). After
calling this and loading a game, you now call emulator->slots() again
to see if the newly loaded game added any new slots. The same,
unfortunately, will have to happen when changing expansion port devices
(MSX tape/floppy drives, and uh ... BS-X Satellaview CompactFlash drives
:P) Basically, the available slots for media change dynamically.
Next up, emulator->regions() is going to replace the per-game folder
load dialog's options list. It's kinda silly for every loaded cart to
ask you what region the system should run in, so instead it appears on
the main load dialog now instead.
Oh, and because I'm using TreeView, this'll only work on Linux/BSD.
Anyway, if you want to torture yourself to be the first to test the new
higan, go for it. Things will probably change a lot still, though.
byuu says:
Couldn't sleep again.
So, this updates all cores to the new options/properties setup, and
connects onModify events to nall/settings.
manifest.bml files are no longer required for .sys folders (I still need
to delete a few of them, I forgot.)
Currently, systems with slightly different properties (WonderSwan EEPROM
sizes, Game Boy boot ROM sizes, ...) require per-system properties()
functions. This in effect exposes a limitation with trying to share the
properties from a single object. What's probably going to be necessary
is to have each Interface class hold a `vector<Settings*>`, and during
construction, add all the members said system needs. The same goes for
options (Master System has controller ports whereas Game Gear does not.)
This also means that we can't pre-declare the default values for all
systems. We'll have to declare defaults inside each Interface instance.
So in light of all of this, I'm probably going to reshape Settings to be
a single-level class holding a ton of `Settings*` objects, and the
serialization functionality will just have to build the tree from a flat
list somehow. I could probably rely on Markup::Node itself to do this
for me.
Oh, nall/primitives gained explicit specializations for converting from
a `const char*` (the string class isn't defined at this point,
regrettably.) So with that, you can make a `Setting<T>` out of any `T` that
can be explicitly constructed from a `const char*`. I want to do the same
for the string class, and allow explicit casting to the nall/primitives
types, as the toInteger(), etc classes are a little wonky to use.
byuu says:
These WIPs are gonna be unstable for a bit, sorry. Large amounts of
changes. Right now, higan+bsnes compile, but only with cores="sfc gb".
There's a new nall::Settings class, which I really dislike the design
of, but as long as the classes that use it remain stable, then ... I'll
have to live with it for now.
Interface loses both the old get/set/cap interface, plus the
configuration interface. It now returns either properties() or
options(). Both return a Settings& object. There's also helpers for
accessing individual properties and options by string lookup.
Properties are immutable traits of the hardware itself: CPU version, PPU
VRAM size, boot ROM information, etc.
Options are mutable traits that users may change.
The idea with nall/settings is to build out a kind of extremely complex
configuration object that'll do everything we'd ever want:
- allow recursive children settings similar to Markup::Node
- access values directly without dynamic_cast (type erasure) or
string conversion (Markup::Node style)
- serialize to and unserialize from BML
- support valid values to guarantee that the settings are never in an
invalid state
- support latching of values to cache reads without another separate
variable (so the GUI can modify any variables at any time safely)
Todo:
- allow binding callback functions on assignment, so that eg changing
video/colorEmulation will regenerate the video palette
- provide a hint on whether an option can be changed dynamically at
run-time, or only statically at first load
- provide descriptions for each setting
And then once the class is fully fleshed out, I want to build a tool
that will generate a fancy modal hiro Window from a Settings& object.
Once that is complete, we'll then have System → Options to configure
per-emulator settings (like bsnes PPU stuff) that otherwise doesn't fit
into higan's GUI. We will be exposing the extended Super Famicom options
to the bsnes GUI, of course. That's the emulator tab there.
Next up, higan's systems tab will need to generate blank default
property files for each system, and let you configure system properties
from this screen. That's going to mean that, by allowing the same system
to appear multiple times, that each entry gets its own options file,
which will have to be stored somewhere.
And to do all of that, we really need to work out how to handle regions
first. It may have to be something radical like FitzRoy's idea, or it
may be that we can come up with something a little less drastic. But I
have no idea right now ...
What I'd really like to do is start trying to get bsnes v107 out
already. The two things holding it up are: fixing the desync between the
settings.bml GUI settings and options.bml SNES properties (I know what's
wrong, I just have to fix it), and getting XAudio2 DRC working (I copied
BearOso's implementation details, but it just doesn't work for me ...).
Then I also have to install Windows, set up a dev environment with
msys2, and build it all.
Lots and lots of work ...
byuu says:
In addition to the restructuring changes mentioned previously, I've
started on yet another attempt at unifying per-emulator core
configuration settings.
This time, everything is based on template<typename T> struct Setting;
which has child elements similar to Markup::Node, but holds the exact
type rather than a string that needs to be converted. If we had a
setting checked millions of times a second in the core (say, a mute flag
for a 2MHz audio chip), it would be too much overhead. I don't even want
it to be a heap-allocated pointer that has to be dynamic_casted
(nall::any), so it ends up more like an std::variadic object.
Setting classes construct the same way hiro does: the children specify
their parents in the variable declarations. From there, you can
serialize (and soon, unserialize) to (and from) BML.
Presently, I'm thinking we are going to want two separate settings
structures: one for fixed system properties (CPU version, PPU1 VRAM
amount, etc) -- basically, variables that describe a certain machine
configuration. And another for user-configurable properties (interframe
blending, color bleed, scanlines, speed hacks, etc.)
The reasoning is for higan: under the systems tab, when you pick a
system to add, it would be nice to display the system configuration
there. Polluting that with options you'd likely change at run-time would
be confusing and annoying.
I'm also hoping to write a rather complex class that will generate a
dialog window for editing all of the settings found. We could *really*
use TreeView on all platforms for this, heh ... I may have to go attempt
to merge hex_usr's previous work there.
In the future, I'd like to flesh out the settings even more with
optional additional things like lists of possible values, that can then
result in drop-downs in the generated dialogs.
The real question is ... is it time to use the new machine properties to
separate NTSC, PAL, etc regions? There's gonna be cases like the Mark
III having the YM2413 module, but only in Japan. The load dialog option
dropdown was always kind of a hacky way of doing regions.
...
Oh, I also wrote nall/instance.hpp, which is a grotesque delayed
construction hack. The amethyst hiro bug was kind of the last straw in
attempting to tame global construction order. I'm going to slowly kill
off hiro::initialize and revert back to requiring hiro objects to be
constructed -after- main().
byuu says:
The bad instruction was due to the instruction before it fetching one
too many bytes. Didn't notice right away as the disassembler got it
right.
The register map was incorrect on the active 16-bit flags.
I fixed and improved some other things along those lines. Hooked up some
basic KnGE (VPU) timings, made it print out VRAM and some of the WRAM
onto the screen each frame, tried to drive Vblank and Hblank IRQs, but
... I don't know for sure what vector addresses they belong to.
MAME says "INT4" for Vblank, and says nothing for Hblank. I am wildly
guessing INT4==SWI 4==0xffff10, but ... I have no idea. I'm also not
emulating the interrupts properly based on line levels, I'm just firing
on the 0→1 transitions. Sounds like Vblank is more nuanced too, but I
guess we'll see.
Emulation is running further along now, even to the point of it
successfully enabling the KnGE IRQs, but VRAM doesn't appear to get much
useful stuff written into it yet.
I reverted the nall/primitive changes, so request for testing is I guess
rescinded, for whatever it was worth.
byuu says:
Changelog:
- fixed a few TLCS900H CPU and disassembler bugs
- hooked up a basic Neo Geo Pocket emulator skeleton and memory map;
can run a few instructions from the BIOS
- emulated the flash memory used by Neo Geo Pocket games
- added sourcery to the higan source archives
- fixed ternary expressions in sfc/ppu-fast [hex_usr]
byuu says:
Changelog:
- reverted nall/inline-if.hpp usage for now, since the
nall/primitives.hpp math operators still cast to (u)int64_t
- improved nall/primitives.hpp more; integer8 x = -128; print(-x) will
now print 128 (unary operator+ and - cast to (u)int64_t)
- renamed processor/lr35902 to processor/sm83; after the Sharp SM83
CPU core [gekkio discovered the name]
- a few bugfixes to the TLCS900H CPU core
- completed the disassembler for the TLCS900H core
As a result of reverting most of the inline if stuff, I guess the
testing priority has been reduced. Which is probably a good thing,
considering I seem to have a smaller pool of testers these days.
Indeed, the TLCS900H core has ended up at 131KiB compared to the M68000
core at 128KiB. So it's now the largest CPU core in all of higan. It's
even more ridiculous because the M68000 core would ordinarily be quite a
bit smaller, had I not gone overboard with the extreme templating to
reduce instruction decoding overhead (you kind of have to do this for
RISC CPUs, and the inverted design of the TLCS900H kind of makes it
infeasible to do the same there.)
This CPU core is bound to have dozens of extremely difficult CPU bugs,
and there's no easy way for me to test them. I would greatly appreciate
any help in looking over the core for bugs. A fresh pair of eyes to spot
a mistake could save me up to several days of tedious debugging work.
The core still isn't ready to actually be tested: I have to hook up
cartridge loading, a memory bus, interrupts, timers, and the micro DMA
controller before it's likely that anything happens at all.
byuu says:
Half of the disassembler is implemented now. Well, the decoding half
anyway. I'm splitting the decoding and string building into separate
components this time around, on account of the instruction encoding
being in reverse order. The string building portion hasn't been written
yet, either.
We're up to 112KiB now, compared to 128KiB for the 68K.
byuu says:
First 32 instructions implemented in the TLCS900H disassembler. Only 992
to go!
I removed the use of anonymous namespaces in nall. It was something I
rarely used, because it rarely did what I wanted.
I updated all nested namespaces to use C++17-style namespace Foo::Bar {}
syntax instead of classic C++-style namespace Foo { namespace Bar {}}.
I updated ruby::Video::acquire() to return a struct, so we can use C++17
structured bindings. Long term, I want to get away from all functions
that take references for output only. Even though C++ botched structured
bindings by not allowing you to bind to existing variables, it's even
worse to have function calls that take arguments by reference and then
write to them. From the caller side, you can't tell the value is being
written, nor that the value passed in doesn't matter, which is terrible.
byuu says:
Any usage of natural and integer cast to 64-bit math operations now.
Hopefully this will be the last of the major changes for a bit on
nall/primitives, at least until serious work begins on removing implicit
conversion to primitive types.
I also completed the initial TLCS900H core, sans SWI (kind of a ways off
from support interrupts.) I really shouldn't say completed, though. The
micro DMA unit is missing, interrupt priority handling is missing,
there's no debugger, and, of course, there's surely dozens of absolutely
critical CPU bugs that are going to be an absolute hellscape nightmare
to track down.
It was a damn shame, right up until the very last eight instructions,
[CP|LD][I|D](R), the instruction encoding was consistent. Of course,
there could be other inconsistencies that I missed. In fact, that's
somewhat likely ... sigh.
byuu says:
This WIP is just work on nall/primitives ...
Basically, I'm coming to the conclusion that it's just not practical to
try and make Natural/Integer implicitly castable to primitive signed and
unsigned integers. C++ just has too many edge cases there.
I also want to get away from the problem of C++ deciding that all math
operations return 32-bit values, unless one of the parameters is 64-bit,
in which case you get a 64-bit value. You know, so things like
array[-1] won't end up accessing the 4 billionth element of the array.
It's nice to be fancy and minimally size operations (eg 32-bit+32-bit =
33-bit), but it's just too unintuitive. I think all
Natural<X>+Natural<Y> expessions should result in a Natural<64> (eg
natural) type.
nall/primitives/operators.hpp has been removed, and new
Natural<>Natural / Integer<>Integer casts exist. My feeling is that
signed and unsigned types should not be implicitly convertible where
data loss can occur. In the future, I think an integer8*natural8 is
fine to return an integer64, and the bitwise operators are probably all
fine between the two types. I could probably add
(Integer,Natural)+Boolean conversions as well.
To simplify expressions, there are new user-defined literals for _b
(boolean), _n (natural), _i (integer), _r (real), _n# (eg _n8),
_i# (eg _i8), _r# (eg _r32), and _s (nall::string).
In the long-term, my intention is to make the conversion and cast
constructors explicit for primitive types, but obviously that'll shatter
most of higan, so for now that won't be the case.
Something I can do in the future is allow implicit conversion and
casting to (u)int64_t. That may be a nice balance.
byuu says:
I've implemented a lot more TLCS900H instructions. There are currently
20 missing spots, all of which are unique instructions (well, MINC and
MDEC could be considered pairs of 3 each), from a map of 1024 slots.
After that, I have to write the disassembler. Then the memory bus. Then
I get to start the fun process of debugging this monstrosity.
Also new is nall/inline-if.hpp. Note that this file is technically a war
crime, so be careful when opening it. This replaces ternary() from the
previous WIP.
byuu says:
So this turned out to be a rather unproductive ten-hour rabbit hole, but
...
I reworked nall/primitives.hpp a lot. And because the changes are
massive, testing of this WIP for regressions is critically important. I
really can't stress that enough, we're almost certainly going to have
some hidden regressions here ...
We now have a nall/primitives/ subfolder that splits up the classes into
manageable components. The bit-field support is now shared between both
Natural and Integer. All of the assignment operator overloads are now
templated and take references instead of values. Things like the
GSU::Register class are non-copyable on account of the function<>
object inside of it, and previously only operator= would work with
classes like that.
The big change is nall/primitives/operators.hpp, which is a really
elaborate system to compute the minimum number of bits needed for any
operation, and to return a Natural<T> or Integer<T> when one or both of
the arguments are such a type.
Unfortunately, it doesn't really work yet ... Kirby's Dream Land 3
breaks if we include operators.hpp. Zelda 3 runs fine with this, but I
had to make a huge amount of core changes, including introducing a new
ternary(bool, lhs, rhs) function to nall/algorithm to get past
Natural<X> and Natural<Y> not being equivalent (is_integral types get a
special exemption to ternary ?: type equivalence, yet it's impossible to
simulate with our own classes, which is bullshit.) The horrifying part
is that ternary() will evaluate both lhs and rhs, unlike ?:
I converted some of the functions to test ? uint(x) : uint(y), and
others to ternary(test, x, y) ... I don't have a strong preference
either way yet.
But the part where things may have gotten broken is in the changes to
where ternary() was placed. Some cases like in the GBA PPU renderer, it
was rather unclear the order of evaluations, so I may have made a
mistake somewhere.
So again, please please test this if you can. Or even better, look over
the diff.
Longer-term, I'd really like the enable nall/primitives/operators.hpp,
but right now I'm not sure why Kirby's Dream Land 3 is breaking. Help
would be appreciated, but ... it's gonna be really complex and difficult
to debug, so I'm probably gonna be on my own here ... sigh.
byuu says:
I added some useful new functions to nall/primitives:
auto Natural<T>::integer() const -> Integer<T>;
auto Integer<T>::natural() const -> Natural<T>;
These let you cast between signed and unsigned representation without
having to care about the value of T (eg if you take a Natural<T> as a
template parameter.) So for instance when you're given an unsigned type
but it's supposed to be a sign-extended type (example: signed
multiplication), eg Natural<T> → Integer<T>, you can just say:
x = y.integer() * z.integer();
The TLCS900H core gained some more pesky instructions such as DAA, BS1F,
BS1B.
I stole an optimization from RACE for calculating the overflow flag on
addition. Assuming: z = x + y + c;
Before: ~(x ^ y) & (x ^ z) & signBit;
After: (x ^ z) & (y ^ z) & signBit;
Subtraction stays the same. Assuming: z = x - y - c;
Same: (x ^ y) & (x ^ z) & signBit;
However, taking a speed penalty, I've implemented the carry computation
in a way that doesn't require an extra bit.
Adding before:
uint9 z = x + y + c;
c = z & 0x100;
Subtracting before:
uint9 z = x - y - c;
c = z & 0x100;
Adding after:
uint8 z = x + y + c;
c = z < x || z == x && c;
Subtracting after:
uint8 z = x - y - c;
c = z > x || z == x && c;
I haven't been able to code golf the new carry computation to be any
shorter, unless I include an extra bit, eg for adding:
c = z < x + c;
But that defeats the entire point of the change. I want the computation
to work even when T is uintmax_t.
If anyone can come up with a faster method, please let me know.
Anyway ... I also had to split off INC and DEC because they compute
flags differently (word and long modes don't set flags at all, byte mode
doesn't set carry at all.)
I also added division by zero support, although I don't know if it's
actually hardware accurate. It's what other emulators do, though.
byuu says:
So tired ... so much left to do still ... sigh.
If someone's up for some code golf, open to suggestions on how to handle
the INTNEST control register. It's the only pure 16-bit register on the
system, and it breaks my `map`/`load`/`store<uint8,16,32>` abstraction.
Basically what I suspect happens is when you access INTNEST in 32-bit
mode, the upper 16-bits are just undefined (probably zero.) But
`map<uint32>(INTNEST)` must return a uint32& or nothing at all. So for the
time being, I'm just making store(ControlRegister) check if it's the
INTNEST ID, and clearing the upper bits of the written byte in that
case. It's hacky, but ... it's the best I can think of.
I added LDX, which is a 900H-only instruction, and the control register
map is for the 900/H CPU. I found the detailed differences between the
CPUs, and it doesn't look likely that I'm gonna support the 900 or
900/H1 at all. Not that there was a reason to anyway, but it's nice to
support more stuff when possible. Oh well.
The 4-byte instruction fetch queue is going to have to get implemented
inside fetch, or just not implemented at all ... not like I'd be able to
figure out the details of it anyway.
The manual isn't clear on how the MULA flags are calculated, but since
MUL doesn't set any flags, I assume the flags are based on the addition
after the multiplication, eg:
uint32 a = indirect<int16>(XDE) * indirect<int16>(XHL);
uint32 b = reg16; //opcode parameter
uint32 c = a + b; //flags set based on a+b
No idea if it's right or not. It doesn't set carry or half-carry, so
it's not just simply the same as calling algorithmAdd.
Up to almost 70KB, not even halfway done, don't even have a disassembler
started yet. There's a real chance this could overtake the 68K for the
biggest CPU core in higan, although at this point I'm still thinking the
68K will end up larger.
byuu says:
So I spent the better part of eight hours refactoring the TLCS900H core
to be more flexible in light of new edge cases.
I'm now including the size information inside of the types (eg
Register<Byte>, Memory<Word>) rather than as parameters to the
instruction handlers. This allows me to eg implement RETI without
needing template arguments in all the instructions. pop(SR), pop(PC) can
deduce how much to pop off of the stack. It's still highly templated,
but not unrolling the 3-bit register indexes and instead going through
the switch table to access registers is going to hurt the performance a
good deal.
A benefit of this is that Register{A} != Register{WA} != Register{XWA}
anymore, despite them sharing IDs.
I also renamed read/write to load/store for the CPU core, because
implicit conversions are nasty. They all call the virtual read/write.
I added more instructions, improved the memory addressing mode support,
and some other things.
I got rid of Byte, Word, Long because there's too many alternate sizes
needed: int8, int16, uint24, etc.
Ran into a really annoying C++ case ...
struct TLCS900H {
template<typename T> auto store(Register<T> target, T source) -> void;
};
If you call store(Register<uint32>(x), uint16(y)); it errors out since
the T types don't match. But you can't specialize it:
template<typename T, typename U> auto store(Register<T>, U) -> void;
template<typename U> auto TLCS900H::store<uint32, U>(Register<uint32>, U) -> void;
Because somehow it's 2019 and we still can't do partial template
specialization inside classes ...
So as a result, I had to make T source be type uint32 even for
Register<uint8> and Register<uint16>. Doesn't matter too much, just
annoying.
byuu says:
This probably won't fix the use of register yet (I imagine ruby and hiro
will complain now), but ... oh well, it's a start. We'll get it
compiling again eventually.
I added JP, JR, JRL, LD instructions this time around. I'm also starting
to feel that Byte, Word, Long labels for the TLCS900H aren't really
working. There's cases of needing uint24, int8, int16, ... it may just
be better to name the types instead of trying to be fancy.
At this point, all of the easy instructions are in. Now it's down to a
whole lot of very awkward bit-manipulation and special-use instructions.
Sigh.
byuu says:
For this WIP, I added more TLCS900H instructions. All of the
ADC,ADD,SBB/SBC,SUB,AND,OR,XOR.CP,PUSH,POP instructions are in.
Still an incredible amount of work left to do on this core ... it has all kinds
of novel instructions that aren't on any other processors.
Still no disassembler support yet, so I can't even test what I'm doing. Fun!
byuu says:
I started working on the Toshiba TLCS900H CPU core today.
It's basically, "what if we took the Z80, added in 32-bit support, added
in SPARC register windows, added a ton of additional addressing modes,
added control registers, and added a bunch of additional instructions?"
-- or in other words, it's basically hell for me.
It took several hours just to wrap my head around the way the opcode
decoder needed to function, but I think I have a decent strategy for
implementing it now.
I should have all of the first-byte register/memory address decoding in
place, although I'm sure there's lots of bugs. I don't have anything in
the way of a disassembler yet.
byuu says:
Changelog:
- Interface::displays() -> vector<Display> → Interface::display() -> Display
- <Platform::videoRefresh(display>, ...) → <Platform::videoFrame>(...)
- <Platform::audioSample>(...) → <Platform::audioFrame>(...)
- higan, icarus: use AboutDialog class instead of ad-hoc
implementations
- about dialog is now modal, but now has a clickable website URL
- icarus: reverted if constexpr for now
- MSX: implemented basic CPU, VDP support
I took out the multiple displays support thing because it was never
really implemented fully (Emulator::Video and the GUIs both ignored it)
or used anyway. If it ends up necessary in the future, I'll worry about
it then.
There's enough MSX emulation now to run Mr. Do! without sound or input.
I'm shipping higan with C-BIOS 0.29a, although it likely won't be good
enough in the future (eg it can't do BASIC, floppy disk, or cassette
loading.) I have keyboard and (not working) AY-3-8910 support in a
different branch, so that won't take too long to implement. Main problem
is naming all the darned keyboard keys. I think I need to change
settings.bml's input mapping lines so that the key names are values
instead of node names, so that any characters can appear inside of them.
It turns out my MSX set uses .rom for the file extensions ... gods. So,
icarus can't really import them like this. I may have to re-design
icarus' importer to stop caring about the file extension and instead ask
you what kind of games you are importing. There's no way icarus can
heuristically guess what systems the images belong to, because many
systems don't have any standardized magic bytes.
I'm struggling with where to put SG-1000, SC-3000, ColecoVision, Coleco
Adam stuff. I think they need to be split to two separate higan
subfolders (sg and cv, most likely ...) The MS/GG share a very
customized and extended VDP that the other systems don't have. The Sega
and Coleco older hardware share the same TMS9918 as the MSX, yet have
very different memory maps and peripherals that I don't want to mix
together. Especially if we start getting into the computer-variants
more.
Debian has served us well, but byuu would like to start using C++17 features
which generally requires GCC7. Debian Stable only has GCC6 right now, while
Ubuntu LTS has the required version, so that should get things going again.
byuu says:
The biggest change was improving WonderSwan emulation. With help from
trap15, I tracked down a bug where I was checking the wrong bit for
reverse DMA transfers. Then I also emulated VTOTAL to support variable
refresh rate. Then I improved HyperVoice emulation which should be
unsigned samples in three of four modes. That got Fire Lancer running
great. I also rewrote the disassembler. The old one disassembled many
instructions completely wrong, and deviated too much from any known x86
syntax. I also emulated some of the quirks of the V30 (two-byte POP into
registers fails, SALC is just XLAT mirrored, etc) which probably don't
matter unless someone tries to run code to verify it's a NEC CPU and not
an Intel CPU, but hey, why not?
I also put more work into the MSX skeleton, but it's still just a
skeleton with no real emulation yet.
byuu says:
Changelog:
- nall: converted range, iterator, vector to 64-bit
- added (very poor) ColecoVision emulation (including Coleco Adam
expansion)
- added MSX skeleton
- added Neo Geo Pocket skeleton
- moved audio,video,resource folders into emulator folder
- SFC heuristics: BS-X Town cart is "ZBSJ" [hex_usr]
The nall change is for future work on things like BPA: I need to be able
to handle files larger than 4GB. It is extremely possible that there are
still some truncations to 32-bit lurking around, and even more
disastrously, possibly some -1s lurking that won't sign-extend to
`(uint64_t)0-1`. There's a lot more classes left to do: `string`,
`array_view`, `array_span`, etc.
byuu says:
Changelog:
- added all pre-requisite to make install rule (note: only for higan,
icarus so far)
- added SG-1000 emulation
- added SC-3000 emulation (no keyboard support yet)
- added MS graphics mode 1 emulation (SC-1000)
- added MS graphics mode 2 emulation (F-16 Fighter)
- improve Audio::process() to prevent a possible hang
- higan: repeat monaural audio to both left+right speakers
- icarus: add heuristics for importing MSX games (not emulated in
higan yet in this WIP)
- added DC bias removal filter [jsd1982]
- improved Audio::Stream::reset() [jsd1982]
I was under the impression that the 20hz highpass filter would have
removed DC bias ... if not, then I don't know why I added that filter to
all of the emulation cores that have it. In any case, if anyone is up
for helping me out ... if we could analyze the output with and without
the DC bias filter to see if it's actually helping, then I'll enable it
if it is. To enable it, edit
higan/audio/stream.cpp::addDCRemovalFilter() and remove the return
statement at the top of the function.
At some point, higan moved system metadata from higan/profile to higan/systems.
Also, higan's Super Famicom core added config options of its own, which it now
writes out.
byuu says:
Changelog:
- moved to GCC 8.2 and C++17
- fixed compilation under FreeBSD 12.0
- don't read beyond the file size in
SuperFamicom::Cartridge::loadMemory
- add missing I/O cycle HuC6280::instructionImmediate
- serialize Mega Drive's Game Genie state
- serialize SPC7110::Thread information
- enable 30-bit color depth support under the GLX/OpenGL 2.0 driver
(doesn't work with OpenGL 3.2 yet)
The 30-bit color depth option isn't super useful, but why not? I need to
update ruby to detect that the display is actually capable of it before
exposing an option that can result in the driver failing to initialize,
however.
Changes include:
- The "Library" menu was replaced with the "Systems" menu
- The "Settings" menu was reorganised
- Game Boy rumble is now under the MBC5 "controller" for the cartridge "port",
instead of being presented as a part of the base console
- Import instructions now mention that icarus ships with some firmware files,
and describe the "Firmware" directory that icarus will use for firmware
it needs.
- Apparently the correct name is "MSU1", not "MSU-1"
- v107 changes the way MSU1 data is stored in game folders
- PowerFest '94 import instructions removed, since I can't get it to work
with v107
- Links to the official forum have been replaced with links to the unofficial
forum archive, since the official forum is shutting down
- Links to Mercurial Magic updated to point at qwertymodo's archive, since
hex_usr is no longer developing it
- Links to nSide updated, since hex_usr no longer uses GitHub.
- Windows build instructions now describe a compiler that is actually
maintained, instead of stale TDM64-GCC.
- Linux build instructions now mention higan requires SDL 2.0.
- minor wording changes, typos, broken links fixed, etc.
The latest WIP renames icarus/database and icarus/firmware to
icarus/Database and icarus/Firmware (in title case).
Also, somewhere along the line we stopped building icarus for higan/Linux,
which seems an oversight.
byuu says:
This synchronizes bsnes/higan with many recent internal nall changes.
This will be the last WIP until I am situated in Japan. Apologies for the
bugfixes that didn't get applied yet, I ran out of time.
byuu says:
Changelog:
- sfc: completed BS Memory Cassette emulation (sans bugs, of course --
testing appreciated)
- bsnes: don't strip - on MSU1 track names in game ROM mode
[hex_usr]
I'm going with "metadata.bml" for the flash metadata filename for the
time being, but I'll say that it's subject to change. I'll have to make
a new extension for it to be supported with bsnes.
byuu says:
Changelog:
- gb/mbc7: rewrote the 93LCx6 EEPROM emulation
- sfc/slot/bsmemory: rewrote the flash emulation for Satellaview
cartridges
As of this release, flash-based BS Memory cartridges will be writable.
So without the bsnes patch to disable write limits, some games will lock
out after a few plays.
byuu says:
Changelog:
- sfc/cx4: added missing instructions [info from Overload]
- sfc/cx4: added instruction cache emulation [info from ikari]
- sfc/sa1: don't let CPU access SA1-only I/O registers, and vice versa
- sfc/sa1: fixed IRQs that were broken from the recent WIP
- sfc/sa1: significantly improved bus conflict emulation
- all tests match hardware now, other than HDMA ROM↔ROM, which
is 0.5 - 0.8% too fast
- sfc/cpu: fixed a bug with DMA→CPU alignment timing
- sfc/cpu: removed the DMA pipe; performs writes on the same cycles as
reads [info from nocash]
- sfc/memory: fix a crashing bug due to not clearing Memory size field
[hex_usr]
- bsnes/gb: use .rtc for real-time clock file extensions on the Game
Boy [hex_usr]
- ruby/cgl: compilation fix [Sintendo]
Now let's see if I can accept being off by ~0.65% on one of twelve SA1
timing tests for the time being and prioritize much more important
things or not.
byuu says:
This release adds ikari's Cx4 notes to bsnes. It fixes the MMX2 intro's
boss fight sequence to be frame perfect to real hardware. It's also very
slightly faster than before.
I've also added an option to toggle the CPU↔coprocessor cycle
synchronization to the emulation settings panel, so you don't have to
recompile to get the more accurate SA1 timings. I'm most likely going to
default this to disabled in bsnes, and *maybe* enabled in higan out of
the box.
StaticRAM (wasn't used) and MappedRAM are gone from the Super Famicom
core. Instead, there's now ReadableMemory, WritableMemory, and
ProtectedMemory (WritableMemory with a toggle for write protection.)
Cartridge::loadMap now takes a template Memory object, which bypasses an
extra virtual function call on memory accesses, but it doesn't really
impact speed much. Whatever.
byuu says:
I added (imperfect) memory conflict timing to the SA1.
Before:
- WRAM↔↔ROM ran 7% too fast
- ROM↔↔ROM ran 100% too fast
- WRAM↔↔IRAM ran 7% too fast
- ROM↔↔IRAM ran 7% too fast
- IRAM↔↔IRAM ran 287% too fast
- BWRAM↔↔BWRAM ran 100% too fast
- HDMA ROM↔↔ROM ran 15% too fast
- HDMA WRAM↔↔ROM ran 15% too fast
- DMA ROM↔↔ROM ran 100% too fast
After:
- ROM↔↔ROM runs 14% too fast
- HDMA WRAM↔↔ROM runs 7% too fast
- DMA ROM↔↔ROM runs 4% too fast
If you enable this with the fast PPU + DSP, your framerate in SA1 games
will drop by 51%. And even if you disable it, you'll still lose 9% speed
in SA1 games, and 2% speed in non-SA1 games, because of changes needed
to make this support possible.
By default, I'm leaving this off. Compile with `-DACCURATE_SA1` (or
uncomment the line in sfc/sfc.hpp) if you want to try it out.
This'll almost certainly cause some SA1 regressions, so I guess we'll
tackle those as they arise.
byuu says:
Changelog:
- fixed bug in Emulator::Game::Memory::operator bool()
- nall: renamed view<string> back to `string_view`
- nall:: implemented `array_view`
- Game Boy: split cartridge-specific input mappings (rumble,
accelerometer) to their own separate ports
- Game Boy: fixed MBC7 accelerometer x-axis
- icarus: Game Boy, Super Famicom, Mega Drive cores output internal
header game titles to heuristics manifests
- higan, icarus, hiro/gtk: improve viewport geometry configuration;
fixed higan crashing bug with XShm driver
- higan: connect Video::poll(),update() functionality
- hiro, ruby: several compilation / bugfixes, should get the macOS
port compiling again, hopefully [Sintendo]
- ruby/video/xshm: fix crashing bug on window resize
- a bit hacky; it's throwing BadAccess Xlib warnings, but they're
not fatal, so I am catching and ignoring them
- bsnes: removed Application::Windows::onModalChange hook that's no
longer needed [Screwtape]
byuu says:
The main thing I worked on today was emulating the MBC7 EEPROM.
And... I have many things to say about that, but not here, and not now...
The missing EEPROM support is why the accelerometer was broken. Although
it's not evidently clear that I'm emulating the actual values
incorrectly. I'll think about it and get it fixed, though.
bsnes went from ~308fps to ~328fps, and I don't even know why. Probably
something somewhere in the 140KB of changes to other things made in this
WIP.
byuu says:
The Windows port can now run the emulation while navigating menus,
moving windows, and resizing windows. The main window also doesn't try
so hard to constantly clear itself. This may leave a bit of unwelcome
residue behind in some video drivers during resize, but under most
drivers, it lets you resize without a huge amount of flickering.
On all platforms, I now also run the emulation during MessageWindow
modal events, where I didn't before.
I'm thinking we should probably mute the audio during modal periods,
since it can generate a good deal of distortion.
The tooltip timeout was increased to ten seconds.
On Windows, the enter key can now activate buttons, so you can more
quickly dismiss MessageDialog windows. This part may not actually work
... I'm in the middle of trying to get messages out of the global
`Application_windowProc` hook and into the individual `Widget_windowProc`
hooks, so I need to do some testing.
I fixed a bug where changing the input driver wouldn't immediately
reload the input/hotkey settings lists properly.
I also went from disabling the driver "Change" button when the currently
active driver is selected in the list, to instead setting it to say
"Reload", and I also added a tool tip to the input driver reload button,
advising that if you're using DirectInput or SDL, you can hit "Reload"
to rescan for hotplugged gamepads without needing to restart the
emulator. XInput and udev have auto hotswap support. If we can ever get
that into DirectInput and SDL, then I'll remove the tooltip. But
regardless, the reload functionality is nice to have for all drivers.
I'm not sure what should happen when a user changes their driver
selection while a game is loaded, gets the warning dialog, chooses not
to change it, and then closes the emulator. Currently, it will make the
change happen the next time you start the emulator. This feels a bit
unexpected, but when you change the selection without a game loaded, it
takes immediate effect. So I'm not really sure what's best here.
byuu says:
This release fixes the XAudio 2.1 and WASAPI drivers on Windows, and
extends XAudio to support device selection (eg headphones, speakers,
monitor, etc.) It also adds DRC to XAudio, however it's not currently
working.
The code is courtesy of Talarubi, I just botched it somewhere upon
porting it to the newer version of ruby.
byuu says:
I've added tool tips to hiro for Windows, GTK, and Qt. I'm unsure how to
add them for Cocoa. I wasted am embarrassing ~14 hours implementing tool
tips from scratch on Windows, because the `TOOLTIPS_CLASS` widget just
absolutely refused to show up, no matter what I tried. As such, they're
not quite 100% native, but I would really appreciate any patch
submissions to help improve my implementation.
I added tool tips to all of the confusing settings in bsnes. And of
course, for those of you who don't like them, there's a configuration
file setting to turn them off globally.
I also improved Mega Drive handling of the Game Genie a bit, and
restructured the way the Settings class works in bsnes.
Starting now, I'm feature-freezing bsnes and higan. From this point
forward:
- polishing up and fixing bugs caused by the ruby/hiro changes
- adding DRC to XAudio2, and maybe exclusive mode to WGL
- correcting FEoEZ (English) to load and work again out of the box
Once that's done, a final beta of bsnes will go out, I'll fix any
reported bugs that I'm able to, and then v107 should be ready. This time
with higan being functional, but marked as v107 beta. v108 will restore
higan to production status again, alongside bsnes.
byuu says:
I fixed all outstanding bugs that I'm aware of, including all of the
errata I listed yesterday.
And now it's time for lots of regression testing.
After that, I need to add Talarubi's XAudio2 DRC code, and then get a
new public bsnes WIP out for final testing.
New errata: when setting an icon (nall::image) larger than a Canvas on
Windows, it's not centering the image, so you end up seeing the overscan
area in the state manager previews, and the bottom of the image gets cut
off. I also need to forcefully disable the Xlib screensaver disable
support. I think I'll remove the GUI option to bypass it as well, and
just force screensaver disable always on with Windows. I'll improve it
in the future to toggle the effect between emulator pauses.
byuu says:
Everything *should* be working again, but of course that won't
actually be the case. Here's where things stand:
- bsnes, higan, icarus, and genius compile and run fine on FreeBSD
with GTK
- ruby video and audio drivers are untested on Windows, macOS, and
Linux
- hiro is untested on macOS
- bsnes' status bar is not showing up properly with hiro/qt
- bsnes and higan's about screen is not showing up properly with
hiro/qt (1x1 window size)
- bsnes on Windows crashes often when saving states, and I'm not sure
why ... it happens inside Encode::RLE
- bsnes on Windows crashes with ruby.input.windows (unsure why)
- bsnes on Windows fails to show the verified emblem on the status bar
properly
- hiro on Windows flickers when changing tabs
To build the Windows bsnes and higan ports, use
ruby="video.gdi audio.directsound"
Compilation error logs for Linux will help me fix the inevitable list of
typos there. I can fix the typos on other platforms, I just haven't
gotten to it yet.
The WonderSwan Color came out in 2000 and the GBA in 2001, so technically
they're not "video-game consoles of the 1980s and 1990s". Since there's no
elegant way to talk about the 2000-2009 timespan, let's just not mention
dates at all.
byuu says:
Changes to hiro will break all but the GTK target. Not that it matters
much given that the only ruby drivers that function are all on BSD
anyway.
But if you are fortunate enough to be able to run this ... you'll find
lots of polishing improvements to the bsnes GUI. I posted some
screenshots on Twitter, if anyone were interested.
byuu says:
Okay, so the WIPs-within-WIPs thing wasn't achieving its desired effect,
and it ended up causing me to have to redo some work on hiro since my
last local snapshot was of r52. So, heck it. I'll just do mostly
non-functional WIPs for a bit, and worry about the fallout years later
when I'm trying to find an emulation regression and cursing that the
WIPs aren't compiling.
I ported all of the ruby input drivers to the new syntax, as well as the
OpenAL driver. If you patch the ruby drivers for Linux with this in
mind, bsnes should compile and run there again.
Also, the bsnes program icon has returned, now that the new hiro layout
code is mature enough and I can simply add and remove the icon as a
Canvas instead of having to try and render into a viewport. The icon
shows up instantly with the main window.
byuu says:
I've completed moving all the class objects from `unique_pointer<T>` to
just T. The one exception is the Emulator::Interface instance. I can
absolutely make that a global object, but only in bsnes where there's
just the one emulation core.
I also moved all the SettingsWindow and ToolsWindow panels out to their
own global objects, and fixed a very difficult bug with GTK TabFrame
controls.
The configuration settings panel is now the emulator settings panel. And
I added some spacing between bold label sections on both the emulator
and driver settings panels.
I gave fixing ComboButtonItem my best shot, given I can't reproduce the
crash. Probably won't work, though.
Also made a very slight consistency improvement to ruby and renamed
driverName() to driver().
...
An important change ... as a result of moving bsnes to global objects,
this means that the constructors for all windows run before the
presentation window is displayed. Before this change, only the
presentation window was constructed first berore displaying it, followed
by the construction of the rest of the GUI windows.
The upside to this is that as soon as you see the main window, the GUI
is ready to go without a period where it's unresponsive.
The downside to this is it takes about 1.5 seconds to show the main
window, compared to around 0.75 seconds before.
I've no intention of changing that back. So if the startup time becomes
a problem, then we'll just have to work on optimizing hiro, so that it
can construct all the global Window objects quicker. The main way to do
that would be to not do calls to the Layout::setGeometry functions for
every widget added, and instead wait until the window is displayed. But
I don't have an easy way to do that, because you want the widget
geometry values to be sane even before the window is visible to help
size certain things.
byuu says:
These WIPs-within-WIPs are getting more and more broken ... this isn't
going the way I wanted.
But ... this time around, I've revamped the entire ruby API again, to
solve a bunch of tough problems that have always made using ruby really
clunky.
But there are *so many* ruby drivers that it's going to take a long
time to work through them all. This WIP is only going to run bsnes, and
only on FreeBSD, and only with some drivers.
hiro's Application::initialize() now calls hiro::initialize(), which you
define inside of your hiro apps. This lets you call
Application::setName(...) before anything else in hiro runs. This is
essential on Xorg to set program icons, for instance.
With the ruby rewrite and the change to hiro, I can get away from the
need to make everything in bsnes/higan pointers to objects, and can now
just declare them as regular objects.
byuu wrote:
Sigh ...
asio.hpp needs #include <nall/windows/registry.hpp>
[Since the last WIP, byuu also posted the following message. -Ed.]
ruby drivers have all been updated (but not tested outside of BSD), and
I redesigned the settings window. The driver functionality all exists on
a new "Drivers" panel, the emulator/hack settings go to a
"Configuration" panel, and the video/audio panels lose driver settings.
As does the settings menu and its synchronize options.
I want to start pushing toward a v107 release. Critically, I will need
DirectSound and ALSA to support dynamic rate control. I'd also like to
eliminate the other system manifest.bml files. I need to update the
cheat code database format, and bundle at least a few quark shaders --
although I still need to default to Direct3D on Windows.
Turbo keys would be nice, if it's not too much effort. Aside from
netplay, it's the last significant feature I'm missing.
I think for v107, higan is going to be a bit rough around the edges
compared to bsnes. And I don't think it's practical to finish the bsnes
localization support.
I'm thinking we probably want another WIP to iron out any critical
issues, but this time there should be a feature freeze with the next
WIP.
byuu says:
Sigh, I seem to be spiraling a bit here ... but the work is very
important. Hopefully I can get a solid WIP together soon. But for now...
I've integrated dynamic rate control into ruby::Audio via
setDynamic(bool) for now. It's very demanding, as you would expect. When
it's not in use, I realized the OSS driver's performance was pretty bad
due to calling write() for every sample for every channel. I implemented
a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my
FreeBSD desktop. It may be possible to do the same buffering with DRC,
but for now, I'm not doing so, and adjusting the audio input frequency
on every sample.
I also added ruby::Video::setFlush(bool), which is available only in the
OpenGL drivers, and this causes glFinish() to be called after swapping
display buffers. I really couldn't think of a good name for this, "hard
GPU sync" sounds kind of silly. In my view, flush is what commits queued
events. Eg fflush(). OpenGL of course treats glFlush differently (I
really don't even know what the point of it is even after reading the
manual ...), and then has glFinish ... meh, whatever. It's
setFlush(bool) until I come up with something better. Also as expected,
this one's a big hit to performance.
To implement the DRC, I started putting helper functions into the ruby
video/audio/input core classes. And then the XVideo driver started
crashing. It took hours and hours and hours to track down the problem:
you have to clear XSetWindowAttributes to zero before calling
XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`,
etc will make Xlib be even remotely helpful in debugging errors like
this.
The GLX, GLX2, and XVideo drivers basically worked by chance before. If
the stack frame had the right memory cleared, it worked. Otherwise it'd
crash with BadValue, and my changing things broke that condition on the
XVideo driver. So this has been fixed in all three now.
Once XVideo was running again, I realized that non-power of two video
sizes were completely broken for the YUV formats. It took a while, but I
managed to fix all of that as well.
At this point, most of ruby is going to be broken outside of FreeBSD, as
I still need to finish updating all the drivers.
byuu says:
Once again, I wasn't able to complete a full WIP revision.
This WIP-WIP adds very sophisticated emulation of the Sega Genesis
Lock-On and Game Genie cartridges ... essentially, through recursion and
a linked list, higan supports an infinite nesting of cartridges.
Of course, on real hardware, after you stack more than three or four
cartridges, the power draw gets too high and things start glitching out
more and more as you keep stacking. I've heard that someone chained up
to ten Sonic & Knuckles cartridges before it finally became completely
unplayable.
And so of course, higan emulates this limitation as well ^-^. On the
fourth cartridge and beyond, it will become more and more likely that
address and/or data lines "glitch" out randomly, causing various
glitches. It's a completely silly easter egg that requires no speed
impact whatsoever beyond the impact of the new linked list cartridge
system.
I also designed the successor to Emulator::Interface::cap,get,set. Those
were holdovers from the older, since-removed ruby-style accessors.
In its place is the new Emulator::Interface::configuration,configure
API. There's the usual per-property access, and there's also access to
read and write all configurable options at once. In essence, this
enables introspection into core-specific features.
So far, you can control processor version#s, PPU VRAM size, video
settings, and hacks. As such, the .sys/manifest.bml files are no longer
necessary. Instead, it all goes into .sys/configuration.bml, which is
generated by the emulator if it's missing.
higan is going to take this even further and allow each option under
"Systems" to have its own editable configuration file. So if you wanted,
you could have a 1/1/1 SNES menu option, and a 2/1/3 SNES menu option.
Or a Model 1 Genesis option, and a Model 2 Genesis option. Or the
various Game Boy model revisions. Or an "SNES-Fast" and "SNES-Accurate"
option.
I've not fully settled on the syntax of the new configuration API. I
feel it might be useful to provide type information, but I really quite
passionately hate any<T> container objects. For now it's all
string-based, because strings can hold anything in nall.
I might also change the access rules. Right now it's like:
emulator→configure("video/blurEmulation", true); but it might be nicer
as "Video::Blur Emulation", or "Video.BlurEmulation", or something like
that.
byuu says:
I stand corrected, I managed to create and even larger diff than ever.
This one weighs in at 309KiB `>__>`
I'll have to create a changelog later, I'm too tired right now to go
through all of that.
byuu says:
I failed to complete a WIP, have five of eight cores updated with some
major changes to Emulator::Interface. I'll just post a quick temporary
WIP in the off chance someone wants to look over the new interface and
comment on it.
Also implemented screen saver suppression into hiro/GTK.
I should also add ... a plan of mine is to develop target-bsnes into a
more generic user interface, with the general idea being that
target-higan is for multiple Emulator::Interface cores at the same time,
and target-bsnes is for just one Emulator::Interface core.
The idea being that if one were to compile target-bsnes with the GBA
core, it'd become bgba, for instance.
I don't plan on releasing single-core emulators like this, but ... I don't see any downsides to being more flexible.
byuu says:
Changelog:
- added `Emulator::Interface::connected(uint port) -> uint device;`
- higan, bsnes: updated emulators to use the new
Emulator::Interface::connected() function
- hiro: fixed Object::cast<T> finally
So, Emulator::Interface::connected() solves two annoying problems at the
same time.
First, on first run of the emulator when the settings file is blank, it
will retrieve the default "sane" device ID, which is usually a gamepad
for a controller port, or nothing for an expansion/extension port.
Second, if you were to select a multi-port device, like the NES Four
Score, the core will set the other port to the Four Score device as
well, and the GUIs query connected() right after any call to connect(),
so it gets updated without needing a system for the emulation core to
send messages alerting the GUI of changes.
byuu says:
Changelog:
- emulator/video,audio: various cleanups
- emulator/audio: removed reverb effect (it breaks very badly on
high-frequency systems)
- emulator/audio: the Nyquist anti-aliasing lowpass filter is now
generated automatically instead of set per-core
- at 44.1KHz output, it's set to 22KHz; at 48KHz, it's set to
22KHz; at 96KHz, it's set to 25KHz
- this filter now takes the bsnes emulation speed setting into
account
- all system/video.cpp files removed; inlined in System::power() and
Interface::set() instead
- sfc/cpu: pre-compute `HTIME` as `HTIME+1<<2` for faster comparisons of
HIRQs
- sfc/cpu: re-add check to block IRQs on the last dot of each frame
(minor speed hit)
- hiro/gtk3: fixed headers for Linux compilation finally
- hiro/gtk,qt: fixed settings.cpp logic so initial values are used
when no settings.bml file exists
- hiro/gtk: started a minor experiment to specify theming information
in settings.bml files
- nall/dsp: allow the precision type (double) to be overridden (to
float)
- nall: add some helpers for generating pre-compiled headers
- it was a failure to try using them for higan, however ...
- nall: add some helpers for reading fallback values from empty
`Markup::Node[search]` statements
Todo:
- CRITICAL: a lot of my IRQ/NMI/HDMA timing tests are failing with the
fast PPU ... need to figure out why
- space between Emulator::video functions and Emulator::audio
functions in gb/system/system.cpp
- remove Audio/Reverb/Enable from settings.bml in target-bsnes
byuu says:
This is a fairly radical WIP with extreme changes to lots of very
important parts.
The result is a ~7% emulation speedup (with bsnes, unsure how much it
helps higan), but it's quite possible there are regressions. As such, I
would really appreciate testing as many games as possible ... especially
the old finnicky games that had issues with DMA and/or interrupts.
One thing to note is that I removed an edge case test that suppresses
IRQs from firing on the very last dot of every field, which is a
behavior I've verified on real hardware in the past. I feel that the
main interrupt polling function (the hottest portion of the entire
emulator) is not the appropriate place for it, and I should instead
factor it into assignment of NMITIMEN/VTIME/HTIME using the new
io.irqEnable (==virqEnable||hirqEnable) flag. But since I haven't done
that yet ... there's an old IRQ test ROM of mine that'll fail for this
WIP. No commercial games will ever rely on this, so it's fine for
testing.
Changelog:
- sfc/cpu.smp: inlined the global status functions
- sfc/cpu: added readRAM, writeRAM to use a function pointer instead
of a lambda for WRAM access
- sfc/cpu,smp,ppu/counter: updated reset functionality to new style
using class inline initializers
- sfc/cpu: fixed power(false) to invoke the reset vector properly
- sfc/cpu: completely rewrote DMA handling to have per-channel
functions
- sfc/cpu: removed unused joylatch(), io.joypadStrobeLatch
- sfc/cpu: cleaned up io.cpp handlers
- sfc/cpu: simplified interrupt polling code using
nall::boolean::flip(),raise(),lower() functions
- sfc/ppu/counter: cleaned up the class significantly and also
optimized things for efficiency
- sfc/ppu/counter: emulated PAL 1368-clock long scanline when
interlace=1, field=1, vcounter=311
- sfc/smp: factored out the I/O and port handlers to io.cpp
byuu says:
The problems with the Windows and Qt4 ports have all been resolved,
although there's a fairly gross hack on a few Qt widgets to not destruct
once Application::quit() is called to avoid a double free crash (I'm
unsure where Qt is destructing the widgets internally.) The Cocoa port
compiles again at least, though it's bound to have endless problems. I
improved the Label painting in the GTK ports, which fixes the background
color on labels inside TabFrame widgets.
I've optimized the Makefile system even further.
I added a "redo state" command to bsnes, which is created whenever you
load the undo state. There are also hotkeys for both now, although I
don't think they're really something you want to map hotkeys to.
I moved the nall::Locale object inside hiro::Application, so that it can
be used to translate the BrowserDialog and MessageDialog window strings.
I improved the Super Game Boy emulation of `MLT_REQ`, fixing Pokemon
Yellow's custom border and probably more stuff.
Lots of other small fixes and improvements. Things are finally stable
once again after the harrowing layout redesign catastrophe.
Errata:
- ICD::joypID should be set to 3 on reset(). joypWrite() may as well
take uint1 instead of bool.
- hiro/Qt: remove pWindow::setMaximumSize() comment; found a
workaround for it
- nall/GNUmakefile: don't set object.path if it's already set (allow
overrides before including the file)
byuu says:
This is probably the largest code-change diff I've done in years.
I spent four days working 10-16 hours a day reworking layouts in hiro
completely.
The result is we now have TableLayout, which will allow for better
horizontal+vertical combined alignment.
Windows, GTK2, and now GTK3 are fully supported.
Windows is getting the initial window geometry wrong by a bit.
GTK2 and GTK3 work perfectly. I basically abandoned trying to detect
resize signals, and instead keep a list of all hiro windows that are
allocated, and every time the main loop runs, it will query all of them
to see if they've been resized. I'm disgusted that I have to do this,
but after fighting with GTK for years, I'm about sick of it. GTK was
doing this crazy thing where it would trigger another size-allocate
inside of a previous size-allocate, and so my layouts would be halfway
through resizing all the widgets, and then the size-allocate would kick
off another one. That would end up leaving the rest of the first layout
loop with bad widget sizes. And if I detected a second re-entry and
blocked it, then the entire window would end up with the older geometry.
I started trying to build a message queue system to allow the second
layout resize to occur after the first one completed, but this was just
too much madness, so I went with the simpler solution.
Qt4 has some geometry problems, and doesn't show tab frame layouts
properly yet.
Qt5 causes an ICE error and tanks my entire Xorg display server, so ...
something is seriously wrong there, and it's not hiro's fault. Creating
a dummy Qt5 application without even using hiro, just int main() {
TestObject object; } with object performing a dynamic\_cast to a derived
type segfaults. Memory is getting corrupted where GCC allocates the
vtables for classes, just by linking in Qt. Could be somehow related to
the -fPIC requirement that only Qt5 has ... could just be that FreeBSD
10.1 has a buggy implementation of Qt5. I don't know. It's beyond my
ability to debug, so this one's going to stay broken.
The Cocoa port is busted. I'll fix it up to compile again, but that's
about all I'm going to do.
Many optimizations mean bsnes and higan open faster. GTK2 and GTK3 both
resize windows very quickly now.
higan crashes when you load a game, so that's not good. bsnes works
though.
bsnes also has the start of a localization engine now. Still a long way
to go.
The makefiles received a rather substantial restructuring. Including the
ruby and hiro makefiles will add the necessary compilation rules for
you, which also means that moc will run for the qt4 and qt5 targets, and
windres will run for the Windows targets.
byuu says:
Changelog:
- bsnes, higan: simplified make output; reordered rules
- hiro: added Window::set(Minimum,Maximum)Size() [only implemented in
GTK+ so far]
- bsnes: only allow the window to be shrunk to the 1x multiplier size
- bsnes: refactored Integral Scaling checkbox to {Center, Scale,
Stretch} radio selection
- nall: call fflush() after nall::print() to stdout or stderr [needed
for msys2/bash]
- bsnes, higan: program/interface.cpp renamed to program/platform.cpp
- bsnes: trim ".shader/" from names in Settings→Shader menu
- bsnes: Settings→Shader menu updated on video driver changes
- bsnes: remove missing games from recent files list each time it is
updated
- bsnes: video multiplier menu generated dynamically based on largest
monitor size at program startup
- bsnes: added shrink window and center window function to video
multiplier menu
- bsnes: de-minimize presentation window when exiting fullscreen mode
or changing video multiplier
- bsnes: center the load game dialog against the presentation window
(important for multi-monitor setups)
- bsnes: screenshots are not immediate instead of delayed one frame
- bsnes: added frame advance menu option and hotkey
- bsnes: added enable cheats checkbox and hotkey; can be used to
quickly enable/disable all active cheats
Errata:
- hiro/Windows: `SW_MINIMIZED`, `SW_MAXIMIZED `=> `SW_MINIMIZE`,
`SW_MAXIMIZE`
- hiro/Windows: add pMonitor::workspace()
- hiro/Windows: add setMaximized(), setMinimized() in
pWindow::construct()
- bsnes: call setCentered() after setMaximized(false)
byuu says:
Changelog:
- sfc/ppu-fast: added hires mode 7 option (doubles the sampling rate
of mode 7 pixels to reduce aliasing)
- sfc/ppu-fast: fixed mode 7 horizontal screen flip [hex_usr]
- bsnes: added capture screenshot function and path selection
- for now, it saves as BMP. I need a deflate implementation that
won't add an external dependency for PNG
- the output resolution is from the emulator: (256 or 512)x(240 or
480 minus overscan cropping if enabled)
- it captures the NEXT output frame, not the current one ... but
it may be wise to change this behavior
- it'd be a problem if the core were to exit and an image was
captured halfway through frame rendering
- bsnes: recovery state renamed to undo state
- bsnes: added manifest viewer tool
- bsnes: mention if game has been verified or not on the status bar
message at load time
- bsnes, nall: fixed a few missing function return values
[SuperMikeMan]
- bsnes: guard more strongly against failure to load games to avoid
crashes
- hiro, ruby: various fixes for macOS [Sintendo]
- hiro/Windows: paint on `WM_ERASEBKGND` to prevent status bar
flickering at startup
- icarus: SPC7110 heuristics fixes [hex_usr]
Errata:
- sfc/ppu-fast: remove debug hires mode7 force disable comment from
PPU::power()
[The `WM_ERASEBKGND` fix was already present in the 106r44 public
beta -Ed.]
byuu says (in the public announcement):
I'm releasing a beta version of bsnes, for the purpose of gathering feedback and
ensuring that the first official release of bsnes is as solid as possible.
With the exception of dynamic rate control for automatic audio/video sync, and
no pack-in video shaders or cheat code database, it is mostly feature complete.
However, please do not form a lasting opinion of bsnes based on this beta.
byuu says:
Changelog:
- hiro/Windows: use `WS_CLIPSIBLINGS` on Label to prevent resize
drawing issues
- bsnes: correct viewport resizing
- bsnes: speed up window resizing a little bit
- bsnes: fix the cheat editor list enable checkbox
- bsnes: fix the state manager filename display in game ROM mode
- bsnes: fix the state manager save/rename/remove functionality in
game ROM mode
- bsnes: correct path searching for IPS and BPS patches in game ROM
mode
- bsnes: patch BS-X town cartridge to disable play limits
- bsnes: do not load (program,data,expansion).(rom,flash) from disk in
game pak mode
- this is required to support soft-patching and ROM hacks
- bsnes: added speed mode selection (50%, 75%, 100%, 150%, 200%);
maintains proper pitch
- bsnes: added icons to the menubar
- this is particularly useful to tell game ROMs from game paks in
the load recent game menu
- bsnes: added emblem at bottom left of status bar to indicate if a
game is verified or not
- verified means it is in the icarus verified game dump database
- the verified diamond is orange; the unverified diamond is blue
- bsnes: added an option (which defaults to off) to warn when loading
unverified games
- working around a bug in GTK, I have to use the uglier
MessageWindow instead of MessageDialog
- bsnes: added (non-functional) link to <https://doc.byuu.org/bsnes/>
to the help menu
- bsnes: added GUI setting to toggle memory auto-save feature
- bsnes: added GUI setting to toggle capturing a backup save state
when closing the emulator
- bsnes: made auto-saving states on exit an option
- bsnes: added an option to auto-load the auto-saved state on load
- basically, the two combined implements auto-resume
- bsnes: when firmware is missing, offer to take the user to the
online help documentation
- bsnes: added fast PPU option to disable the sprite limit
- increase from 32 items/line + 34 tiles/line to 128 items/line +
128 tiles/line
- technically, 1024 tiles/line are possible with 128 sprites at
64-width
- but this is just a waste of cache locality and worst-case
performance; it'll never happen
Errata:
- hiro/Windows: fallthrough on Canvas `WM_ERASEBKGND` to prevent
startup flicker
byuu says:
Changelog:
- bsnes: added video settings panel
- bsnes: added audio settings panel
- bsnes: disable assign/clear buttons at startup for hotkeys panel
- bsnes: program initialization restructured: drivers initialize last
- this lets me reinitialize the settings panel values on driver
changes
- so eg things like input/hotkey remappings should work after
input driver changes now
- ... but I had to disable the window icon for this ... it takes
too long to show up this way
- bsnes: added synchronize video/audio options to settings menu
- bsnes: added audio skew slider for video/audio synchronization
- bsnes: state manager edit/remove works on game ROM .bsz archives now
- bsnes: removed View→Color Emulation; default to 150% gamma instead
(it's a touch brighter but similar)
At this point, I'm pretty much ready to make an initial beta release for
wider testing.
Please use this WIP to indicate any must-fix issues before I do so.
byuu says:
Changelog:
- emulator: added `Thread::setHandle(cothread_t)`
- icarus: added special heuristics support for the Tengai Maykou Zero
fan translation
- board identifier is: EXSPC7110-RAM-EPSONRTC (match on SPC7110 +
ROM size=56mbit)
- board ROM contents are: 8mbit program, 40mbit data, 8mbit
expansion (sizes are fixed)
- bsnes: show messages on game load, unload, and reset
- bsnes: added support for BS Memory and Sufami Turbo games
- bsnes: added support for region selection (Auto [default], NTSC,
PAL)
- bsnes: correct presentation window size from 223/239 to 224/240
- bsnes: add SA-1 internal RAM on cartridges with BS Memory slot
- bsnes: fixed recovery state to store inside .bsz archive
- bsnes: added support for custom manifests in both game pak and game
ROM modes
- bsnes: added icarus game database support (manifest → database →
heuristics)
- bsnes: added flexible SuperFX overclocking
- bsnes: added IPS and BPS soft-patching support to all ROM types
(sfc,smc,gb,gbc,bs,st)
- can load patches inside of ZIP archives (matches first “.ips” or
“.bps” file)
- bsnes/ppu: cache interlace/overscan/vdisp (277 → 291fps with fast
PPU)
- hiro/Windows: faster painting of Label widget on expose
- hiro/Windows: immediately apply LineEdit::setBackgroundColor changes
- hiro/Qt: inherit Window backgroundColor when one is not assigned to
Label
Errata:
- sfc/ppu-fast: remove `renderMode7Hires()` function (the body isn't in
the codebase)
- bsnes: advanced note label should probably use a lighter text color
and/or smaller font size instead of italics
I didn't test the soft-patching at all, as I don't have any patches on
my dev box. If anyone wants to test, that'd be great. The Tengai Makyou
Zero fan translation would be a great test case.
byuu says:
Changelog:
- hiro: added Label::set(Background,Foreground)Color (not implemented
on Cocoa backend)
- hiro: added (Horizontal,Vertical)Layout::setPadding()
- setMargin(m) is now an alias to setPadding({m, m, m, m})
- hiro/Windows: update Label rendering to draw to an offscreen canvas
to prevent flickering
- sfc: reverted back to 224/240-line height (from 223/239-line height
in earlier v106 WIPs)
- bsnes: new multi-segment status bar added
- bsnes: exiting fullscreen mode will resize and recenter window
- this is required; the window geometry gets all scrambled when
toggling fullscreen mode
- bsnes: updated to a new logo [Ange Albertini]
Errata:
- hiro/Windows: try to paint Label backgroundColor quicker to avoid
startup flicker
- `WM_ERASEBKGND` fallthrough to `WM_PAINT` seems to work
- hiro/Qt: use Window backgroundColor for Label when no Label
backgroundColor set
- bsnes: update size multipliers in presentation.cpp to 224/240 (main
window size is off in this WIP)
byuu says:
Changelog:
- hiro: added BrowserDialog::openObject() [match file *or* folder
by filters]
- hiro: BrowserDialog accept button is now disabled when it would
otherwise do nothing
- eg openFile without a folder to enter or file to open selected
- eg saveFile without a file name or with a file name that matches
a folder name
- bsnes: added support for gamepaks (game folders)
- bsnes: store all save states inside per-game .bsz (ZIP) archives
instead of .bst/ folders
- this reduces the number of state files from 10+ to 1; without
having folders sort before files
- hiro: both gtk2 and gtk3 now use cairo to render Canvas; supports
sx,sy [BearOso]
- higan, bsnes: fast PPU/DSP are now run-time options instead of
compile-time options
- bsnes: disable fast PPU when loading Air Strike Patrol / Desert
Fighter
- bsnes: disable fast DSP when loading Koushien 2
- bsnes: added options to advanced panel to disable fast PPU and/or
fast DSP
byuu says:
Changelog:
- ruby/video: implement onUpdate() callback to signal when redraws are
necessary
- ruby/video/GLX,GLX2,XVideo,XShm: implement onUpdate() support
- bsnes: implement Video::onUpdate() support to redraw Viewport icon
as needed
- bsnes: save RAM before ruby driver changes
- sfc/sa1: clip signed multiplication to 32-bit [Jonas Quinn]
- sfc/sa1: handle negative dividends in division [Jonas Quinn]
- hiro/gtk3: a few improvements
- bsnes: added empty stub video and audio settings panels
- bsnes: restructured advanced settings panel
- bsnes: experiment: input/hotkeys name column bolded and colored for
increased visual distinction
- bsnes: added save button to state manager
byuu says:
Changelog:
- hiro: added Qt5 support
- hiro: added GTK3 support (currently runs very poorly)
- bsnes: number of recent games and quick state slots can be changed
programmatically now
- I may expose this as a configuration file setting, but probably
not within the GUI
- nall: use -Wno-everything when compiling with Clang
- sorry, Clang's meaningless warning messages are just endless ...
byuu says:
Changelog:
- bsnes: cheat code “enabled” option changed to “enable”
- bsnes: connected “Cancel” action on add/edit cheat code window
- hiro: improved BrowserDialog::selectFolder() behavior
- can choose “Select” inside of a target folder when no items are
selected
- bsnes: implemented state manager
- bsnes: save a recovery state before loading a state, quitting, or
changing drivers
- bsnes: input settings, hotkey settings, cheat editor, state manager
entries are now batchable
- this allows bulk clearing/deleting of entries
- bsnes: cheat code list now auto-sorts alphabetically instead of
using up/down move arrows
I know most people will probably prefer to order cheat codes the way
they want, but the issue is that the state manager can't really work
this way. Each state is a file on disk. So yes, we could store a
states-manifest.bml to track the order of the states, or try to insert
numbers into the filenames and do bulk filesystem rename operations on
sorting, but then we would run into oddities when users delete state
files manually. And really, manual sorting is just clumsy. If you really
want a specific ordering, you can prefix cheats/states with numeric
indices instead.
byuu says:
Changelog:
- nall: renamed array to adaptive_array; marked it as deprecated
- nall: created new array class; which is properly static (ala
std::array) with optional bounds-checking
- sfc/ppu-fast: converted unmanaged arrays to use nall/array (no speed
penalty)
- bsnes: rewrote the cheat code editor to a new design
- nall: string class can stringify pointer types directly now, so
pointer() was removed
- nall: added array_view and pointer types (still unsure if/how I'll
use pointer)
byuu says:
Changelog:
- sfc/ppu-fast: fixed overscan crash
- sfc/ppu-fast: fixed direct color mode
- sfc: reconnected MSU1 support
- higan: game.sfc/msu1/data.rom, game.sfc/msu1/track-#.pcm
- bsnes: game.msu, game-#.pcm
- bsnes: added cheat code editor
- bsnes: added cheat code database support
- sfc/ppu-fast: clear overscan lines when overscan disabled
- sfc: output 223/239 lines instead of 224/240 lines
- bsnes: fix aspect correction calculation
- bsnes: crop line 224 when overscan masking is enabled
- bsnes: exposed Expansion Port menu; but hid “21fx” from the list of
devices
- bsnes: tools menu is hidden until a game is loaded
- ruby/input/keyboard/quartz: fixed compilation error
So only bsnes the automated overscan cropping option. In higan, you can
crop however many lines you like from the top or bottom of the image.
But for bsnes, it automatically eats sixteen lines. My view right now is
that if bsnes is meant to be the casual gaming emulator, that it should
eat line 224 in this mode. Most games show content here, but because of
the way the SNES PPU works, the very last line ends up on its very own
tile row (line 0 isn't rendered), if the scroll registers don't account
for it. There's a small number of games that will draw junk data to the
very last scanline of the frame as a result of this. So I chose, at
least for now, to hide it. Users can obviously disable overscan cropping
to see this scanline. I'm open to being convinced not to do this, if
someone has a compelling reason.
We're pretty much screwed one way or the other with no overscan masking.
If we output 239 lines, then most games will render 7 blank lines + 224
drawn lines + 8 blank lines, and the black top and bottom aren't
centered. But if we output 240 lines to get 8 + 224 + 8, then games that
do use overscan will have a blank line at the very bottom of the window.
I'm also trying out a modified cheat code file format. It's been forever
since I bothered to look at it, and the “cartridge” parent node doesn't
match what I'm doing with trying to rename “cartridge” to “game” in
manifests. And indeed, the idea of requiring a root node is rather
superfluous for a cheat code file. Current format looks like this:
cheat
description: foo
code: 7e2000=20+7e2001=30?40
enabled
cheat
description: bar
code: 7e4000=80
Open to discussing this, and I'd like to sync up with Snes9X before they
push out a new release, and I'll agree to finalize and never change this
format again.
I chose to use .cht for the extension when using game files (eg
gamename.cht)
Also, since byuu changes the defaults according to what he's working on, let's
be explicit tat higan gets the accuracy core and bsnes gets the performance
core.
byuu says:
Changelog:
- sfc/ppu-fast:
- don't use mosaicSize unless mosaicEnable is set
- fix background tiles that aren't 8x8 in size
- flush (render) queued lines whenever VRAM or OAM are modified
mid-frame
- queue tile outputs to buffer for object rendering final pass
- fix object window mask indexing
- disable color bleed when output width is 256 pixels
- handle reset(bool) events
- implemented save states
- icarus: fixed SPC7110-RAM-EPSONRTC mapping typo [hex_usr]
- bsnes: fixed overscan masking mode when output height is 240
Todo:
- sfc/ppu-fast: should not have deleted the tilecache freeing in
~PPU()
- ruby/input/carbon: change setPath() call to setPathID()
Errata:
- Rendering Ranger R2 crashes at startup, seems to be an issue with
the expansion port device
Bug reports on the new fast SNES PPU are now welcome.
byuu says:
Changelog:
- nall/GNUmakefile: added `openmp=(true,false)` option; can be toggled
when building higan/bsnes
- defaults to disabled on macOS, because Xcode doesn't stupidly
doesn't ship with support for it
- higan/GNUmakefile: forgot to switch target,profile back from
bsnes,fast to higan,accurate
- this is just gonna happen from time to time, sorry
- sfc/dsp: when using the fast profile, the DSP syncs per sample
instead of per clock
- should only negatively impact Koushien 2, but is a fairly
significant speedup otherwise
- sfc/ppc,ppu-fast: optimized the code a bit (ppu 130fps to 133fps)
- sfc/ppu-fast: basic vertical mosaic support (not accurate, but
should look okay hopefully)
- sfc/ppu-fast: added missing mode7 hflip support
- sfc/ppu-fast: added support to render at 256-width and/or 240-height
- gives a decent speed boost, and also allows all of the older
quark shaders to work nicely again
- it does violate the contract of Emulator::Interface, but oh
well, it works fine in the bsnes GUI
- sfc/ppu-fast: use cached CGRAM values for mode7 and sprites
- sfc/ppu-fast: use global range/time over flags in object rendering
- may not actually work as we intended since it's a race condition
even if it's only ORing the flags
- really don't want to have to make those variables atomic if I
don't have to
- sfc/ppu-fast: should fully support interlace and overscan modes now
- hiro/cocoa: updated macOS Gatekeeper disable support to work on
10.13+
- ruby: forgot to fix macOS input driver, sorry
- nall/GNUmakefile: if uname is present, then just default to rm
instead of del (fixes Msys)
Note: blur emulation option will break pretty badly in 256x240 output
mode. I'll fix it later.
byuu says:
Changelog:
- sfc/ppu-fast: everything other than vertical mosaic and interlace
support is in
Games are quite playable now, and you're welcome to try things out, but
please don't report bugs yet. It's still too early for that.
byuu says:
Changelog:
- sfc/ppu-fast: added a barebones background renderer; very incomplete
Right now, the 2bpp Mega Man X2 splash screen is rendering correctly,
but everything else looks really garbled. I'm thinking my tile cache
conversions from 4bpp to bitmap pixels is wrong, but I'm not seeing any
obvious issues.
If anyone wants to take a look at it, I'd appreciate it. The renderer is
mostly modeled after ppu-performance's.
byuu says:
Changelog:
- nall/GNUmakefile: fixed findstring parameter arguments [Screwtape]
- nall/Windows: always include -mthreads -lpthread for all
applications
- nall/memory: code restructuring
I really wanted to work on the new PPU today, but I thought I'd spend a
few minutes making some minor improvements to nall::memory, that was
five and a half hours ago. Now I have a 67KiB diff of changes. Sigh.
byuu says:
Changelog:
- sfc/ppu: collapsed folders to a single directory to match all other
emulated processors
- sfc/ppu-fast: implemented I/O registers
byuu says:
Changelog:
- SNES: started on skeleton of the new parallel PPU core
To build the new PPU core, set profile=fast via GNU make. The old core
is profile=accurate.
The names of the profiles, and the name of the folder for the fast PPU
are subject to change.
The new PPU core doesn't do anything but demonstrate the proof of
concept: every scanline, make a copy of all the PPU registers and CGRAM.
Share the VRAM and OAM. Batch render all scanlines at once using OpenMP
at the end of each frame and blit the result.
With no PPU core at all, bsnes runs 91% faster than with the accuracy
PPU (230fps vs 120fps.) That's the absolute theoretical best-case
scenario. With the skeleton in place, we're already around 220fps. It'll
go down more as the PPU line renderer starts to do real work. I don't
know where things will end up yet. I suppose we'll find out in time.
My own copy of TDM/GCC can't use OpenMP on Windows, so ... it won't
parallelize if you build with that. I'm going to have to switch to a
different MinGW distribution once this is complete, I suppose.
byuu says:
Changelog:
- nall: merged Path::config() and Path::local() to Path::userData()
- ~/.local/share or %appdata or ~/Library/ApplicationSupport
- higan, bsnes: render main window icon onto viewport instead of
canvas
- should hopefully fix a brief flickering glitch that appears on
Windows
- icarus: improved Super Famicom heuristics for Starfox / Starwing RAM
- ruby/Direct3D: handle viewport size changes in lock() instead of
output()
- fixes icon disappearing when resizing main window
- hiro/Windows: remove WS_DISABLED from StatusBar to fix window
resize grip
- this is experimental: I initially used WS_DISABLED to work
around a focus bug
- yet trying things now, said bug seems(?) to have gone away at
some point ...
- bsnes: added advanced settings panel with real-time driver change
support
I'd like feedback on the real-time driver change, for possible
consideration into adding this to higan as well.
Some drivers just crash, it's a fact of life. The ASIO driver in
particular likes to crash inside the driver itself, without any error
messages ever returned to try and catch.
When you try to change a driver with a game loaded, it gives you a scary
warning, asking if you want to proceed.
When you change a driver, it sets a crash flag, and if the driver
crashes while initializing, then restarting bsnes will disable the
errant driver. If it fails in a recoverable way, then it sets the driver
to “None” and warns you that the driver cannot be used.
What I'm thinking of further adding is to call emulator→save() to
write out the save RAM contents beforehand (although the periodic
auto-saving RAM will handle this anyway when it's enabled), and possibly
it might be wise to capture an emulator save state, although those can't
be taken without advancing the emulator to the next frame, so that might
not be a good idea.
I'm also thinking we should show some kind of message somewhere when a
driver is set to “None”. The status bar can be hidden, so perhaps on the
title bar? Or maybe just a warning on startup that a driver is set to
“None”.
byuu says:
Changelog:
- nall: added -static-libgcc -static-libstdc++ to Windows/GCC link
flags
- bsnes, higan: added program icons to main window when game isn't
loaded
- bsnes: improved recent games menu sorting
- bsnes: fixed multi-game recent game loading on Windows
- bsnes: completed path override support
- bsnes, higan: added screensaver suppression on Windows
- icarus: add 32K volatile RAM to SuperFX boards that report no RAM
(fixes Starfox)
- bsnes, higan: added automatic dependency generation [Talarubi]
- hiro/GTK: appending actions to menus restores enabled() state
- higan: use board node inside manifest.bml if it exists
- bsnes: added blur emulation and color emulation options to view menu
- ruby: upgraded input.sdl to SDL 2.0 (though it makes no functional
difference sadly)
- ruby: removed video.sdl (due to deprecating SDL 1.2)
- nall, ruby: improvements to HID class (generic vendor and product
IDs)
Errata:
- bsnes, higan: on Windows, Application::Windows::onScreenSaver needs
`[&]` lambda capture, not `[]`
- find it in presentation/presentation.cpp
byuu says:
Changelog:
- bsnes:
- added full input mapping support (multi-mapping, digital+analog
inputs, rumble, hotkeys, etc)
- can now load multi-part games (eg Super Game Boy) from the
command-line
- added recent games menu with list clear function; supports
multi-part games (sorting logic incomplete)
- added automatic binding of gamepads on new configuration files
- added view scaling support with aspect correction, overscan
cropping, and integral scaling modes
- added video shader support
- added status bar (can be hidden)
- added save states (both menu and hotkeys)
- added fullscreen mode support
- added support for loading compressed (ZIP) archives for any
supported media type (SNES, GB, etc)
- added frame counter
- added auto-memory saving
- added pause / block-input modes when main window loses focus
- added --fullscreen command-line option to start bsnes in
fullscreen mode
- added input settings panel
- added hotkeys settings panel
- added path settings panel (paths aren't actually used set, but
can be assigned)
- higan: fixed macOS install rule [Sintendo]
- higan: minor UI code cleanups
- nall: renamed Processor to Architecture to fix macOS builds
[Sintendo]
Yeah, you read right: recent games menu, path settings. And dynamic rate
control + screensaver suppression is on the todo list. I'm not fucking
around this time. I really want to make something special here.
byuu says:
Changelog:
* yes.
But seriously, a list of changes on a pre-alpha GUI is going to get annoying.
Basically, work on embedding stuff in the binary, firmware loading (both
appended to the ROM and in a firmware/ subfolder) added, SGB games can be
loaded, config file holds more values for driver settings, added ruby drivers to
other platforms, etc.
byuu says:
Changelog:
- bsnes: work on the new GUI; can load games now, but no input support
yet
- icarus: heuristics game/label uses filename instead of internal
header name
byuu says:
Changelog:
- created new bsnes target (it currently does nothing)
- Super Famicom: fixed BS Memory pack support in the MCC emulation
- icarus: fixed manifest-free support for BS Memory flash-based
cartridges
- icarus: database improvements
byuu says:
Changelog:
- higan: target-tomoko has been renamed to target-higan
- Super Famicom: event has been renamed to
processor(architecture=uPD78214)
- Super Famicom: SNES-EVENT supported once more; under board IDs
EVENT-CC92 and EVENT-PF94
- Super Famicom: SNES-EVENT preliminarily set up to use DIP switch
settings ala the Nintendo Super System (incomplete)
- Super Famicom: MCC PSRAM moved inside the MCU, as it is remappable
- Super Famicom: MCC emulation rewritten from scratch; it is now
vastly more accurate than before
- Super Famicom: added BSC-1A5B9P-01 board definition to database;
corrected BS-MCC-RAM board definition
- Super Famicom: moved SHVC-LN3B-01 RAM outside of
processor(identifier=SDD1)
- higan: when selecting a default game to load for a new system entry,
it will change the system option to match the media type
- higan: the load text box on the system entry window is now editable;
can be used to erase entries
- icarus: fixed bug in Famicom importing
- icarus: importing unappended SNES coprocessor firmware will now
rename the firmware properly
- hiro/GTK,Qt: WM_CLASS is now set correctly in `argv[0]`, so
applications should show “higan”, “icarus” instead of “hiro” now
Note: if you wish to run the BS-X town cartridge, the database currently
lists the download RAM as type “PSRAM”. This needs to be changed to
“RAM” in order to load properly. Otherwise, the emulator will bomb
out on the load window, because BSC-1A5B9P-01 expects PSRAM to always be
present, but it won't find it with the wrong memory type. I'll correct
this in the database in a later release. For now, you can copy the game
portion of the manifest to a new manifest.bml file and drop it into the
gamepak folder until I fix the database.
byuu says:
Changelog:
- Super Famicom: fixed loading of BS Memory and Sufami Turbo
cartridges
- Super Famicom: renamed NSS to DIP; as that's really all it is, it's
not true NSS emulation
- Super Famicom: slot loading now happens inside of board parsing
instead of generically in loadCartridge()
- Super Famicom: BS-X cartridges with flash memory now serialize their
data and write it out to disk¹
- icarus: fixed Famicom game importing (hopefully) and set file import
title to “Load ROM File”
¹: there's no emulation of write commands yet, so the data is never
going to change anyway. This is just in preparation for more advanced
emulation of BS Memory cartridges.
byuu says:
Changelog:
- Super Famicom: everything outside of Nintendo Super System, Campus
Challenge '92 and Powerfest '94 should play
- Super Famicom: removed RAM from coprocessor/event (should use global
RAM)
- Super Famicom: removed RAM from SDD1 (should use global RAM)
- icarus: fixed Super Famicom game importing [hex_usr]
Also worth reminding that you'll need to disable database lookup in
order to run the BS-X Town cartridge right now. Plus, Star Ocean's
database entry still has the RAM in the wrong spot. The MSU1 code is not
looking at the right locations for data, so it's not going to work in
this release either.
I need to figure out what to call coprocessor/event and coprocessor/nss,
as neither are slots or processors like everything else.
Outside of those issues, all games for all systems should be playable,
at least to the extent they were in v106.
byuu says:
Changelog:
- major restructuring of board manifests
- cleanup of generic board names
- Super Famicom: updates to SA1, SuperFX, Cx4, SPC7110, EpsonRTC,
SharpRTC load/save code
- Super Famicom: added experimental SuperFX plot dithering fix
[qwertymodo]
- higan, icarus: rename shared folders to lowercase names; put .sys
folders into new subfolder
- Video Shaders/ → shaders/
- Database/ → database/
- Firmware/ → firmware/
- \*.sys/ → systems/\*.sys/
So right now, only standard SNES games, SA-1, SuperFX, and Cx4 games
load. I have not tested SPC7110 or RTC support, because icarus import
seems to be completely broken? It's creating blank folders when I try it
now. I'll have to fix that ...
Since we are now up to thirteen systems, I've put the .sys folders into
a subfolder. This should declutter the main higan-windows release folder
a good deal. Linux users will need to re-run make install, or manually
move things into a new systems/ subfolder.
Same goes for icarus: lowercase the database/ and firmware/ folders or
re-run make install.
I don't know if qwertymodo's SuperFX fix is exactly correct or not.
Hopefully it is, but I didn't write a test ROM or anything to be
certain. Since SuperFX games should run, if people could please play
through some of them and look for any regressions, that'd be very much
appreciated.
byuu says:
Changelog:
- tomoko: the library menu is now called the systems menu (even in
code)
- tomoko: added icons to menus (disambiguates systems menu entries)
- icarus: added missing .ws, .wsc extensions to scan dialog search
list
- higan: added Benesse - Pocket Challenge V2 emulation¹
¹: the Benesse - Pocket Challenge V2 is a WonderSwan (ASWAN) SoC
inside a custom designed shell. Games made for the WonderSwan (mostly)
run on the Pocket Challenge V2 and vice versa. The big difference is
that the Benesse has a different number of input buttons, that are also
named differently. Of course, right now, I don't know what the buttons
are named or where they're mapped on the 16-input keypad matrix I/O
port. It's also possible that the internal EEPROM doesn't exist, it
definitely has a unique (and also undumped) IPLROM, and other things.
The ROMs have their own .pc2 file extension. So it's getting its own
system entry.
What I'm going to do for v107 and above is utilize the new systems
configuration to mark the Benesse as hidden by default from the main
menu. I don't think anyone in the world will actually care or want to
play this, but there was really no reason not to add it.
byuu says:
Changelog:
- main menu renamed again (Library→System→Systems)
- the 'Hidden' checkbox on system properties was moved to the main
list as a 'Show' checkbox instead
- the move up/move down buttons on the systems panel now function
- added icons to indicate 'system' versus 'game boot' entries in the
systems list
I still didn't add ComboEdit to the Windows hiro port, so once again
this will be Linux/BSD only.
I polished the browse button for selecting a boot game. It'll use a list
of all bootable media file extensions, so that if you double-click any
supported game, it'll select it instead of going inside the folder. If
you pick a non-bootable folder, like say a Sufami Turbo cartridge, it
will go inside the folder instead, because it will treat it like any
other regular folder.
Having a checkbox next to text in the same cell doesn't work so well on
lists that have an onActivate action. Say you tried to double-click the
“Name” field on the Systems tab, it would toggle the checkbox twice
before popping open the system properties editor window. So because of
this, I made the show checkbox its own column. And for consistency, I
did the same for the slot# on the cheat editor window.
As a bit of really pedantic polish: if there are no systems enabled,
then the main menu won't show the separator before the “Load ROM Image”
option anymore.
I think something is wrong with the Markup::Node::insert syntax, but I
realized I have Markup::Node::swap, and just used that for the up/down
arrows on the systems panel for now. But we should probably fix insert()
at some point ... sigh.
byuu says:
Changelog:
- Super Game Boy: fixed loading of boot ROM
- hiro: added ComboEdit::setEditable(bool = true);
- tomoko: added new systems settings panel
Note!!: this release will not compile on Windows or macOS due to the
missing ComboEdit control! I'll try to merge in hex's implementation
for the Windows release here soon. macOS users will probably be out of
luck for a while, sorry.
The new systems panel is an idea I've been meaning to implement for
quite a while, but finally got around to starting on it. It's still
fairly unpolished, but the basic idea is there for Linux/BSD users to
try out now.
So imagine the Super Game Boy, BS-X Satellaview, Sufami Turbo, and the
associated BS Memory Pack-slotted SNES cartridges. To play any of those,
you needed to choose Nintendo→Super Famicom, and then select the
relevant cartridge, and then select any slotted cartridges to play with
it.
This was acceptable-ish, if not ideal. But now imagine in the future if
we wanted to support the Famicom Disk System, which is technically a
cartridge that plugs into the Famicom deck. Or the PC Engine CD, which
has one of three special HuCards that must be inserted (ignoring the
Turbo Duo where it's built-in—I'm going to be emulating the Super CD
as if you're using a stock PCE CD.) Or the Mega CD, where there are
probably a half dozen or more BIOS + hardware revisions that are
region-specific, which connect to an expansion port that is identical to
the cartridge port save for the Mega Drive seeing an I/O register bit
toggled here.
In all of these cases, it's going to be a real pain to have to choose
the 'BIOS' every time you want to play a game for them.
I can't distribute these BIOSes with higan due to copyright
restrictions, and trying to ship dummy folders for every possible
combination would become quite odious, and difficult for people to use
(compare to setting up the Game Boy Advance system BIOS.)
And so I've created the new systems settings panel. Here, you can manage
a list of systems that show up under the higan library menu (now renamed
to “System”), where each entry contains name, boot, and hidden
parameters.
The name parameter is what shows up in the system menu. You can call any
system higan emulates whatever you like here. Don't like “Super
Famicom”? Change it to “SNES”, then.
The boot parameter is a combo edit with a dropdown for all of the
systems higan emulates. If you choose one of these, then the higan
system menu option will work exactly like in previous releases, and
prompt you for a cartridge. But if you choose the browse button next to
the combo edit control, you'll get to pick any gamepak from the higan
library of your choosing.
So you could choose the SGB2 BIOS, and name the menu option “Super Game
Boy 2”, and when you choose the menu option, it will load the SFC core,
load the SGB2 BIOS, and only prompt you for the Game Boy game you wish
to play on it. The same deal goes for the FDS, PCE-CD, Mega CD, Mega
Drive Sonic & Knuckles lock-on cartridge, BS-X Satellaview, SD Gundam
G-Next, etc. Whatever you want to be in the menu, you can put in there
by pointing higan at the appropriate 'BIOS' gamepak to load.
Astute readers have probably already noticed, but you can technically
use this on non-slotted games as well, thus creating instant boot
options for your absolute favorite games, if you so wanted. Point it at
Zelda 3, and you can boot it instantly from the main menu, without any
need for file selection.
The hidden option is a way to hide the system entries from the system
menu. Primarily this would be a fast way for users to disable emulation
cores they never use in higan, without having to remove the options.
The major concession with this change is the collapsing of the
per-manufacturer submenus. What this means is you will now have all
twelve higan emulated systems in the main menu by default. This makes
the list rather long, but ... oh well. I may try to offer some form of
grouping in the future, but the grouping defeats the “list order =
display order” design, and I'm not willing to auto-sort the list. I want
people to be able to control the ordering of the system menu, and have
added (as yet non-functional) sorting arrows for that purpose. I also
don't have a combined tree+table view widget in higan to try to and
group things. But ... we'll see how things go in the future.
Another idea is to add a specialty load option that opens up the user's
Emulation library path, and lets you pick a gamepak for any system,
which would boot the same way as when you drop a gamepak onto the higan
executable or main window. So say you almost never play Wonderswan
games, this would be a way to play them without them cluttering your
system menu list.
The “import ROM files” option has been removed. All it does is launch
icarus directly. I would rather users become familiar with using icarus.
The “load ROM file” option remains.
Anyway, this is all still a work in progress, so please give it time and
don't overload me with too many suggested changes right now, thanks :3
byuu says:
Changelog:
- game/memory/type/battery → game/memory/volatile
- (manufacturer.)content.type → (architecture.)content.type
- nall: Markup::find() strips spaces from values in comparisons
- higan: updated game manifest loading/saving code for all cores
- GBA: flash memory ID is internally selected based on the
manufacturer and memory size
- SFC: ST018 (ARM6) frequency can be modified via game manifest now
- WS: EEPROM::name removed (not useful)
- icarus, genius: battery→volatile updates
I did my best to look over the diff between r13 and r14, but it's 84KiB
excluding the game database changes. It's just too much for me. I'd
greatly appreciate if someone could look over it and check for any
errors in this update. But more than likely, I suppose we'll iron out
any issues by determining which games fail to load.
Right now, I know the Super Game Boy support doesn't seem to work. But
all non-SFC cores should work fully, and all normal + NEC DSP SFC games
should work as well. Unsure about the rest.
Also, I'm planning to change the Game Boy “MBC1M” mapper to “MBC1#A” to
indicate it's an alternate wiring configuration of the stock MBC1, and
not a new mapper type.
byuu says:
Changelog:
- game/memory/category → game/memory/content
- game/memory/model → game/memory/architecture
- game/memory/identity → game/memory/identifier
- Super Famicom: memory/content=Bitmap → memory/content=Save
- Super Famicom: memory/architecture=DMG,MGB →
memory/architecture=LR35902
The game manifest field names are now officially set in stone. I won't
change them again, I'll only add new fields if required.
As for the values in the field, I'm still undecided on the manufacturer
of the ST018, and I could be talked into different identifiers for the
Super Game Boy (SGB1/SGB2, DMG/MGB, or just ICD(2)?)
The board manifest format is still in flux, as is the choice of what to
name firmware files (it's between manufacturer and architecture, where
I'm leaning toward the latter currently.)
Board memory to Game memory mappings will require both the manufacturer
and architecture fields to match.
I'll be updating doc.byuu.org soon with the finalized game manifest
format.
byuu says:
Changelog:
- Emulator: update to final manifest syntax
- Super Famicom: new board syntax (still experimental)
- Super Famicom: match (manufacturer.)category.type instead of
(model.)category.type
Errata:
- Markup::Node::find() needs to be extended to support multiple
subtype matches
- Sufami Turbo ROM/RAM nodes are part of separate gamepaks; need to
refactor this
byuu says:
Changelog:
- manifest: memory/battery now resides under type at
memory/type/battery
- genius: volatile option changed to battery; auto-disables when not
RAM or RTC type
- higan: added new Emulator::Game class to parse manifests for all
emulated systems consistently
- Super Famicom: board manifest appended to manifest viewer now
- Super Famicom: cartridge class updated to use Emulator::Game objects
- hiro: improve suppression of userland callbacks once
Application::quit() is called
- this fixes a crash in genius when closing the window with a tree
view item selected
My intention is to remove Emulator::Interface::sha256(), as it's not
really useful. They'll be removed from save states as well. I never
bothered validating the SHA256 within them, because that'd be really
annoying for ROM hackers.
I also intend to rename Emulator::Interface::title() to label() instead.
Most everything is still broken. The SNES still needs all the board
definitions updated, all the other cores need to move to using
Emulator::Game.
byuu says:
Changelog:
- higan, icarus, genius: new manifest syntax (work in progress)
Pretty much only LoROM and HiROM SNES games will load right now, and RAM
will only work right if the save.ram file already exists to pull its
file size from (a temporary cheap hack was used.)
Basically, I'm just getting this out there for evaluation.
One minor errata is that I switched icarus to using “memory/battery” to
indicate battery-backed RAM, whereas genius still uses “memory/volatile”
to indicate non-battery-backed RAM.
I intend to make it “memory/battery” in genius, and have the field
auto-enable when RAM or RTC is selected for type (obviously allowing it
to be unchecked for volatile memory.)
I need to update all 64 production boards, and 25 of 29 generic boards,
to use the new slot syntax; and I also need to update every single core
in higan to use the new manifest game syntax. I want to build out a
generic manifest game parser that all emulation cores will use.
Once I finish this, I'll also need to write a database converter to
update all of my licensed game dumps to the new database syntax.
I also need to write up something for doc.byuu.org explaining the new
manifest game syntax. The manifest board syntax will still be “internal”
and subject to revisions, but once v107 is out, the gamepak manifest
format will be set in stone sans extensions.
byuu says:
Changelog:
- Game Boy: fixed RAM/RTC saving¹
- Super Famicom: ICD2 renamed to ICD (there exists an SGB prototype
with a functionally identical ICD1)
- Sufami Turbo: removed short-circuiting when loading an unlinkable
cartridge into slot A²
- Super Game Boy: the 20971520hz clock of the SGB2 is now emulated
- Super Famicom: BSC-1Lxx (SA1) boards now prompt for BS memory
cartridges; and can make use of them³
- Super Famicom: fixed a potential for out-of-bounds reads with BS
Memory flash carts
¹: I'm using a gross hack of replacing `type: ` with `type:` so that
`memory(type=...)` will match without the extra spaces. I need to
think about whether I want the BPath query syntax to strip whitespace or
not. But longer term, I want to finalize game/memory's design, and build
a higan/emulation/manifest parser that produces a nicer interface to
reading manifests for all cores, which will make this irrelevant for
higan anyway.
²: I don't think it's appropriate for higan to enforce this. Nothing
stops you from inserting games that can't be linked into a real Sufami
Turbo. I do short-circuit if you cancel the first load, but I may allow
loading an empty slot A with a populated slot B. I think the BIOS does
something when you do that. Probably just yells at you.
³: I know it's emulated correctly now, but I still don't know what
the heck changes when you load the SD Gundam G Next - Unit & Map
Collection BS Memory cartridge with SD Gundam G Next to actually test
it.
byuu says:
Changelog:
- Super Game Boy: for the 50th time, higan won't segfault if you
cancel the Game Boy cartridge load request
- icarus: moved to new manifest syntax for all remaining systems
- Game Boy: moved to new manifest syntax
Errata:
- Game Boy: save RAM does not appear to be working for some reason
- Famicom: higan won't even start to run this system; it just acts
like a cartridge was never loaded ...
- cores outside of the Super Famicom and Game Boy/Color will not run
due to icarus/higan manifest syntax differences
byuu says:
Changelog:
- icarus: new Firmware/ folder, which is used to import external
firmware when it's missing from the ROM image
- icarus: improved Super Famicom heuristics; including Shift-JIS to
UTF-8 encoding of game titles
Errata:
- if firmware isn't appended, it still cuts out the size from the
memory/program.rom file
- boards.bml is still missing the new Japanese production boards
byuu says:
Changelog:
- Super Famicom: added remaining generic board types
- icarus: improved Super Famicom heuristics
- icarus: reworked BS Memory heuristics
- icarus: reworked Sufami Turbo heuristics
Notes: this is really complicated, and is going to take a long time to
work 100% smoothly again.
Starting off, I am trying to get rid of the weird edge case zero-byte
SRAM mapping for the Cx4. It has the RAM region present, but returns
logic low (0x00) instead of open bus, when SRAM isn't present. I started
by making it `map=ram` instead of `ram/map`, which is gross, and then it ended
up detecing the map tag ending in RAM and pulling the Cx4 data RAM into that
slot. Ugh. The preservation board mapping is still as it was before and will
need to be updated once I get the syntax down.
The BS Memory and Sufami Turbo moving to the new `game/memory`
ending means I can't use the SuperFamicom::Cartridge::loadMemory
function that looks at the old-style rom/ram tags. Because I didn't
write more code, the result is those sub-carts won't load now.
The old heuristics were short-circuiting on SA1 before bothering with
BS-X slots, so that's why SD Gundam G-Next wasn't asking for a data
pack. The problem is, I don't know where the BS-X pack maps to on this
cartridge. It's at c0-ef on the other BS-X slotted cartridges, but
that's mapped to the SA1 on regular SA1 cartridges, so ... for now, it's
not actually mapped in.
I'm still struggling with naming conventions on all these boards. I'll
make a public post about that, though.
byuu says:
Changelog:
- nall: `Markup::Node::operator[]` now uses `find()` instead of `lookup()`
behind the scenes
- Super Famicom: RAM memory ordering is now independent of ROM memory
ordering
- Super Famicom: added 19 new generic board definitions
- icarus: improved Super Famicom heuristics generation
Not putting it in the changelog, but the SPC7110 RAM now has write
protection disabled again.
99% of games should now be playable with heuristics. The exceptions
should be:
- 4MB LoROM games with SRAM (Ys 3, FE: Thracia 776)
- 2MB DSP LoROM games
- BS-X Town
- BS-X slotted games
- SA1 BSX slotted games
- SPC7110 games without the RTC (Momotarou Dentetsu Happy, Super Power
League 4)
- SPC7110 7MB fan translation (wasn't supported earlier either)
- ExLoROM games (wasn't supported earlier either)
- Sufami Turbo
- Campus Challenge '92 and Powerfest '94
- ST010 is going to run at 15MHz instead of 11MHz
- MSU1 (needs to be supported in higan, not icarus)
I'll add support for most of these before the release of v107.
byuu says:
Changelog:
- Super Famicom: update to newer board markup syntax
- Super Famicom: update all mapped ROMs to be write-protected
- errata: SPC7110 set ram.writeProtect(true), I'll fix it in the
next WIP
- icarus: rewrote the Super Famicom heuristics module from scratch
Instead of icarus heuristics generating higan-specific mappings, it now
generates generic board IDs that can be used by any emulator. I had
originally planned to print out real PCB ID codes here, but these board
mappings are meant to be more generic, and I don't want them to look
real. The pseudo-codes are easy to parse, for example: `DSP-LOROM-NVRAM`
for Super Mario Kart, `SUPERFX-RAM` for Doom.
I'm going to make a `Boards (Generic).bml` file that will contain mapping
definitions for every board. Until this is done, any games not in the SNES
preservation database will fail to play because the mapping information is
now missing.
byuu says:
Changelog:
- Super Famicom: added support for loading manifests without embedded
mapping information¹
- genius: initial commit
- various Makefile cleanups
¹: so the idea here is to try and aim for a stable manifest format,
and to allow direct transposition of icarus/genius database entries into
manifest files. The exact mechanics of how this is going to work is
currently in flux, but we'll get there.
For right now, `Super Famicom.sys` gains `boards.bml`, which is the raw
database from my board-editor tool, and higan itself tries to load
`boards.bml`, match an entry to game/board from the game's `manifest.bml`
file, and then transform it into the format currently used by higan. It
does this only when the game's `manifest.bml` file lacks a board node.
When such a board node exists, it works as previous versions of higan
did.
The only incompatible change right now is information/title is now
located at game/label. I may transition window title display to just use
the filenames instead.
Longer term, some thought is going to need to go into the format of the
`boards.bml` database itself, and at which point in the process I should
be transforming things.
Give it time, we'll refine this into something nicer.
byuu says:
Changelog:
- Z80: infinite DD/FD prefixes will no longer cause an emulator crash;
but will still deadlock savestates
- Z80: emulated R incrementing on M1 cycles
- Z80: `LD a, [ir]` should update flags [hex_usr]
- Z80: minor code cleanups
- tomoko: added “Pause Emulation” toggle to Tools menu
- you can still use the hotkey to pause emulation before starting
a game if you really want to
- this will be useful if and when I re-add trace logging to
capture instructions from power-on
- icarus: more PAL games added to the SNES database
I hope I've implemented R correctly. It should only increment twice on
DD,FD CB xx instructions. LDI/LDD/LDIR/LDDR should work as expected as
well. It increments once when interrupts are executed (and not maksed.)
The top bit is ignored in increments.
byuu says:
Changelog (since v105tr1):
Changelog:
- added Emulation/AutoSaveMemory/Interval setting to specify number of
seconds between auto-saves
- added Game Notes tool
- added 64 new SNES PAL games to the icarus preservation database
The Games Notes tool is a new feature that gives you a blank text box to
enter notes about a game that you're playing: so you can write down
things like level select codes for games with save RAM, combo moves, or
whatever other information you'd like quick and easy access to.
This is kind of an experiment. Ideally, we'd wanna allow more
personalized information, drawings, etc. But hey, let's try it out and
see what people think.
It seems on Windows, `compiler` has defaulted to `g++` for a while now,
so we didn't need to override it in the `make` invocation.
Since v105r01, `compiler` defaults to `g++` on Linux too, so we don't
need to override it there either.
By default, mkdocs uses "highlight.js" to apply syntax-highlighting
to code blocks. Left to its own devices, highlight.js will guess the
language being used in the code block, apply the "hljs" CSS class
(so the code block will be given a nice border, a sensible font-size,
etc.) and apply the appropriate formatting markup. If it guesses wrongly,
you can give a language hint on the opening line of the block.
If you use a language that highlight.js does not recognise, or
the special name "nohighlight", highlight.js will leave the block
alone. Unfortunately, in mkdocs' default theme, that means it will be
formatted like *inline* code, with a border and background that wraps
behind each line of the block.
In order to make a code-block that looks like a code-block, you have
to carefully pick a language that highlight.js has heard of, but whose
syntax is sufficiently different from whatever's in the block that no
unwanted highlighting will occur.
This seems to be fixed in the readthedocs theme that comes with mkdocs
0.16.1, but ReadTheDocs doesn't actually seem to be using that version. :/
byuu says:
Changelog:
- higan: readded support for soft-reset to Famicom, Super Famicom,
Mega Drive cores (work in progress)
- handhelds lack soft reset obviously
- the PC Engine also lacks a physical reset button
- the Master System's reset button acts like a gamepad button, so
can't show up in the menu
- Mega Drive: power cycle wasn't initializing CPU (M68K) or APU (Z80)
RAM
- Super Famicom: fix SPC700 opcode 0x3b regression; fixes Majuu Ou
[Jonas Quinn]
- Super Famicom: fix SharpRTC save regression; fixes Dai Kaijuu
Monogatari II's real-time clock [Talarubi]
- Super Famicom: fix EpsonRTC save regression; fixes Tengai Makyou
Zero's real-time clock [Talarubi]
- Super Famicom: removed `*::init()` functions, as they were never used
- Super Famicom: removed all but two `*::load()` functions, as they
were not used
- higan: added option to auto-save backup RAM every five seconds
(enabled by default)
- this is in case the emulator crashes, or there's a power outage;
turn it off under advanced settings if you want
- libco: updated license from public domain to ISC, for consistency
with nall, ruby, hiro
- nall: Linux compiler defaults to g++; override with g++-version if
g++ is <= 4.8
- FreeBSD compiler default is going to remain g++49 until my dev
box OS ships with g++ >= 4.9
Errata: I have weird RAM initialization constants, thanks to hex_usr
and onethirdxcubed for both finding this:
http://wiki.nesdev.com/w/index.php?title=CPU_power_up_state&diff=11711&oldid=11184
I'll remove this in the next WIP.
Added LICENSE.txt and GPLv3.txt. Also updated libco documentation.
After discussion with byuu, libco gets a more specific ISC license
to match nall, ruby and hiro. higan, as clarified in LICENSE.txt,
continues to be GPL version 3 only (no "or later" clause).
Loading and unloading the RTC is a little odd, since it's normally
always powered in the first place. What we want, and what the load()
functions really do, is to resync using the saved timestamps or
reset it. unload() proper doesn't do anything.
However, an interface refactoring after v098 reordered the above
operations, and this (along with a typo, shh!) was causing the already
synced time to be cleared.
I've added checks so that whenever rtc.ram can't be found, load() gets
called with empty arguments to initialise the defaults (like putting
in a fresh battery).
git requires a name and email to be configured before it can commit a change. We're not going to push the merge result anywhere, so we don't strictly speaking need it to commit.
byuu says:
This release provides several major improvements to Mega Drive emulation
which enhances compatibility a good deal. It also includes important
Super Famicom mosaic emulation improvements, plus a much-needed SuperFX
save state issue fix.
Changelog (since v104):
- higan: many improvements to Emulator::Interface to support
forks/frontends
- higan: refreshed program icon
- icarus: new program icon
- Game Boy Advance: slight emulation speedup over v104
- Game Boy Advance: synchronize APU FIFO updates better
- Mega Drive: added automatic region detection [hex_usr]
- Mega Drive: support 8-bit SRAM
- Game Boy Advance: fixed bug when changing to THUMB mode via MSR
[MerryMage]
- Master System: fix bug in backdrop color and background 0 priority
[hex_usr]
- Mega Drive: backgrounds always update output priority bit [Cydrak]
- Mega Drive: emulated interlaced video output
- Mega Drive: emulated shadow/highlight mode [Cydrak]
- Super Famicom: auto joypad polling clears the shift register when
starting
- Super Famicom: added new low-entropy RAM initialization mode to more
closely match hardware
- Game Boy Advance: rumble will now time out after being left on for
500ms
- ruby: improved rumble support in udev input driver [ma_rysia]
- M68K: `move.b (a7)[+/-]` adjust a7 by two
- M68K: illegal/lineA/lineF opcodes do not modify the stack register
- Mega Drive: emulate VIP status bit
- uPD7725: improved emulation of OV1/S1 flags [byuu, AWJ, Lord
Nightmare]
- uPD7725: improved handling of DP, RP updates [Jonas Quinn]
- Super Famicom: improved emulation of mosaic effects in hires,
interlace, and offset-per-tile modes [byuu, Cydrak]
- ruby: improved Direct3D exclusive mode monitor selection [Cydrak]
- Super Famicom: fixed save state bug affecting SuperFX games
[Cydrak]
- Mega Drive: added workaround for Clang compiler bug; allowing this
core to work on macOS [Cydrak, Sintendo]
- higan: hotkeys now also trigger when the main window lacks focus yet
higan is set to allow input on focus loss
- higan: fixed an edge case where `int16_t` ↔ `double` audio
conversion could possibly result in overflows
- higan: fixed a crash on macOS when choosing quit from the
application menu [ncbncb]
Changelog (since the previous WIP):
- higan: restored `make console=true`
- tomoko: if you allow input when main window focus is lost, hotkeys
can now be triggered without focus as well
- hiro/cocoa: fix crash on exit from menu [ncbncb]
- ruby: smarter `double` → `int16_t` conversion to prevent
underflow/overflow
byuu says:
Changelog:
- processor/m68k: fix error in disassembler [Sintendo]
- processor/m68k: work around Clang compiler bug [Cydrak, Sintendo]
This is one of the shortest WIPs I've done, but I'm trying not to change
anything before v105.
byuu says:
Changelog:
- processor/upd96050: always potentially update S1 on ALU ops, sans NOP
- theory by Lord Nightmare. I'm impartial on this one, but may as
well match his design
- sfc: fixed save state hang [reported by FitzRoy; fixed by Cydrak]
- icarus: do not save settings.bml file when in library mode
byuu says:
Changelog:
- processor/huc6280,mos6502,wdc65816: replaced abbreviated opcode
names with descriptive names
- nall: replaced `PLATFORM_MACOSX` define with `PLATFORM_MACOS`
- icarus: added `Icarus::missing() -> string_vector` to list missing
appended firmware files by name
- ruby, hiro: fix macosx→macos references
The processor instruction renaming was really about consistency with the
other processor cores. I may still need to do this for one or two more
processors.
The icarus change should allow a future release of the icarus
application to import games with external SNES coprocessor firmware once
again. It will also allow this to be possible when used in library mode.
byuu says:
Changelog:
- Emulator::Interface::videoResolution() -\> VideoResolution renamed
to videoInformation() -\> VideoInformation
- added double VideoInformation::refreshRate
- higan: added `binary := (application|library)` — set this to
`library` to produce a dynamic link library
- higan: removed `-march=native` for macOS application builds; and for
all library builds
- higan: removed `console` build flag; uncomment `link += -mwindows`
instead
- nall/GNUmakefile: `macosx` platform renamed `macos`
- still need to do this for nall/intrinsics.hpp
- Game Gear: return region=NTSC as the only option, so that the system
frequency is always set correctly
- hiro/cocoa: fixed typo [Sintendo]
- hiro/Windows: removed GetDpiForMonitor, as it's Windows 8+ only; DPI
is no longer per-monitor aware
- icarus: core Icarus class now has virtual functions for
directory::create, <file::exists>, <file::copy>, <file::write>
- icarus: Sufami Turbo can import save RAM files now
- icarus: setting `ICARUS_LIBRARY` define will compile icarus without
main(), GUI components
- ruby/video/Direct3D: choose the current monitor instead of top-left
monitor for fullscreen exclusive [Cydrak]
- ruby/video/Direct3D: do not set `WS_EX_TOPMOST` on fullscreen
exclusive window [Cydrak]
- this isn't necessary for exclusive mode, and it just makes
getting out of the application more difficult
byuu says:
Changelog:
- nall/GNUmakefile: build=release changed to -O2, build=optimize is
now -O3
- hiro: added Monitor::dpi(uint index) → Position [returns logical
DPI for x, y]
- Position is a bad name, but dpi(monitor).(x,y)() make more sense
than .(width,height)()
- hiro: Position, Size, Geometry, Font changed from using signed int
to float
- hiro: Alignment changed from using double to float
- hiro: added skeleton (unused) Application::scale(), setScale()
functions
Errata:
- hiro/cocoa's Monitor::dpi() is untested. Probably will cause issues
with macOS' automatic scaling.
- hiro/gtk lacks a way to get both per-monitor and per-axis (x,y) DPI
scaling
- hiro/qt lacks a way to get per-monitor DPI scaling (Qt 5.x has this,
but I still use Qt 4.x)
- and just to get global DPI, hiro/qt's DPI retrieval has to use
undocumented functions ... fun
The goal with this WIP was basically to prepare hiro for potential
automatic scaling. It'll be extremely difficult, but I'm convinced that
it must be possible if macOS can do it.
By moving from signed integers to floats for coordinates, we can now
scale and unscale without losing precision. That of course isn't the
hard part, though. The hard part is where and how to do the scaling. In
the ideal application, hiro/core and hiro/extension will handle 100% of
this, and the per-platform hiro/(cocoa,gtk,qt,windows) will not be aware
of what's going on, but ... to even make that possible, things will need
to change in every per-platform core, eg the per-platform code will have
to call a core function to change geometry, which will know about the
scaling and unscale the values back down again.
Gonna be a lot of work, but ... it's a start.
byuu says:
Changelog:
- higan: URLs updated to HTTPS
- sfc/ppu/background: use hires/interlace/mosaic-adjusted X/Y
coordinates for offset-per-tile mode
- sfc/ppu/background: hires mosaic seems to advance pixel counter on
subscreen pixels
- tomoko: added “Help→Credits” menu option (currently the page does
not exist; should before v105)
- tomoko: reduced volume slider from {0% - 500%} to {0% - 200%}.
Distortion is too intense above 200%.
- technically, I've encountered distortion at 200% as well in
Prince of Persia for the SNES
- nall/run/invoke: use program path for working directory
- allows you to choose “Library→Import ROMs” from a different
directory on the command-line
I don't know how to assign credit for the mosaic stuff. It's been a
work-in-progress with me, Cydrak, and hex_usr.
The current design should be correct, but very unpleasant. The code
desperately needs to be refactored, but my recent attempt at doing so
ended in spectacular failure.
byuu says:
Changelog:
- sfc/ppu/background: minor code cleanup and simplification
- sfc/ppu/background: $2106 MOSAIC register was implemented
incorrectly
- sfc/ppu/background: fixed mosaic effects in hires mode (temporary
fix)
- sfc/ppu/background: fixed mosaic effects in interlace mode [Cydrak]
Errata:
- sfc/ppu/background/background.cpp:48: should be
`if(!mosaic.enable) {`
Turns out there is only one mosaic size, and the other four bits are
per-BG mosaic enable. This matters a lot for hires/interlace, as
mosaicSize=0 (2x2) is not the same thing as mosaicEnable=false (1x1).
Although I've now implemented this, I really don't like how my mosaic
implementation works right now. I tried to redesign the entire system,
and completely failed. So I started over from v104r10 again and instead
went with a more evolutionary improvement for now. I'll keep trying.
Also, the combination of mosaic + offset-per-tile is still sketchy, as
is mode 6 offset-per-tile. I'll get to those in the future as well.
byuu says:
Changelog:
- processor/upd96050: per manual errata note, SGN always uses SA1;
never SB1 [fixes v104r09 regression]
- processor/upd96050: new OV1/S1 calculation that doesn't require OV0
history buffer [AWJ]
- processor/upd96050: do not update DP in OP if DST=4 [Jonas Quinn]
- processor/upd96050: do not update RP in OP if DST=5 [Jonas Quinn]
- resource: recreated higan+icarus icons, higan logo as 32-bit PNGs
So higan v104r08 and earlier were 930KiB for the source tarball. After
creating new higan and icarus icons, the size jumped to 1090KiB, which
was insane for only adding one additional icon.
After digging into why, I discovered that ImageMagick defaults to
64-bit!! (16-bits per channel) PNG images when converting from SVG.
You know, for all those 16-bit per channel monitors that don't exist.
Sigh. Amazingly, nobody ever noticed this.
The logo went from 78.8KiB to 24.5KiB, which in turn also means the
generated resource.cpp shrank dramatically.
The old higan icon was 32-bit PNG, because it was created before I
installed FreeBSD and switched to ImageMagick. But the new higan icon,
plus the new icarus icon, were both 64-bit as well. And they're now
32-bit.
So the new tarball size, thanks to the logo optimization, dropped to
830KiB.
Cydrak had some really interesting results in converting higan's
resources to 8-bit palletized PNGs with the tRNS extension for alpha
transparency. It reduces the file sizes even more without much visual
fidelity loss. Eg the higan logo uses 778 colors currently, and 256
represents nearly all of it very well to the human eye. It's based off
of only two colors, the rest are all anti-aliasing. Unfortunately,
nall/image doesn't support this yet, and I didn't want to flatten the
higan logo to not have transparency, in case I ever want to change the
about screen background color.
byuu says:
Changelog:
- processor/upd96050: SGN should select between (A,B).S1 flag using
ASL opcode bit
- processor/upd96050: use a temporary to cache new S1, then compute
OV1 using old S1, then assign new S1
- processor/upd96050: add SR.(siack,soack) and connect to relevant
jump instructions (serial not implemented)
- processor/upd96050: initialize SR properly in power() [r08
regression]
- icarus: improve Makefile rules [Screwtape]
- higan: new program icon
- icarus: new program icon
I've generally tried to keep to en_AU spellings rather than en_US spellings
for the sake of my own sanity, but it's difficult when documenting a program
that exclusively uses en_US spellings since I'm quoting the text on
menu-items and in config files.
Strictly speaking, there's no dependency between them, but higan's
install target happens to create the destination bin directory if it
doesn't already exist, so we want to run that install script first.
Sufami Turbo games are in a separate set now, they don't have the "(ST)"
marker in the filename.
Satellaview memory paks may have "(BS)", "(BS SoundLink)" or "(BSROM)"
for various reasons that aren't important to higan, so let's just not mention
them at all.
byuu says:
Changelog:
- processor/upd96050: code cleanups
- processor/upd96050: improved emulation of S1/OV1 flags [thanks to
Cydrak, Lord Nightmare]
- tomoko/settings/audio: reduced the size of the frequency/latency
combo boxes to show longer device driver names
Errata: I need to clear regs.sr in uPD96050::power()
Note: the S1/OV1 emulation is likely not 100% correct yet, but it's a
step in the right direction. No SNES games actually use S1/OV1, so this
shouldn't result in any issues, I'd just like to have this part of the
chip emulated correctly.
byuu says:
Changelog:
- md/vdp: added VIP bit to status register; fixes Cliffhanger
- processor/m68k/disassembler: added modes 7 and 8 to LEA address
disassembly
- processor/m68k/disassembler: enhanced ILLEGAL to display LINEA/LINEF
$xxx variants
- processor/m68k: ILLEGAL/LINEA/LINEF do not modify the stack
register; fixes Caeser no Yabou II
- icarus/sfc: request sgb1.boot.rom and sgb2.boot.rom separately; as
they are different
- icarus/sfc: removed support for external firmware when loading ROM
images
The hack to run Mega Drive Ballz 3D isn't in place, as I don't know if
it's correct, and the graphics were corrupted anyway.
The SGB boot ROM change is going to require updating the icarus database
as well. I will add that in when I start dumping more cartridges here
soon.
Finally ... I explained this already, but I'll do so here as well: I
removed icarus' support for loading SNES coprocessor firmware games with
external firmware files (eg dsp1.program.rom + dsp1.data.rom in the same
path as supermariokart.sfc, for example.)
I realize most are going to see this as an antagonizing/stubborn move
given the recent No-Intro discussion, and I won't deny that said thread
is why this came to the forefront of my mind. But on my word, I honestly
believe this was an ineffective solution for many reasons not related to
our disagreements:
1. No-Intro distributes SNES coprocessor firmware as a merged file, eg
"DSP1 (World).zip/DSP1 (World).bin" -- icarus can't possibly know
about every ROM distribution set's naming conventions for firmware.
(Right now, it appears GoodSNES and NSRT are mostly dead; but there
may be more DATs in the future -- including my own.)
2. Even if the user obtains the firmware and tries to rename it, it
won't work: icarus parses manifests generated by the heuristics
module and sees two ROM files: dsp1.program.rom and dsp1.data.rom.
icarus cannot identify a file named dsp1.rom as containing both
of these sub-files. Users are going to have to know how to split
files, which there is no way to do on stock Windows. Merging files,
however, can be done via `copy /b supermariokart.sfc+dsp1.rom
supermariokartdsp.sfc`; - and dsp1.rom can be named whatever now.
I am not saying this will be easy for the average user, but it's
easier than splitting files.
3. Separate firmware breaks icarus' database lookup. If you have
pilotwings.sfc but without firmware, icarus will not find a match
for it in the database lookup phase. It will then fall back on
heuristics. The heuristics will pick DSP1B for compatibility with
Ballz 3D which requires it. And so it will try to pull in the
wrong firmware, and the game's intro will not work correctly.
Furthermore, the database information will be unavailable, resulting
in inaccurate mirroring.
So for these reasons, I have removed said support. You must now load
SNES coprocessor games into higan in one of two ways: 1) game paks with
split files; or 2) SFC images with merged firmware.
If and when No-Intro deploys a method I can actually use, I give you all
my word I will give it a fair shot and if it's reasonable, I'll support
it in icarus.
byuu says:
Changelog:
- gba,ws: removed Thread::step() override¹
- processor/m68k: move.b (a7)+ and move.b (a7)- adjust a7 by two, not
by one²
- tomoko: created new initialize(Video,Audio,Input)Driver() functions³
- ruby/audio: split Audio::information into
Audio::available(Devices,Frequencies,Latencies,Channels)³
- ws: added Model::(WonderSwan,WonderSwanColor,SwanCrystal)()
functions for consistency with other cores
¹: this should hopefully fix GBA Pokemon Pinball. Thanks to
SuperMikeMan for pointing out the underlying cause.
²: this fixes A Ressaha de Ikou, Mega Bomberman, and probably more
games.
³: this is the big change: so there was a problem with WASAPI where
you might change your device under the audio settings panel. And your
new device may not support the frequency that your old device used. This
would end up not updating the frequency, and the pitch would be
distorted.
The old Audio::information() couldn't tell you what frequencies,
latencies, or channels were available for all devices simultaneously, so
I had to split them up. The new initializeAudioDriver() function
validates you have a correct driver, or it defaults to none. Then it
validates a correct device name, or it defaults to the first entry in
the list. Then it validates a correct frequency, or defaults to the
first in the list. Then finally it validates a correct latency, or
defaults to the first in the list.
In this way ... we have a clear path now with no API changes required to
select default devices, frequencies, latencies, channel counts: they
need to be the first items in their respective lists.
So, what we need to do now is go through and for every audio driver that
enumerates devices, we need to make sure the default device gets added
to the top of the list. I'm ... not really sure how to do this with most
drivers, so this is definitely going to take some time.
Also, when you change a device, initializeAudioDriver() is called again,
so if it's a bad device, it will disable the audio driver instead of
continuing to send samples at it and hoping that the driver blocked
those API calls when it failed to initialize properly.
Now then ... since it was a decently-sized API change, it's possible
I've broken compilation of the Linux drivers, so please report any
compilation errors so that I can fix them.
byuu says:
Changelog:
- emulator/random: new array function with more realistic RAM
initializations
- emulator/random: both low and high entropy register initializations
now use PCG
- gba/player: rumble will time out and disable after being left on for
500ms; fixes Pokemon Pinball issue
- ruby/input/udev: fixed rumble effects [ma\_rysia]
- sfc/system: default to low-entropy randomization of memory
The low-entropy memory randomization is modeled after one of my SHVC
2/1/3 systems. It generates striped patterns in memory, using random
inputs (biased to 0x00/0xff), and has a random chance of corrupting 1-2
bits of random values in the pool of memory (to prevent easy emulator
detection and to match observed results on hardware.)
The reasoning for using PCG on register initializations, is that I don't
believe they're going to have repeating patterns like RAM does anyway.
And register initializations are way more vital.
I want to have the new low-entropy RAM mode tested, so at least for the
next few WIPs, I've set the SNES randomization over to low-entropy.
We'll have to have a long discussion and decide whether we want official
releases to use high-entropy or low-entropy.
Also, I figured out the cause of the Prince of Persia distortion ... I
had the volume under the audio settings tab set to 200%. I didn't
realize there were SNES games that clipped so easily, given how
incredibly weak SNES audio is compared to every other sound source on my
PC. So with no entropy or low-entropy, indeed the game now sounds just
fine.
I can't actually test the udev fixes, so I guess we'll see how that goes
for Screwtape and ma\_rysia.
I made a change to ruby/input/joypad/udev.cpp while diagnosing a problem
with higan's rumble behaviour on Linux, and accidentally committed it
in 15b3dc8b0b as part of a documentation
change.
byuu says:
Changelog:
- higan/emulator: added new Random class with three entropy settings:
none, low, and high
- md/vdp: corrected Vcounter readout in interlace mode [MoD]
- sfc: updated core to use the new Random class; defaults to high
entropy
No entropy essentially returns 0, unless the random.bias(n) function is
called, in which case, it returns n. In this case, n is meant to be the
"logical/ideal" default value that maximizes compatibility with games.
Low entropy is a very simple entropy modeled after RAM initialization
striping patterns (eg 32 0x00s, followed by 32 0xFFs, repeating
throughout.) It doesn't "glitch" like real hardware does on rare
occasions (parts of the pattern being broken from time to time.) It also
only really returns 0 or ~0. So the entropy is indeed extremely low, and
not very useful at all for detecting bugs. Over time, we can try to
improve this, of course.
High entropy is PCG. This replaces the older, lower-entropy and more
predictable, LFSR. PCG should be more than enough for emulator
randomness, while still being quite fast.
Unfortunately, the bad news ... both no entropy and low entropy fix the
Konami logo popping sound in Prince of Persia, but all three entropy
settings still cause the distortion in-game, especially evident at the
title screen. So ... this may be a more serious bug than first
suspected.
The file was originally named `higan-config.md` because the dialog box
it described was called "higan Configuration", which was because the
menu-item to open it was in a menu called "Settings" and it would have
been weird to have a "Settings" item in a "Settings" menu.
Now there are individual menu-items for each tab in the Settings dialog,
none of which are named Settings, so the dialog has been renamed back to
"Settings", and the filename should match.
For Windows documentation, "folder" is the correct term. For generic
documentation, probably either would do but I suspect people are
slightly more likely to be familiar with "folder".
byuu says:
Changelog:
- md/vdp: added full interlace emulation [byuu, Sik, Eke, Mask of
Destiny]
- md/vdp: fix an issue with overscan/highlight when setting was
disabled [hex\_usr]
- md/vdp: serialize field, and all oam/objects state
- icarus/md: do not enable RAM unless header 0x1b0-1b1 == "RA"
[hex\_usr]
I really can't believe how difficult the interlace support was to add. I
must have tried a hundred combinations of adjusting Y, Vscroll, tile
addressing, heights, etc. Many of the changes were a wash that improved
some things, regressed others.
In the end I ended up needing input from three different people to
implement what should have been trivial. I don't know if the Mega Drive
is just that weird, if I've declined that much in skill since the days
when I implemented SNES interlace, or if I've just never been that good.
But either way, I'm disappointed in myself for not being able to figure
either this or shadow/highlight out on my own. Yet I'm extremely
grateful to my friends for helping carry me when I get stuck.
Since it wasn't ever documented before, I'm going to try and document
the changes necessary to implement interlace mode for any future
emudevs.
Also, some of the text in the higan and icarus settings docs wanted to
link to a discussion of why we ignore manifests by default; now we have
such a thing.
byuu says:
Changelog:
- md/vdp: backgrounds always update priority bit output [Cydrak]
- md/vdp: vcounter.d0 becomes vcounter.d8 in interlace mode 3
- md/vdp: return field number in interlace modes from status register
- md/vdp: rework scanline/frame counting in main loop so first frame
won't clock to field 1 instead of field 0
- md/vdp: add support for shadow/highlight mode; optimize to minimal
code [Cydrak]
- md/vdp: update outputPixel() to support interlace modes
- sfc/cpu: auto joypad polling start should clear the shift registers;
fixes Nuke (PD)
- thanks to BMF54123 for this bug report
- tomoko: if an invalid video/audio/input driver is found in the
configuration file, it's reset to "None"
- prevents showing the wrong driver under advanced settings; no
longer requires possibly two reboots to fix
Note: the Mega Drive interlace mode 1 should be working fully, but I
don't know any games that use it. Interlace mode 3 (Sonic 2's two-player
mode) does not work at all yet, but this is a good start.
Also, moved the "you should install the GBA BIOS" advice from the
install pages (where I doubt anybody would see it) to the "importing and
playing" guide, which I figure people are more likely to stumble across.
The actually instructions are still in `install/general.md` for lack of
anywhere more appropriate.
byuu says:
Changelog:
- gba/cpu: synchronize to the PPU, not oneself, when the CPU is
stopped
- this bug was patched in the official v104 release; but not in
the .tar.xz archive
- ms/vdp: backdrop color is on the second 16-entry palette, not the
first [hex\_usr]
- ms/vdp: fix background color 0 priority; fixes Alex Kidd in High
Tech World text boxes [hex\_usr]
- tomoko: choose first option when loading files via the command-line
[hex\_usr]
- icarus: lo/hi RAM addressing was backwards; M68K is big endian;
fixes save files in Sonic 3
Many thanks to hex\_usr for the Master System / Game Gear VDP fix.
That's a tricky system to get good technical information on. The fix
should be correct, but please report if you spot any regressions just in
case.
[As mentioned in the v104 internal release notes, byuu fixed a small typo in
the GBA core. -Ed.]
byuu says:
There are lots of improvements in this new release, both to core
emulation and to the user interface. However, some of these changes are
quite substantial, so regressions are a possibility. Please report any
regressions from v103 on the forums if found.
Note that Mega Drive save RAM files will not be compatible with v103,
but will now be compatible with save RAM files from all other Mega Drive
emulators, and the format will be stable going forward.
Also!! Thanks to the tireless work of Screwtape, the
Help->Documentation link in higan now takes you to a very comprehensive
user guide. Please be sure to consult this if you have any questions
about using higan.
Lastly, I've added a link to my Patreon page (https://patreon.com/byuu/)
to the higan downloads page. The money will go exclusively toward
purchasing SNES games for preservation, hardware and flash carts for
reverse engineering, equipment such as backup drives, etc. Donating is
entirely optional and comes with no rewards, but would of course be
greatly appreciated! ^^;
Changelog (since v103):
- nall/dsp: improved first-order IIR filtering
- Famicom: improved audio filtering (90hz lowpass + 440hz lowpass +
14khz highpass)
- Game Boy Advance: corrected bug in PSG wave channel emulation
[Cydrak]
- Mega Drive: added first-order 2.84KHz low-pass filter to match VA6
model hardware
- Mega Drive: lowered PSG volume relative to YM2612 to match VA6 model
hardware
- Mega Drive: Hblank flag is not always set during Vblank
- Mega Drive: fix PAL mode reporting from control port reads
- Famicom: improved phase duty cycle emulation (mode 3 is 25% phase
inverted; counter decrements)
- Mega Drive: reset does not cancel 68K bus requests
- Mega Drive: 68K is not granted bus access on Z80 reset
- Mega Drive: CTRL port is now read-write, maintains value across
controller changes
- Z80: IX, IY override mode can now be serialized in save states
- 68K: fixed calculations for ABCD, NBCD, SBCD [hex\_usr,
SuperMikeMan]
- SPC700: improved all cycle timings to match results observed by
Overload with a logic anaylzer
- Super Famicom: SMP uses a separate 4x8-bit buffer for $f4-f7; not
APU RAM [hex\_usr]
- Super Famicom: SMP TEST register is now finally 100% fully emulated
[byuu, AWJ]
- Game Boy Advance: DMA can run between CPU instruction cycles
- Game Boy Advance: added 2-cycle delay between DMA activation and
transfers
- higan: improved aspect ratio correction accuracy at higher video
scaling sizes
- higan: overscan masking will now actually crop the underlying video
instead of just blanking it
- Mega Drive: center video when overscan is disabled
- higan: added increment/decrement quick save slot hotkeys
- Game Boy Advance: fixed wave RAM nibble ordering (fixes audio in
Castlevania, Pocket NES)
- higan: added new adaptive windowed mode: resizes the window to the
current emulated system's size
- higan: added new integral scaling mode: resizes the window to fill
as much of the screen as possible
- higan: main window is now resizable and will automatically scale
contents based on user settings
- higan: fixed one-time blinking of the main window on startup caused
by focus stealing bug
- ruby: fixed major memory leak in Direct3D driver
- ruby: added fullscreen exclusive mode to Direct3D driver
- Super Famicom: corrected latching behavior of BGnHOFS PPU registers
- higan: all windows sans the main viewport can be dismissed with the
escape key now
- ruby: complete API rewrite; many audio drivers now support device
selection
- higan: output frequency can now be modified
- higan: configuration settings split to individual menu options for
faster access to individual pages
- ruby: improved WASAPI driver to event-driven model; more compatible
in exclusive mode now
- libco: fix compilation of sjlj and fiber targets [Screwtape]
- ruby: added YV12 and I420 support to X-Video driver
- Game Boy: added TAMA emulation (RTC emulation is not working yet)
[thanks to endrift for notes]
- Game Boy: correct data ordering of MMM01 ROMs (MMM01 ROMs will need
to be re-imported into higan)
- Game Boy: store MBC2 save RAM as 256-bytes instead of 512-bytes (RAM
is 4-bit; not 8-bit with padding)
- Game Boy: fixed a bug with RAM serialization in games without a
battery
- Mega Drive: fix CRAM reads (fixes Sonic Spinball) [hex\_usr]
- Game Boy: added rumble support to MBC5 games such as Pokemon Pinball
- Game Boy: added MBC7 emulation (accelerometer X-axis, EEPROM not
working yet) [thanks to endrift for notes]
- hiro: macOS compilation fixes and UI improvements [MerryMage,
ncbncb]
- Game Boy: added MBC6 emulation (no phone link or flash support;
timing bugs in game still)
- Game Boy: HDMA syncs to other components after each byte transfer
now
- Game Boy: disabling the LCD completely halts the PPU (fixes onscreen
graphical corruption in some games)
- Mega Drive: added 6-button Fighting Pad emulation [hex\_usr]
- 68K: TAS sets d7 when EA mode is a direct register (fixes Asterix
graphical corruption)
- Game Boy: STAT mode is forced to zero when LCD is disabled (fixes
Pokemon Pinball)
- LR35902: complete rewrite
- icarus: high-DPI is not supported on Windows yet; remove setting for
consistency with higan window sizes
- hiro: added full support for high-DPI displays on macOS [ncbncb]
- ARM7TDMI: complete rewrite
- Super Famicom: disabled channels during HDMA initialization appear
to set DoTransfer flag
- V30MZ: code cleanup
- Mega Drive: added optional TMSS emulation; disabled by default
[hex\_usr]
- ARM7TDMI: pipeline decode stage caches CPSR.T [MerryMage]
- ARM7TDMI: fixed timing of THUMB stack multiple instruction
[Cydrak]
- higan: detect when ruby drivers crash; disable drivers on next
startup to prevent crash loop
- Mega Drive: added automatic region detection (favors NTSC-J >
NTSC-U > PAL) [hex\_usr]
- Mega Drive: support 8-bit SRAM
- ARM7TDMI: PC should be incremented by 2 when setting CPSR.T via MSR
instruction [MerryMage]
- ruby: add Windows ASIO driver support (does not work on some systems
due to buggy vendor drivers)
- higan: default to safe drivers on a new install; due to instability
with some optimal drivers
The existing documentation was getting *way* too long to be a single
document.
I've just bulk moved the existing content into the new structure, but it
definitely needs another pass to make the prose match, fix hyperlinks,
etc. etc.
Also, remove the sections for importing and playing Game Boy and GBA
games... the Game Boy section was just going to be about black cartridges
anyway, and I have no idea what the GBA section was going to be for.
Wrap SHA256 hashes in `<code/>` so they'll all be visually the same length.
Make the references from DSP1 and DSP1B to the notes below more obviously
references, not content.
Reword the DSP1 note so that it makes sense even if you didn't just come
from the DSP1/1A row of the table.
Also, move the higher-level questions about the game library
and game folders to the end of the section,
so people can more easily find the bits about importing types of game.
byuu says:
Changelog:
- emulator/interface: removed unused Region struct
- gba/cpu: optimized CPU::step() as much as I could for a slight
speedup¹
- gba/cpu: synchronize the APU better during FIFO updates
- higan/md, icarus: add automatic region detection; make it the
default option [hex\_usr]
- picks NTSC-J if there's more than one match ... eventually, this
will be a setting
- higan/md, icarus: support all three combinations of SRAM (8-bit low,
8-bit high, 16-bit)
- processor/arm7tdmi: fix bug when changing to THUMB mode via MSR
[MerryMage]
- tomoko: redesigned crash detector to only occur once for all three
ruby drivers
- this will reduce disk thrashing since the configuration file
only needs to be written out one extra time
- technically, it's twice ... but we should've always been writing
one out on first run in case it crashes then
- tomoko: defaulted back to the safest ruby drivers, given the optimal
drivers have some stability concerns
¹: minor errata: spotted a typo saying `synchronize(cpu)` when the CPU
is stopped, instead of `synchronize(ppu)`. This will be fixed in the v104
official 7zip archives.
I'm kind of rushing here but, it's really good timing for me to push out
a new official release. The blocking issues are resolved or close to it,
and we need lots of testing of the new major changes.
I'm going to consider this a semi-stable testing release and leave links
to v103 just in case.
byuu says:
Changelog:
- Master System: merged Bus into CPU
- Mega Drive: merged BusCPU into CPU; BusAPU into AU
- Mega Drive: added TMSS emulation; disabled by default [hex\_usr]
- VDP lockout not yet emulated
- processor/arm7tdmi: renamed interrupt() to exception()
- processor/arm7tdmi: CPSR.F (FIQ disable) flag is set on reset
- processor/arm7tdmi: pipeline decode stage caches CPSR.T (THUMB mode)
[MerryMage]
- fixes `msr_tests.gba` test F
- processor/arm7tdmi/disassembler: add PC address to left of currently
executing instruction
- processor/arm7tdmi: stop forcing CPSR.M (mode flags) bit 4 high (I
don't know what really happens here)
- processor/arm7tdmi: undefined instructions now generate Undefined
0x4 exception
- processor/arm7tdmi: thumbInstructionAddRegister masks PC by &~3
instead of &~2
- hopefully this is correct; &~2 felt very wrong
- processor/arm7tdmi: thumbInstructionStackMultiple can use sequential
timing for PC/LR PUSH/POP [Cydrak]
- systems/Mega Drive.sys: added tmss.rom; enable with cpu version=1
- tomoko: detect when a ruby video/audio/input driver crashes higan;
disable it on next program startup
v104 blockers:
- Mega Drive: support 8-bit SRAM (even if we don't support 16-bit;
don't force 8-bit to 16-bit)
- Mega Drive: add region detection support to icarus
- ruby: add default audio device information so certain drivers won't
default to silence out of the box
byuu says:
Changelog:
- gba/cpu: slight speedup to CPU::step()
- processor/arm7tdmi: fixed about ten bugs, ST018 and GBA games are
now playable once again
- processor/arm: removed core from codebase
- processor/v30mz: code cleanup (renamed functions; updated
instruction() for consistency with other cores)
It turns out on my much faster system, the new ARM7TDMI core is very
slightly slower than the old one (by about 2% or so FPS.) But the
CPU::step() improvement basically made it a wash.
So yeah, I'm in really serious trouble with how slow my GBA core is now.
Sigh.
As for higan/processor ... this concludes the first phase of major
cleanups and rewrites.
There will always be work to do, and I have two more phases in mind.
One is that a lot of the instruction disassemblers are very old. One
even uses sprintf still. I'd like to modernize them all. Also, the
ARM7TDMI core (and the ARM core before it) can't really disassemble
because the PC address used for instruction execution is not known prior
to calling instruction(), due to pipeline reload fetches that may occur
inside of said function. I had a nasty hack for debugging the new core,
but I'd like to come up with a clean way to allow tracing the new
ARM7TDMI core.
Another is that I'd still like to rename a lot of instruction function
names in various cores to be more descriptive. I really liked how the
LR35902 core came out there, and would like to get that level of detail
in with the other cores as well.
byuu says:
Changelog:
- processor/arm7tdmi: completed implemented
- gba/cpu, sfc/coprocessor/armdsp: use arm7tdmi instead of arm
- sfc/cpu: experimental fix for newly discovered HDMA emulation issue
Notes:
The ARM7TDMI core crashes pretty quickly when trying to run GBA games,
and I'm certain the same will be the case with the ST018. It was never
all that likely I could rewrite 70KiB of code in 20 hours and have it
work perfectly on the first try. So, now it's time for lots and lots of
debugging. Any help would *really* be appreciated, if anyone were up for
comparing the two implementations for regressions =^-^= I often have a
really hard time spotting simple typos that I make.
Also, the SNES HDMA fix is temporary. I would like it if testers could
run through a bunch of games that are known for being tricky with HDMA
(or if these aren't known to said tester, any games are fine then.) If
we can confirm regressions, then we'll know the fix is either incorrect
or incomplete. But if we don't find any, then it's a good sign that
we're on the right path.
byuu says:
Changelog:
- processor/arm7tdmi: implementation all nine remaining ARM
instructions
- processor/arm7tdmi: implemented five more THUMB instructions
(sixteen remain)
byuu says:
Changelog:
- processor/arm7tdmi: implemented 10 of 19 ARM instructions
- processor/arm7tdmi: implemented 1 of 22 THUMB instructions
Today's WIP was 6 hours of work, and yesterday's was 5 hours.
Half of today was just trying to come up with the design to use a
lambda-based dispatcher to map both instructions and disassembly,
similar to the 68K core. The problem is that the ARM core has 28 unique
bits, which is just far too many bits to have a full lookup table like
the 16-bit 68K core.
The thing I wanted more than anything else was to perform the opcode
bitfield decoding once, and have it decoded for both instructions and
the disassembler. It took three hours to come up with a design that
worked for the ARM half ... relying on #defines being able to pull in
other #defines that were declared and changed later after the first
one. But, I'm happy with it. The decoding is in the table building, as
it is with the 68K core. The decoding does happen at run-time on each
instruction invocation, but it has to be done.
As to the THUMB core, I can create a 64K-entry lambda table to cover all
possible encodings, and ... even though it's a cache killer, I've
decided to go for it, given the outstanding performance it obtained in
the M68K core, as well as considering that THUMB mode is far more common
in GBA games.
As to both cores ... I'm a little torn between two extremes:
On the one hand, I can condense the number of ARM/THUMB instructions
further to eliminate more redundant code. On the other, I can split them
apart to reduce the number of conditional tests needed to execute each
instruction. It's really the disassembler that makes me not want to
split them up further ... as I have to split the disassembler functions
up equally to the instruction functions. But it may be worth it if it's
a speed improvement.
byuu says:
Changelog:
- hiro/windows: set dpiAware=false, fixes icarus window sizes relative
to higan window sizes
- higan, icarus, hiro, ruby: add support for high resolution displays
on macOS [ncbncb]
- processor/lr35902-legacy: removed
- processor/arm7tdmi: new processor core started; intended to one day
be a replacement for processor/arm
It will probably take several WIPs to get the new ARM core up and
running. It's the last processor rewrite. After this, all processor
cores will be up to date with all my current programming conventions.
byuu says:
Changelog:
- processor/lr35902: completed rewrite
I'd appreciate regression testing of the Game Boy and Game Boy Color
emulation between v103r24 and v103r26 (skip r25) if anyone wouldn't
mind.
I fixed up processor/lr35902-legacy to compile and run, so that trace
logs can be created between the two cores to find errors. I'm going to
kill processor/lr35902-legacy with the next WIP release, as well as make
changes to the trace format (add flags externally from AF; much easier
to read them that way), which will make it more difficult to do these
comparisons in the future, hence r26 may prove important later on if we
miss regressions this time.
As for the speed of the new CPU core, not too much to report ... at
least it's not slower :)
Mega Man II: 212.5 to 214.5fps
Shiro no Sho: 191.5 to 191.5fps
Oracle of Ages: 182.5 to 190.5fps
byuu says:
Changelog:
- gb/cpu: force STAT mode to 0 when LCD is disabled (fixes Pokemon
Pinball, etc)
- gb/ppu: when LCD is disabled, require at least one-frame wait to
re-enable, display white during this time
- todo: should step by a scanline at a time: worst-case is an
extra 99% of a frame to enable again
- gba/ppu: cache tilemap lookups and attribute parsing
- it's more accurate because the GBA wouldn't read this for every
pixel
- but unfortunately, this didn't provide any speedup at all ...
sigh
- ruby/audio/alsa: fixed const issue with free()
- ruby/video/cgl: removed `glDisable(GL_ALPHA_TEST)` [deprecated]
- ruby/video/cgl: removed `glEnable(GL_TEXTURE_2D)` [unnecessary as
we use shaders]
- processor/lr35902: started rewrite¹
¹: so, the Game Boy and Game Boy Color cores will be completely
broken for at least the next two or three WIPs.
The old LR35902 was complete garbage, written in early 2011. So I'm
rewriting it to provide a massive cleanup and consistency with other
processor cores, especially the Z80 core.
I've got about 85% of the main instructions implemented, and then I have
to do the CB instructions. The CB instructions are easier because
they're mostly just a small number of opcodes in many small variations,
but it'll still be tedious.
byuu says:
Changelog:
- gb/mbc6: mapper is now functional, but Net de Get has some text
corruption¹
- gb/mbc7: mapper is now functional²
- gb/cpu: HDMA syncs other components after each byte transfer now
- gb/ppu: LY,LX forced to zero when LCDC.d7 is lowered (eg disabled),
not when it's raised (eg enabled)
- gb/ppu: the LCD does not run at all when LCDC.d7 is clear³
- fixes graphical corruption between scene transitions in Legend
of Zelda - Oracle of Ages
- thanks to Cydrak, Shonumi, gekkio for their input on the cause
of this issue
- md/controller: renamed "Gamepad" to "Control Pad" per official
terminology
- md/controller: added "Fighting Pad" (6-button controller) emulation
[hex\_usr]
- processor/m68k: fixed TAS to set data.d7 when
EA.mode==DataRegisterDirect; fixes Asterix
- hiro/windows: removed carriage returns from mouse.cpp and
desktop.cpp
- ruby/audio/alsa: added device driver selection [SuperMikeMan]
- ruby/audio/ao: set format.matrix=nullptr to prevent a crash on some
systems [SuperMikeMan]
- ruby/video/cgl: rename term() to terminate() to fix a crash on macOS
[Sintendo]
¹: The observation that this mapper split $4000-7fff into two banks
came from MAME's implementation. But their implementation was quite
broken and incomplete, so I didn't actually use any of it. The
observation that this mapper split $a000-bfff into two banks came from
Tauwasser, and I did directly use that information, plus the knowledge
that $0400/$0800 are the RAM bank select registers.
The text corruption is due to a race condition with timing. The game is
transferring font letters via HDMA, but the game code ends up setting
the bank# with the font a bit too late after the HDMA has already
occurred. I'm not sure how to fix this ... as a whole, I assumed my Game
Boy timing was pretty good, but apparently it's not that good.
²: The entire design of this mapper comes from endrift's notes.
endrift gets full credit for higan being able to emulate this mapper.
Note that the accelerometer implementation is still not tested, and
probably won't work right until I tweak the sensitivity a lot.
³: So the fun part of this is ... it breaks the strict 60fps rate of
the Game Boy. This was always inevitable: certain timing conditions can
stretch frames, too. But this is pretty much an absolute deal breaker
for something like Vsync timing. This pretty much requires adaptive sync
to run well without audio stuttering during the transition.
There's currently one very important detail missing: when the LCD is
turned off, presumably the image on the screen fades to white. I do not
know how long this process takes, or how to really go about emulating
it. Right now as an incomplete patch, I'm simply leaving the last
displayed image on the screen until the LCD is turned on again. But I
will have to output white, as well as add code to break out of the
emulation loop periodically when the LCD is left off eg indefinitely, or
bad things would happen. I'll work something out and then implement.
Another detail is I'm not sure how long it takes for the LCD to start
rendering again once enabled. Right now, it's immediate. I've heard it's
as long as 1/60th of a second, but that really seems incredibly
excessive? I'd like to know at least a reasonably well-supported
estimate before I implement that.
byuu says:
Changelog:
- gb: added accelerometer X-axis, Y-Axis inputs¹
- gb: added rumble input¹
- gb/mbc5: added rumble support²
- gb/mbc6: added skeleton driver, but it doesn't boot Net de Get
- gb/mbc7: added mostly complete driver (only missing EEPROM), but it
doesn't boot Kirby Tilt 'n' Tumble
- gb/tama: added leap year assignment
- tomoko: fixed macOS compilation [MerryMage]
- hiro/cocoa: fix table cell redrawing on updates and automatic column
resizing [ncbncb]
- hiro/cocoa: fix some weird issue with clicking table view checkboxes
on Retina displays [ncbncb]
- icarus: enhance Game Boy heuristics³
- nall: fix three missing return statements [Jonas Quinn]
- ruby: hopefully fixed all compilation errors reported by Screwtape
et al⁴
¹: because there's no concept of a controller for cartridge inputs,
I'm attaching to the base platform for now. An idea I had was to make
separate ports for each cartridge type ... but this would duplicate the
rumble input between MBC5 and MBC7. And would also be less discoverable.
But it would be more clean in that users wouldn't think the Game Boy
hardware had this functionality. I'll think about it.
²: it probably won't work yet. Rumble isn't documented anywhere, but
I dug through an emulator named GEST and discovered that it seems to use
bit 3 of the RAM bank select to be rumble. I don't know if it sets the
bit for rumbling, then clears when finished, or if it sets it and then
after a few milliseconds it stops rumbling. I couldn't test on my
FreeBSD box because SDL 1.2 doesn't support rumble, udev doesn't exist
on FreeBSD, and nobody has ever posted any working code for how to use
evdev (or whatever it's called) on FreeBSD.
³: I'm still thinking about specifying the MBC7 RAM as EEPROM, since
it's not really static RAM.
⁴: if possible, please test all drivers if you can. I want to ensure
they're all working. Especially let me know if the following work:
macOS: input.carbon Linux: audio.pulseaudiosimple, audio.ao (libao)
If I can confirm these are working, I'm going to then remove them from
being included with stock higan builds.
I'm also considering dropping SDL video on Linux/BSD. XShm is much
faster and supports blurring. I may also drop SDL input on Linux, since
udev works better. That will free a dependency on SDL 1.2 for building
higan. FreeBSD is still going to need it for joypad support, however.
byuu says:
Changelog:
- ruby: ported all remaining drivers to new API¹
- ruby/wasapi: fix for dropping one sample per period [SuperMikeMan]
- gb: emulated most of the TAMA RTC; but RTC state is still volatile²
¹: the new ports are:
- audio/{directsound, alsa, pulseaudio, pulseaudiosimple, ao}
- input/{udev, quartz, carbon}
It's pretty much guaranteed many of them will have compilation errors.
Please paste the error logs and I'll try to fix them up. It may take a
WIP or two to get there.
It's also possible things broke from the updates. If so, I could use
help comparing the old file to the new file, looking for mistakes, since
I can't test on these platforms apart from audio/directsound.
Please report working drivers in this list, so we can mark them off the
list. I'll need both macOS and Linux testers.
audio/directsound.cpp:112:
if(DirectSoundCreate(0, &_interface, 0) != DS_OK) return terminate(), false;
²: once I get this working, I'll add load/save support for the RTC
values. For now, the RTC data will be lost when you close the emulator.
Right now, you can set the date/time in real-time mode, and when you
start the game, the time will be correct, and the time will tick
forward. Note that it runs off emulated time instead of actual real
time, so if you fast-forward to 300%, one minute will be 20 seconds.
The really big limitation right now is that when you exit the game, and
restart it, and resume a new game, the hour spot gets corrupted, and
this seems to instantly kill your pet. Fun. This is crazy because the
commands the game sends to the TAMA interface are identical between
starting a new game and getting in-game versus loading a game.
It's likely going to require disassembling the game's code and seeing
what in the hell it's doing, but I am extremely bad at LR35092 assembly.
Hopefully endrift can help here :|
byuu says:
Changelog:
- gb: added TAMA emulation [thanks to endrift for the initial notes]
- gb: save RTC memory to disk (MBC3 doesn't write to said memory yet;
TAMA doesn't emulate it yet)
- gb: expect MMM01 boot loader to be at end of ROM instead of start
- gb: store MBC2 save RAM as 256-bytes (512x4-bit) instead of
512-bytes (with padding)
- gb: major cleanups to every cartridge mapper; moved to Mapper class
instead of MMIO class
- gb: don't serialize all mapper states with every save state; only
serialize the active mapper
- gb: serialize RAM even if a battery isn't present¹
- gb/cartridge: removed unnecessary code; refactored other code to
eliminate duplication of functions
- icarus: improve GB(C) heuristics generation to not include filenames
for cartridges without battery backup
- icarus: remove incorrect rearrangement of MMM01 ROM data
- md/vdp: fix CRAM reads -- fixes Sonic Spinball colors [hex\_usr]
- tomoko: hide the main higan window when entering fullscreen
exclusive mode; helps with multi-monitor setups
- tomoko: destroy ruby drivers before calling Application::quit()
[Screwtape]
- libco: add settings.h and defines to fiber, ucontext [Screwtape]
¹: this is one of those crystal clear indications that nobody's
actually playing the higan DMG/CGB cores, or at least not with save
states. This was a major mistake.
Note: I can't find any official documentation that `GL_ALPHA_TEST` was
removed from OpenGL 3.2. Since it's not hurting anything except showing
some warnings in debug mode, I'm just going to leave it there for now.
byuu says:
Changelog:
- ruby/audio/xaudio2: ported to new ruby API
- ruby/video/cgl: ported to new ruby API (untested, won't compile)
- ruby/video/directdraw: ported to new ruby API
- ruby/video/gdi: ported to new ruby API
- ruby/video/glx: ported to new ruby API
- ruby/video/wgl: ported to new ruby API
- ruby/video/opengl: code cleanups
The macOS CGL driver is sure to have compilation errors. If someone will
post the compilation error log, I can hopefully fix it in one or two
iterations of WIPs.
I am unable to test the Xorg GLX driver, because my FreeBSD desktop
video card drivers do not support OpenGL 3.2. If the driver doesn't
work, I'm going to need help tracking down what broke from the older
releases.
The real fun is still yet to come ... all the Linux-only drivers, where
I don't have a single Linux machine to test with.
Todo:
- libco/fiber
- libco/ucontext (I should really just delete this)
- tomoko: hide main UI window when in exclusive fullscreen mode
byuu says:
Changelog:
- tomoko: Application::onMain assigned at end of Program::Program()
[Screwtape]¹
- libco: add `#define _XOPEN_SOURCE 500` to fix compilation of sjlj.c
[Screwtape]
- ruby/audio/openal: fixed device driver string list enumeration
- ruby/audio/wasapi: changing device re-initializes the driver now
- ruby/audio/wasapi: probably a pointless change, but don't fill the
buffer beyond the queue size with silence
- ruby/video/xvideo: renamed from ruby/video/xv
- ruby/video/xvideo: check to see if `XV_AUTOPAINT_COLORKEY` exists
before setting it [SuperMikeMan]
- ruby/video/xvideo: align buffer sizes to be evenly divisible by four
[SuperMikeMan]
- ruby/video/xvideo: fail nicely without crashing (hopefully)
- ruby/video/xvideo: add support for YV12 and I420 12-bit planar YUV
formats²
¹: prevents crashes when drivers fail to initialize from running the
main loop that polls input drivers before the input driver is
initialized (or fails to initialize itself.) Some drivers still don't
block their main functions when initialization fails, so they will still
crash, but I'll work to fix them.
²: this was a **major** pain in the ass, heh. You only get one chroma
sample for every four luma samples, so the color reproduction is even
worse than UYVY and YUYV (which is two to four chroma to luma.) Further,
the planar format took forever to figure out. Apparently it doesn't care
what portion of the image you specify in XvShmPutImage, it expects you
to use the buffer dimensions to locate the U and V portions of the data.
This is probably the most thorough X-Video driver in existence now.
Notes:
- forgot to rename the configuration settings dialog window title to
just "Settings"
byuu says:
Changelog:
- tomoko: improved handling of changing audio devices on the audio
settings panel
- ruby/audio/wasapi: added device enumeration and selection support¹
- ruby/audio/wasapi: release property store handle from audio device
- ruby/audio/wasapi: fix exclusive mode buffer filling
- ruby/video/glx2: ported to new API -- tested and confirmed working
great²
- ruby/video/sdl: fixed initialization -- tested and confirmed working
on FreeBSD now³
- ruby/video/xv: ported to new API -- tested and mostly working great,
sans fullscreen mode⁴
Errata:
- accidentally changed "Driver Settings" label to "Driver" on the
audio settings tab because I deleted the line and forgot the
"Settings" part
- need to use "return initialize();" from setDevice() in the WASAPI
driver, instead of "return true;", so device selection is currently
not functioning in this WIP for said driver
¹: for now, this will likely end up selecting the first available
endpoint device, which is probably wrong. I need to come up with a
system to expose good 'default values' when selecting new audio drivers,
or changing audio device settings.
²: glx2 is a fallback driver for system with only OpenGL 2.0 and no
OpenGL 3.2 drivers, such as FreeBSD 10.1 with AMD graphics cards.
³: although I really should track down why InputManager::poll() is
crashing the emulator when Video::ready() returns false ...
⁴: really bizarrely, when entering fullscreen mode, it looks like the
image was a triangle strip, and the bottom right triange is missing, and
the top left triangle skews the entire image into it. I'm suspecting
this is a Radeon driver bug when trying to create a 2560x1600 X-Video
surface. The glitch persists when exiting fullscreen, too.
If anyone can test the X-Video driver on their Linux/BSD system, it'd be
appreciated. If it's just my video card, I'll ignore it. If not,
hopefully someone can find the cause of the issue :|
byuu says:
Changelog:
- tomoko: re-hid the video sync option¹
- tomoko: removed " Settings" duplication on all the individual
settings tab options
- ruby/audio/wasapi: finished port to new syntax; adapted to an
event-driven model; support 32-bit integral audio²
- ruby/video/sdl: ported to new syntax; disabled driver on FreeBSD³
¹: still contemplating a synchronize submenu of {none, video, audio},
but ... the fact that video can't work on PAL, WonderSwan games is a
real limitation for it
²: this driver actually received a ton of work. There's also a new
ring-buffer queue, and I added special handling for when exclusive mode
fails because the latency requested is lower than the hardware can
support. It'll pick the closest latency to the minimum that is possible
in this case.
On my Audigy Rx, the results for non-exclusive mode are the same. For
exclusive mode, the framerate drops from 60fps to ~50fps for smaller
buffers, and ~55fps for larger buffers (no matter how big, it never hits
60fps.) This is a lot better than before where it was hitting ~15fps,
but unfortunately it's the best I can do.
The event system used by WASAPI is really stupid. It just uses SetEvent
at some arbitrary time, and you have to query to see how many samples
it's waiting on. This makes it unknowable how many samples we should
buffer before calling `WaitForSingleObject(INFINITE)`, and it's also
unclear how we should handle cases where there's more samples available
than our queue has: either we can fill it with zeroes, or we can write
less samples. The former should prevent audio looping effects when
running too slowly, whereas the latter could potentially be too
ambitious when the audio could've recovered from a minor stall.
It's shocking to me how there's as many ways to send audio to a sound
card as there are sound card APIs, when all that's needed is a simple
double buffer and a callback event from another thread to do it right.
It's also terrifying how unbelievably shitty nearly all sound card
drivers apparently are.
Also, I don't know if cards can output an actual 24-bit mode with three
byte audio samples, or if they always just take 32-bit samples and
ignore the lower 8-bits. Whatever, it's all nonsense for the final
output to be >16-bits anyway (hi, `double[]` input from ruby.)
³: unfortunately, this driver always crashes on FreeBSD (even before
the rewrite), so I'll need someone on Linux to test it and make sure it
actually works. I'll also need testing for a lot of the other drivers as
well, once they're ported over (I don't have X-video, PulseAudio, ALSA,
or udev.)
Note that I forgot to set `_ready=true` at the end of `initialize()`,
and `_ready=false` in `terminate()`, but it shouldn't actually matter
beyond showing you a false warning message on startup about it failing
to initialize.
byuu says:
Changelog:
- emulator/audio: added the ability to change the output frequency at
run-time without emulator reset
- tomoko: display video synchronize option again¹
- tomoko: Settings→Configuration expanded to Settings→{Video,
Audio, Input, Hotkey, Advanced} Settings²
- tomoko: fix default population of audio settings tab
- ruby: Audio::frequency is a double now (to match both
Emulator::Audio and ASIO)³
- tomoko: changing the audio device will repopulate the frequency and
latency lists
- tomoko: changing the audio frequency can now be done in real-time
- ruby/audio/asio: added missing device() information, so devices can
be changed now
- ruby/audio/openal: ported to new API; added device selection support
- ruby/audio/wasapi: ported to new API, but did not test yet (it's
assuredly still broken)⁴
¹: I'm uneasy about this ... but, I guess if people want to disable
audio and just have smooth scrolling video ... so be it. With
Screwtape's documentation, hopefully that'll help people understand that
video synchronization always breaks audio synchronization. I may change
this to a child menu that lets you pick between {no synchronization,
video synchronization, audio synchronization} as a radio selection.
²: given how much more useful the video and audio tabs are now, I
felt that four extra menu items were worth saving a click and going
right to the tab you want. This also matches the behavior of the Tools
menu displaying all tool options and taking you directly to each tab.
This is kind of a hard change to get used to ... but I think it's for
the better.
³: kind of stupid because I've never seen a hardware sound card where
floor(frequency) != frequency, but whatever. Yay consistency.
⁴: I'm going to move it to be event-driven, and try to support 24-bit
sample formats if possible. Who knows which cards that'll fix and which
cards that'll break. I may end up making multiple WASAPI drivers so
people can find one that actually works for them. We'll see.
byuu says:
Changelog:
- ruby: rewrote the API interfaces for Video, Audio, Input
- ruby/audio: can now select the number of output channels (not useful
to higan, sorry)
- ruby/asio: various improvements
- tomoko: audio settings panel can now select separate audio devices
(for ASIO, OSS so far)
- tomoko: audio settings panel frequency and latency lists are
dynamically populated now
Note: due to the ruby API rewrite, most drivers will not compile. Right
now, the following work:
- video: Direct3D, XShm
- audio: ASIO, OSS
- input: Windows, SDL, Xlib
It takes a really long time to rewrite these (six hours to do the
above), so it's going to be a while before we're back at 100%
functionality again.
Errata:
- ASIO needs device(), setDevice()
- need to call setDevice() at program startup to populate
frequency/latency settings properly
- changing the device and/or frequency needs to update the emulator
resampler rates
The really hard part is going to be the last one: the only way to change
the emulator frequency is to flush all the audio streams and then
recompute all the coefficients for the resamplers. If this is called
during emulation, all audio streams will be erased and thus no sound
will be output. I'll most likely be forced to simply ignore
device/frequency changes until the user loads another game. It is at
least possible to toggle the latency dynamically.
byuu says:
Changelog:
- tomoko: by popular choice, default to adaptive mode on new installs
- hiro/windows: fix bug that was preventing the escape key from
closing some dialog windows
- nall/registry: use "\\\\" as separator instead of "/" ... because
some registry keys contain "/" in them >_>
- ruby: add ASIO driver stub (so far it can only initialize and grab
the driver name/version information)
byuu says:
Changelog:
- gb/interface: fix Game Boy Color extension to be "gbc" and not "gb"
[hex\_usr]
- ms/interface: move Master System hardware controls below controller
ports
- sfc/ppu: improve latching behavior of BGnHOFS registers (not
hardware verified) [AWJ]
- tomoko/input: rework port/device mapping to support non-sequential
ports and devices¹
- todo: should add move() to inputDevice.mappings.append and
inputPort.devices.append
- note: there's a weird GCC 4.9 bug with brace initialization of
InputEmulator; have to assign each field separately
- tomoko: all windows sans the main presentation window can be
dismissed with the escape key
- icarus: the single file selection dialog ("Load ROM Image...") can
be dismissed with the escape key
- tomoko: do not pause emulation when FocusLoss/Pause is set during
exclusive fullscreen mode
- hiro/(windows,gtk,qt): implemented Window::setDismissable() function
(missing from cocoa port, sorry)
- nall/string: fixed printing of largest possible negative numbers (eg
`INT_MIN`) [Sintendo]
- only took eight months! :D
¹: When I tried to move the Master System hardware port below the
controller ports, I ran into a world of pain.
The input settings list expects every item in the
`InputEmulator<InputPort<InputDevice<InputMapping>>>>` arrays to be
populated with valid results. But these would be sparsely populated
based on the port and device IDs from inside higan. And that is done so
that the Interface::inputPoll can have O(1) lookup of ports and devices.
This worked because all the port and device IDs were sequential (they
left no gaps in the maps upon creating the lists.)
Unfortunately by changing the expectation of port ID to how it appears
in the list, inputs would not poll correctly. By leaving them alone and
just moving Hardware to the third position, the Game Gear would be
missing port IDs of 0 and 1 (the controller ports of the Master System).
Even by trying to make separate MasterSystemHardware and
GameGearHardware ports, things still fractured when the devices were no
longer contigious.
I got pretty sick of this and just decided to give up on O(1)
port/device lookup, and moved to O(n) lookup. It only knocked the
framerate down by maybe one frame per second, enough to be in the margin
of error. Inputs aren't polled *that* often for loops that usually
terminate after 1-2 cycles to be too detrimental to performance.
So the new input system now allows non-sequential port and device IDs.
Remember that I killed input IDs a while back. There's never any reason
for those to need IDs ... it was easier to just order the inputs in the
order you want to see them in the user interface. So the input lookup is
still O(1). Only now, everything's safer and I return a
maybe<InputMapping&>, and won't crash out the program trying to use a
mapping that isn't found for some reason.
Errata: the escape key isn't working on the browser/message dialogs on
Windows, because of course nothing can ever just be easy and work for
me. If anyone else wouldn't mind looking into that, I'd greatly
appreciate it.
Having the `WM_KEYDOWN` test inside the main `Application_sharedProc`, it
seems to not respond to the escape key on modal dialogs. If I put the
`WM_KEYDOWN` test in the main window proc, then it doesn't seem to get
called for `VK_ESCAPE` at all, and doesn't get called period for modal
windows. So I'm at a loss and it's past 4AM here >_>
byuu says:
Changelog:
- ruby/video: cleaned up Direct3D9 driver and fixed catastrophic
memory leak
- ruby/video: added fullscreen exclusive mode support to the Direct3D9
driver¹
- ruby/video: minor cosmetic code cleanups to various drivers
- tomoko: added support to always allow input when in fullscreen
exclusive mode
- tomoko: fixed window to not remove resizability flag when exiting
fullscreen mode
¹: I am assuming that exclusive mode will try to capture the primary
monitor. I don't know what will happen in multi-monitor setups, however,
as I don't use such a setup here.
Also, I am using `D3DPRESENT_DISCARD` instead of `D3DPRESENT_FLIP`. I'm
not sure if this will prove better or worse, but I've heard it will
waste less memory, and having a BackBufferCount of 1 should still result
in page flipping anyway. The difference is supposedly just that you
can't rely on the back buffer being a valid copy of the previous frame
like you can with FLIP.
Lastly, if you want Vsync, you can edit the configuration file to enable
that, and then turn off audio sync.
Errata: "pause emulation when focus is lost" is not working with
exclusive mode. I need to add a check to never auto-pause when in
exclusive mode. Thanks to bun for catching that one.
byuu says:
Changelog:
- tomoko: removed "Settings→Video Emulation→Overscan Mask" setting¹
- tomoko: remove a few unnecessary calls to resizeViewport on startup
- tomoko: only resize main window from video settings when in adaptive
or toggling adaptive mode²
- hiro/windows: add `SWP_NOACTIVATE` flag to prevent focus stealing on
resizing invisible windows³
- hiro/windows: suppress spurious API-generated `onSize()` callback
when calling `setVisible()`
¹: it just seemed like bad design to default to overscan masking
being disabled with overscan masks of 8 horizontal, 8 vertical out of
the box. Users would adjust the sliders and not see anything happening.
Instead, I've set the default masks to zero. If you want to turn off
overscan masking, simply slide those to zero again.
²: I figure the only way we're going to be able to fairly evaluate
Screwtape's suggestion is to try it both ways. And I will admit, I kind
of like the way this works as well ... a lot more so than I thought I
would, so I think it was a great suggestion. Still, now's the time if
people have strong opinions on this. Be sure to try both r10 and r11 to
compare. Barring no other feedback, I'm going to keep it this way.
³: this fixes the blinking of the main window on startup.
Screwtape, thanks again for the improvement suggestions. At this point
though, I am not using a tiling window manager. If you are able to patch
hiro/gtk and/or hiro/qt (I mostly use GTK) to work with tiling window
managers better, I wouldn't mind applying said patches, so long as they
don't break things on my own Xfce desktop with xfwm4.
Also, I noticed one issue with Xfce ... if the window is maximized and I
try to call `Window::setSize()`, it's not actually removing the maximize
flag. We'll need to look into how to add that to GTK, but I don't think
it's a huge issue. A similar glitch happens on windows where the icon
still reflects being maximized, but it does actually shrink, it just
sticks to the top left corner of the screen. So this isn't really a
critical bug, but would be extra polish.
byuu says:
Changelog:
- tomoko: video scaling options are now resolutions in the
configuration file, eg "640x480", "960x720", "1280x960"
- tomoko: main window is now always resizable instead of fixed width
(also supports maximizing)
- tomoko: added support for non-integral scaling in windowed mode
- tomoko: made the quick/managed state messaging more consistent
- tomoko: hide "Find Codes ..." button from the cheat editor window if
the cheat database is not present
- tomoko: per-game cheats.bml file now goes into the higan/ subfolder
instead of the root folder
So the way the new video system works is you have the following options
on the video settings panel:
Windowed mode: { Aspect correction, Integral scaling, Adaptive }
Fullscreen mode: { Aspect correction, Integral scaling } (and one day,
hopefully Exclusive will be added here)
Whenever you adjust the overscan masking, or you change any of the
windowed or fullscreen mode settings, or you choose a different video
scale from the main menu, or you load a new game, or you unload a game,
or you rotate the display of an emulated system, the resizeViewport
logic will be invoked. This logic will remember the last option you
chose for video scale, and base the new window size on that value as an
upper limit of the new window size.
If you are in windowed mode and have adaptive enabled, it will shrink
the window to fit the contents of the emulated system's video output.
Otherwise, if you are not in integral scaling mode, it will scale the
video as large as possible to fit into the video scaled size you have
selected. Otherwise, it will perform an integral scale and center the
video inside of the viewport.
If you are in fullscreen mode, it's much the same, only there is no
adaptive mode.
A major problem with Xorg is that it's basically impossible to change
the resizability attribute of a window post-creation. You can do it, but
all kinds of crazy issues start popping up. Like if you toggle
fullscreen, then you'll find that the window won't grow past a certain
fairly small size that it's already at, and cannot be shrunk. And the
multipliers will stop expanding the window as large as they should. And
sometimes the UI elements won't be placed in the correct position, or
the video will draw over them. It's a big mess. So I have to keep the
main window always resizable. Also, note that this is not a limitation
of hiro. It's just totally broken in Xorg itself. No amount of fiddling
has ever allowed this to work reliably for me on either GTK+ 2 or Qt 4.
So what this means is ... the adaptive mode window is also resizable.
What happens here is, whenever you drag the corners of the main window
to resize it, or toggle the maximize window button, higan will bypass
the video scale resizing code and instead act as though the adaptive
scaling mode were disabled. So if integral scaling is checked, it'll
begin scaling in integral mode. Otherwise, it'll begin scaling in
non-integral mode.
And because of this flexibility, it no longer made sense for the video
scale menu to be a radio box. I know, it sucks to not see what the
active selection is anymore, but ... say you set the scale to small,
then you accidentally resized the window a little, but want it snapped
back to the proper small resolution dimensions. If it were a radio item,
you couldn't reselect the same option again, because it's already active
and events don't propagate in said case. By turning them into regular
menu options, the video scale menu can be used to restore window sizing.
Errata:
On Windows, the main window blinks a few times on first load. The fix
for that is a safeguard in the video settings code, roughly like so ...
but note you'd need to make a few other changes for this to work against
v103r10:
auto VideoSettings::updateViewport(bool firstRun) -> void {
settings["Video/Overscan/Horizontal"].setValue(horizontalMaskSlider.position());
settings["Video/Overscan/Vertical"].setValue(verticalMaskSlider.position());
settings["Video/Windowed/AspectCorrection"].setValue(windowedModeAspectCorrection.checked());
settings["Video/Windowed/IntegralScaling"].setValue(windowedModeIntegralScaling.checked());
settings["Video/Windowed/AdaptiveSizing"].setValue(windowedModeAdaptiveSizing.checked());
settings["Video/Fullscreen/AspectCorrection"].setValue(fullscreenModeAspectCorrection.checked());
settings["Video/Fullscreen/IntegralScaling"].setValue(fullscreenModeIntegralScaling.checked());
horizontalMaskValue.setText({horizontalMaskSlider.position()});
verticalMaskValue.setText({verticalMaskSlider.position()});
if(!firstRun) presentation->resizeViewport();
}
That'll get it down to one blink, as with v103 official. Not sure I can
eliminate that one extra blink.
I forgot to remove the setResizable toggle on fullscreen mode exit. On
Windows, the main window will end up unresizable after toggling
fullscreen. I missed that one because like I said, toggling resizability
is totally broken on Xorg. You can fix that with the below change:
auto Presentation::toggleFullScreen() -> void {
if(!fullScreen()) {
menuBar.setVisible(false);
statusBar.setVisible(false);
//setResizable(true);
setFullScreen(true);
if(!input->acquired()) input->acquire();
} else {
if(input->acquired()) input->release();
setFullScreen(false);
//setResizable(false);
menuBar.setVisible(true);
statusBar.setVisible(settings["UserInterface/ShowStatusBar"].boolean());
}
resizeViewport();
}
Windows is stealing focus on calls to resizeViewport(), so we need to
deal with that somehow ...
I'm not really concerned about the behavior of shrinking the viewport
below the smallest multiplier for a given system. It might make sense to
snap it to the window size and forego all other scaling, but honestly
... meh. I don't really care. Nobody sane is going to play like that.
byuu says:
Changelog:
- gba/apu: fixed wave RAM nibble ordering (fixes audio in Castlevania,
PocketNES)
- emulator: restructured video information to just a single
videoResolution() → VideoResolution function
- returns "projected size" (between 160x144 and 320x240)
- "internal buffer size" (up to 1280x480)
- returns aspect correction multiplier that is to be applied to
the width field
- the value could be < 1.0 to handle systems with taller
pixels; although higan doesn't emulate such a system
- tomoko: all calculations for scaling and overscan masking are done
by the GUI now
- tomoko: aspect correction can be enabled in either windowed or
fullscreen mode separately; moved to Video settings panel
- tomoko: video scaling multipliers (against 320x240) can now me
modified from the default (2,3,4) via the configuration file
- use this as a really barebones way of supporting high DPI
monitors; although the GUI elements won't scale nicely
- if you set a value less than two, or greater than your
resolution divided by 320x240, it's your own fault when things
blow up. I'm not babysitting anyone with advanced config-file
only options.
- tomoko: added new adaptive windowed mode
- when enabled, the window will shrink to eliminate any black
borders when loading a game or changing video settings. The
window will not reposition itself.
- tomoko: added new adaptive fullscreen mode
- when enabled, the integral scaling will be disabled for
fullscreen mode, forcing the video to fill at least one
direction of the video monitor completely.
I expect we will be bikeshedding for the next month on how to describe
the new video options, where they should appear in the GUI, changes
people want, etc ... but suffice to say, I'm happy with the
functionality, so I don't intend to make changes to -what- things do,
but I will entertain better ways to name things.
byuu says:
Changelog:
- emulator: improved aspect correction accuracy by using
floating-point calculations
- emulator: added videoCrop() function, extended videoSize() to take
cropping parameters¹
- tomoko: the overscan masking function will now actually resize the
viewport²
- gba/cpu: fixed two-cycle delay on triggering DMAs; not running DMAs
when the CPU is stopped
- md/vdp: center video when overscan is disabled
- pce/vce: resize video output from 1140x240 to 1120x240
- tomoko: resize window scaling from 326x240 to 320x240
- tomoko: changed save slot naming and status bar messages to indicate
quick states vs managed states
- tomoko: added increment/decrement quick state hotkeys
- tomoko: save/load quick state hotkeys now save to slots 1-5 instead
of always to 0
- tomoko: increased overscan range from 0-16 to 0-24 (in case you want
to mask the Master System to 240x192)
¹: the idea here was to decouple raw pixels from overscan masking.
Overscan was actually horrifically broken before. The Famicom outputs at
256x240, the Super Famicom at 512x480, and the Mega Drive at 1280x480.
Before, a horizontal overscan mask of 8 would not reduce the Super
Famicom or Mega Drive by nearly as much as the Famicom. WIth the new
videoCrop() function, the internals of pixel size distortions can be
handled by each individual core.
²: furthermore, by taking optional cropping information in
videoSize(), games can scale even larger into the viewport window. So
for example, before the Super Famicom could only scale to 1536x1440. But
by cropping the vertical resolution by 6 (228p effectively, still more
than NTSC can even show), I can now scale to 1792x1596. And wiht aspect
correction, that becomes a perfect 8:7 ratio of 2048x1596, giving me
perfectly crisp pixels without linear interpolation being required.
Errata: for some reason, when I save a new managed state with the SFC
core, the default description is being set to a string of what looks to
be hex numbers. I found the cause ... I'll fix this in the next release.
Note: I'd also like to hide the "find codes..." button if cheats.bml
isn't present, as well as update the SMP TEST register comment from
smp/timing.cpp
byuu says:
Changelog:
- gba/cpu: massive code cleanup effort
- gba/cpu: DMA can run in between active instructions¹
- gba/cpu: added two-cycle startup delay between DMA activation and
DMA transfers²
- processor/spc700: BBC, BBC, CBNE cycle 4 is an idle cycle
- processor/spc700: ADDW, SUBW, MOVW (read) cycle 4 is an idle cycle
¹: unfortunately, this causes yet another performance penalty for the
poor GBA core =( Also, I think I may have missed disabling DMAs while
the CPU is stopped. I'll fix that in the next WIP.
²: I put the waiting counter decrement at the wrong place, so this
doesn't actually work. Needs to be more like
this:
auto CPU::step(uint clocks) -> void {
for(auto _ : range(clocks)) {
for(auto& timer : this->timer) timer.run();
for(auto& dma : this->dma) if(dma.active && dma.waiting) dma.waiting--;
context.clock++;
}
...
auto CPU::DMA::run() -> bool {
if(cpu.stopped() || !active || waiting) return false;
transfer();
if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;
if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;
return true;
}
Of course, the real fix will be restructuring how DMA works, so that
it's always running in parallel with the CPU instead of this weird
design where it tries to run all channels in some kind of loop until no
channels are active anymore whenever one channel is activated.
Not really sure how to design that yet, however.
byuu says:
Changelog:
- processor/spc700: restored fetch/load/store/pull/push shorthand
functions
- processor/spc700: split functions that tested the algorithm used (`op
!= &SPC700:...`) to separate instructions
- mostly for code clarity over code size: it was awkward having
cycle counts change based on a function parameter
- processor/spc700: implemented Overload's new findings on which
cycles are truly internal (no bus reads)
- sfc/smp: TEST register emulation has been vastly improved¹
¹: it turns out that TEST.d4,d5 is the external clock divider (used
when accessing RAM through the DSP), and TEST.d6,d7 is the internal
clock divider (used when accessing IPLROM, IO registers, or during idle
cycles.)
The DSP (24576khz) feeds its clock / 12 through to the SMP (2048khz).
The clock divider setting further divides the clock by 2, 4, 8, or 16.
Since 8 and 16 are not cleanly divislbe by 12, the SMP cycle count
glitches out and seems to take 10 and 2 clocks instead of 8 or 16. This
can on real hardware either cause the SMP to run very slowly, or more
likely, crash the SMP completely until reset.
What's even stranger is the timers aren't affected by this. They still
clock by 2, 4, 8, or 16.
Note that technically I could divide my own clock counters by 24 and
reduce these to {1,2,5,10} and {1,2,4,8}, I instead chose to divide by
12 to better illustrate this hardware issue and better model that the
SMP clock runs at 2048khz and not 1024khz.
Further, note that things aren't 100% perfect yet. This seems to throw
off some tests, such as blargg's `test_timer_speed`. I can't tell how
far off I am because blargg's test tragically doesn't print out fail
values. But you can see the improvements in that higan is now passing
all of Revenant's tests that were obviously completely wrong before.
byuu says:
Changelog:
- fc/controller: added ControllerPort class; removed Peripherals class
- md/controller/gamepad: removed X,Y,Z buttons since this isn't a
6-button controller
- ms/controller: added ControllerPort class (not used in Game Gear
mode); removed Peripherals class
- pce/controller: added ControllerPort class; removed Peripherals
class
- processor/spc700: idle(address) is part of SMP class again, contains
flag to detect mov (x)+ edge case
- sfc/controller/super-scope,justifier: use CPU frequency instead of
hard-coding NTSC frequency
- sfc/cpu: move 4x8-bit SMP ports to SMP class
- sfc/smp: move APU RAM to DSP class
- sfc/smp: improved emulation of TEST registers bits 4-7 [information
from nocash]
- d4,d5 is RAM wait states (1,2,5,10)
- d6,d7 is ROM/IO wait states (1,2,5,10)
- sfc/smp: code cleanup to new style (order from lowest to highest
bits; use .bit(s) functions)
- sfc/smp: $00f8,$00f9 are P4/P5 auxiliary ports; named the registers
better
byuu says:
Changelog:
- fc/apu: $4003,$4007 writes initialize duty counter to 0 instead of 7
- fc/apu: corrected duty table entries for use with decrementing duty
counter
- processor/spc700: emulated the behavior of cycle 3 of (x)+
instructions to not read I/O registers
- specifically, this prevents reads from $fd-ff from resetting the
timers, as observed on real hardware
- sfc/controller: added ControllerPort class to match Mega Drive
design
- sfc/expansion: added ExpansionPort class to match Mega Drive design
- sfc/system: removed Peripherals class
- sfc/system: changed `colorburst()` to `cpuFrequency()`; added
`apuFrequency()`
- sfc: replaced calls to `system.region == System::Region::*` with
`Region::*()`
- sfc/expansion: remove thread from scheduler when device is destroyed
- sfc/smp: `{read,write}Port` now use a separate 4x8-bit buffer instead
of underlying APU RAM [hex\_usr]
byuu says:
Changelog:
- md/psg: fixed output frequency rate regression from v103r02
- processor/m68k: fixed calculations for ABCD, NBCD, SBCD [hex\_usr,
SuperMikeMan]
- processor/spc700: renamed abbreviated instructions to functional
descriptions (eg `XCN` → `ExchangeNibble`)
- processor/spc700: removed memory.cpp shorthand functions (fetch,
load, store, pull, push)
- processor/spc700: updated all instructions to follow cycle behavior
as documented by Overload with a logic analyzer
Once again, the changes to the SPC700 core are really quite massive. And
this time it's not just cosmetic: the idle cycles have been updated to
pull from various memory addresses. This is why I removed the shorthand
functions -- so that I could handle the at-times very bizarre addresses
the SPC700 has on its address bus during its idle cycles.
There is one behavior Overload mentioned that I don't emulate ... one of
the cycles of the (X) transfer functions seems to not actually access
the $f0-ff internal SMP registers? I don't fully understand what
Overload is getting at, so I haven't tried to support it just yet.
Also, there are limits to logic analyzers. In many cases the same
address is read from twice consecutively. It is unclear which of the two
reads the SPC700 actually utilizes. I tried to choose the most logical
values (usually the first one), but ... I don't know that we'll be able
to figure this one out. It's going to be virtually impossible to test
this through software, because the PC can't really execute out of
registers that have side effects on reads.
byuu says:
Changelog:
- fc/apu: improved phase duty cycle emulation (mode 3 is 25% phase
inverted; counter decrements)
- md/apu: power/reset do not cancel 68K bus requests
- md/apu: 68K is not granted bus access on Z80 power/reset
- md/controller: replaced System::Peripherals with ControllerPort
concept
- md/controller: CTRL port is now read-write, maintains value across
controller changes (and soon, soft resets)
- md/psg: PSG sampling rate unintentionally modified¹
- processor/spc700: improve cycle timing of (indirect),y instructions
[Overload]
- processor/spc700: idle() cycles actually read from the program
counter; much like the 6502 [Overload]
- some of the idle() cycles should read from other addresses; this
still needs to be supported
- processor/spc700: various cleanups to instruction function naming
- processor/z80: prefix state (HL→IX,IY override) can now be
serialized
- icarus: fix install rule for certain platforms (it wasn't buggy on
FreeBSD, but was on Linux?)
¹: the clock speed of the PSG is oscillator/15. But I was setting the
sampling rate to oscillator/15/16, which was around 223KHz. I am not
sure whether the PSG should be outputting at 3MHz or 223KHz. Amazingly
... I don't really hear a difference either way `o_O` I didn't actually
mean to make this change; I just noticed it after comparing the diff
between r01 and r02. If this turns out to be wrong, set
stream = Emulator::audio.createStream(1, frequency() / 16.0);
in md/psg.cpp to revert this change.
byuu says:
Changelog:
- nall/dsp: improve one pole coefficient calculations [Fatbag]
- higan/audio: reworked filters to support selection of either one
pole (first-order) or biquad (second-order) filters
- note: the design is not stable yet; so forks should not put too
much effort into synchronizing with this change yet
- fc: added first-order filters as per NESdev wiki (90hz lowpass +
440hz lowpass + 14khz highpass)
- fc: created separate NTSC-J and NTSC-U regions
- NESdev wiki says the Japanese Famicom uses a separate audio
filtering strategy, but details are fuzzy
- there's also cartridge audio output being disabled on NES units;
and differences with controllers
- this stuff will be supported in the future, just adding the
support for it now
- gba: corrected serious bugs in PSG wave channel emulation [Cydrak]
- note that if there are still bugs here, it's my fault
- md/psg,ym2612: added first-order low-pass 2840hz filter to match
VA3-VA6 Mega Drives
- md/psg: lowered volume relative to the YM2612
- using 0x1400; multiple people agreed it was the closest to the
hardware recordings against a VA6
- ms,md/psg: don't serialize the volume levels array
- md/vdp: Hblank bit acts the same during Vblank as outside of it (it
isn't always set during Vblank)
- md/vdp: return isPAL in bit 0 of control port reads
- tomoko: change command-line option separator from : to |
- [Editor's note: This change was present in the public v103,
but it's in this changelog because it was made after the v103 WIP]
- higan/all: change the 20hz high-pass filters from second-order
three-pass to first-order one-pass
- these filters are meant to remove DC bias, but I honestly can't
hear a difference with or without them
- so there's really no sense wasting CPU power with an extremely
powerful filter here
Things I did not do:
- change icarus install rule
- work on 8-bit Mega Drive SRAM
- work on Famicom or Mega Drive region detection heuristics in icarus
My long-term dream plan is to devise a special user-configurable
filtering system where you can set relative volumes and create your own
list of filters (any number of them in any order at any frequency), that
way people can make the systems sound however they want.
Right now, the sanest place to put this information is inside the
$system.sys/manifest.bml files. But that's not very user friendly, and
upgrading to new versions will lose these changes if you don't copy them
over manually. Of course, cluttering the GUI with a fancy filter editor
is probably supreme overkill for 99% of users, so maybe that's fine.
byuu says (in the public annoucement):
With this release, PC Engine, Master System, Game Gear, Mega Drive and
the newly added SuperGrafx support are now quite usable! They're far
from the best emulators for these systems, but with many bugfixes, full
sound emulation, and save state support ... many games are now fully
playable with decent accuracy. The Game Boy Advance emulation is also
now substantially improved with vastly improved sound quality and a new
dot-based PPU renderer. With that change, every single component in
higan is now cycle-based. Regrettably, these changes do carry a ~20%
performance penalty compared to GBA emulation in v102.
Changelog (since the previous release):
- added SuperGrafx emulation
- improved audio band-pass filtering for all emulated systems
- screen rotation is now a hotkey; automatically rotates control
bindings
- screen rotation now supported on the Game Boy Advance as well (used
by a small number of games)
- massive improvements to Mega Drive emulation
- massive code cleanups and rewrites to many CPU emulation cores
(MOS6502, WDC65816, SPC700, etc)
- Famicom, Master System, Mega Drive: added PAL emulation support
- PC Engine, SuperGrafx, Master System, Game Gear, Mega Drive: added
save state support
- PC Engine, SuperGrafx: added PSG sound emulation
- Master System, Game Gear: added PSG sound emulation
- Mega Drive: added Z80 APU emulation [with help from Cydrak]
- Mega Drive: added PSG sound emulation
- Mega Drive: added YM2612 sound emulation [Cydrak]
- Super Famicom: fixed Super Game Boy emulation
- PC Engine: added save RAM support (using per-game PCE-CD backup RAM)
- Game Boy Advance: substantial improvements to audio emulation
quality
- Game Boy Advance: convert scanline-based PPU renderer to a dot-based
renderer
- Game Boy Advance: properly initialize CPU state (fixes Classic NES
Series games)
- Game Boy Advance: MUL timing corrected [Jonas Quinn]
- Mega Drive: emulate special mappers for Phantasy Star IV, Super
Street Fighter II, etc.
- Super Famicom: use darker luma for INIDISP=0 (large improvement to
Final Fantasy III opening)
- Super Famicom: fixed bugs in SMP OR1,AND1 instructions
- cheat code database regrettably removed from official releases; will
be made available separately
- Famicom: PAL emulation improvements [hex\_usr]
byuu says (in the WIP forum):
Changelog:
- higan: cheat codes accept = and ? separators now
- the new preferred code format is: address=value or
address=if-match?value
- the old code format of address/value and address/if-match/value
will continue to work
- higan: cheats.bml is no longer included with the base distribution
- mightymo stopped updating it in 2015, and it's not source code;
it can still be pulled in from older releases
- fc: improved PAL mode timing; use PAL APU timing tables; fix PAL
noise period table [hex\_usr]
- md: support aborting a Z80 bus wait in order to capture save states
without freezing
- note that this will violate accuracy; but in practice a slight
desync is better than an emulator deadlock
- sfc: revert DSP ENDX randomization for now (want to research it more
before deploying in an official release)
- sfc: fix Super Famicom.sys/manifest.bml APU RAM size [hex\_usr]
- tomoko: cleaned up make install rules
- hiro/cocoa: use ABGR for pixel data [Sintendo]
Note: I forgot to change the command-line and drag-and-drop separator
from : to | in this WIP. However, it is corrected in the v103 official
binary and source published on download.byuu.org. Sorry about that, I
know it makes the Git repository history more difficult. I'm not
concerned whether the : → | change is part of v103 or v103r01 in the
repository, and will leave this to your discretion, Screwtape.
I also still need to set the VDP bit to indicate PAL mode in the Mega
Drive core. This is what happens when I have 47 things I have to do,
given how lousy my memory is. I miss things.
byuu says:
Changelog:
- higan: `Emulator::<Platform::load>()` now returns a struct containing
both a path ID and a string option
- higan: `Emulator::<Platform::load>()` now takes an optional final
argument of string options
- fc: added PAL emulation (finally, only took six years)
- md: added PAL emulation
- md: fixed address parameter to `VDP::Sprite::write()`; fixes missing
sprites in Super Street Fighter II
- md: emulated HIRQ counter; fixes many games
- Super Street Fighter II - status bar
- Altered Beast - status bar
- Sonic the Hedgehog - Labyrinth Zone - water effect
- etc.
- ms: added PAL emulation
- sfc: added the ability to override the default region auto-detection
- sfc: removed "system.region" override setting from `Super Famicom.sys`
- tomoko: added options list to game folder load dialog window
- tomoko: added the ability to specify game folder load options on the
command-line
So, basically ... Sega forced a change with the way region detection
works. You end up with games that can run on multiple regions, and the
content changes accordingly. Bare Knuckle in NTSC-J mode will become
Streets of Rage in NTSC-U mode. Some games can even run in both NTSC and
PAL mode.
In my view, there should be a separate ROM for each region a game was
released in, even if the ROM content were identical. But unfortunately
that's not how things were done by anyone else.
So to support this, the higan load dialog now has a drop-down at the
bottom-right, where you can choose the region to load games from. On the
SNES, it defaults to "Auto", which will pull the region setting from the
manifest, or fall back on NTSC. On the Mega Drive ... unfortunately, I
can't auto-detect the region from the ROM header. $1f0 is supposed to
contain a string like "JUE", but instead you get games like Maui Mallard
that put an "A" there, and other such nonsense. Sega was far more lax
than Nintendo with the ROM header validity. So for now at least, you
have to manually select your region every time you play a Mega Drive
game, thus you have "NTSC-J", "NTSC-U", and "PAL". The same goes for the
Master System for the same reason, but there's only "NTSC" and "PAL"
here. I'm not sure if games have a way to detect domestic vs
international consoles.
And for now ... the Famicom is the same as well, with no auto-detection.
I'd sincerely hope iNES has a header bit for the region, but I didn't
bother with updating icarus to support that yet.
The way to pass these parameters on the command-line is to prefix the
game path with "option:", so for example:
higan "PAL:/path/to/Sonic the Hedgehog (USA, Europe).md"
If you don't provide a prefix, it uses the default (NTSC-J, NTSC, or
Auto.) Obviously, it's not possible to pass parameters with
drag-and-drop, so you will always get the default option in said case.
byuu says:
Changelog:
- processor/gsu: minor code cleanup
- processor/hg51b: renamed reg(Read,Write) to register(Read,Write)
- processor/lr35902: minor code cleanup
- processor/spc700: completed code cleanup (sans disassembler)
- no longer uses internal global state inside instructions
- processor/spc700: will no longer hang the emulator if stuck in a WAI
(SLEEP) or STP (STOP) instruction
- processor/spc700: fixed bug in handling of OR1 and AND1 instructions
- processor/z80: minor code cleanup
- sfc/dsp: revert to initializing registers to 0x00; save for
ENDX=random(), FLG=0xe0 [Jonas Quinn]
Major testing of the SNES game library would be appreciated, now that
its CPU cores have all been revised.
We know the DSP registers read back as randomized data ... mostly, but
there are apparently internal latches, which we can't emulate with the
current DSP design. So until we know which registers have separate
internal state that actually *is* initialized, I'm going to play it safe
and not break more games.
Thanks again to Jonas Quinn for the continued research into this issue.
EDIT: that said ... `MD works if((ENDX&0x30) > 0)` is only a 3:4 chance
that the game will work. That seems pretty unlikely that the odds of it
working are that low, given hardware testing by others in the past :/ I
thought if worked if `PITCH != 0` before, which would have been way more
likely.
The two remaining CPU cores that need major cleanup efforts are the
LR35902 and ARM cores. Both are very large, complicated, annoying cores
that will probably be better off as full rewrites from scratch. I don't
think I want to delay v103 in trying to accomplish that, however.
So I think it'll be best to focus on allowing the Mega Drive core to not
lock when processors are frozen waiting on a response from other
processors during a save state operation. Then we should be good for a
new release.
byuu says:
Changelog:
- md/ym2612: initialize DAC sample to center volume [Cydrak]
- processor/arm: add accumulate mode extra cycle to mlal [Jonas
Quinn]
- processor/huc6280: split off algorithms, improve naming of functions
- processor/mos6502: split off algorithms
- processor/spc700: major revamp of entire core (~50% completed)
- processor/wdc65816: fixed several bugs introduced by rewrite
For the SPC700, this turns out to be very old code as well, with global
object state variables, those annoying `{Boolean,Natural}BitField` types,
`under_case` naming conventions, heavily abbreviated function names, etc.
I'm working to get the code to be in the same design as the MOS6502,
HuC6280, WDC65816 cores, since they're all extremely similar in terms of
architectural design (the SPC700 is more of an off-label
reimplementation of a 6502 core, but still.)
The main thing left is that about 90% of the actual instructions still
need to be adapted to not use the internal state (`aa`, `rd`, `dp`,
`sp`, `bit` variables.) I wanted to finish this today, but ran out of
time before work.
I wouldn't suggest too much testing just yet. We should wait until the
SPC700 core is finished for that. However, if some does want to and
spots regressions, please let me know.
byuu says:
Changelog:
- processor/arm: corrected MUL instruction timings [Jonas Quinn]
- processor/wdc65816: finished phase two of the rewrite
I'm really pleased with the visual results of the wdc65816 core rewrite.
I was able to eliminate all of the weird `{Boolean,Natural}BitRange`
templates, as well as the need to use unions/structs. Registers are now
just simple `uint24` or `uint16` types (technically they're `Natural<T>`
types, but then all of higan uses those), flags are now just bool types.
I also eliminated all of the implicit object state inside of the core
(aa, rd, dp, sp) and instead do all computations on the stack frame with
local variables. Through using macros to reference the registers and
individual parts of them, I was able to reduce the visual tensity of all
of the instructions. And by using normal types without implicit states,
I was able to eliminate about 15% of the instructions necessary, instead
reusing existing ones.
The final third phase of the rewrite will be to recode the disassembler.
That code is probably the oldest code in all of higan right now, still
using sprintf to generate the output. So it is very long overdue for a
cleanup.
And now for the bad news ... as with any large code cleanup, regression
errors have seeped in. Currently, no games are running at all. I've left
the old disassembler in for this reason: we can compare trace logs of
v102r23 against trace logs of v102r25. The second there's any
difference, we've spotted a buggy instruction and can correct it.
With any luck, this will be the last time I ever rewrite the wdc65816
core. My style has changed wildly over the ~10 years since I wrote this
core, but it's really solidifed in recent years.
byuu says
Changelog:
- FC: fixed three MOS6502 regressions [hex\_usr]
- GBA: return fetched instruction instead of 0 for unmapped MMIO
(passes all of endrift's I/O tests)
- MD: fix VDP control port read Vblank bit to test screen height
instead of hard-code 240 (fixes Phantasy Star IV)
- MD: swap USP,SSP when executing an exception (allows Super Street
Fighter II to run; but no sprites visible yet)
- MD: grant 68K access to Z80 bus on reset (fixes vdpdoc demo ROM from
freezing immediately)
- SFC: reads from $00-3f,80-bf:4000-43ff no longer update MDR
[p4plus2]
- SFC: massive, eight-hour cleanup of WDC65816 CPU core ... still not
complete
The big change this time around is the SFC CPU core. I've renamed
everything from R65816 to WDC65816, and then went through and tried to
clean up the code as much as possible. This core is so much larger than
the 6502 core that I chose cleaning up the code to rewriting it.
First off, I really don't care for the BitRange style functionality. It
was an interesting experiment, but its fatal flaw are that the types are
just bizarre, which makes them hard to pass around generically to other
functions as arguments. So I went back to the list of bools for flags,
and union/struct blocks for the registers.
Next, I renamed all of the functions to be more descriptive: eg
`op_read_idpx_w` becomes `instructionIndexedIndirectRead16`. `op_adc_b`
becomes `algorithmADC8`. And so forth.
I eliminated about ten instructions because they were functionally
identical sans the index, so I just added a uint index=0 parameter to
said functions. I added a few new ones (adjust→INC,DEC;
pflag→REP,SEP) where it seemed appropriate.
I cleaned up the disaster of the instruction switch table into something
a whole lot more elegant without all the weird argument decoding
nonsense (still need M vs X variants to avoid having to have 4-5
separate switch tables, but all the F/I flags are gone now); and made
some things saner, like the flag clear/set and branch conditions, now
that I have normal types for flags and registers once again.
I renamed all of the memory access functions to be more descriptive to
what they're doing: eg writeSP→push, readPC→fetch,
writeDP→writeDirect, etc. Eliminated some of the special read/write
modes that were only used in one single instruction.
I started to clean up some of the actual instructions themselves, but
haven't really accomplished much here. The big thing I want to do is get
rid of the global state (aa, rd, iaddr, etc) and instead use local
variables like I am doing with my other 65xx CPU cores now. But this
will take some time ... the algorithm functions depend on rd to be set
to work on them, rather than taking arguments. So I'll need to rework
that.
And then lastly, the disassembler is still a mess. I want to finish the
CPU cleanups, and then post a new WIP, and then rewrite the disassembler
after that. The reason being ... I want a WIP that can generate
identical trace logs to older versions, in case the CPU cleanup causes
any regressions. That way I can more easily spot the errors.
Oh ... and a bit of good news. v102 was running at ~140fps on the SNES
core. With the new support to suspend/resume WAI/STP, plus the internal
CPU registers not updating the MDR, the framerate dropped to ~132fps.
But with the CPU cleanups, performance went back to ~140fps. So, hooray.
Of course, without those two other improvements, we'd have ended up at
possibly ~146-148fps, but oh well.
byuu says:
Changelog:
- rewrote the 6502 CPU core from scratch. Now called MOS6502,
supported BCD mode
- Famicom core disables BCD mode via MOS6502::BCD = 0;
- renamed r65816 folder to wdc65816 (still need to rename the actual
class, though ...)
Note: need to remove build rules for the now renamed r6502, r65816
objects from processor/GNUmakefile.
So this'll seem like a small WIP, but it was a solid five hours to
rewrite the entire 6502 core. The reason I wanted to do this was because
the old 6502 core was pretty sloppy. My coding style improved a lot, and
I really liked how the HuC6280 CPU core came out, so I wanted the 6502
core to be like that one.
The core can now support BCD mode, so hopefully that will prove useful
to hex\_usr and allow one core to run both the NES and his Atari 2600
cores at some point.
Note that right now, the core doesn't support any illegal instructions.
The old core supported a small number of them, but were mostly the no
operation ones. The goal is support all of the illegal instructions at
some point.
It's very possible the rewrite introduced some regressions, so thorough
testing of the NES core would be appreciated if anyone were up for it.
byuu says:
Changelog:
- higan: Emulator::Interface::videoSize() renamed to videoResolution()
- higan: Emulator::Interface::rtcsync() renamed to rtcSynchronize()
- higan: added video display rotation support to Video
- GBA: substantially improved audio mixing
- fixed bug with FIFO 50%/100% volume setting
- now properly using SOUNDBIAS amplitude to control output
frequencies
- reduced quantization noise
- corrected relative volumes between PSG and FIFO channels
- both PSG and FIFO values cached based on amplitude; resulting in
cleaner PCM samples
- treating PSG volume=3 as 200% volume instead of 0% volume now
(unverified: to match mGBA)
- GBA: properly initialize ALL CPU state; including the vital
prefetch.wait=1 (fixes Classic NES series games)
- GBA: added video rotation with automatic key translation support
- PCE: reduced output resolution scalar from 285x242 to 285x240
- the extra two scanlines won't be visible on most TVs; and they
make all other cores look worse
- this is because all other cores output at 240p or less; so they
were all receiving black bars in windowed mode
- tomoko: added "Rotate Display" hotkey setting
- tomoko: changed hotkey multi-key logic to OR instead of AND
- left support for flipping it back inside the core; for those so
inclined; by uncommenting one line in input.hpp
- tomoko: when choosing Settings→Configuration, it will
automatically select the currently loaded system
- for instance, if you're playing a Game Gear game, it'll take you
to the Game Gear input settings
- if no games are loaded, it will take you to the hotkeys panel
instead
- WS(C): merged "Hardware-Vertical", "Hardware-Horizontal" controls
into combined "Hardware"
- WS(C): converted rotation support from being inside the core to
using Emulator::Video
- this lets WS(C) video content scale larger now that it's not
bounded by a 224x224 square box
- WS(C): added automatic key rotation support
- WS(C): removed emulator "Rotate" key (use the general hotkey
instead; I recommend F8 for this)
- nall: added serializer support for nall::Boolean (boolean) types
- although I will probably prefer the usage of uint1 in most cases
byuu says:
Changelog:
- GBA: fixed WININ2 reads, BG3PB writes [Jonas Quinn]
- R65816: added support for yielding/resuming from WAI/STP¹
- SFC: removed status.dmaCounter functionality (also fixes possible
TAS desync issue)
- tomoko: added support for combinatorial inputs [hex\_usr\]²
- nall: fixed missing return value from Arithmetic::operator--
[Hendricks266]
Now would be the time to start looking for major regressions with the
new GBA PPU renderer, I suppose ...
¹: this doesn't matter for the master thread (SNES CPU), but is
important for slave threads (SNES SA1). If you try to save a state and
the SA1 is inside of a WAI instruction, it will get stuck there forever.
This was causing attempts to create a save state in Super Bomberman
- Panic Bomber W to deadlock the emulator and crash it. This is now
finally fixed.
Note that I still need to implement similar functionality into the Mega
Drive 68K and Z80 cores. They still have the possibility of deadlocking.
The SNES implementation was more a dry-run test for this new
functionality. This possible crashing bug in the Mega Drive core is the
major blocking bug for a new official release.
²: many, many thanks to hex\_usr for coming up with a really nice
design. I mostly implemented it the exact same way, but with a few tiny
differences that don't really matter (display " and ", " or " instead of
" & ", " | " in the input settings windows; append → bind;
assignmentName changed to displayName.)
The actual functionality is identical to the old higan v094 and earlier
builds. Emulated digital inputs let you combine multiple possible keys
to trigger the buttons. This is OR logic, so you can map to eg
keyboard.up OR gamepad.up for instance. Emulated analog inputs always
sum together. Emulated rumble outputs will cause all mapped devices to
rumble, which is probably not at all useful but whatever. Hotkeys use
AND logic, so you have to press every key mapped to trigger them. Useful
for eg Ctrl+F to trigger fullscreen.
Obviously, there are cases where OR logic would be nice for hotkeys,
too. Eg if you want both F11 and your gamepad's guide button to trigger
the fullscreen toggle. Unfortunately, this isn't supported, and likely
won't ever be in tomoko. Something I might consider is a throw switch in
the configuration file to swap between AND or OR logic for hotkeys, but
I'm not going to allow construction of mappings like "(Keyboard.Ctrl and
Keyboard.F) or Gamepad.Guide", as that's just too complicated to code,
and too complicated to make a nice GUI to set up the mappings for.
byuu says:
Changelog:
- nall: `#undef OUT` on Windows platform
- GBA: add missing CPU prefetch state to serialization (this was
breaking serialization in games using ROM prefetch)
- GBA: reset all PPU data in the power() function (some things were
missing before, causing issues on reset)
- GBA: restored horizontal mosaic emulation to the new pixel-based
renderer
- GBA: fixed tilemap background horizontal flipping (Legend of Spyro -
warning screen)
- GBA: fixed d8 bits of scroll registers (ATV - Thunder Ridge Racers -
menu screen)
- SFC: DRAM refresh ticks the ALU MUL/DIV registers five steps forward
[reported by kevtris]
- SFC: merged dmaCounter and autoJoypadCounter into new shared
clockCounter
- left stub for old dmaCounter so that I can do some traces to
ensure the new code's 100% identical
GBA save states would have been broken since whenever I emulated ROM
prefetch. I guess not many people are using the GBA core ...
byuu says:
Note: add `#undef OUT` to the top of higan/gba/ppu/ppu.hpp to compile on
Windows (ugh ...) Now to await posts about this in four more threads
again ;)
Changelog:
- GBA: rewrote PPU from a scanline-based renderer to a pixel-based
renderer
- ruby: fixed video/gdi bugs
Note that there's an approximately 21% speed penalty compared to v102r18
for the pixel-based renderer.
Also, horizontal mosaic effects are not yet implemented. But they should
be prior to v103. This one is a little tricky as it currently works on
fully rendered scanlines. I need to roll the mosaic into the background
renderers, and then for sprites, well ... see below.
The trickiest part by far of this new renderer is the object (sprite)
system. Unlike every other system I emulate, the GBA supports affine
rendering of its sprites. Or in other words, rotation effects. And it
also has a very complex priority system.
Right now, I can't see any way that the GBA PPU could render pixels in
real-time like this. My belief is that there's a 240-entry buffer that
fills up the next scanline's row of pixels. Which means it probably also
runs on the last scanline of Vblank so that the first scanline has
sprite data.
However, I didn't design my object renderer like this just yet. For now,
it creates a buffer of all 240 pixels right away at the start of the
scanline. I know\!\! That's technically scanline-based. But it's only
for fetching object tiledata, and it's only temporary.
What needs to happen is I need a way to run something like a "mini libco
thread" inside of the main thread, so that the object renderer can run
in parallel with the rest of the PPU, yet not be a hideous abomination
of a state machine, yet also not be horrendously slow as a full libco
thread would be.
I'm envisioning some kind of stackless yielding coroutine. But I'll need
to think through how to design that, given the absence of coroutines
even in C++17.
byuu says:
This WIP fixes all the critical pending issues I had open. I'm sure
there's many more that simply didn't make their way into said list. So
by all means, please report important issues you're aware of so they can
get fixed.
Changelog:
- ruby: add variable texture support to GDI video driver [bug
reported by Cydrak]
- ruby: minor cleanups to XShm video driver
- ruby: fix handling of up+down, left+right hat cases for XInput
driver [bug reported by Cydrak]
- nall: fixed vector class so that compilation with GCC 7.1 should
succeed [SuperMikeMan]
- sfc: initialize most DSP registers to random values to fix Magical
Drop [Jonas Quinn]
- sfc: lower PPU brightness when luma=0 from 50% scale to 25% scale;
helps scenes like Final Fantasy III's intro
byuu says:
Changelog:
- GBA: process audio at 2MHz instead of 32KHz¹
- MD: do not allow the 68K to stop the Z80, unless it has been granted
bus access first
- MD: do not reset bus requested/granted signals when the 68K resets
the Z80
- the above two fix The Lost Vikings
- MD: clean up the bus address decoding to be more readable
- MD: add support for a13000-a130ff (#TIME) region; pass to cartridge
I/O²
- MD: emulate SRAM mapping used by >16mbit games; bank mapping used
by >32mbit games³
- MD: add 'reset pending' flag so that loading save states won't
reload 68K PC, SP registers
- this fixes save state support ... mostly⁴
- MD: if DMA is not enabled, do not allow CD5 to be set [Cydrak]
- this fixes in-game graphics for Ristar. Title screen still
corrupted on first run
- MD: detect and break sprite lists that form an infinite loop
[Cydrak]
- this fixes the emulator from dead-locking on certain games
- MD: add DC offset to sign DAC PCM samples [Cydrak]
- this improves audio in Sonic 3
- MD: 68K TAS has a hardware bug that prevents writing the result back
to RAM
- this fixes Gargoyles
- MD: 68K TRAP should not change CPU interrupt level
- this fixes Shining Force II, Shining in the Darkness, etc
- icarus: better SRAM heuristics for Mega Drive games
Todo:
- need to serialize the new cartridge ramEnable, ramWritable, bank
variables
¹: so technically, the GBA has its FIFO queue (raw PCM), plus a GB
chipset. The GB audio runs at 2MHz. However, I was being lazy and
running the sequencer 64 times in a row, thus decimating the audio to
32KHz. But simply discarding 63 out of every 64 samples resorts in
muddier sound with more static in it.
However ... increasing the audio thread processing intensity 64-fold,
and requiring heavy-duty three-chain lowpass and highpass filters is not
cheap. For this bump in sound quality, we're eating a loss of about 30%
of previous performance.
Also note that the GB audio emulation in the GBA core still lacks many
of the improvements made to the GB core. I was hoping to complete the GB
enhancements, but it seems like I'm never going to pass blargg's
psychotic edge case tests. So, first I want to clean up the GB audio to
my current coding standards, and then I'll port that over to the GBA,
which should further increase sound quality. At that point, it sound
exceed mGBA's audio quality (due to the ridiculously high sampling rate
and strong-attenuation audio filtering.)
²: word writes are probably not handled correctly ... but games are
only supposed to do byte writes here.
³: the SRAM mapping is used by games like "Story of Thor" and
"Phantasy Star IV." Unfortunately, the former wasn't released in the US
and is region protected. So you'll need to change the NTSU to NTSCJ in
md/system/system.cpp in order to boot it. But it does work nicely now.
The write protection bit is cleared in the game, and then it fails to
write to SRAM (soooooooo many games with SRAM write protection do this),
so for now I've had to disable checking that bit. Phantasy Star IV has a
US release, but sadly the game doesn't boot yet. Hitting some other bug.
The bank mapping is pretty much just for the 40mbit Super Street Fighter
game. It shows the Sega and Capcom logos now, but is hitting yet another
bug and deadlocking.
For now, I emulate the SRAM/bank mapping registers on all cartridges,
and set sane defaults. So long as games don't write to $a130XX, they
should all continue to work. But obviously, we need to get to a point
where higan/icarus can selectively enable these registers on a per-game
basis.
⁴: so, the Mega Drive has various ways to lock a chip until another
chip releases it. The VDP can lock the 68K, the 68K can lock the Z80,
etc. If this happens when you save a state, it'll dead-lock the
emulator. So that's obviously a problem that needs to be fixed. The fix
will be nasty ... basically, bypassing the dead-lock, creating a
miniature, one-instruction-long race condition. Extremely unlikely to
cause any issues in practice (it's only a little worse than the SNES
CPU/SMP desync), but ... there's nothing I can do about it. So you'll
have to take it or leave it. But yeah, for now, save states may lock up
the emulator. I need to add code to break the loops when in the process
of creating a save state still.
byuu says:
Changelog:
- Emulator::Stream now allows adding low-pass and high-pass filters
dynamically
- also accepts a pass# count; each pass is a second-order biquad
butterworth IIR filter
- Emulator::Stream no longer automatically filters out >20KHz
frequencies for all streams
- FC: added 20Hz high-pass filter; 20KHz low-pass filter
- GB: removed simple 'magic constant' high-pass filter of unknown
cutoff frequency (missed this one in the last WIP)
- GB,SGB,GBC: added 20Hz high-pass filter; 20KHz low-pass filter
- MS,GG,MD/PSG: added 20Hz high-pass filter; 20KHz low-pass filter
- MD: added save state support (but it's completely broken for now;
sorry)
- MD/YM2612: fixed Voice#3 per-operator pitch support (fixes sound
effects in Streets of Rage, etc)
- PCE: added 20Hz high-pass filter; 20KHz low-pass filter
- WS,WSC: added 20Hz high-pass filter; 20KHz low-pass filter
So, the point of the low-pass filters is to remove frequencies above
human hearing. If we don't do this, then resampling will introduce
aliasing that results in sounds that are audible to the human ear. Which
basically an annoying buzzing sound. You'll definitely hear the
improvement from these in games like Mega Man 2 on the NES. Of course,
these already existed before, so this WIP won't sound better than
previous WIPs.
The high-pass filters are a little more complicated. Their main role is
to remove DC bias and help to center the audio stream. I don't
understand how they do this at all, but ... that's what everyone who
knows what they're talking about says, thus ... so be it.
I have set all of the high-pass filters to 20Hz, which is below the
limit of human hearing. Now this is where it gets really interesting ...
technically, some of these systems actually cut off a lot of range. For
instance, the GBA should technically use an 800Hz high-pass filter when
output is done through the system's speakers. But of course, if you plug
in headphones, you can hear the lower frequencies.
Now 800Hz ... you definitely can hear. At that level, nearly all of the
bass is stripped out and the audio is very tinny. Just like the real
system. But for now, I don't want to emulate the audio being crushed
that badly.
I'm sticking with 20Hz everywhere since it won't negatively affect audio
quality. In fact, you should not be able to hear any difference between
this WIP and the previous WIP. But theoretically, DC bias should mostly
be removed as a result of these new filters. It may be that we need to
raise the values on some cores in the future, but I don't want to do
that until we know for certain that we have to.
What I can say is that compared to even older WIPs than r15 ... the
removal of the simple one-pole low-pass and high-pass filters with the
newer three-pass, second-order filters should result in much better
attenuation (less distortion of audible frequencies.) Probably not
enough to be noticeable in a blind test, though.
byuu says:
Changelog:
- nall: added DSP::IIR::OnePole (which is a first-order IIR filter)
- FC/APU: removed strong highpass, weak hipass filters (and the
dummied out lowpass filter)
- MS,GG,MD/PSG: removed lowpass filter
- MS,GG,MD/PSG: audio was not being centered properly; removed
centering for now
- MD/YM2612: fixed clipping of accumulator from 18 signed bits to 14
signed bits (-0x2000 to +0x1fff) [Cydrak]
- MD/YM2612: removed lowpass filter
- PCE/PSG: audio was not being centered properly; removed centering
for now
First thing is that I've removed all of the ad-hoc audio filtering.
Emulator::Stream intrinsically provides a three-pass, second-order
biquad IIR butterworth lowpass filter that clips frequencies above 20KHz
with very good attenuation (as good as IIR gets, anyway.)
It doesn't really make sense to have the various cores running
additional lowpass filters. If we want to filter frequencies below
20KHz, then I can adapt Emulator::Audio::createStream() to take a cutoff
frequency value, and we can do it all at once, with much better quality.
Right now, I don't know what frequencies are best to cut off the various
other audio cores, so they're just gone for now.
As for the highpass filters for the Famicom core, well ... you don't get
aliasing from resampling low frequencies. And generally speaking, too
low a frequency will be inaudible anyway. All these were doing was
killing possible bass (if they were too strong.) We can add them again,
but only if someone can convert Ryphecha's ad-hoc magic integers into a
frequency cutoff. In which case, I'll use my biquad IIR filter to do it
even better. On this note, it may prove useful to do this for the MD PSG
as well, to try and head off unnecessary clamping when mixing with the
YM2612.
Finally, there was the audio centering issue that affected the
MS,GG,MD,PCE,SG cores. It was flooring the "silent" audio level, which
was resulting in extremely heavy distortion if you tried listening to
higan and, say, audacious at the same time. Without the botched
centering, this distortion is completely gone now.
However, without any centering, we've halved the potential volume range.
This means the audio slider in higan's audio settings panel will start
clamping twice as quickly. So ultimately, we need to figure out how to
fix the centering. This isn't as simple as just subtracting less. We
will probably have to center every individual audio channel before
summing them to do this properly.
Results:
On the Mega Drive, Altered Beast sounds quite a bit better, a lot less
distortion now. But it's still not perfect, especially sound effects.
Further, Bare Knuckle / Streets of Rage still has really bad sound
effects. It looks like I broke something in Cydrak's code when trying to
adapt it to my style =(
byuu says:
Changelog:
- (MS,GG,MD)/PSG: flip output bit from noise channel [TmEE]
- MD/YM2612: rewrite YM2612::Channel functions to
YM2612::Channel::Operator functions¹
- MD/YM2612: pitch/octave I/O registers should set reload, not value
(fixes sound in most games)
- MD/YM2612: don't try to sign-extend raw PCM values (fixes Shining
Force opening music)
- MD/YM2612: various algorithm simplifications; conversions from
`*`, `/`, `%` to `<<`, `>>`; etc.
Overall ... Sonic the Hedgehog sounds really, really great. Almost
perfect, but there's a bit of clamping going on in the special zones.
Langrisser II sounds really great. Shining Force sounds pretty much
perfect. Bare Knucles (Streets of Rage) does pretty badly ... punches
sound more like dinging a salad fork on a wine glass, heh. Altered Beast
is extremely broken ... no music at the title screen, very distorted
in-game music. I suspect a bug outside of the YM2612 is affecting this
game.
So, the YM2612 emulation isn't perfect, but it's a really good start to
the most complex sound chip in all of higan. Hopefully the VRC7 and
YM2413 will prove to be less ferocious ... not that I'm in any rush to
work on either. The former is going to need the NES mapper rewrite to be
done first, and the latter is cool but not very necessary since all
those games have fallbacks to the inferior PSG audio.
But really ... I can't thank Cydrak enough for doing this for me. It
would have probably taken me months to parse through all of the
documentation on this chip (most of which is in a 55-page thread on
spritesmind that is filled with wrong/outdated information at the start,
and corrections as you go deeper.) Not to mention, learning about what
the hell detuning, low-frequency oscillation, tremolo, vibrato, etc were
all about. Or how those algorithms to compute the final output work. Or
the dozens of special cases littered in there to make everything sound
good. Fierce, nasty chip that.
Now the last real problem is save states ... the Mega Drive is going to
be the trickiest of all to implement with libco. There are lots of areas
where one chip will deadlock another chip while it completes some
operation. We don't have a choice but to force those stalls to abort
anyway, in order to let libco reach the start of its entry point once
again. I don't know what kind of impact that'll have on states ... I
suspect they'll work almost as reliably as the SNES does, but I can't
know that until I implement it. It's going to be pretty nasty, though.
¹: this basically removes a lot of unnecessary op. prefixes and the
need to capture `auto& op = operators[index]` at the start of every
function.
I wanted to have subfunctions like
`YM2612::Channel::Operator::Envelope::run()`, etc but unfortunately,
pretty much all of the envelope, phase, pitch, level functions need to
access each other's state.
byuu says:
Changelog:
- removed Emulator::Interface::videoFrequency(), audioFrequency()¹
- (MS,GG,MD)/PSG: removed inversion on noise channel LFSR update
[mic_]
- MD/PSG: lowered volume to match YM2612 volume
- MD/YM2612: added Cydrak's emulation of FM channels and LFO²
¹: These were no longer used by the UI. The video frequency is
adaptive on many systems. And the audio frequency is meaningless due to
Emulator::Audio always outputting a consistent frequency specified by
the UI. Plus, take the Genesis where there's two sound chips running at
different frequencies. So, these had to go.
²: Due to some lurking bugs, the audio is completely broken
unfortunately. Will need to be debugged :(
First pass looking for any typos didn't yield any obvious results.
byuu says:
Changelog:
- MD/PSG: fixed 68K bus Z80 status read address location
- MS, GG, MD/PSG: channels post-decrement their counters, not
pre-decrement [Cydrak]¹
- MD/VDP: cache screen width registers once per scanline; screen
height registers once per frame
- MD/VDP: support 256-width display mode (used in Shining Force, etc)
- MD/YM2612: implemented timers²
- MD/YM2612: implemented 8-bit PCM DAC²
- 68000: TRAP instruction should index the vector location by 32 (eg
by 128 bytes), fixes Shining Force
- nall: updated hex(), octal(), binary() functions to take uintmax
instead of template<typename T> parameter³
¹: this one makes an incredible difference. Sie noticed that lots of
games set a period of 0, which would end up being a really long period
with pre-decrement. By fixing this, noise shows up in many more games,
and sounds way better in games even where it did before. You can hear
extra sound on Lunar - Sanposuru Gakuen's title screen, the noise in
Sonic The Hedgehog (Mega Drive) sounds better, etc.
²: this also really helps sound. The timers allow PSG music to play
back at the correct speed instead of playing back way too quickly. And
the PCM DAC lets you hear a lot of drum effects, as well as the
"Sega!!" sound at the start of Sonic the Hedgehog, and the infamous,
"Rise from your grave!" line from Altered Beast.
Still, most music on the Mega Drive comes from the FM channels, so
there's still not a whole lot to listen to.
I didn't implement Cydrak's $02c test register just yet. Sie wasn't 100%
certain on how the extended DAC bit worked, so I'd like to play it a
little conservative and get sound working, then I'll go back and add a
toggle or something to enable undocumented registers, that way we can
use that to detect any potential problems they might be causing.
³: unfortunately we lose support for using hex() on nall/arithmetic
types. If I have a const Pair& version of the function, then the
compiler gets confused on whether Natural<32> should use uintmax or
const Pair&, because compilers are stupid, and you can't have explicit
arguments in overloaded functions. So even though either function would
work, it just decides to error out instead >_>
This is actually really annoying, because I want hex() to be useful for
printing out nall/crypto keys and hashes directly.
But ... this change had to be made. Negative signed integers would crash
programs, and that was taking out my 68000 disassembler.
byuu says:
Changelog:
- MD: connected 32KB cartridge RAM up to every Genesis game under 2MB
loaded¹
- MS, GG, MD: improved PSG noise channel emulation, hopefully²
- MS, GG, MD: lowered PSG volume so that the lowpass doesn't clamp
samples³
- MD: added read/write handlers for VRAM, VSRAM, CRAM
- MD: block VRAM copy when CD4 is clear⁴
- MD: rewrote VRAM fill, VRAM copy to be byte-based⁵
- MD: VRAM fill byte set should fall through to regular data port
write handler⁶
¹: the header parsing for backup RAM is really weird. It's spaces
when not used, and seems to be 0x02000001-0x02003fff for the Shining
games. I don't understand why it starts at 0x02000001 instead of
0x02000000. So I'm just forcing every game to have 32KB of RAM for now.
There's also special handling for ROMs > 2MB that also have RAM
(Phantasy Star IV, etc) where there's a toggle to switch between ROM and
RAM. For now, that's not emulated.
I was hoping the Shining games would run after this, but they're still
dead-locking on me :(
²: Cydrak pointed out some flaws in my attempt to implement what he
had. I was having trouble understanding what he meant, so I went back
and read the docs on the sound chip and tried implementing the counter
the way the docs describe. Hopefully I have this right, but I don't know
of any good test ROMs to make sure my noise emulation is correct. The
docs say the shifted-out value goes to the output instead of the low bit
of the LFSR, so I made that change as well.
I think I hear the noise I'm supposed to in Sonic Marble Zone now, but
it seems like it's not correct in Green Hill Zone, adding a bit of an
annoying buzz to the background music. Maybe it sounds better with the
YM2612, but more likely, I still screwed something up :/
³: it's set to 50% range for both cores right now. For the MD, it
will need to be 25% once YM2612 emulation is in.
⁴: technically, this deadlocks the VDP until a hard reset. I could
emulate this, but for now I just don't do the VRAM copy in this case.
⁵: VSRAM fill and CRAM fill not supported in this new mode. They're
technically undocumented, and I don't have good notes on how they work.
I've been seeing conflicting notes on whether the VRAM fill buffer is
8-bits or 16-bits (I chose 8-bits), and on whether you write the low
byte and then high byte of each words, or the high byte and then low
byte (I chose the latter.)
The VRAM copy improvements fix the opening text in Langrisser II, so
that's great.
⁶: Langrisser II sets the transfer length to one less than needed to
fill the background letter tile on the scenario overview screen. After
moving to byte-sized transfers, a black pixel was getting stuck there.
So effectively, VRAM fill length becomes DMA length + 1, and the first
byte uses the data port so it writes a word value instead of just a byte
value. Hopefully this is all correct, although it probably gets way more
complicated with the VDP FIFO.
byuu says:
Changelog:
- removed Emulator::Interface::Capabilities¹
- MS: improved the PSG emulation a bit
- MS: added cheat code support
- MS: added save state support²
- MD: emulated the PSG³
¹: there's really no point to it anymore. I intend to add cheat codes
to the GBA core, as well as both cheat codes and save states to the Mega
Drive core. I no longer intend to emulate any new systems, so these
values will always be true. Further, the GUI doesn't respond to these
values to disable those features anymore ever since the hiro rewrite, so
they're double useless.
²: right now, the Z80 core is using a pointer for HL-\>(IX,IY)
overrides. But I can't reliably serialize pointers, so I need to convert
the Z80 core to use an integer here. The save states still appear to
work fine, but there's the potential for an instruction to execute
incorrectly if you're incredibly unlucky, so this needs to be fixed as
soon as possible. Further, I still need a way to serialize
array<T, Size> objects, and I should also add nall::Boolean
serialization support.
³: I don't have a system in place to share identical sound chips. But
this chip is so incredibly simple that it's not really much trouble to
duplicate it. Further, I can strip out the stereo sound support code
from the Game Gear portion, so it's even tinier.
Note that the Mega Drive only just barely uses the PSG. Not at all in
Altered Beast, and only for a tiny part of the BGM music on Sonic 1,
plus his jump sound effect.
byuu says:
Changelog:
- MD: restructured DMA to a subclass of VDP
- MD: implemented VRAM copy mode (fixes Langrisser II ... mostly)
- MS: implemened PSG support [Cydrak]
- GG: implemented PSG stereo sound support
- MS: use the new struct Model {} design that other cores use
The MS/GG PSG should be feature complete, but I don't have good tests
for Game Gear stereo mode, nor for the noise channel. There's also a
really weird behavior with when to reload the channel counters on volume
register writes. I can confirm what Cydrak observed in that following
the docs and reloading always creates serious audio distortion problems.
So, more research is needed there.
To get the correct sound out of the PSG, I have to run it at 3.58MHz /
16, which seems really weird to me. The docs make it sound like it's
supposed to run at the full 3.58MHz. If we can really run it at
223.7KHz, then that's help reduce the overhead of PSG emulation, which
will definitely come in handy for Mega Drive, and possibly later Mega
CD, emulation.
I have not implemented the PSG into the Mega Drive just yet. Nor have I
implemented save states or cheat code support into the MS/GG cores yet.
The latter is next on my list.
byuu says:
Changelog:
- PCE: restructured VCE, VDCs to run one scanline at a time
- PCE: bound VDCs to 1365x262 timing (in order to decouple the VDCs
from the VCE)
- PCE: the two changes above allow save states to function; also
grants a minor speed boost
- PCE: added cheat code support (uses 21-bit bus addressing; compare
byte will be useful here)
- 68K: fixed `mov *,ccr` to read two bytes instead of one [Cydrak]
- Z80: emulated /BUSREQ, /BUSACK; allows 68K to suspend the Z80
[Cydrak]
- MD: emulated the Z80 executing instructions [Cydrak]
- MD: emulated Z80 interrupts (triggered during each Vblank period)
[Cydrak]
- MD: emulated Z80 memory map [Cydrak]
- MD: added stubs for PSG, YM2612 accesses [Cydrak]
- MD: improved bus emulation [Cydrak]
The PCE core is pretty much ready to go. The only major feature missing
is FM modulation.
The Mega Drive improvements let us start to see the splash screens for
Langrisser II, Shining Force, Shining in the Darkness. I was hoping I
could get them in-game, but no such luck. My Z80 implementation is
probably flawed in some way ... now that I think about it, I believe I
missed the BusAPU::reset() check for having been granted access to the
Z80 first. But I doubt that's the problem.
Next step is to implement Cydrak's PSG core into the Master System
emulator. Once that's in, I'm going to add save states and cheat code
support to the Master System core.
Next, I'll add the PSG core into the Mega Drive. Then I'll add the
'easy' PCM part of the YM2612. Then the rest of the beastly YM2612 core.
Then finally, cap things off with save state and cheat code support.
Should be nearing a new release at that point.
byuu says:
Changelog:
- PCE: emulated PSG volume controls (vastly enhances audio quality)
- PCE: emulated PSG noise as a square wave (somewhat enhances audio
quality)
- PCE: added save state support (currently broken and deadlocks the
emulator though)
Thankfully, MAME had some rather easy to read code on how the volume
adjustment works, which they apparently ripped out of expired patents.
Hooray!
The two remaining sound issues are:
1. the random number generator for the noise channel is definitely not
hardware accurate. But it won't affect the sound quality at all. You'd
only be able to tell the difference by looking at hex bytes of a stream
rip.
2. I have no clue how to emulate the LFO (frequency modulation). A comment
in MAME's code (they also don't emulate it) advises that they aren't
aware of any games that even use it. But I'm there has to be at least one?
Given LFO not being used, and the RNG not really mattering all that much
... the sound's pretty close to perfect now.
byuu says:
Changelog:
- added higan/emulator/platform.hpp (moved out Emulator::Platform from
emulator/interface.hpp)
- moved gmake build paramter to nall/GNUmakefile; both higan and
icarus use it now
- added build=profile mode
- MD: added the region select I/O register
- MD: started to add region selection support internally (still no
external select or PAL support)
- PCE: added cycle stealing when reading/writing to the VDC or VCE;
and when using ST# instructions
- PCE: cleaned up PSG to match the behavior of Mednafen (doesn't
improve sound at all ;_;)
- note: need to remove loadWaveSample, loadWavePeriod
- HuC6280: ADC/SBC decimal mode consumes an extra cycle; does not set
V flag
- HuC6280: block transfer instructions were taking one cycle too many
- icarus: added code to strip out PC Engine ROM headers
- hiro: added options support to BrowserDialog
The last one sure ended in failure. The plan was to put a region
dropdown directly onto hiro::BrowserDialog, and I had all the code for
it working. But I forgot one important detail: the system loads
cartridges AFTER powering on, so even though I could technically change
the system region post-boot, I'd rather not do so.
So that means we have to know what region we want before we even select
a game. Shit.
byuu says:
Changelog:
- higan: added Makefile option,
`build=(release|debug|instrument|optimize)` , defaults to release
- PCE: added preliminary PSG (sound) emulation
The Makefile thing is just to make it easier to build debug releases
without having to hand-edit the Makefile. Just say "gmake build=debug"
and you'll get -g, otherwise you'll get -O3 -s. I'll probably start
adding these build= blocks to my other projects. Or maybe I'll put it
into nall, in which case release will need a different name ... a stable
-01, and a fast -03 mode. I also want to add a mode to generate
profiling information (via gprof.)
Unfortunately, the existing documentation on the PCE's PSG is as
barebones as humanly possible.
Right now, I support waveform mode, direct D/A mode, and noise
generation mode. However for noise, I'm not actually generating a proper
square wave, and I don't know the PRNG algorithm used for choosing the
random values. So for now, I'm just feeding in nall::random() values to
it.
I'm also not sure about the noise mode's frequency counter. Magic Kit is
implying it's 64*~frequency, but that results in an 11-bit period. It
seems only logical that we'd want a 12-bit period. So my guess is that
it's actually 12-bit, and halfway through it alternates between two
randomly generated values every 32 samples, and the two values are
generated every time the period hits zero.
Next up, it's not clear when the period counter is reloaded, either for
the waveform or the noise mode. So for now, when enabling the channel, I
reload the waveform period. And when enabling noise mode, I reload the
noise period. I don't know if you need to do it when writing to the
frequency registers or not.
Next, it's not clear whether the period is a decrement-and-compare, or a
compare-and-decrement, and whether we reload with frequency,
frequency-1, or frequency+1. There's this cryptic note in
pcetext.txt:
> The PSG channel frequency is 12 bits, $001 is the highest frequency,
> $FFF is the next to lowest frequency, and $000 is the lowest frequency.
As best I can tell, he's trying to say that it's decrement-and-compare.
Whatever the case, there's periodic popping noises every few seconds. I
thought it might be because this is the first system with a fractional
sampling rate (~3.57MHz), but rounding the frequency to a whole number
doesn't help at all, and emulator/audio should be able to handle
fractional resampling rates anyway.
The popping noises could also be due to PSG writes being cycle-timed,
and my HuC6280 cycle timings not being very great yet. The PSG has no
kind of interrupts, so I think careful timing is the only way to do
certain things, especially D/A mode.
Next up, I really don't understand the frequency modulation mode at all.
I don't have any idea whatsoever how to support that. It also has a
frequency value that we'll need to understand how the period works and
reloads. Basic idea though is the channel 1 output turns into a value to
modulate channel 0's frequency by, and channel 1's output gets muted.
Next up, I don't know how the volume controls work at all. There's a
master volume left+right, per-channel volume left+right, and per-channel
overall volume. The documentation lists their effects in terms of
decibels. I have no fucking clue how to turn decibels into multiply-by
values. Let alone how to stack THREE levels of audio volume controls
>_>
Next, it looks like the output is always 5-bit unsigned per-channel, but
there's also all the volume adjustments. So I don't know the final
bit-depth of the final output to normalize the value into a signed
floating point value between -1.0 and +1.0. So for now, half the
potential speaker range (anything below zero) isn't used in the
generated output.
As bad as all this sounds, and it is indeed bad ... the audio's about
~75% correct, so you can definitely play games like this, it just won't
be all that much fun.
byuu says:
Changelog:
- Super Game Boy support is functional once again
- new GameBoy::SuperGameBoyInterface class
- system.(dmg,cgb,sgb) is now Model::(Super)GameBoy(Color) ala the PC
Engine
- merged WonderSwanInterface, WonderSwanColorInterface shared
functions to WonderSwan::Interface
- merged GameBoyInterface, GameBoyColorInterface shared functions to
GameBoy::Interface
- Interface::unload() now calls Interface::save() for Master System,
Game Gear, Mega Drive, PC Engine, SuperGrafx
- PCE: emulated PCE-CD backup RAM; stored per-game as save.ram (2KiB
file)
- this means you can now save your progress in games like Neutopia
- the PCE-CD I/O registers like BRAM write protect are not
emulated yet
- PCE: IRQ sources now hold the IRQ line state, instead of the CPU
holding it
- this fixes most SuperGrafx games, which were fighting over the
VDC IRQ line previously
- PCE: CPU I/O $14xx should return the pending IRQ bits even if IRQs
are disabled
- PCE: VCE and the VDCs now synchronize to each other; fixes pixel
widths in all games
- PCE: greatly increased the accuracy of the VPC priority selection
code (windows may be buggy still)
- HuC6280: PLA, PLX, PLY should set Z, N flags; fixes many game bugs
[Jonas Quinn]
The big thing I wanted to do was enslave the VDC(s) to the VCE. But
unfortunately, I forgot about the asynchronous DMA channels that each
VDC supports, so this isn't going to be possible I'm afraid.
In the most demanding case, Daimakaimura in-game, we're looking at 85fps
on my Xeon E3 1276v3. So ... not great, and we don't even have sound
connected yet.
We are going to have to profile and optimize this code once sound
emulation and save states are in.
Basically, think of it like this: the VCE, VDC0, and VDC1 all have the
same overhead, scheduling wise (which is the bulk of the performance
loss) as the dot-renderer for the SNES core. So it's like there's three
bsnes-accuracy PPU threads running just for video.
-----
Oh, just a fair warning ... the hooks for the SGB are a work in
progress.
If anyone is working on higan or a fork and want to do something similar
to it, don't use it as a template, at least not yet.
Right now, higan looks like this:
- Emulator::Video handles the platform→videoRefresh calls
- Emulator::Audio handles the platform→audioSample calls
- each core hard-codes the platform→inputPoll, inputRumble calls
- each core hard-codes calls to path, open, load to process files
- dipSettings and notify are specialty hacks, neither are even hooked
up right now to anything
With the SGB, it's an emulation core inside an emulation core, so
ideally you want to hook all of those functions. Emulator::Video and
Emulator::Audio aren't really abstractions over that, as the GB core
calls them and we have to special case not calling them in SGB mode.
The path, open, load can be implemented without hooks, thanks to the UI
only using one instance of Emulator::Platform for all cores. All we have
to do is override the folder path ID for the "Game Boy.sys" folder, so
that it picks "Super Game Boy.sfc/" and loads its boot ROM instead.
That's just a simple argument to GameBoy::System::load() and we're done.
dipSettings, notify and inputRumble don't matter. But we do also have to
hook inputPoll as well.
The nice idea would be for SuperFamicom::ICD2 to inherit from
Emulator::Platform and provide the desired functions that we need to
overload. After that, we'd just need the GB core to keep an abstraction
over the global Emulator::platform\* handle, to select between the UI
version and the SFC::ICD2 version.
However ... that doesn't work because of Emulator::Video and
Emulator::Audio. They would also have to gain an abstraction over
Emulator::platform\*, and even worse ... you'd have to constantly swap
between the two so that the SFC core uses the UI, and the GB core uses
the ICD2.
And so, for right now, I'm checking Model::SuperGameBoy() -> bool
everywhere, and choosing between the UI and ICD2 targets that way. And
as such, the ICD2 doesn't really need Emulator::Platform inheritance,
although it certainly could do that and just use the functions it needs.
But the SGB is even weirder, because we need additional new signals
beyond just Emulator::Platform, like joypWrite(), etc.
I'd also like to work on the Emulator::Stream for the SGB core. I don't
see why we can't have the GB core create its own stream, and let the
ICD2 just use that instead. We just have to be careful about the ICD2's
CPU soft reset function, to make sure the GB core's Stream object
remains valid. What I think that needs is a way to release an
Emulator::Stream individually, rather than calling
Emulator::Audio::reset() to do it. They are shared\_pointer objects, so
I think if I added a destructor function to remove it from
Emulator::Audio::streams, then that should work.
byuu says:
Changelog:
- PCE: split VCE from VDC
- HuC6280: changed bus from (uint21 addr) to (uint8 bank, uint13 addr)
- added SuperGrafx emulation (adds secondary VDC, plus new VPC)
The VDC now has no concept of the actual display raster timing, and
instead is driven by Vpulse (start of frame) and Hpulse (start of
scanline) signals from the VCE. One still can't render the start of the
next scanline onto the current scanline through overly aggressive
timings, but it shouldn't be too much more difficult to allow that to
occur now. This process incurs quite a major speed hit, so low-end
systems with Atom CPUs can't run things at 60fps anymore.
The timing needs a lot of work. The pixels end up very jagged if the VCE
doesn't output batches of 2-4 pixels at a time. But this should not be a
requirement at all, so I'm not sure what's going wrong there.
Yo, Bro and the 512-width mode of TV Sports Basketball is now broken as
a result of these changes, and I'm not sure why.
To load SuperGrafx games, you're going to have to change the .pce
extensions to .sg or .sgx. Or you can manually move the games from the
PC Engine folder to the SuperGrafx folder and change the game folder
extensions. I have no way to tell the games apart. Mednafen uses CRC32
comparisons, and I may consider that since there's only five games, but
I'm not sure yet.
The only SuperGrafx game that's playable right now is Aldynes. And the
priorities are all screwed up. I don't understand how the windows or the
priorities work at all from sgxtech.txt, so ... yeah. It's pretty
broken, but it's a start.
I could really use some help with this, as I'm very lost right now with
rendering :/
-----
Note that the SuperGrafx is technically its own system, it's not an
add-on.
As such, I'm giving it a separate .sys folder, and a separate library.
There's debate over how to name this thing. "SuperGrafx" appears more
popular than "Super Grafx". And you might also call it the "PC Engine
SuperGrafx", but I decided to leave off the prefix so it appears more
distinct.
byuu says:
Changelog:
- I caved on the `samples[] = {0.0}` thing, but I'm very unhappy about it
- if it's really invalid C++, then GCC needs to stop accepting it
in strict `-std=c++14` mode
- Emulator::Interface::Information::resettable is gone
- Emulator::Interface::reset() is gone
- FC, SFC, MD cores updated to remove soft reset behavior
- split GameBoy::Interface into GameBoyInterface,
GameBoyColorInterface
- split WonderSwan::Interface into WonderSwanInterface,
WonderSwanColorInterface
- PCE: fixed off-by-one scanline error [hex_usr]
- PCE: temporary hack to prevent crashing when VDS is set to < 2
- hiro: Cocoa: removed (u)int(#) constants; converted (u)int(#)
types to (u)int_(#)t types
- icarus: replaced usage of unique with strip instead (so we don't
mess up frameworks on macOS)
- libco: added macOS-specific section marker [Ryphecha]
So ... the major news this time is the removal of the soft reset
behavior. This is a major!! change that results in a 100KiB diff file,
and it's very prone to accidental mistakes!! If anyone is up for
testing, or even better -- looking over the code changes between v102r01
and v102r02 and looking for any issues, please do so. Ideally we'll want
to test every NES mapper type and every SNES coprocessor type by loading
said games and power cycling to make sure the games are all cleanly
resetting. It's too big of a change for me to cover there not being any
issues on my own, but this is truly critical code, so yeah ... please
help if you can.
We technically lose a bit of hardware documentation here. The soft reset
events do all kinds of interesting things in all kinds of different
chips -- or at least they do on the SNES. This is obviously not ideal.
But in the process of removing these portions of code, I found a few
mistakes I had made previously. It simplifies resetting the system state
a lot when not trying to have all the power() functions call the reset()
functions to share partial functionality.
In the future, the goal will be to come up with a way to add back in the
soft reset behavior via keyboard binding as with the Master System core.
What's going to have to happen is that the key binding will have to send
a "reset pulse" to every emulated chip, and those chips are going to
have to act independently to power() instead of reusing functionality.
We'll get there eventually, but there's many things of vastly greater
importance to work on right now, so it'll be a while. The information
isn't lost ... we'll just have to pull it out of v102 when we are ready.
Note that I left the SNES reset vector simulation code in, even though
it's not possible to trigger, for the time being.
Also ... the Super Game Boy core is still disconnected. To be honest, it
totally slipped my mind when I released v102 that it wasn't connected
again yet. This one's going to be pretty tricky to be honest. I'm
thinking about making a third GameBoy::Interface class just for SGB, and
coming up with some way of bypassing platform-> calls when in this
mode.
byuu says:
Changelog:
- MS, MD, PCE: remove controllers from scheduler in destructor
[hex_usr]
- PCE: no controller should return all bits set (still causing errant
key presses when swapping gamepads)
- PCE: emulate MDR for hardware I/O $0800-$17ff
- PCE: change video resolution to 1140x242
- PCE: added tertiary background Vscroll register (secondary cache)
- PCE: create classes out of VDC VRAM, SATB, CRAM for cleaner access
and I/O registers
- PCE: high bits of CRAM read should be set
- PCE: partially emulated VCE display registers: color frequency, HDS,
HDW, VDS, VDW
- PCE: 32-width sprites now split to two 16-width sprites to handle
overflow properly
- PCE: hopefully emulated sprite zero hit correctly (it's not well
documented, and not often used)
- PCE: trigger line coincidence interrupts during the previous
scanline's Hblank period
- tomoko: raise viewport from 320x240 to 326x242 to accommodate PC
Engine's max resolution
- nall: workaround for Clang compilation bug that can't figure out
that a char is an integral data type
byuu says (in the public announcement):
This release adds very preliminary emulation of the Sega Master System
(Mark III), Sega Game Gear, Sega Mega Drive (Genesis), and NEC PC Engine
(Turbografx-16). These cores do not yet offer sound emulation, save
states or cheat codes.
I'm always very hesitant to release a new emulation core in its alpha
stages, as in the past this has resulted in lasting bad impressions
of cores that have since improved greatly. For instance, the Game Boy
Advance emulation offered today is easily the second most accurate around,
yet it is still widely judged by its much older alpha implementation.
However, it's always been tradition with higan to not hold onto code
in secret. Rather than delay future releases for another year or two,
I'll put my faith in you all to understand that the emulation of these
systems will improve over time.
I hope that by releasing things as they are now, I might be able to
receive some much needed assistance in improving these cores, as the
documentation for these new systems is very much less than ideal.
byuu says (in the WIP forum):
Changelog:
- PCE: latch background scroll registers (fixes Neutopia scrolling)
- PCE: clip background attribute table scrolling (fixes Blazing Lazers
scrolling)
- PCE: support background/sprite enable/disable bits
- PCE: fix large sprite indexing (fixes Blazing Lazers title screen
sprites)
- HuC6280: wrap zeropage accesses to never go beyond $20xx
- HuC6280: fix alternating addresses for block move instructions
(fixes Neutopia II)
- HuC6280: block move instructions save and restore A,X,Y registers
- HuC6280: emulate BCD mode (may not be 100% correct, based on SNES
BCD) (fixes Blazing Lazers scoring)
byuu says:
Changelog:
- PCE: added 384KB HuCard ROM mirroring mode
- PCE: corrected D-pad polling order
- PCE: corrected palette color ordering (GRB, not RGB -- yes,
seriously)
- PCE: corrected SATB DMA -- should write to SATB, not to VRAM
- PCE: broke out Background, Sprite VDC settings to separate
subclasses
- PCE: emulated VDC backgrounds
- PCE: emulated VDC sprites
- PCE: emulated VDC sprite overflow, collision interrupts
- HuC6280: fixed disassembler output for STi instructions
- HuC6280: added missing LastCycle check to interrupt()
- HuC6280: fixed BIT, CMP, CPX, CPY, TRB, TSB, TST flag testing and
result
- HuC6280: added extra cycle delays to the block move instructions
- HuC6280: fixed ordering for flag set/clear instructions (happens
after LastCycle check)
- HuC6280: removed extra cycle from immediate instructions
- HuC6280: fixed indirectLoad, indirectYStore absolute addressing
- HuC6280: fixed BBR, BBS zeropage value testing
- HuC6280: fixed stack push/pull direction
Neutopia looks okay until the main title screen, then there's some
gibberish on the bottom. The game also locks up with some gibberish once
you actually start a new game. So, still not playable just yet =(
byuu says:
Changelog:
- PCE: emulated gamepad polling
- PCE: emulated CPU interrupt sources
- PCE: emulated timer
- PCE: smarter emulation of ST0,ST1,ST2 instructions
- PCE: better structuring of CPU, VDP IO registers
- PCE: connected palette generation to the interface
- PCE: emulated basic VDC timing
- PCE: emulated VDC Vblank, Coincidence, and DMA completion IRQs
- PCE: emulated VRAM, SATB DMA transfers
- PCE: emulated VDC I/O registers
Everything I've implemented today likely has lots of bugs, and is
untested for obvious reasons.
So basically, after I fix many horrendous bugs, it should now be
possible to implement the VDC and start getting graphical output.
byuu says:
Changelog:
- PCE: HuC6280 core completed
There's bound to be a countless stream of bugs, and the cycle counts are
almost certainly not exact yet, but ... all instructions are implemented.
So at this point, I can start comparing trace logs against Mednafen's
debugger output.
Of course, we're very likely to immediately slam into a wall of needing
I/O registers implemented for the VDC in order to proceed further.
byuu says:
Changelog:
- SMS: fixed controller connection bug
- SMS: fixed Z80 reset bug
- PCE: emulated HuC6280 MMU
- PCE: emulated HuC6280 RAM
- PCE: emulated HuCard ROM reading
- PCE: implemented 178 instructions
- tomoko: removed "soft reset" functionality
- tomoko: moved "power cycle" to just above "unload" option
I'm not sure of the exact number of HuC6280 instructions, but it's less
than 260.
Many of the ones I skipped are HuC6280-originals that I don't know how
to emulate just yet.
I'm also really unsure about the zero page stuff. I believe we should be
adding 0x2000 to the addresses to hit page 1, which is supposed to be
mapped to the zero page (RAM). But when I look at turboEMU's source, I
have no clue how the hell it could possibly be doing that. It looks to
be reading from page 0, which is almost always ROM, which would be ...
really weird.
I also don't know if I've emulated the T mode opcodes correctly or not.
The documentation on them is really confusing.
byuu says:
Changelog:
- converted Emulator::Interface::Bind to Emulator::Platform
- temporarily disabled SGB hooks
- SMS: emulated Game Gear palette (latching word-write behavior not
implemented yet)
- SMS: emulated Master System 'Reset' button, Game Gear 'Start' button
- SMS: removed reset() functionality, driven by the mappable input now
instead
- SMS: split interface class in two: one for Master System, one for
Game Gear
- SMS: emulated Game Gear video cropping to 160x144
- PCE: started on HuC6280 CPU core—so far only registers, NOP
instruction has been implemented
Errata:
- Super Game Boy support is broken and thus disabled
- if you switch between Master System and Game Gear without
restarting, bad things happen:
- SMS→GG, no video output on the GG
- GG→SMS, no input on the SMS
I'm not sure what's causing the SMS\<-\>GG switch bug, having a hard
time debugging it. Help would be very much appreciated, if anyone's up
for it. Otherwise I'll keep trying to track it down on my end.
byuu says:
Changelog:
- SMS: added cartridge ROM/RAM mirroring (fixes Alex Kidd)
- SMS: fixed 8x16 sprite mode (fixes Wonder Boy, Ys graphics)
- Z80: emulated "ex (sp),hl" instruction
- Z80: fixed INx NF (should be set instead of cleared)
- Z80: fixed loop condition check for CPxR, INxR, LDxR, OTxR (fixes
walking in Wonder Boy)
- SFC: removed Debugger and sfc/debugger.hpp
- icarus: connected MS, GG, MD importing to the scan dialog
- PCE: added emulation skeleton to higan and icarus
At this point, Master System games are fairly highly compatible, sans
audio. Game Gear games are running, but I need to crop the resolution
and support the higher color palette that they can utilize. It's really
something else the way they handled the resolution shrink on that thing.
The last change is obviously going to be the biggest news.
I'm very well aware it's not an ideal time to start on a new emulation
core, with the MS and MD cores only just now coming to life with no
audio support.
But, for whatever reason, my heart's really set on working on the PC
Engine. I wanted to write the final higan skeleton core, and get things
ready so that whenever I'm in the mood to work on the PCE, I can do so.
The skeleton is far and away the most tedious and obnoxious part of the
emulator development, because it's basically all just lots of
boilerplate templated code, lots of new files to create, etc.
I really don't know how things are going to proceed ... but I can say
with 99.9% certainty that this will be the final brand new core ever
added to higan -- at least one written by me, that is. This was
basically the last system from my childhood that I ever cared about.
It's the last 2D system with games that I really enjoy playing. No other
system is worth dividing my efforts and reducing the quality and amount
of time to work on the systems I have.
In the future, there will be potential for FDS, Mega CD and PCE-CD
support. But those will all be add-ons, and they'll all be really
difficult and challenge the entire design of higan's UI (it's entirely
cartridge-driven at this time.) None of them will be entirely new cores
like this one.
byuu says:
Changelog:
- SMS: background VDP clips partial tiles on the left (math may not be
right ... it's hard to reason about)
- SMS: fix background VDP scroll locks
- SMS: fix VDP sprite coordinates
- SMS: paint black after the end of the visible display
- todo: shouldn't be a brute force at the end of the main VDP
loop, should happen in each rendering unit
- higan: removed emulator/debugger.hpp
- higan: removed privileged: access specifier
- SFC: removed debugger hooks
- todo: remove sfc/debugger.hpp
- Z80: fixed disassembly of (fd,dd) cb (displacement) (opcode)
instructions
- Z80: fix to prevent interrupts from firing between ix/iy prefixes
and opcodes
- todo: this is a rather hacky fix that could, if exploited, crash
the stack frame
- Z80: fix BIT flags
- Z80: fix ADD hl,reg flags
- Z80: fix CPD, CPI flags
- Z80: fix IND, INI flags
- Z80: fix INDR, INIT loop flag check
- Z80: fix OUTD, OUTI flags
- Z80: fix OTDR, OTIR loop flag check
byuu says:
Changelog:
- SMS: emulated the remaining 240 instructions in the (0xfd, 0xdd)
0xcb (displacement) (opcode) set
- 1/8th of these were "legal" instructions, and apparently games
use them a lot
- SMS: emulated the standard gamepad controllers
- reset button not emulated yet
The reset button is tricky. In every other case, reset is a hardware
thing that instantly reboots the entire machine.
But on the SMS, it's more like a gamepad button that's attached to the
front of the device. When you press it, it fires off a reset vector
interrupt and the gamepad polling routine lets you query the status of
the button.
Just having a reset option in the "Master System" hardware menu is not
sufficient to fully emulate the behavior. Even more annoying is that the
Game Gear doesn't have such a button, yet the core information structs
aren't flexible enough for the Master System to have it, and the Game
Gear to not have it, in the main menu. But that doesn't matter anyway,
since it won't work having it in the menu for the Master System.
So as a result, I'm going to have to have a new "input device" called
"Hardware" that has the "Reset" button listed under there. And for the
sake of consistency, I'm not sure if we should treat the other systems
the same way or not :/
byuu says:
Changelog:
- SMS: emulated the generic Sega memory mapper (none of the more
limited forms of it yet)
- (missing ROM shift, ROM write enable emulation -- no commercial
games use either, though)
- SMS: bus I/O returns 0xff instead of 0x00 so games don't think every
key is being pressed at once
- (this is a hack until I implement proper controller pad reading)
- SMS: very limited protection against reading/writing past the end of
ROM/RAM (todo: should mirror)
- SMS: VDP background HSCROLL subtracts, rather than adds, to the
offset (unlike VSCROLL)
- SMS: VDP VSCROLL is 9-bit, modulates voffset+vscroll to 224 in
192-line mode (32x28 tilemap)
- SMS: VDP tiledata for backgrounds and sprites use `7-(x&7)` rather
than `(x&7)`
- SMS: fix output color to be 6-bit rather than 5-bit
- SMS: left clip uses register `#7`, not palette color `#7`
- (todo: do we want `color[reg7]` or `color[16 + reg7]`?)
- SMS: refined handling of 0xcb, 0xed prefixes in the Z80 core and its
disassembler
- SMS: emulated (0xfd, 0xdd) 0xcb opcodes 0x00-0x0f (still missing
0x10-0xff)
- SMS: fixed 0xcb 0b-----110 opcodes to use direct HL and never allow
(IX,IY)+d
- SMS: fixed major logic bug in (IX,IY)+d displacement
- (was using `read(x)` instead of `operand()` for the displacement
byte fetch before)
- icarus: fake there always being 32KiB of RAM in all SMS cartridges
for the time being
- (not sure how to detect this stuff yet; although I've read it's
not even really possible `>_>`)
TODO: remove processor/z80/dissassembler.cpp code block at line 396 (as it's unnecessary.)
Lots of commercial games are starting to show trashed graphical output now.
byuu says:
Changelog:
- Makefile: added $(windres), -lpthread to Windows port
- GBA: WAITCNT.prefetch is not writable (should fix Donkey Kong: King
of Swing) \[endrift\]
- SMS: fixed hcounter shift value \[hex\_usr\]
- SMS: emulated interrupts (reset button isn't hooked up anywhere, not
sure where to put it yet)
This WIP actually took a really long time because the documentation on
SMS interrupts was all over the place. I'm hoping I've emulated them
correctly, but I honestly have no idea. It's based off my best
understanding from four or five different sources. So it's probably
quite buggy.
However, a few interrupts fire in Sonic the Hedgehog, so that's
something to start with. Now I just have to hope I've gotten some games
far enough in that I can start seeing some data in the VDP VRAM. I need
that before I can start emulating graphics mode 4 to get some actual
screen output.
Or I can just say to hell with it and use a "Hello World" test ROM.
That'd probably be smarter.
byuu says:
Changelog:
- SMS: extended bus mapping of in/out ports: now decoding them fully
inside ms/bus
- SMS: moved Z80 disassembly code from processor/z80 to ms/cpu
(cosmetic)
- SMS: hooked up non-functional silent PSG sample generation, so I can
cap the framerate at 60fps
- SMS: hooked up the VDP main loop: 684 clocks/scanline, 262
scanlines/frame (no PAL support yet)
- SMS: emulated the VDP Vcounter and Hcounter polling ... hopefully
it's right, as it's very bizarre
- SMS: emulated VDP in/out ports (data read, data write, status read,
control write, register write)
- SMS: decoding and caching all VDP register flags (variable names
will probably change)
- nall: \#undef IN on Windows port (prevent compilation warning on
processor/z80)
Watching Sonic the Hedgehog, I can definitely see some VDP register
writes going through, which is a good sign.
Probably the big thing that's needed before I can get enough into the
VDP to start showing graphics is interrupt support. And interrupts are
never fun to figure out :/
What really sucks on this front is I'm flying blind on the Z80 CPU core.
Without a working VDP, I can't run any Z80 test ROMs to look for CPU
bugs. And the CPU is certainly too buggy still to run said test ROM
anyway. I can't find any SMS emulators with trace logging from reset.
Such logs vastly accelerate tracking down CPU logic bugs, so without
them, it's going to take a lot longer.
byuu says:
This is a really tiny WIP. Just wanted to add the known fixes before I start debugging it against Mednafen in a fork.
Changelog:
- Z80: fixed flag calculations on 8-bit ADC, ADD, SBC, SUB
- Z80: fixed flag calculations on 16-bit ADD
- Z80: simplified DAA logic \[AWJ\]
- Z80: RETI sets IFF1=IFF2 (same as RETN)
byuu says:
Changelog:
- Z80: emulated 83 new instructions
- Z80: timing improvements
DAA is a skeleton implementation to complete the normal opcode set. Also
worth noting that I don't know exactly what the hell RETI is doing,
so for now it acts like RET. RETN probably needs some special handling
besides just setting IFF1=IFF2 as well.
I'm now missing 24 ED-prefix instructions, plus DAA, for a total of 25
opcodes remaining. And then, of course, several weeks worth of debugging
all of the inevitable bugs in the core.
byuu says:
Changelog:
- added \~130 new PAL games to icarus (courtesy of Smarthuman
and aquaman)
- added all three Korean-localized games to icarus
- sfc: removed SuperDisc emulation (it was going nowhere)
- sfc: fixed MSU1 regression where the play/repeat flags were not
being cleared on track select
- nall: cryptography support added; will be used to sign future
databases (validation will always be optional)
- minor shims to fix compilation issues due to nall changes
The real magic is that we now have 25-30% of the PAL SNES library in
icarus!
Signing will be tricky. Obviously if I put the public key inside the
higan archive, then all anyone has to do is change that public key for
their own releases. And if you download from my site (which is now over
HTTPS), then you don't need the signing to verify integrity. I may just
put the public key on my site on my site and leave it at that, we'll
see.
byuu says:
Changelog:
- added 30 new PAL games to icarus (courtesy of Mikerochip)
- new version of libco no longer requires mprotect nor W|X permissions
- nall: default C compiler to -std=c11 instead of -std=c99
- nall: use `-fno-strict-aliasing` during compilation
- updated nall/certificates (hopefully for the last time)
- updated nall/http to newer coding conventions
- nall: improve handling of range() function
I didn't really work on higan at all, this is mostly just a release
because lots of other things have changed.
The most interesting is `-fno-strict-aliasing` ... basically, it joins
`-fwrapv` as being "stop the GCC developers from doing *really* evil
shit that could lead to security vulnerabilities or instabilities."
For the most part, it's a ~2% speed penalty for higan. Except for the
Sega Genesis, where it's a ~10% speedup. I have no idea how that's
possible, but clearly something's going very wrong with strict aliasing
on the Genesis core.
So ... it is what it is. If you need the performance for the non-Genesis
cores, you can turn it off in your builds. But I'm getting quite sick of
C++'s "surprises" and clever compiler developers, so I'm keeping it on
in all of my software going forward.
byuu says:
Changelog:
- Z80: added most opcodes between 0x00 and 0x3f (two or three hard
ones missing still)
- Z80: redid register declaration *again* to handle AF', BC', DE',
HL' (ugggggh, the fuck? Alternate registers??)
- basically, using `#define <register name>` values to get around
horrendously awful naming syntax
- Z80: improved handling of displace() so that it won't ever trigger
on (BC) or (DE)
byuu says:
Changelog:
- Z80: implemented 113 new instructions (all the easy
LD/ADC/ADD/AND/OR/SBC/SUB/XOR ones)
- Z80: used alternative to castable<To, With> type (manual cast inside
instruction() register macros)
- Z80: debugger: used register macros to reduce typing and increase
readability
- Z80: debugger: smarter way of handling multiple DD/FD prefixes
(using gotos, yay!)
- ruby: fixed crash with Windows input driver on exit (from SuperMikeMan)
I have no idea how the P/V flag is supposed to work on AND/OR/XOR, so
that's probably wrong for now. HALT is also mostly a dummy function for
now. But I typically implement those inside instruction(), so it
probably won't need to be changed? We'll see.
byuu says:
Changelog:
- added (poorly-named) castable<To, With> template
- Z80 debugger rewritten to make declaring instructions much simpler
- Z80 has more instructions implemented; supports displacement on
(IX), (IY) now
- added `Processor::M68K::Bus` to mirror `Processor::Z80::Bus`
- it does add a pointer indirection; so I'm not sure if I want to
do this for all of my emulator cores ...
byuu says:
Changelog:
- rewrote the Z80 core to properly handle 0xDD (IX0 and 0xFD (IY)
prefixes
- added Processor::Z80::Bus as a new type of abstraction
- all of the instructions implemented have their proper T-cycle counts
now
- added nall/certificates for my public keys
The goal of `Processor::Z80::Bus` is to simulate the opcode fetches being
2-read + 2-wait states; operand+regular reads/writes being 3-read. For
now, this puts the cycle counts inside the CPU core. At the moment, I
can't think of any CPU core where this wouldn't be appropriate. But it's
certainly possible that such a case exists. So this may not be the
perfect solution.
The reason for having it be a subclass of Processor::Z80 instead of
virtual functions for the MasterSystem::CPU core to define is due to
naming conflicts. I wanted the core to say `in(addr)` and have it take
the four clocks. But I also wanted a version of the function that didn't
consume time when called. One way to do that would be for the core to
call `Z80::in(addr)`, which then calls the regular `in(addr)` that goes to
`MasterSystem::CPU::in(addr)`. But I don't want to put the `Z80::`
prefix on all of the opcodes. Very easy to forget it, and then end up not
consuming any time. Another is to use uglier names in the
`MasterSystem::CPU` core, like `read_`, `write_`, `in_`, `out_`, etc. But,
yuck.
So ... yeah, this is an experiment. We'll see how it goes.
byuu says:
Changelog:
- MS: added ms/bus
- Z80: implemented JP/JR/CP/DI/IM/IN instructions
- MD/VDP: added window layer emulation
- MD/controller/gamepad: fixed d2,d3 bits (Altered Beast requires
this)
The Z80 is definitely a lot nastier than the LR35902. There's a lot of
table duplication with HL→IX→IY; and two of them nest two levels deep
(eg FD CB xx xx), so the design may change as I implement more.
byuu says:
Changelog:
- new md/bus/ module for bus reads/writes
- abstracts byte/word accesses wherever possible (everything but
RAM; forces all but I/O to word, I/O to byte)
- holds the system RAM since that's technically not part of the
CPU anyway
- added md/controller and md/system/peripherals
- added emulation of gamepads
- added stub PSG audio output (silent) to cap the framerate at 60fps
with audio sync enabled
- fixed VSRAM reads for plane vertical scrolling (two bugs here: add
instead of sub; interlave plane A/B)
- mask nametable read offsets (can't exceed 8192-byte nametables
apparently)
- emulated VRAM/VSRAM/CRAM reads from VDP data port
- fixed sprite width/height size calculations
- added partial emulation of 40-tile per scanline limitation (enough
to fix Sonic's title screen)
- fixed off-by-one sprite range testing
- fixed sprite tile indexing
- Vblank happens at Y=224 with overscan disabled
- unsure what happens when you toggle it between Y=224 and Y=240
... probably bad things
- fixed reading of address register for ADDA, CMPA, SUBA
- fixed sign extension for MOVEA effect address reads
- updated MOVEM to increment the read addresses (but not writeback)
for (aN) mode
With all of that out of the way, we finally have Sonic the Hedgehog
(fully?) playable. I played to stage 1-2 and through the special stage,
at least. EDIT: yeah, we probably need HIRQs for Labyrinth Zone.
Not much else works, of course. Most games hang waiting on the Z80, and
those that don't (like Altered Beast) are still royally screwed. Tons of
features still missing; including all of the Z80/PSG/YM2612.
A note on the perihperals this time around: the Mega Drive EXT port is
basically identical to the regular controller ports. So unlike with the
Famicom and Super Famicom, I'm inheriting the exension port from the
controller class.
byuu says:
Changelog:
- 68K: fixed NEG/NEGX operand order
- 68K: fixed bug in disassembler that was breaking trace logging
- VDP: improved sprite rendering (still 100% broken)
- VDP: added horizontal/vertical scrolling (90% broken)
Forgot:
- 68K: fix extension word sign bit on indexed modes for disassembler
as well
- 68K: emulate STOP properly (use r.stop flag; clear on IRQs firing)
I'm really wearing out fast here. The Genesis documentation is somehow
even worse than Game Boy documentation, but this is a far more complex
system.
It's a massive time sink to sit here banging away at every possible
combination of how things could work, only to see no positive
improvements. Nothing I do seems to get sprites to do a goddamn thing.
squee says the sprite Y field is 10-bits, X field is 9-bits. genvdp says
they're both 10-bits. BlastEm treats them like they're both 10-bits,
then masks off the upper bit so it's effectively 9-bits anyway.
Nothing ever bothers to tell you whether the horizontal scroll values
are supposed to add or subtract from the current X position. Probably
the most basic detail you could imagine for explaining horizontal
scrolling and yet ... nope. Nothing.
I can't even begin to understand how the VDP FIFO functionality works,
or what the fuck is meant by "slots".
I'm completely at a loss as how how in the holy hell the 68K works with
8-bit accesses. I don't know whether I need byte/word handlers for every
device, or if I can just hook it right into the 68K core itself. This
one's probably the most major design detail. I need to know this before
I go and implement the PSG/YM2612/IO ports-\>gamepads/Z80/etc.
Trying to debug the 68K is murder because basically every game likes to
start with a 20,000,000-instruction reset phase of checksumming entire
games, and clearing out the memory as agonizingly slowly as humanly
possible. And like the ARM, there's too many registers so I'd need three
widescreen monitors to comfortably view the entire debugger output lines
onscreen.
I can't get any test ROMs to debug functionality outside of full games
because every **goddamned** test ROM coder thinks it's acceptable to tell
people to go fetch some toolchain from a link that died in the late '90s
and only works on MS-DOS 6.22 to build their fucking shit, because god
forbid you include a 32KiB assembled ROM image in your fucking archives.
... I may have to take a break for a while. We'll see.
byuu says:
Changelog:
- 68K: MOVEQ is 8-bit signed
- 68K: disassembler was print EOR for OR instructions
- 68K: address/program-counter indexed mode had the signed-word/long
bit backward
- 68K: ADDQ/SUBQ #n,aN always works in long mode; regardless of size
- 68K→VDP DMA needs to use `mode.bit(0)<<22|dmaSource`; increment by
one instead of two
- Z80: added registers and initial two instructions
- MS: hooked up enough to load and start running games
- Sonic the Hedgehog can execute exactly one instruction... whoo.
byuu says:
Sorry, two WIPs in one day. Got excited and couldn't wait.
Changelog:
- ADDQ, SUBQ shouldn't update flags when targeting an address register
- ADDA should sign extend effective address reads
- JSR was pushing the PC too early
- some improvements to 8-bit register reads on the VDP (still needs
work)
- added H/V counter reads to the VDP IO port region
- icarus: added support for importing Master System and Game Gear ROMs
- tomoko: added library sub-menus for each manufacturer
- still need to sort Game Gear after Mega Drive somehow ...
The sub-menu system actually isn't all that bad. It is indeed a bit more
annoying, but not as annoying as I thought it was going to be. However,
it looks a hell of a lot nicer now.
byuu says:
Added VDP sprite rendering. Can't get any games far enough in to see if
it actually works. So in other words, it doesn't work at all and is 100%
completely broken.
Also added 68K exceptions and interrupts. So far only the VDP interrupt
is present. It definitely seems to be firing in commercial games, so
that's promising. But the implementation is almost certainly completely
wrong. There is fuck all of nothing for documentation on how interrupts
actually work. I had to find out the interrupt vector numbers from
reading the comments from the Sonic the Hedgehog disassembly. I have
literally no fucking clue what I0-I2 (3-bit integer priority value in
the status register) is supposed to do. I know that Vblank=6, Hblank=4,
Ext(gamepad)=2. I know that at reset, SR.I=7. I don't know if I'm
supposed to block interrupts when I is >, >=, <, <= to the interrupt
level. I don't know what level CPU exceptions are supposed to be.
Also implemented VDP regular DMA. No idea if it works correctly since
none of the commercial games run far enough to use it. So again, it's
horribly broken for usre.
Also improved VDP fill mode. But I don't understand how it takes
byte-lengths when the bus is 16-bit. The transfer times indicate it's
actually transferring at the same speed as the 68K->VDP copy, strongly
suggesting it's actually doing 16-bit transfers at a time. In which case,
what happens when you set an odd transfer length?
Also, both DMA modes can now target VRAM, VSRAM, CRAM. Supposedly there's
all kinds of weird shit going on when you target VSRAM, CRAM with VDP
fill/copy modes, but whatever. Get to that later.
Also implemented a very lazy preliminary wait mechanism to to stall out
a processor while another processor exerts control over the bus. This
one's going to be a major work in progress. For one, it totally breaks
the model I use to do save states with libco. For another, I don't
know if a 68K->VDP DMA instantly locks the CPU, or if it the CPU could
actually keep running if it was executing out of RAM when it started
the DMA transfer from ROM (eg it's a bus busy stall, not a hard chip
stall.) That'll greatly change how I handle the waiting.
Also, the OSS driver now supports Audio::Latency. Sound should be
even lower latency now. On FreeBSD when set to 0ms, it's absolutely
incredible. Cannot detect latency whatsoever. The Mario jump sound seems
to happen at the very instant I hear my cherry blue keyswitch activate.
byuu says:
I reworked the video sizing code. Ended up wasting five fucking hours
fighting GTK. When you call `gtk_widget_set_size_request`, it doesn't
actually happen then. This is kind of a big deal because when I then go
to draw onto the viewport, the actual viewport child window is still the
old size, so the image gets distorted. It recovers in a frame or so with
emulation, but if we were to put a still image on there, it would stay
distorted.
The first thought is, `while(gtk_events_pending())
gtk_main_iteration_do(false);` right after the `set_size_request`. But
nope, it tells you there's no events pending. So then you think, go
deeper, use `XPending()` instead. Same thing, GTK hasn't actually issued
the command to Xlib yet. So then you think, if the widget is realized,
just call a blocking `gtk_main_iteration`. One call does nothing, two
calls results in a deadlock on the second one ... do it before program
startup, and the main window will never appear. Great.
Oh, and it's not just the viewport. It's also the widget container area
of the windows, as well as the window itself, as well as the fullscreen
mode toggle effect. They all do this.
For the latter three, I couldn't find anything that worked, so I just
added 20ms loops of constantly calling `gtk_main_iteration_do(false)`
after each one of those things. The downside here is toggling the status
bar takes 40ms, so you'll see it and it'll feel a tiny bit sluggish.
But I can't have a 20ms wait on each widget resize, that would be
catastrophic to performance on windows with lots of widgets.
I tried hooking configure-event and size-allocate, but they were very
unreliable. So instead I ended up with a loop that waits up to a maximm
of 20ms that inspects the `widget->allocation.(width,height)` values
directly and waits for them to be what we asked for with
`set_size_request`.
There was some extreme ugliness in GTK with calling
`gtk_main_iteration_do` recursively (`hiro::Widget::setGeometry` is
called recursively), so I had to lock it to only happen on the top level
widgets (the child ones should get resized while waiting on the
top-level ones, so it should be fine in practice), and also only run it
on realized widgets.
Even still, I'm getting ~3 timeouts when opening the settings dialog in
higan, but no other windows. But, this is the best I can do for now.
And the reason for all of this pain? Yeah, updated the video code.
So the Emulator::Interface now has this:
struct VideoSize { uint width, height; }; //or requiem for a tuple
auto videoSize() -> VideoSize;
auto videoSize(uint width, uint height, bool arc) -> VideoSize;
The first function, for now, is just returning the literal surface size.
I may remove this ... one thing I want to allow for is cores that send
different texture sizes based on interlace/hires/overscan/etc settings.
The second function is more interesting. Instead of having the UI trying
to figure out sizing, I figure the emulation cores can do a better job
and we can customize it per-core now. So it gets the window's width and
height, and whether the user asked for aspect correction, and then
computes the best width/height ratio possible. For now they're all just
doing multiples of a 1x scale to the UI 2x,3x,4x modes.
We still need a third function, which will probably be what I repurpose
videoSize() for: to return the 'effective' size for pixel shaders, to
then feed into ruby, to then feed into quark, to then feed into our
shaders. Since shaders use normalized coordinates for pixel fetching,
this should work out just fine. The real texture size will be exposed to
quark shaders as well, of course.
Now for the main window ... it's just hard-coded to be 640x480, 960x720,
1280x960 for now. It works nicely for some cores on some modes, not so
much for others. Work in progress I guess.
I also took the opportunity to draw the about dialog box logo on the
main window. Got a bit fancy and used the old spherical gradient and
impose functionality of nall/image on it. Very minor highlight, nothing
garish. Just something nicer than a solid black window.
If you guys want to mess around with sizes, placements, and gradient
styles/colors/shapes ... feel free. If you come up with something nicer,
do share.
That's what led to all the GTK hell ... the logo wasn't drawing right as
you resized the window. But now it is, though I am not at all happy with
the hacking I had to do.
I also had to improve the video update code as a result of this:
- when you unload a game, it blacks out the screen
- if you are not quitting the emulator, it'll draw the logo; if
you are, it won't
- when you load a game, it black out the logo
These options prevent any unsightliness from resizing the viewport with
image data on it already
I need to redraw the logo when toggling fullscreen with no game loaded
as well for Windows, it seems.
byuu says:
Changelog:
- 68K: fixed bug that affected BSR return address
- VDP: added very preliminary emulation of planes A, B, W (W is
entirely broken though)
- VDP: added command/address stuff so you can write to VRAM, CRAM,
VSRAM
- VDP: added VRAM fill DMA
I would be really surprised if any commercial games showed anything at
all, so I'd probably recommend against wasting your time trying, unless
you're really bored :P
Also, I wanted to add: I am accepting patches\! So if anyone wants to
look over the 68K core for bugs, that would save me untold amounts of
time in the near future :D
byuu says:
Changelog:
- pulled the (u)intN type aliases into higan instead of leaving them
in nall
- added 68K LINEA, LINEF hooks for illegal instructions
- filled the rest of the 68K lambda table with generic instance of
ILLEGAL
- completed the 68K disassembler effective addressing modes
- still unsure whether I should use An to decode absolute
addresses or not
- pro: way easier to read where accesses are taking place
- con: requires An to be valid; so as a disassembler it does a
poor job
- making it optional: too much work; ick
- added I/O decoding for the VDP command-port registers
- added skeleton timing to all five processor cores
- output at 1280x480 (needed for mixed 256/320 widths; and to handle
interlace modes)
The VDP, PSG, Z80, YM2612 are all stepping one clock at a time and
syncing; which is the pathological worst case for libco. But they also
have no logic inside of them. With all the above, I'm averaging around
250fps with just the 68K core actually functional, and the VDP doing a
dumb "draw white pixels" loop. Still way too early to tell how this
emulator is going to perform.
Also, the 320x240 mode of the Genesis means that we don't need an aspect
correction ratio. But we do need to ensure the output window is a
multiple 320x240 so that the scale values work correctly. I was
hard-coding aspect correction to stretch the window an additional \*8/7.
But that won't work anymore so ... the main higan window is now 640x480,
960x720, or 1280x960. Toggling aspect correction only changes the video
width inside the window.
It's a bit jarring ... the window is a lot wider, more black space now
for most modes. But for now, it is what it is.
byuu says:
The 68K core now implements all 88 instructions. It ended up being 111
instructions in my core due to splitting up opcodes with the same name
but different addressing modes or directions (removes conditions at the
expense of more code.)
Technically, I don't have exceptions actually implemented yet, and
RESET/STOP don't do anything but set flags. So there's still more to
go. But ... close enough for statistics time!
The M68K core source code is 124,712 bytes in size. The next largest
core is the ARM7 core at 70,203 bytes in size.
The M68K object size is 942KiB; with the next largest being the V30MZ
core at 173KiB.
There are a total of 19,656 invalid opcodes in the 68000 revision (unless
of course I've made mistakes in my mappings, which is very probably.)
Now the fun part ... figuring out how to fix bugs in this core without
VDP emulation :/
byuu says:
Changelog:
- Emulator: use `(uintmax)-1 >> 1` for the units of time
- MD: implemented 13 new 68K instructions (basically all of the
remaining easy ones); 21 remain
- nall: replaced `(u)intmax_t` (64-bit) with *actual* `(u)intmax` type
(128-bit where available)
- this extends to everything: atoi, string, etc. You can even
print 128-bit variables if you like
22,552 opcodes still don't exist in the 68K map. Looking like quite a
few entries will be blank once I finish.
byuu says:
Changelog:
- added eight more 68K instructions
- split ADD(direction) into two separate ADD functions
I now have 54 out of 88 instructions implemented (thus, 34 remaining.)
The map is missing 25,182 entries out of 65,536. Down from 32,680 for
v101.00
Aside: this version number feels really silly. r10 and r11 surely will
as well ...
byuu says (in the public announcement):
Not a large changelog this time, sorry. This release is mostly to fix
the SA-1 issue, and to get some real-world testing of the new scheduler
model. Most of the work in the past month has gone into writing a 68000
CPU core; yet it's still only about half-way finished.
Changelog (since the previous release):
- fixed SNES SA-1 IRQ regression (fixes Super Mario RPG level-up
screen)
- new scheduler for all emulator cores (precision of 2^-127)
- icarus database adds nine new SNES games
- added Input/Frequency to settings file (allows simulation of
latency)
byuu says (in the WIP forum):
Changelog:
- in 32-bit mode, Thread uses uint64\_t with 2^-63 time units (10^-7
precision in the worst case)
- nearly ten times the precision of an attosecond
- in 64-bit mode, Thread uses uint128\_t with 2^-127 time units
(10^-26 precision in the worst case)
- far more accurate than yoctoseconds; almost closing in on planck
time
Note: a quartz crystal is accurate to 10^-4 or 10^-5. A cesium fountain
atomic clock is accurate to 10^-15. So ... yeah. 2^-63 was perfectly
fine; but there was no speed penalty whatsoever for using uint128\_t in
64-bit mode, so why not?
byuu says:
(Windows users may need to include <sys/time.h> at the top of
nall/chrono.hpp, not sure.)
Unchangelog:
- forgot to add the Scheduler clock=0 fix because I have the memory of
a goldfish
Changelog:
- new icarus database with nine additional games
- hiro(GTK,Qt) won't constantly write its settings.bml file to disk
anymore
- added latency simulator for fun (settings.bml => Input/Latency in
milliseconds)
So the last one ... I wanted to test out nall::chrono, and I was also
thinking that by polling every emulated frame, it's pretty wasteful when
you are using Fast Forward and hitting 200+fps. As I've said before,
calls to ruby::input::poll are not cheap.
So to get around this, I added a limiter so that if you called the
hardware poll function within N milliseconds, it'll return without
doing any actual work. And indeed, that increases my framerate of Zelda
3 uncapped from 133fps to 142fps. Yay. But it's not a "real" speedup,
as it only helps you when you exceed 100% speed (theoretically, you'd
need to crack 300% speed since the game itself will poll at 16ms at 100%
speed, but yet it sped up Zelda 3, so who am I to complain?)
I threw the latency value into the settings file. It should be 16,
but I set it to 5 since that was the lowest before it started negatively
impacting uncapped speeds. You're wasting your time and CPU cycles setting
it lower than 5, but if people like placebo effects it might work. Maybe
I should let it be a signed integer so people can set it to -16 and think
it's actually faster :P (I'm only joking. I took out the 96000hz audio
placebo effect as well. Not really into psychological tricks anymore.)
But yeah seriously, I didn't do this to start this discussion again for
the billionth time. Please don't go there. And please don't tell me this
WIP has higher/lower latency than before. I don't want to hear it.
The only reason I bring it up is for the fun part that is worth
discussing: put up or shut up time on how sensitive you are to
latency! You can set the value above 5 to see how games feel.
I personally can't really tell a difference until about 50. And I can't
be 100% confident it's worse until about 75. But ... when I set it to
150, games become "extra difficult" ... the higher it goes, the worse
it gets :D
For this WIP, I've left no upper limit cap. I'll probably set a cap of
something like 500ms or 1000ms for the official release. Need to balance
user error/trolling with enjoyability. I'll think about it.
[...]
Now, what I worry about is stupid people seeing it and thinking it's an
"added latency" setting, as if anyone would intentionally make things
worse by default. This is a limiter. So if 5ms have passed since the
game last polled, and that will be the case 99.9% of the time in games,
the next poll will happen just in time, immediately when the game polls
the inputs. Thus, a value below 1/<framerate>ms is not only pointless,
if you go too low it will ruin your fast forward max speeds.
I did say I didn't want to resort to placebo tricks, but I also don't
want to spark up public discussion on this again either. So it might
be best to default Input/Latency to 0ms, and internally have a max(5,
latency) wrapper around the value.
byuu wrote:
Aforementioned scheduler changes added. Longer explanation of why here:
http://hastebin.com/raw/toxedenece
Again, we really need to test this as thoroughly as possible for
regressions :/
This is a really major change that affects absolutely everything: all
emulation cores, all coprocessors, etc.
Also added ADDX and SUB to the 68K core, which brings us just barely
above 50% of the instruction encoding space completed.
[Editor's note: The "aformentioned scheduler changes" were described in
a previous forum post:
Unfortunately, 64-bits just wasn't enough precision (we were
getting misalignments ~230 times a second on 21/24MHz clocks), so
I had to move to 128-bit counters. This of course doesn't exist on
32-bit architectures (and probably not on all 64-bit ones either),
so for now ... higan's only going to compile on 64-bit machines
until we figure something out. Maybe we offer a "lower precision"
fallback for machines that lack uint128_t or something. Using the
booth algorithm would be way too slow.
Anyway, the precision is now 2^-96, which is roughly 10^-29. That
puts us far beyond the yoctosecond. Suck it, MAME :P I'm jokingly
referring to it as the byuusecond. The other 32-bits of precision
allows a 1Hz clock to run up to one full second before all clocks
need to be normalized to prevent overflow.
I fixed a serious wobbling issue where I was using clock > other.clock
for synchronization instead of clock >= other.clock; and also another
aliasing issue when two threads share a common frequency, but don't
run in lock-step. The latter I don't even fully understand, but I
did observe it in testing.
nall/serialization.hpp has been extended to support 128-bit integers,
but without explicitly naming them (yay generic code), so nall will
still compile on 32-bit platforms for all other applications.
Speed is basically a wash now. FC's a bit slower, SFC's a bit faster.
The "longer explanation" in the linked hastebin is:
Okay, so the idea is that we can have an arbitrary number of
oscillators. Take the SNES:
- CPU/PPU clock = 21477272.727272hz
- SMP/DSP clock = 24576000hz
- Cartridge DSP1 clock = 8000000hz
- Cartridge MSU1 clock = 44100hz
- Controller Port 1 modem controller clock = 57600hz
- Controller Port 2 barcode battler clock = 115200hz
- Expansion Port exercise bike clock = 192000hz
Is this a pathological case? Of course it is, but it's possible. The
first four do exist in the wild already: see Rockman X2 MSU1
patch. Manifest files with higan let you specify any frequency you
want for any component.
The old trick higan used was to hold an int64 counter for each
thread:thread synchronization, and adjust it like so:
- if thread A steps X clocks; then clock += X * threadB.frequency
- if clock >= 0; switch to threadB
- if thread B steps X clocks; then clock -= X * threadA.frequency
- if clock < 0; switch to threadA
But there are also system configurations where one processor has to
synchronize with more than one other processor. Take the Genesis:
- the 68K has to sync with the Z80 and PSG and YM2612 and VDP
- the Z80 has to sync with the 68K and PSG and YM2612
- the PSG has to sync with the 68K and Z80 and YM2612
Now I could do this by having an int64 clock value for every
association. But these clock values would have to be outside the
individual Thread class objects, and we would have to update every
relationship's clock value. So the 68K would have to update the Z80,
PSG, YM2612 and VDP clocks. That's four expensive 64-bit multiply-adds
per clock step event instead of one.
As such, we have to account for both possibilities. The only way to
do this is with a single time base. We do this like so:
- setup: scalar = timeBase / frequency
- step: clock += scalar * clocks
Once per second, we look at every thread, find the smallest clock
value. Then subtract that value from all threads. This prevents the
clock counters from overflowing.
Unfortunately, these oscillator values are psychotic, unpredictable,
and often times repeating fractions. Even with a timeBase of
1,000,000,000,000,000,000 (one attosecond); we get rounding errors
every ~16,300 synchronizations. Specifically, this happens with a CPU
running at 21477273hz (rounded) and SMP running at 24576000hz. That
may be good enough for most emulators, but ... you know how I am.
Plus, even at the attosecond level, we're really pushing against the
limits of 64-bit integers. Given the reciprocal inverse, a frequency
of 1Hz (which does exist in higan!) would have a scalar that consumes
1/18th of the entire range of a uint64 on every single step. Yes, I
could raise the frequency, and then step by that amount, I know. But
I don't want to have weird gotchas like that in the scheduler core.
Until I increase the accuracy to about 100 times greater than a
yoctosecond, the rounding errors are too great. And since the only
choice above 64-bit values is 128-bit values; we might as well use
all the extra headroom. 2^-96 as a timebase gives me the ability to
have both a 1Hz and 4GHz clock; and run them both for a full second;
before an overflow event would occur.
Another hastebin includes demonstration code:
#include <libco/libco.h>
#include <nall/nall.hpp>
using namespace nall;
//
cothread_t mainThread = nullptr;
const uint iterations = 100'000'000;
const uint cpuFreq = 21477272.727272 + 0.5;
const uint smpFreq = 24576000.000000 + 0.5;
const uint cpuStep = 4;
const uint smpStep = 5;
//
struct ThreadA {
cothread_t handle = nullptr;
uint64 frequency = 0;
int64 clock = 0;
auto create(auto (*entrypoint)() -> void, uint frequency) {
this->handle = co_create(65536, entrypoint);
this->frequency = frequency;
this->clock = 0;
}
};
struct CPUA : ThreadA {
static auto Enter() -> void;
auto main() -> void;
CPUA() { create(&CPUA::Enter, cpuFreq); }
} cpuA;
struct SMPA : ThreadA {
static auto Enter() -> void;
auto main() -> void;
SMPA() { create(&SMPA::Enter, smpFreq); }
} smpA;
uint8 queueA[iterations];
uint offsetA;
cothread_t resumeA = cpuA.handle;
auto EnterA() -> void {
offsetA = 0;
co_switch(resumeA);
}
auto QueueA(uint value) -> void {
queueA[offsetA++] = value;
if(offsetA >= iterations) {
resumeA = co_active();
co_switch(mainThread);
}
}
auto CPUA::Enter() -> void { while(true) cpuA.main(); }
auto CPUA::main() -> void {
QueueA(1);
smpA.clock -= cpuStep * smpA.frequency;
if(smpA.clock < 0) co_switch(smpA.handle);
}
auto SMPA::Enter() -> void { while(true) smpA.main(); }
auto SMPA::main() -> void {
QueueA(2);
smpA.clock += smpStep * cpuA.frequency;
if(smpA.clock >= 0) co_switch(cpuA.handle);
}
//
struct ThreadB {
cothread_t handle = nullptr;
uint128_t scalar = 0;
uint128_t clock = 0;
auto print128(uint128_t value) {
string s;
while(value) {
s.append((char)('0' + value % 10));
value /= 10;
}
s.reverse();
print(s, "\n");
}
//femtosecond (10^15) = 16306
//attosecond (10^18) = 688838
//zeptosecond (10^21) = 13712691
//yoctosecond (10^24) = 13712691 (hitting a dead-end on a rounding error causing a wobble)
//byuusecond? ( 2^96) = (perfect? 79,228 times more precise than a yoctosecond)
auto create(auto (*entrypoint)() -> void, uint128_t frequency) {
this->handle = co_create(65536, entrypoint);
uint128_t unitOfTime = 1;
//for(uint n : range(29)) unitOfTime *= 10;
unitOfTime <<= 96; //2^96 time units ...
this->scalar = unitOfTime / frequency;
print128(this->scalar);
this->clock = 0;
}
auto step(uint128_t clocks) -> void { clock += clocks * scalar; }
auto synchronize(ThreadB& thread) -> void { if(clock >= thread.clock) co_switch(thread.handle); }
};
struct CPUB : ThreadB {
static auto Enter() -> void;
auto main() -> void;
CPUB() { create(&CPUB::Enter, cpuFreq); }
} cpuB;
struct SMPB : ThreadB {
static auto Enter() -> void;
auto main() -> void;
SMPB() { create(&SMPB::Enter, smpFreq); clock = 1; }
} smpB;
auto correct() -> void {
auto minimum = min(cpuB.clock, smpB.clock);
cpuB.clock -= minimum;
smpB.clock -= minimum;
}
uint8 queueB[iterations];
uint offsetB;
cothread_t resumeB = cpuB.handle;
auto EnterB() -> void {
correct();
offsetB = 0;
co_switch(resumeB);
}
auto QueueB(uint value) -> void {
queueB[offsetB++] = value;
if(offsetB >= iterations) {
resumeB = co_active();
co_switch(mainThread);
}
}
auto CPUB::Enter() -> void { while(true) cpuB.main(); }
auto CPUB::main() -> void {
QueueB(1);
step(cpuStep);
synchronize(smpB);
}
auto SMPB::Enter() -> void { while(true) smpB.main(); }
auto SMPB::main() -> void {
QueueB(2);
step(smpStep);
synchronize(cpuB);
}
//
#include <nall/main.hpp>
auto nall::main(string_vector) -> void {
mainThread = co_active();
uint masterCounter = 0;
while(true) {
print(masterCounter++, " ...\n");
auto A = clock();
EnterA();
auto B = clock();
print((double)(B - A) / CLOCKS_PER_SEC, "s\n");
auto C = clock();
EnterB();
auto D = clock();
print((double)(D - C) / CLOCKS_PER_SEC, "s\n");
for(uint n : range(iterations)) {
if(queueA[n] != queueB[n]) return print("fail at ", n, "\n");
}
}
}
...and that's everything.]
byuu says:
(Windows: compile with -fpermissive to silence an annoying error. I'll
fix it in the next WIP.)
I completely replaced the time management system in higan and overhauled
the scheduler.
Before, processor threads would have "int64 clock"; and there would
be a 1:1 relationship between two threads. When thread A ran for X
cycles, it'd subtract X * B.Frequency from clock; and when thread B ran
for Y cycles, it'd add Y * A.Frequency from clock. This worked well
and allowed perfect precision; but it doesn't work when you have more
complicated relationships: eg the 68K can sync to the Z80 and PSG; the
Z80 to the 68K and PSG; so the PSG needs two counters.
The new system instead uses a "uint64 clock" variable that represents
time in attoseconds. Every time the scheduler exits, it subtracts
the smallest clock count from all threads, to prevent an overflow
scenario. The only real downside is that rounding errors mean that
roughly every 20 minutes, we have a rounding error of one clock cycle
(one 20,000,000th of a second.) However, this only applies to systems
with multiple oscillators, like the SNES. And when you're in that
situation ... there's no such thing as a perfect oscillator anyway. A
real SNES will be thousands of times less out of spec than 1hz per 20
minutes.
The advantages are pretty immense. First, we obviously can now support
more complex relationships between threads. Second, we can build a
much more abstracted scheduler. All of libco is now abstracted away
completely, which may permit a state-machine / coroutine version of
Thread in the future. We've basically gone from this:
auto SMP::step(uint clocks) -> void {
clock += clocks * (uint64)cpu.frequency;
dsp.clock -= clocks;
if(dsp.clock < 0 && !scheduler.synchronizing()) co_switch(dsp.thread);
if(clock >= 0 && !scheduler.synchronizing()) co_switch(cpu.thread);
}
To this:
auto SMP::step(uint clocks) -> void {
Thread::step(clocks);
synchronize(dsp);
synchronize(cpu);
}
As you can see, we don't have to do multiple clock adjustments anymore.
This is a huge win for the SNES CPU that had to update the SMP, DSP, all
peripherals and all coprocessors. Likewise, we don't have to synchronize
all coprocessors when one runs, now we can just synchronize the active
one to the CPU.
Third, when changing the frequencies of threads (think SGB speed setting
modes, GBC double-speed mode, etc), it no longer causes the "int64
clock" value to be erroneous.
Fourth, this results in a fairly decent speedup, mostly across the
board. Aside from the GBA being mostly a wash (for unknown reasons),
it's about an 8% - 12% speedup in every other emulation core.
Now, all of this said ... this was an unbelievably massive change, so
... you know what that means >_> If anyone can help test all types of
SNES coprocessors, and some other system games, it'd be appreciated.
----
Lastly, we have a bitchin' new about screen. It unfortunately adds
~200KiB onto the binary size, because the PNG->C++ header file
transformation doesn't compress very well, and I want to keep the
original resource files in with the higan archive. I might try some
things to work around this file size increase in the future, but for now
... yeah, slightly larger archive sizes, sorry.
The logo's a bit busted on Windows (the Label control's background
transparency and alignment settings aren't working), but works well on
GTK. I'll have to fix Windows before the next official release. For now,
look on my Twitter feed if you want to see what it's supposed to look
like.
----
EDIT: forgot about ICD2::Enter. It's doing some weird inverse
run-to-save thing that I need to implement support for somehow. So, save
states on the SGB core probably won't work with this WIP.
byuu says:
All of the above fixes, plus I added all 24 variations on the shift
opcodes, plus SUBQ, plus fixes to the BCC instruction.
I can now run 851,767 instructions into Sonic the Hedgehog before hitting
an unimplemented instruction (SUB).
The 68K core is probably only ~35% complete, and yet it's already within
4KiB of being the largest CPU core, code size wise, in all of higan. Fuck
this chip.
byuu says:
I split the Register class and read/write handlers into DataRegister and
AddressRegister, given that they have different behaviors on byte/word
accesses (data tends to preserve the upper bits; address tends to
sign-extend things.)
I expanded EA to EffectiveAddress. No sense in abbreviating things
to death.
I've now implemented 26 instructions. But the new ones are just all the
stupid from/to ccr/sr instructions.
Ryphecha confirmed that you can't set the undefined bits, so I don't
think the BitField concept is appropriate for the CCR/SR. Instead, I'm
just storing direct flags and have (read,write)(CCR,SR) instead. This
isn't like the 65816 where you have subroutines that push and pop the
flag register. It's much more common to access individual flags. Doesn't
match the consistency angle of the other CPU cores, but ... I think this
is the right thing to for the 68K specifically.
byuu says:
Redesigned the handling of reading/writing registers to be about eight
times faster than the old system. More work may be needed ... it seems
data registers tend to preserve their upper bits upon assignment; whereas
address registers tend to sign-extend values into them. It may make
sense to have DataRegister and AddressRegister classes with separate
read/write handlers. I'd have to hold two Register objects inside the
EffectiveAddress (EA) class if we do that.
Implemented 19 opcodes now (out of somewhere between 60 and 90.) That gets
the first ~530,000 instructions in Sonic the Hedgehog running (though
probably wrong. But we can run a lot thanks to large initialization
loops.)
If I force the core to loop back to the reset vector on an invalid opcode,
I'm getting about 1500fps with a dumb 320x240 blit 60 times a second and
just the 68K running alone (no Z80, PSG, VDP, YM2612.) I don't know if
that's good or not. I guess we'll find out.
I had to stop tonight because the final opcode I execute is an RTS
(return from subroutine) that's branching back to address 0; which is
invalid ... meaning something went terribly wrong and the system crashed.
byuu says:
Another six hours in ...
I have all of the opcodes, memory access functions, disassembler mnemonics
and table building converted over to the new template<uint Size> format.
Certainly, it would be quite easy for this nightmare chip to throw me
another curveball, but so far I can handle:
- MOVE (EA to, EA from) case
- read(from) has to update register index for +/-(aN) mode
- MOVEM (EA from) case
- when using +/-(aN), RA can't actually be updated until the transfer
is completed
- LEA (EA from) case
- doesn't actually perform the final read; just returns the address
to be read from
- ANDI (EA from-and-to) case
- same EA has to be read from and written to
- for -(aN), the read has to come from aN-2, but can't update aN yet;
so that the write also goes to aN-2
- no opcode can ever fetch the extension words more than once
- manually control the order of extension word fetching order for proper
opcode decoding
To do all of that without a whole lot of duplicated code (or really
bloating out every single instruction with red tape), I had to bring
back the "bool valid / uint32 address" variables inside the EA struct =(
If weird exceptions creep in like timing constraints only on certain
opcodes, I can use template flags to the EA read/write functions to
handle that.
byuu says:
Six and a half hours this time ... one new opcode, and all old opcodes
now in a deprecated format. Hooray, progress!
For building the table, I've decided to move from:
for(uint opcode : range(65536)) {
if(match(...)) bind(opNAME, ...);
}
To instead having separate for loops for each supported opcode. This
lets me specialize parts I want with templates.
And to this aim, I'm moving to replace all of the
(read,write)(size, ...) functions with (read,write)<Size>(...) functions.
This will amount to the ~70ish instructions being triplicated ot ~210ish
instructions; but I think this is really important.
When I was getting into flag calculations, a ton of conditionals
were needed to mask sizes to byte/word/long. There was also lots of
conditionals in all the memory access handlers.
The template code is ugly, but we eliminate a huge amount of branch
conditions this way.
byuu says:
Four and a half hours of work and ... zero new opcodes implemented.
This was the best job I could do refining the effective address
computations. Should have all twelve 68000 modes implemented now. Still
have a billion questions about when and how I'm supposed to perform
certain edge case operations, though.
byuu says:
Up to ten 68K instructions out of somewhere between 61 and 88, depending
upon which PDF you look at. Of course, some of them aren't 100% completed
yet, either. Lots of craziness with MOVEM, and BCC has a BSR variant
that needs stack push/pop functions.
This WIP actually took over eight hours to make, going through every
possible permutation on how to design the core itself. The updated design
now builds both the instruction decoder+dispatcher and the disassembler
decoder into the same main loop during M68K's constructor.
The special cases are also really psychotic on this processor, and
I'm afraid of missing something via the fallthrough cases. So instead,
I'm ordering the instructions alphabetically, and including exclusion
cases to ignore binding invalid cases. If I end up remapping an existing
register, then it'll throw a run-time assertion at program startup.
I wanted very much to get rid of struct EA (EffectiveAddress), but
it's too difficult to keep track of the internal effective address
without it. So I split out the size to a separate parameter, since
every opcode only has one size parameter, and otherwise it was getting
duplicated in opcodes that take two EAs, and was also awkward with the
flag testing. It's a bit more typing, but I feel it's more clean this way.
Overall, I'm really worried this is going to be too slow. I don't want
to turn the EA stuff into templates, because that will massively bloat
out compilation times and object sizes, and will also need a special DSL
preprocessor since C++ doesn't have a static for loop. I can definitely
optimize a lot of EA's address/read/write functions away once the core
is completed, but it's never going to hold a candle to a templatized
68K core.
----
Forgot to include the SA-1 regression fix. I always remember immediately
after I upload and archive the WIP. Will try to get that in next time,
I guess.
byuu says:
Alright, I'm definitely going to need to find some people willing to
tolerate my questions on this chip, so I'm going to go ahead and announce
I'm working on this I guess.
This core is way too big for a surprise like the NES and WS cores
were. It'll probably even span multiple v10x releases before it's
even ready.
byuu says:
I now have enough of three instructions implemented to get through the
first four instructions in Sonic the Hedgehog.
But they're far from complete. The very first instruction uses EA
addressing, which is similar to x86's ModRM in terms of how disgustingly
complex it is. And it also accesses Z80 control registers, which obviously
isn't going to do anything yet.
The slow speed was me being stupid again. It's not 7.6MHz per frame,
it's 7.67MHz per second. So yeah, speed is so far acceptable again. But
we'll see how things go as I keep emulating more. The 68K decode is not
pretty at all.
byuu says:
Changelog:
- moved Thread, Scheduler, Cheat functionality into emulator/ for
all cores
- start of actual Mega Drive emulation (two 68K instructions)
I'm going to be rather terse on MD emulation, as it's too early for any
meaningful dialogue here.
byuu says:
Sigh ... I'm really not a good person. I'm inherently selfish.
My responsibility and obligation right now is to work on loki, and
then on the Tengai Makyou Zero translation, and then on improving the
Famicom emulation.
And yet ... it's not what I really want to do. That shouldn't matter;
I should work on my responsibilities first.
Instead, I'm going to be a greedy, self-centered asshole, and work on
what I really want to instead.
I'm really sorry, guys. I'm sure this will make a few people happy,
and probably upset even more people.
I'm also making zero guarantees that this ever gets finished. As always,
I wish I could keep these things secret, so if I fail / give up, I could
just drop it with no shame. But I would have to cut everyone out of the
WIP process completely to make it happen. So, here goes ...
This WIP adds the initial skeleton for Sega Mega Drive / Genesis
emulation. God help us.
(minor note: apparently the new extension for Mega Drive games is .md,
neat. That's what I chose for the folders too. I thought it was .smd,
so that'll be fixed in icarus for the next WIP.)
(aside: this is why I wanted to get v100 out. I didn't want this code in
a skeleton state in v100's source. Nor did I want really broken emulation,
which the first release is sure to be, tarring said release.)
...
So, basically, I've been ruminating on the legacy I want to leave behind
with higan. 3D systems are just plain out. I'm never going to support
them. They're too complex for my abilities, and they would run too slowly
with my design style. I'm not willing to compromise my design ideals. And
I would never want to play a 3D game system at native 240p/480i resolution
... but 1080p+ upscaling is not accurate, so that's a conflict I want
to avoid entirely. It's also never going to emulate computer systems
(X68K, PC-98, FM-Towns, etc) because holy shit that would completely
destroy me. It's also never going emulate arcade machines.
So I think of higan as a collection of 2D emulators for consoles
and handhelds. I've gone over every major 2D gaming system there is,
looking for ones with games I actually care about and enjoy. And I
basically have five of those systems supported already. Looking at the
remaining list, I see only three systems left that I have any interest
in whatsoever: PC-Engine, Master System, Mega Drive. Again, I'm not in
any way committing to emulating any of these, but ... if I had all of
those in higan, I think I'd be content to really, truly, finally stop
writing more emulators for the rest of my life.
And so I decided to tackle the most difficult system first. If I'm
successful, the Z80 core should cover a lot of the work on the SMS. And
the HuC6280 should land somewhere between the NES and SNES in terms of
difficulty ... closer to the NES.
The systems that just don't appeal to me at all, which I will never touch,
include, but are not limited to:
* Atari 2600/5200/7800
* Lynx
* Jaguar
* Vectrex
* Colecovision
* Commodore 64
* Neo-Geo
* Neo-Geo Pocket / Color
* Virtual Boy
* Super A'can
* 32X
* CD-i
* etc, etc, etc.
And really, even if something were mildly interesting in there ... we
have to stop. I can't scale infinitely. I'm already way past my limit,
but I'm doing this anyway. Too many cores bloats everything and kills
quality on everything. I don't want higan to become MESS v2.
I don't know what I'll do about the Famicom Disk System, PC-Engine CD,
and Mega CD. I don't think I'll be able to achieve 60fps emulating the
Mega CD, even if I tried to.
I don't know what's going to happen here with even the Mega Drive. Maybe
I'll get driven crazy with the documentation and quit. Maybe it'll end
up being too complicated and I'll quit. Maybe the emulation will end up
way too slow and I'll give up. Maybe it'll take me seven years to get
any games playable at all. Maybe Steve Snake, AamirM and Mike Pavone
will pool money to hire a hitman to come after me. Who knows.
But this is what I want to do, so ... here goes nothing.
2016-07-09 14:21:37 +10:00
4186 changed files with 677488 additions and 176882 deletions
about:Report an issue running a specific game in ares
title:"[system] Game"
labels:bug
assignees:''
---
Before submitting an issue, please use the search to make sure an issue doesn't already exist, you should also make sure your rom is not a bad dump, by comparing against the hashes in the No-Intro (Cartridges) or Redump (CD-ROM) databases.
**Describe the issue**
A clear and concise description of what the bug is.
**Rom Information**
Specify the impacted rom filename and any associated hashes (sha256 preferred)
**ares** is a multi-system emulator that began development on October 14th, 2004.
It is a descendent of [higan](https://github.com/higan-emu/higan) and [bsnes](https://github.com/bsnes-emu/bsnes/), and focuses on accuracy and preservation.
Official Releases
-----------------
Official releases are available from
[the ares website](https://ares-emu.net).
Nightly Builds
--------------
Automated, untested builds of ares are available for Windows and macOS as a [pre-release](https://github.com/higan-emu/ares/releases/tag/nightly).
Only the latest nightly build is kept.
Prerequisites
-------------
### *nix building
###### Minimum required packages:
```
g++ make pkg-config libgtk-3-dev libcanberra-gtk-module libgl-dev libasound2-dev
```
###### Additional Audio Drivers
ares supports additional audio drivers besides the ALSA drivers included above. Installing these additional packages will allow them to be selected in Settings > Drivers:
`libao-dev libopenal-dev'
###### GTK2 & GTK3
By default, GTK3 is used, but support for GTK2 is available. You will need to install the additional package `libgtk2.0-dev` as well as specifying the command line option `hiro=gtk2` at compile time.
###### SDL2 for input
If you would like to use SDL for input, you will need to install the following the `libsdl2-dev` and `libsdl2-0.0` packages and perform a clean build of ares. You should then be able to select SDL for input in the Settings > Drivers menu.
##### Building with clang
clang++ is now the preferred compiler for ares. If it is detected, the build will default to building with clang. It is necessary to install both the `clang` and `lld` packages. If you would like to manually specify a compiler, you can use the following option: `compiler=[g++|clang++]`
--------------
### Windows building
To build on Windows, using MSYS2 is recommended which can be download [here](https://www.msys2.org/). Follow the instructions
on this page to install and setup an appropriate MINGW64 environment. Running the command:
from the MSYS2 MSYS terminal should setup everything you need to compile ares. Note that in order to compile, you will want to be in a MINGW64 terminal window after install and setup is complete.
##### Building with clang
clang is available through Visual Studio (or Build Tools for Visual Studio) through its installer and can be used to build ares. You will still need to supply GNU make in this instance. MSYS2 also offers a clang environment. You will want to make sure you select the clangw64 option during installation of MSYS2 which should provide and additional CLANG64 pre-configured environment. Install the clang toolchain package from the MSYS2 terminal:
```
pacman -S mingw-w64-clang-x86_64-toolchain
```
Once complete, open a CLANG64 terminal window and proceed with building ares.
###### Debug Symbols
When building with clang, by default symbols will be generated for debug builds using an MSVC compatible format (CodeView) for use with Windows debugging tools. In order to generate GDB compatible symbols, specify the following option: `symformat=gdb`
Compilation
-----------
Check out the source code by running this command:
`-j#` indicates number of parallel build processes, and shouldn't be set higher than N-1 cores on your processor. Specifying this option can significantly decrease the time to build this project. There are multiple build types available and it defaults to an 'optimized' build. Build types can be specified using: `build=[debug|stable|release|minified|optimized]`
Build options can be found in the following two make files: nall/GNUmakefile desktop-ui/GNUmakefile
To start compilation from the beginning, run the following prior to compiling:
```
make clean
```
#### Building specific cores
If you would like to build a subset of cores, you can specify the `cores="core1 core2"` option. Currently available cores:
```
a26 fc sfc n64 sg ms md ps1 pce ng msx cv gb gba ws ngp spec
```
Build Output
------------
There is a single binary produced at the end of compilation which can be found in `desktop-ui/out`. On OS's besides Linux, the `Database` & `Shader` directories are copied over here as well. On Linux, running `make install` after compilation will copy these directories and binary into suitable locations (see desktop-ui/GNUmakefile for details). Alternatively, these directories can be copied from `ares/Shaders/*` and `mia/Database/*`.
Command-line options
--------------------
When started from the command-line, ares accepts a few options.
```
Usage: ./ares [options] game(s)
--help Displays available options and exit
--fullscreen Start in full screen mode
--system system Specify the system name
--shader shader Specify GLSL shader name to load (requires OpenGL driver)
--setting name=value Specify a value for a setting
--dump-all-settings Show a list of all existing settings and exit
--no-file-prompt Do not prompt to load (optional) additional roms (eg: 64DD)
```
The --system option is useful when the system type cannot be auto-detected.
--fullscreen will only have an effect if a game is also passed in argument.
Example:
`ares --system MSX examples.rom --fullscreen`
Specifying multiple games allows for multi-cart support. For example, to load
the Super GameBoy BIOS and a game in one command (to avoid a file prompt), you
can do:
`ares "Super GameBoy.sfc" "Super Mario Land.gb"`
The --no-file-prompt option is useful if you wish to launch a game from CLI
without being prompted to load additional roms. For example, some Nintendo 64
games optionally support 64DD expansion disks, so this option can be used to
suppress the "64DD Disk" file dialog, and assume any secondary content is
disconnected.
High-level Components
---------------------
* __ares__: emulator cores and component implementations
* __desktop-ui__: main GUI implementation for this project
* __hiro__: cross-platform GUI toolkit that utilizes native APIs on supported platforms
* __nall__: Near's alternative to the C++ standard library
* __ruby__: interface between a hiro application and platform-specific APIs for emulator video, audio, and input
* __mia__: internal ROM database and ROM/image loader
* __libco__: cooperative multithreading library
Contributing
------------
Please join our discord to chat with other ares developers: https://discord.com/invite/gz2quhk2kv
Loaded 100 of 4186 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.