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.
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/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.
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.
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.
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:
- 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/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:
- 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:
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:
- 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:
(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:
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:
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.
[This version, with the internal version number changed back to "v100",
replaced the original v100 source archive on byuu.org soon after v100's
release, because it fixes important bugs in that version. --Ed]
byuu says:
Changelog:
- fixed default paths for Sufami Turbo slotted games
- moved WonderSwan orientation controls to the port rather than the device
- I do like hex_usr's idea here; but that'll need more consideration;
so this is a temporary fix
- added new debugger interface (see the public topic for more on that)
byuu says:
Changelog:
- (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel
like they were contributing enough to be worth it]
- cleaned up nall::integer,natural,real functionality
- toInteger, toNatural, toReal for parsing strings to numbers
- fromInteger, fromNatural, fromReal for creating strings from numbers
- (string,Markup::Node,SQL-based-classes)::(integer,natural,real)
left unchanged
- template<typename T> numeral(T value, long padding, char padchar)
-> string for print() formatting
- deduces integer,natural,real based on T ... cast the value if you
want to override
- there still exists binary,octal,hex,pointer for explicit print()
formatting
- lstring -> string_vector [but using lstring = string_vector; is
declared]
- would be nice to remove the using lstring eventually ... but that'd
probably require 10,000 lines of changes >_>
- format -> string_format [no using here; format was too ambiguous]
- using integer = Integer<sizeof(int)*8>; and using natural =
Natural<sizeof(uint)*8>; declared
- for consistency with boolean. These three are meant for creating
zero-initialized values implicitly (various uses)
- R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees
up struct IO {} io; naming]
- SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {}
(status,registers); now
- still some CPU::Status status values ... they didn't really fit into
IO functionality ... will have to think about this more
- SFC CPU, PPU, SMP now use step() exclusively instead of addClocks()
calling into step()
- SFC CPU joypad1_bits, joypad2_bits were unused; killed them
- SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it
- SFC PPU OAM moved into PPU::Object; since nothing else uses it
- the raw uint8[544] array is gone. OAM::read() constructs values from
the OAM::Object[512] table now
- this avoids having to determine how we want to sub-divide the two
OAM memory sections
- this also eliminates the OAM::synchronize() functionality
- probably more I'm forgetting
The FPS fluctuations are driving me insane. This WIP went from 128fps to
137fps. Settled on 133.5fps for the final build. But nothing I changed
should have affected performance at all. This level of fluctuation makes
it damn near impossible to know whether I'm speeding things up or slowing
things down with changes.
byuu says:
Changelog:
- GB core code cleanup completed
- GBA core code cleanup completed
- some more cleanup on missed processor/arm functions/variables
- fixed FC loading icarus bug
- "Load ROM File" icarus functionality restored
- minor code unification efforts all around (not perfect yet)
- MMIO->IO
- mmio.cpp->io.cpp
- read,write->readIO,writeIO
It's been a very long work in progress ... starting all the way back with
v094r09, but the major part of the higan code cleanup is now completed! Of
course, it's very important to note that this is only for the basic style:
- under_score functions and variables are now camelCase
- return-type function-name() are now auto function-name() -> return-type
- Natural<T>/Integer<T> replace (u)intT_n types where possible
- signed/unsigned are now int/uint
- most of the x==true,x==false tests changed to x,!x
A lot of spot improvements to consistency, simplicity and quality have
gone in along the way, of course. But we'll probably never fully finishing
beautifying every last line of code in the entire codebase. Still,
this is a really great start. Going forward, WIP diffs should start
being smaller and of higher quality once again.
I know the joke is, "until my coding style changes again", but ... this
was way too stressful, way too time consuming, and way too risky. I'm
too old and tired now for extreme upheavel like this again. The only
major change I'm slowly mulling over would be renaming the using
Natural<T>/Integer<T> = (u)intT; shorthand to something that isn't as
easily confused with the (u)int_t types ... but we'll see. I'll definitely
continue to change small things all the time, but for the larger picture,
I need to just accept the style I have and live with it.
byuu says:
Changelog:
- fixed FC AxROM / VRC7 regression
- BitField split to BooleanBitField/NaturalBitField (in preparation
for IntegerBitField)
- BitFieldReference removed
- GB CPU cleaned up
- GB Cartridge + Mappers cleaned up
- SFC CGRAM is now emulated as uint15[256] instead of uint[512]
- sfc/ppu/memory.cpp no longer needed; removed
- purged SFC Debugger hooks for now (some of the operator[] calls were
bypassing them anyway)
Unfortunately, for reasons that defy all semblance of logic, the CGRAM
change caused a slight speed hit. As have the last few changes. We're
now down to around 129.5fps compared to 123.fps for v099 and 134.5fps
at our peak (v099r01-r02).
I really like the style I came up with for the Game Boy mappers to settle
the purpose(ROM,RAM) vs (rom,ram)Purpose naming convention. If I ever get
around to redoing the NES mappers, that's likely the approach I'll take.
byuu says:
Changelog:
- Emulator::Interface::Medium::bootable removed
- Emulator::Interface::load(bool required) argument removed
[File::Required makes no sense on a folder]
- Super Famicom.sys now has user-configurable properties (CPU,PPU1,PPU2
version; PPU1 VRAM size, Region override)
- old nall/property removed completely
- volatile flags supported on coprocessor RAM files now (still not in
icarus, though)
- (hopefully) fixed SNES Multitap support (needs testing)
- fixed an OAM tiledata range clipping limit in 128KiB VRAM mode (doesn't
fix Yoshi's Island, sadly)
- (hopefully, again) fixed the input polling bug hex_usr reported
- re-added dialog box for when File::Required files are missing
- really cool: if you're missing a boot ROM, BIOS ROM, or IPL ROM,
it warns you immediately
- you don't have to select a game before seeing the error message
anymore
- fixed cheats.bml load/save location
byuu says:
Changelog:
- finished cleaning up the SFC core to my new coding conventions
- removed sfc/controller/usart (superseded by 21fx)
- hid Synchronize Video option from the menu (still in the configuration
file)
Pretty much the only minor detail left is some variable names in the
SA-1 core that really won't look good at all if I move to camelCase,
so I'll have to rethink how I handle those. It's probably a good area
to attempt using BitFields, to see how it impacts performance. But I'll
do that in a test branch first.
But for the most part, this should be the end of the gigantic diffs (this
one was 174KiB), at least for the SFC/WS cores. Still have the FC/GB/GBA
cores to clean up more fully. Assuming we don't spot any new regressions,
we should be ~95% out of the woods on code cleanups breaking things.
byuu says:
Changelog:
- fixed nall/path.hpp compilation issue
- fixed ruby/audio/xaudio header declaration compilation issue (again)
- cleaned up xaudio2.hpp file to match my coding syntax (12.5% of the
file was whitespace overkill)
- added null terminator entry to nall/windows/utf8.hpp argc[] array
- nall/windows/guid.hpp uses the Windows API for generating the GUID
- this should stop all the bug reports where two nall users were
generating GUIDs at the exact same second
- fixed hiro/cocoa compilation issue with uint# types
- fixed major higan/sfc Super Game Boy audio latency issue
- fixed higan/sfc CPU core bug with pei, [dp], [dp]+y instructions
- major cleanups to higan/processor/r65816 core
- merged emulation/native-mode opcodes
- use camel-case naming on memory.hpp functions
- simplify address masking code for memory.hpp functions
- simplify a few opcodes themselves (avoid redundant copies, etc)
- rename regs.* to r.* to match modern convention of other CPU cores
- removed device.order<> concept from Emulator::Interface
- cores will now do the translation to make the job of the UI easier
- fixed plurality naming of arrays in Emulator::Interface
- example: emulator.ports[p].devices[d].inputs[i]
- example: vector<Medium> media
- probably more surprises
Major show-stoppers to the next official release:
- we need to work on GB core improvements: LY=153/0 case, multiple STAT
IRQs case, GBC audio output regs, etc.
- we need to re-add software cursors for light guns (Super Scope,
Justifier)
- after the above, we need to fix the turbo button for the Super Scope
I really have no idea how I want to implement the light guns. Ideally,
we'd want it in higan/video, so we can support the NES Zapper with the
same code. But this isn't going to be easy, because only the SNES knows
when its output is interlaced, and its resolutions can vary as
{256,512}x{224,240,448,480} which requires pixel doubling that was
hard-coded to the SNES-specific behavior, but isn't appropriate to be
exposed in higan/video.
byuu says:
It took several hours, but I've rebuilt much of the SNES' bus memory
mapping architecture.
The new design unifies the cartridge string-based mapping
("00-3f,80-bf:8000-ffff") and internal bus.map calls. The map() function
now has an accompanying unmap() function, and instead of a fixed 256
callbacks, it'll scan to find the first available slot. unmap() will
free slots up when zero addresses reference a given slot.
The controllers and expansion port are now both entirely dynamic.
Instead of load/unload/power/reset, they only have the constructor
(power/reset/load) and destructor (unload). What this means is you can
now dynamically change even expansion port devices after the system is
loaded.
Note that this is incredibly dangerous and stupid, but ... oh well. The
whole point of this was for 21fx. There's no way to change the expansion
port device prior to loading a game, but if the 21fx isn't active, then
the reset vector hijack won't work. Now you can load a 21fx game, change
the expansion port device, and simply reset the system to active the
device.
The unification of design between controller port devices and expansion
port devices is nice, and overall this results in a reduction of code
(all of the Mapping stuff in Cartridge is gone, replaced with direct bus
mapping.) And there's always the potential to expand this system more in
the future now.
The big missing feature right now is the ability to push/pop mappings.
So if you look at how the 21fx does the reset vector, you might vomit
a little bit. But ... it works.
Also changed exit(0) to _exit(0) in the POSIX version of nall::execute.
[The _exit(0) thing is an attempt to make higan not crash when it tries
to launch icarus and it's not on $PATH. The theory is that higan forks,
then the child tries to exec icarus and fails, so it exits, all the
unique_ptrs clean up their resources and tell the X server to free
things the parent process is still using. Calling _exit() prevents
destructors from running, and seems to prevent the problem. -Ed.]
byuu says:
Changelog:
- SFC: fixed a regression on auto joypad polling due to missing
parentheses
- SFC: exported new PPU::vdisp() const -> uint; function [1]
- SFC: merged PPU MMIO functions into the read/write handles (as
I previously did for the CPU)
- higan: removed individual emulator core names (bnes, bsnes, bgb, bgba,
bws) [2] Forgot:
- to remove /tomoko from the about dialog
[1] note that technically I was relying on the cached, per-frame
overscan setting when the CPU and light guns were polling the number of
active display scanlines per frame. This was technically incorrect as
you can change this value mid-frame and it'll kick in. I've never seen
any game toggle overscan every frame, we only know about this because
anomie tested this a long time ago. So, nothing should break, but ...
you know how the SNES is. You can't even look at the code without
something breaking, so I figured I'd mention it >_>
[2] I'll probably keep referring to the SNES core as bsnes anyway.
I don't mind if you guys use the b<system> names as shorthand. The
simplification is mostly to make the branding easier.
byuu says:
Changelog:
- SFC: balanced profile removed
- SFC: performance profile removed
- SFC: code for handling non-threaded CPU, SMP, DSP, PPU removed
- SFC: Coprocessor, Controller (and expansion port) shared Thread code
merged to SFC::Cothread
- Cothread here just means "Thread with CPU affinity" (couldn't think
of a better name, sorry)
- SFC: CPU now has vector<Thread*> coprocessors, peripherals;
- this is the beginning of work to allow expansion port devices to be
dynamically changed at run-time
- ruby: all audio drivers default to 48000hz instead of 22050hz now if
no frequency is assigned
- note: the WASAPI driver can default to whatever the native frequency
is; doesn't have to be 48000hz
- tomoko: removed the ability to change the frequency from the UI (but
it will display the frequency used)
- tomoko: removed the timing settings panel
- the goal is to work toward smooth video via adaptive sync
- the model is broken by not being in control of the audio frequency
anyway
- it's further broken by PAL running at 50hz and WSC running at 75hz
- it was always broken anyway by SNES interlace timing varying from
progressive timing
- higan: audio/ stub created (for now, it's just nall/dsp/ moved here
and included as a header)
- higan: video/ stub created
- higan/GNUmakefile: now includes build rules for essential components
(libco, emulator, audio, video)
The audio changes are in preparation to merge wareya's awesome WASAPI
work without the need for the nall/dsp resampler.
byuu says:
Changelog:
- bsnes-accuracy emulates reset vector properly[1]
- bsnes-balanced compiles once more
- bsnes-performance compiles once more
The balanced and performance profiles are fixed for the last time. They
will be removed for v098r01.
Please test this WIP as much as you can. I intend to release v098 soon.
I know save states are a little unstable for the WS/WSC, but they work
well enough for a release. If I can't figure it out soon, I'm going to
post v098 anyway.
[1] this one's been a really long time coming, but ... one of the bugs
I found when I translated Tekkaman Blade was that my translation patch
would crash every now and again when you hit the reset button on a real
SNES, but it always worked upon power on.
Turns out that while power-on initializes the stack register to $01ff,
reset does things a little bit differently. Reset actually triggers the
reset interrupt vector after putting the CPU into emulation mode, but it
doesn't initialize the stack pointer. The net effect is that the stack
high byte is set to $01, and the low byte is left as it was. And then
the reset vector runs, which pushes the low 16-bits of the program
counter, plus the processor flags, onto the stack frame. So you can
actually tell where the game was at when the system was reset ... sort
of.
It's a really weird behavior to be sure. But here's the catch: say
you're hacking a game, and so you hook the reset vector with jsl
showMyTranslationCreditsSplashScreen, and inside this new subroutine,
you then perform whatever bytes you hijacked, and then initialize the
stack frame to go about your business drawing the screen, and when
you're done, you return via rtl.
Generally, this works fine. But if S={0100, 0101, or 0102}, then the
stack will wrap due to being in emulation mode at reset. So it will
write to {0100, 01ff, 01fe}. But now in your subroutine, you enable
native mode. So when you return from your subroutine hijack, it reads
the return address from {01ff, 0200, 0201} instead of the expected
{01ff, 0100, 0101}. Thus, you get an invalid address back, and you
"return" to the wrong location, and your program dies.
The odds of this happening depend on how the game handles S, but
generally speaking, it's a ~1:85 chance.
By emulating this behavior, I'll likely expose this bug in many ROM
hacks that do splash screen hooks like this, including my own Tekkaman
Blade translation. And it's also very possible that there are commercial
games that screw this up as well.
But, it's what the real system does. So if any crashes start happening
as of this WIP upon resetting the game, well ... it'd happen on real
hardware, too.
byuu says:
Changelog:
- fixed DAS instruction (Judgment Silversword score)
- fixed [VH]TMR_FREQ writes (Judgement Silversword audio after area 20)
- fixed initialization of SP (fixes seven games that were hanging on
startup)
- added SER_STATUS and SER_DATA stubs (fixes four games that were
hanging on startup)
- initialized IEEP data (fixes Super Robot Taisen Compact 2 series)
- note: you'll need to delete your internal.com in WonderSwan
(Color).sys folders
- fixed CMPS and SCAS termination condition (fixes serious bugs in four
games)
- set read/writeCompleted flags for EEPROM status (fixes Tetsujin 28
Gou)
- major code cleanups to SFC/R65816 and SFC/CPU
- mostly refactored disassembler to output strings instead of using
char* buffer
- unrolled all the subfolders on sfc/cpu to a single directory
- corrected casing for all of sfc/cpu and a large portion of
processor/r65816
I kind of went overboard on the code cleanup with this WIP. Hopefully
nothing broke. Any testing one can do with the SFC accuracy core would
be greatly appreciated.
There's still an absolutely huge amount of work left to go, but I do
want to eventually refresh the entire codebase to my current coding
style, which is extremely different from stuff that's been in higan
mostly untouched since ~2006 or so. It's dangerous and fickle work, but
if I don't do it, then the code will be a jumbled mess of several
different styles.
byuu says:
Changelog:
- higan now uses Natural<Size>/Integer<Size> for its internal types
- Super Famicom emulation now uses uint24 instead of uint for bus
addresses (it's a 24-bit bus)
- cleaned up gb/apu MMIO writes
- cleaned up sfc/coprocessor/msu1 MMIO writes
- ~3% speed penalty
I've wanted to do that 24-bit bus thing for so long, but have always
been afraid of the speed impact. It's probably going to hurt
balanced/performance once they compile again, but it wasn't significant
enough to harm the accuracy core's frame rate, thankfully. Only lost one
frame per second.
The GBA core handlers are clearly going to take a lot more work. The
bit-ranges will make it substantially easier to handle, though. Lots of
32-bit registers where certain values span multiple bytes, but we have
to be able to read/write at byte-granularity.
byuu says:
Got it. Wow, that didn't hurt nearly as much as I thought it was going
to.
Dropped from 127.5fps to 123.5fps to use Natural/Integer for
(u)int(8,16,32,64).
That's totally worth the cost.
byuu says:
I refactored my schedulers. Added about ten lines to each scheduler, and
removed about 100 lines of calling into internal state in the scheduler
for the FC,SFC cores and about 30-40 lines for the other cores. All of
its state is now private.
Also reworked all of the entry points to static auto Enter() and auto
main(). Where Enter() handles all the synchronization stuff, and main()
doesn't need the while(true); loop forcing another layer of indentation
everywhere.
Took a few hours to do, but totally worth it. I'm surprised I didn't do
this sooner.
Also updated icarus gmake install rule to copy over the database.
byuu says:
Changelog:
- restructured the project and removed a whole bunch of old/dead
directives from higan/GNUmakefile
- huge amounts of work on hiro/cocoa (compiles but ~70% of the
functionality is commented out)
- fixed a masking error in my ARM CPU disassembler [Lioncash]
- SFC: decided to change board cic=(411,413) back to board
region=(ntsc,pal) ... the former was too obtuse
If you rename Boolean (it's a problem with an include from ruby, not
from hiro) and disable all the ruby drivers, you can compile an
OS X binary, but obviously it's not going to do anything.
It's a boring WIP, I just wanted to push out the project structure
change now at the start of this WIP cycle.
byuu says:
Changelog:
- added Cocoa target: higan can now be compiled for OS X Lion
[Cydrak, byuu]
- SNES/accuracy profile hires color blending improvements - fixes
Marvelous text [AWJ]
- fixed a slight bug in SNES/SA-1 VBR support caused by a typo
- added support for multi-pass shaders that can load external textures
(requires OpenGL 3.2+)
- added game library path (used by ananke->Import Game) to
Settings->Advanced
- system profiles, shaders and cheats database can be stored in "all
users" shared folders now (eg /usr/share on Linux)
- all configuration files are in BML format now, instead of XML (much
easier to read and edit this way)
- main window supports drag-and-drop of game folders (but not game files
/ ZIP archives)
- audio buffer clears when entering a modal loop on Windows (prevents
audio repetition with DirectSound driver)
- a substantial amount of code clean-up (probably the biggest
refactoring to date)
One highly desired target for this release was to default to the optimal
drivers instead of the safest drivers, but because AMD drivers don't
seem to like my OpenGL 3.2 driver, I've decided to postpone that. AMD
has too big a market share. Hopefully with v093 officially released, we
can get some public input on what AMD doesn't like.
byuu says:
This will be another massive diff from the previous version.
All of higan was updated to use the new foo& bar syntax, and I also
updated switch statements to be consistent as well (but not in the
disassemblers, was starting to get an RSI just from what I already did.)
phoenix/{windows, cocoa, qt} need to be updated to use "string foo"
instead of "const string& foo", and after that, the major diffs should
be finished.
This archive is the first time I'm posting my copy-on-write,
size+capacity nall::string class, so any feedback on that is welcome as
well.
[No prior releases were posted to the WIP thread. -Ed.]
byuu says:
Super Famicom mapping system has been reworked as discussed with the
mask= changes. offset becomes base, mode is gone. Also added support for
comma-separated fields in the address fields, to reduce the number of
map lines needed.
<?xml version="1.0" encoding="UTF-8"?>
<cartridge region="NTSC">
<superfx revision="2">
<rom name="program.rom" size="0x200000"/>
<ram name="save.rwm" size="0x8000"/>
<map id="io" address="00-3f,80-bf:3000-32ff"/>
<map id="rom" address="00-3f:8000-ffff" mask="0x8000"/>
<map id="rom" address="40-5f:0000-ffff"/>
<map id="ram" address="00-3f,80-bf:6000-7fff" size="0x2000"/>
<map id="ram" address="70-71:0000-ffff"/>
</superfx>
</cartridge>
Or in BML:
cartridge region=NTSC
superfx revision=2
rom name=program.rom size=0x200000
ram name=save.rwm size=0x8000
map id=io address=00-3f,80-bf:3000-32ff
map id=rom address=00-3f:8000-ffff mask=0x8000
map id=rom address=40-5f:0000-ffff
map id=ram address=00-3f,80-bf:6000-7fff size=0x2000
map id=ram address=70-71:0000-ffff
As a result of the changes, old mappings will no longer work. The above
XML example will run Super Mario World 2: Yoshi's Island. Otherwise,
you'll have to write your own.
All that's left now is to work some sort of database mapping system in,
so I can start dumping carts en masse.
The NES changes that FitzRoy asked for are mostly in as well.
Also, part of the reason I haven't released a WIP ... but fuck it, I'm
not going to wait forever to post a new WIP.
I've added a skeleton driver to emulate Campus Challenge '92 and
Powerfest '94. There's no actual emulation, except for the stuff I can
glean from looking at the pictures of the board. It has a DSP-1 (so
SR/DR registers), four ROMs that map in and out, RAM, etc.
I've also added preliminary mapping to upload high scores to a website,
but obviously I need the ROMs first.
byuu says:
Basically just a project rename, with s/bsnes/higan and the new icon
from lowkee added in.
It won't compile on Windows because I forgot to update the resource.rc
file, and a path transform command isn't working on Windows.
It was really just meant as a starting point, so that v091 WIPs can flow
starting from .00 with the new name (it overshadows bsnes v091, so
publicly speaking this "shouldn't exist" and will probably be deleted
from Google Code when v092 is ready.)