Commit Graph

55 Commits

Author SHA1 Message Date
Tim Allen 7af270aa59 Update to v103r09 release.
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.
2017-07-06 18:29:12 +10:00
Tim Allen 191a71b291 Update to v103r08 release.
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
2017-07-05 16:39:14 +10:00
Tim Allen d4876a831f Update to v103r07 release.
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.
2017-07-05 15:29:27 +10:00
Tim Allen ecc7e899e0 Update to v103r01 release.
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.
2017-06-26 11:41:58 +10:00
Tim Allen 8476f35153 Update to v102r28 release.
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.
2017-06-20 22:34:50 +10:00
Tim Allen 6e8406291c Update to v102r24 release.
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.
2017-06-13 11:42:31 +10:00
Tim Allen 8af3e4a6e2 Update to v102r22 release.
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
2017-06-09 00:08:02 +10:00
Tim Allen a4629e1f64 Update to v102r21 release.
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.
2017-06-06 23:44:40 +10:00
Tim Allen 3bcf3c24c9 Update to v102r20 release.
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 ...
2017-06-06 11:39:27 +10:00
Tim Allen 2461293ff0 Update to v102r19 release.
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.
2017-06-04 13:16:44 +10:00
Tim Allen 82c58527c3 Update to v102r17 release.
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.
2017-03-10 21:23:29 +11:00
Tim Allen 04072b278b Update to v102r16 release.
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.
2017-03-09 07:20:40 +11:00
Tim Allen 0bf2c9d4e1 Update to v102r13 release.
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.
2017-03-02 07:40:55 +11:00
Tim Allen 68f04c3bb8 Update to v102r10 release.
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.
2017-02-23 08:25:01 +11:00
Tim Allen fa6cbac251 Update to v102r06 release.
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.
2017-02-11 10:56:42 +11:00
Tim Allen bdc100e123 Update to v102r02 release.
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.
2017-01-23 08:04:26 +11:00
Tim Allen bf90bdfcc8 Update to v101r31 release.
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.
2017-01-13 12:15:45 +11:00
Tim Allen e30780bb72 Update to v101r25 release.
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.
2016-12-26 23:11:08 +11:00
Tim Allen 427bac3011 Update to v101r06 release.
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.
2016-08-15 14:52:05 +10:00
Tim Allen c50723ef61 Update to v100r15 release.
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.]
2016-07-31 12:11:20 +10:00
Tim Allen ca277cd5e8 Update to v100r14 release.
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.
2016-07-30 13:56:12 +10:00
Tim Allen 76a8ecd32a Update to v100r03 release.
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.
2016-07-10 15:28:26 +10:00
Tim Allen 67457fade4 Update to v099r13 release.
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.
2016-06-29 21:10:28 +10:00
Tim Allen 3a9c7c6843 Update to v099r09 release.
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
2016-06-25 18:53:11 +10:00
Tim Allen f48b332c83 Update to v099r08 release.
byuu says:

Changelog:
- nall/vfs work 100% completed; even SGB games load now
- emulation cores now call load() for the base cartridges as well
- updated port/device handling; portmask is gone; device ID bug should
  be resolved now
- SNES controller port 1 multitap option was removed
- added support for 128KiB SNES PPU VRAM (for now, edit sfc/ppu/ppu.hpp
  VRAM::size=0x10000; to enable)

Overall, nall/vfs was a huge success!! We've substantially reduced
the amount of boilerplate code everywhere, while still allowing (even
easier than before) support for RAM-based game loading/saving. All of
nall/stream is dead and buried.

I am considering removing Emulator::Interface::Medium::id and/or
bootable flag. Or at least, doing something different with it. The
values for the non-bootable GB/BS/ST entries duplicate the ID that is
supposed to be unique. They are for GB/GBC and WS/WSC. Maybe I'll use
this as the hardware revision selection ID, and then gut non-bootable
options. There's really no reason for that to be there. I think at one
point I was using it to generate library tabs for non-bootable systems,
but we don't do that anymore anyway.

Emulator::Interface::load() may not need the required flag anymore ... it
doesn't really do anything right now anyway.

I have a few reasons for having the cores load the base cartridge. Most
importantly, it is going to enable a special mode for the WonderSwan /
WonderSwan Color in the future. If we ever get the IPLROMs dumped ... it's
possible to boot these systems with no games inserted to set user profile
information and such. There are also other systems that may accept being
booted without a cartridge. To reach this state, you would load a game and
then cancel the load dialog. Right now, this results in games not loading.

The second reason is this prevents nasty crashes when loading fails. So
if you're missing a required manifest, the emulator won't die a violent
death anymore. It's able to back out at any point.

The third reason is consistency: loading the base cartridge works the
same as the slot cartridges.

The fourth reason is Emulator::Interface::open(uint pathID)
values. Before, the GB, SB, GBC modes were IDs 1,2,3 respectively. This
complicated things because you had to pass the correct ID. But now
instead, Emulator::Interface::load() returns maybe<uint> that is nothing
when no game is selected, and a pathID for a valid game. And now open()
can take this ID to access this game's folder contents.

The downside, which is temporary, is that command-line loading is
currently broken. But I do intend on restoring it. In fact, I want to do
better than before and allow multi-cart booting from the command-line by
specifying the base cartridge and then slot cartridges. The idea should
be pretty simple: keep a queue of pending filenames that we fill from
the command-line and/or drag-and-drop operations on the main window,
and then empty out the queue or prompt for load dialogs from the UI
when booting a system. This also might be a bit more unorthodox compared
to the traditional emulator design of "loadGame(filename)", but ... oh
well. It's easy enough still.

The port/device changes are fun. We simplified things quite a bit. The
portmask stuff is gone entirely. While ports and devices keep IDs,
this is really just sugar-coating so UIs can use for(auto& port :
emulator->ports) and access port.id; rather than having to use for(auto
n : range(emulator->ports)) { auto& port = emulator->ports[n]; ... };
but they should otherwise generally be identical to the order they appear
in their respective ranges. Still, don't rely on that.

Input::id is gone. There was no point since we also got rid of the nasty
Input::order vector. Since I was in here, I went ahead and caved on the
pedantics and renamed Input::guid to Input::userData.

I removed the SNES controller port 1 multitap option. Basically, the only
game that uses this is N-warp Daisakusen and, no offense to d4s, it's
not really a good game anyway. It's just a quick demo to show 8-players
on the SNES. But in the UI, all it does is confuse people into wasting
time mapping a controller they're never going to use, and they're going
to wonder which port to use. If more compelling use cases for 8-players
comes about, we can reconsider this. I left all the code to support this
in place, so all you have to do is uncomment one line to enable it again.

We now have dsnes emulation! :D
If you change PPU::VRAM::size to 0x10000 (words), then you should now
have 128KiB of VRAM. Even better, it serializes the used-VRAM size,
so your save states shouldn't crash on you if you swap between the two
(though if you try this, you're nuts.)

Note that this option does break commercial software. Yoshi's Island in
particular. This game is setting A15 on some PPU register writes, but
not on others. The end result of this is things break horribly in-game.

Also, this option is causing a very tiny speed hit for obvious reasons
with the variable masking value (I'm even using size-1 for now.) Given
how niche this is, I may just leave it a compile-time constant to avoid
the overhead cost. Otherwise, if we keep the option, then it'll go into
Super Famicom.sys/manifest.bml ... I'll flesh that out in the near-future.

----

Finally, some fun for my OCD ... my monitor suddenly cut out on me
in the middle of working on this WIP, about six hours in of non-stop
work. Had to hit a bunch of ctrl+alt+fN commands (among other things)
and trying to log in headless on another TTY to do issue commands,
trying to recover the display. Finally power cycled the monitor and it
came back up. So all my typing ended up going to who knows where.

Usually this sort of thing terrifies me enough that I scrap a WIP and
start over to ensure I didn't screw anything up during the crashed screen
when hitting keys randomly.

Obviously, everything compiles and appears to work fine. And I know
it's extremely paranoid, but OCD isn't logical, so ... I'm going
to go over every line of the 100KiB r07->r08 diff looking for any
corruption/errors/whatever.

----

Review finished.

r08 diff review notes:
- fc/controller/gamepad/gamepad.cpp:
  use uint device = ID::Device::Gamepad; not id = ...;
- gb/cartridge/cartridge.hpp:
  remove redundant uint _pathID; (in Information::pathID already)
- gb/cartridge/cartridge.hpp:
  pull sha256 inside Information
- sfc/cartridge/load/cpp:
  add " - Slot (A,B)" to interface->load("Sufami Turbo"); to be more
  descriptive
- sfc/controller/gamepad/gamepad.cpp:
  use uint device = ID::Device::Gamepad; not id = ...;
- sfc/interface/interface.cpp:
  remove n variable from the Multitap device input generation loop
  (now unused)
- sfc/interface/interface.hpp:
  put struct Port above struct Device like the other classes
- ui-tomoko:
  cheats.bml is reading from/writing to mediumPaths(0) [system folder
  instead of game folder]
- ui-tomoko:
  instead of mediumPaths(1) - call emulator->metadataPathID() or something
  like that
2016-06-24 22:16:53 +10:00
Tim Allen ccd8878d75 Update to v099r07 release.
byuu says:

Changelog:
- (hopefully) fixed BS Memory and Sufami Turbo slot loading
- ported GB, GBA, WS cores to use nall/vfs
- completely removed loadRequest, saveRequest functionality from
  Emulator::Interface and ui-tomoko
  - loadRequest(folder) is now load(folder)
- save states now use a shared Emulator::SerializerVersion string
  - whenever this is bumped, all older states will break; but this makes
    bumping state versions way easier
  - also, the version string makes it a lot easier to identify
    compatibility windows for save states
- SNES PPU now uses uint16 vram[32768] for memory accesses [hex_usr]

NOTE: Super Game Boy loading is currently broken, and I'm not entirely
sure how to fix it :/
The file loading handoff was -really- complicated, and so I'm kind of
at a loss ... so for now, don't try it.
Everything else should theoretically work, so please report any bugs
you find.

So, this is pretty much it. I'd be very curious to hear feedback from
people who objected to the old nall/stream design, whether they are
happy with the new file loading system or think it could use further
improvements.

The 16-bit VRAM turned out to be a wash on performance (roughly the same
as before. 1fps slower on Zelda 3, 1fps faster on Yoshi's Island.) The
main reason for this was because Yoshi's Island was breaking horribly
until I changed the vramRead, vramWrite functions to take uint15 instead
of uint16.

I suspect the issue is we're using uint16s in some areas now that need
to be uint15, and this game is setting the VRAM address to 0x8000+,
causing us to go out of bounds on memory accesses.

But ... I want to go ahead and do something cute for fun, and just because
we can ... and this new interface is so incredibly perfect for it!! I
want to support an SNES unit with 128KiB of VRAM. Not out of the box,
but as a fun little tweakable thing. The SNES was clearly designed to
support that, they just didn't use big enough VRAM chips, and left one
of the lines disconnected. So ... let's connect it anyway!

In the end, if we design it right, the only code difference should be
one area where we mask by 15-bits instead of by 16-bits.
2016-06-24 22:09:30 +10:00
Tim Allen c074c6e064 Update to v099 release.
byuu says:

Time for a new release. There are a few important emulation improvements
and a few new features; but for the most part, this release focuses on
major code refactoring, the details of which I will mostly spare you.

The major change is that, as of v099, the SNES balanced and performance
cores have been removed from higan. Basically, in addition to my five
other emulation cores, these were too much of a burden to maintain. And
they've come along as far as I was able to develop them. If you need to
use these cores, please use these two from the v098 release.

I'm very well aware that ~80% of the people using higan for SNES
emulation were using the two removed profiles. But they simply had
to go. Hopefully in the future, we can compensate for their loss by
increasing the performance of the accuracy core.

Changelog (since v098):

SFC: balanced profile removed
SFC: performance profile removed
SFC: expansion port devices can now be changed during gameplay (atlhough
    you shouldn't)
SFC: fixed bug in SharpRTC leap year calculations
SFC: emulated new research findings for the S-DD1 coprocessor
SFC: fixed CPU emulation-mode wrapping bug with pei, [dp], [dp]+y
    instructions [AWJ]
SFC: fixed Super Game Boy bug that caused the bottom tile-row to flicker
    in games
GB: added MBC1M (multi-cart) mapper; icarus can't detect these so manual
    manifests are needed for now
GB: corrected return value when HuC3 unmapped RAM is read; fixes Robopon
    [endrift]
GB: improved STAT IRQ emulation; fixes Altered Space, etc [endrift,
    gekkio]
GB: partial emulation of DMG STAT write IRQ bug; fixes Legend of Zerd,
    Road Rash, etc
nall: execute() fix, for some Linux platforms that had trouble detecting
    icarus
nall: new BitField class; which allows for simplifying flag/register
    emulation in various cores
ruby: added Windows WASAPI audio driver (experimental)
ruby: remove attempts to call glSwapIntervalEXT (fixes crashing on some
    Linux systems)
ui: timing settings panel removed
video: restored saturation, gamma, luminance settings
video: added new post-emulation sprite system; light gun cursors are
    now higher-resolution
audio: new resampler (6th-order Butterworth biquad IIR); quite a bit
    faster than the old one
audio: added optional basic reverb filter (for fun)
higan: refresh video outside cooperative threads (workaround for shoddy
    code in AMD graphics drivers)
higan: individual emulation cores no longer have unique names
higan: really substantial code refactoring; 43% reduction in binary size

Off the bat, here are the known bugs:

hiro/Windows: focus stealing bug on startup. Needs to be fixed in hiro,
    not with a cheap hack to tomoko.

higan/SFC: some of the coprocessors are saving some volatile memory to
    disk. Completely harmless, but still needs to be fixed.

ruby/WASAPI: some sound cards have a lot of issues with the current driver
    (eg FitzRoy's). We need to find a clean way to fix this before it
    can be made the default driver. Which would be a huge win because
    the latency improvements are substantial, and in exclusive mode,
    WASAPI allows G-sync to work very well.

[From the v099 WIP thread, here's the changelog since v098r19:

- GB: don't force mode 1 during force-blank; fixes v098r16 regression
  with many Game Boy games
- GB: only perform the STAT write IRQ bug during vblank, not hblank
  (still not hardware accurate, though)

-Ed.]
2016-06-11 11:13:18 +10:00
Tim Allen fdc41611cf Update to v098r14 release.
byuu says:

Changelog:
- improved attenuation of biquad filter by computing butterworth Q
  coefficients correctly (instead of using the same constant)
- adding 1e-25 to each input sample into the biquad filters to try and
  prevent denormalization
- updated normalization from [0.0 to 1.0] to [-1.0 to +1.0]; volume/reverb
  happen in floating-point mode now
- good amount of work to make the base Emulator::Audio support any number
  of output channels
  - so that we don't have to do separate work on left/right channels;
    and can instead share the code for each channel
- Emulator::Interface::audioSample(int16 left, int16 right); changed to:
  - Emulator::Interface::audioSample(double* samples, uint channels);
  - samples are normalized [-1.0 to +1.0]
  - for now at least, channels will be the value given to
    Emulator::Audio::reset()
- fixed GUI crash on startup when audio driver is set to None

I'm probably going to be updating ruby to accept normalized doubles as
well; but I'm not sure if I will try and support anything other 2-channel
audio output. It'll depend on how easy it is to do so; perhaps it'll be
a per-driver setting.

The denormalization thing is fierce. If that happens, it drops the
emulator framerate from 220fps to about 20fps for Game Boy emulation. And
that happens basically whenever audio output is silent. I'm probably
also going to make a nall/denormal.hpp file at some point with
platform-specific functionality to set the CPU state to "denormals as
zero" where applicable. I'll still add the 1e-25 offset (inaudible)
as another fallback.
2016-06-01 21:23:22 +10:00
Tim Allen ae5d380d06 Update to v098r11 release.
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.
2016-05-25 21:13:02 +10:00
Tim Allen 7cdae5195a Update to v098r07 release.
byuu says:

Changelog:
- GB: support modeSelect and RAM for MBC1M (Momotarou Collection)
- audio: implemented native resampling support into Emulator::Stream
- audio: removed nall::DSP completely

Unfortunately, the new resampler didn't turn out quite as fast as I had
hoped. The final hermite resampling added some overhead; and I had to
bump up the kernel count to 500 from 400 to get the buzzing to go away
on my main PC. I think that's due to it running at 48000hz output
instead of 44100hz output, maybe?

Compared to Ryphecha's:
(NES) Mega Man 2: 167fps -> 166fps
(GB) Mega Man II: 224fps -> 200fps
(WSC) Riviera: 143fps -> 151fps

Odd that the WS/WSC ends up faster while the DMG/CGB ends up slower.

But this knocks 922 lines down to 146 lines. The only files left in all
of higan not written (or rewritten) by me are ruby/xaudio2.h and
libco/ppc.c
2016-04-23 17:55:59 +10:00
Tim Allen e2ee6689a0 Update to v098r06 release.
byuu says:

Changelog:
- emulation cores now refresh video from host thread instead of
  cothreads (fix AMD crash)
- SFC: fixed another bug with leap year months in SharpRTC emulation
- SFC: cleaned up camelCase on function names for
  armdsp,epsonrtc,hitachidsp,mcc,nss,sharprtc classes
- GB: added MBC1M emulation (requires manually setting mapper=MBC1M in
  manifest.bml for now, sorry)
- audio: implemented Emulator::Audio mixer and effects processor
- audio: implemented Emulator::Stream interface
  - it is now possible to have more than two audio streams: eg SNES
    + SGB + MSU1 + Voicer-Kun (eventually)
- audio: added reverb delay + reverb level settings; exposed balance
  configuration in UI
- video: reworked palette generation to re-enable saturation, gamma,
  luminance adjustments
- higan/emulator.cpp is gone since there was nothing left in it

I know you guys are going to say the color adjust/balance/reverb stuff
is pointless. And indeed it mostly is. But I like the idea of allowing
some fun special effects and configurability that isn't system-wide.

Note: there seems to be some kind of added audio lag in the SGB
emulation now, and I don't really understand why. The code should be
effectively identical to what I had before. The only main thing is that
I'm sampling things to 48000hz instead of 32040hz before mixing. There's
no point where I'm intentionally introducing added latency though. I'm
kind of stumped, so if anyone wouldn't mind taking a look at it, it'd be
much appreciated :/

I don't have an MSU1 test ROM, but the latency issue may affect MSU1 as
well, and that would be very bad.
2016-04-22 23:35:51 +10:00
Tim Allen 55e507d5df Update to v098r05 release.
byuu says:

Changelog:
- WS/WSC: re-added support for screen rotation (code is inside WS core)
- ruby: changed sample(uint16_t left, uint16_t right) to sample(int16_t
  left, int16_t right);
  - requires casting to uint prior to shifting in each driver, but
    I felt it was misleading to use uint16_t just to avoid that
- ruby: WASAPI is now built in by default; has wareya's improvements,
  and now supports latency adjust
- tomoko: audio settings panel has new "Exclusive Mode" checkbox for
  WASAPI driver only
  - note: although the setting *does* take effect in real-time, I'd
    suggest restarting the emulator after changing it
- tomoko: audio latency can now be set to 0ms (which in reality means
  "the minimum supported by the driver")
- all: increased cothread size from 512KiB to 2MiB to see if it fixes
  bullshit AMD driver crashes
  - this appears to cause a slight speed penalty due to cache locality
    going down between threads, though
2016-04-18 20:49:45 +10:00
Tim Allen a2d3b8ba15 Update to v098r04 release.
byuu says:

Changelog:
- SFC: fixed behavior of 21fx $21fe register when no device is connected
  (must return zero)
- SFC: reduced 21fx buffer size to 1024 bytes in both directions to
  mirror the FT232H we are using
- SFC: eliminated dsp/modulo-array.hpp [1]
- higan: implemented higan/video interface and migrated all cores to it
  [2]

[1] the echo history buffer was 8-bytes, so there was no need for it at
all here. Not sure what I was thinking. The BRR buffer was 12-bytes, and
has very weird behavior ... but there's only a single location in the
code where it actually writes to this buffer. It's much easier to just
write to the buffer three times there instead of implementing an entire
class just to abstract away two lines of code. This change actually
boosted the speed from ~124.5fps to around ~127.5fps, but that's within
the margin of error for GCC. I doubt it's actually faster this way.

The DSP core could really use a ton of work. It comes from a port of
blargg's spc_dsp to my coding style, but he was extremely fond of using
32-bit signed integers everywhere. There's a lot of opportunity to
remove red tape masking by resizing the variables to their actual state
sizes.

I really need to find where I put spc_dsp6.sfc from blargg. It's a great
test to verify if I've made any mistakes in my implementation that would
cause regressions. Don't suppose anyone has it?

[2] so again, the idea is that higan/audio and higan/video are going to
sit between the emulation cores and the user interfaces. The hope is to
output raw encoding data from the emulation cores without having to
worry about the video display format (generally 24-bit RGB) of the host
display. And also to avoid having to repeat myself with eg three
separate implementations of interframe blending, and so on.

Furthermore, the idea is that the user interface can configure its side
of the settings, and the emulation cores can configure their sides.
Thus, neither has to worry about the other end. And now we can spin off
new user interfaces much easier without having to mess with all of these
things.

Right now, I've implemented color emulation, interframe blending and
SNES horizontal color bleed. I did not implement scanlines (and
interlace effects for them) yet, but I probably will at some point.

Further, for right now, the WonderSwan/Color screen rotation is busted
and will only show games in the horizontal orientation. Obviously this
must be fixed before the next official release, but I'll want to think
about how to implement it.

Also, the SNES light gun pointers are missing for now.

Things are a bit messy right now as I've gone through several revisions
of how to handle these things, so a good house cleaning is in order once
everything is feature-complete again. I need to sit down and think
through how and where I want to handle things like light gun cursors,
LCD icons, and maybe even rasterized text messages.

And obviously ... higan/audio is still just nall::DSP's headers. I need
to revamp that whole interface. I want to make it quite powerful with
a true audio mixer so I can handle things like
SNES+SGB+MSU1+Voicer-Kun+SNES-CD (five separate audio streams at once.)

The video system has the concept of "effects" for things like color
bleed and interframe blending. I want to extend on this with useful
other effects, such as NTSC simulation, maybe bringing back my mini-HQ2x
filter, etc. I'd also like to restore the saturation/gamma/luma
adjustment sliders ... I always liked allowing people to compensate for
their displays without having to change settings system-wide. Lastly,
I've always wanted to see some audio effects. Although I doubt we'll
ever get my dream of CoreAudio-style profiles, I'd like to get some
basic equalizer settings and echo/reverb effects in there.
2016-04-12 07:29:56 +10:00
Tim Allen 7403e69307 Update to v098r02 release.
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.
2016-04-09 15:20:41 +10:00
Tim Allen 7dc62e3a69 Update to v097r19 release.
byuu says:

Changelog:
- fixed nall/windows/guard.hpp
- fixed hiro/(windows,gtk)/header.hpp
- fixed Famicom PPU OAM reads (mask the correct bits when writing)
  [hex_usr]
- removed the need for (system := system) lines from higan/GNUmakefile
- added "All" option to filetype dropdown for ROM loading
  - allows loading GBC games in SGB mode (and technically non-GB(C)
    games, which will obviously fail to do anything)
- loki can load and play game folders now (command-line only) (extremely
  unimpressive; don't waste your time :P)
  - the input is extremely hacked in as a quick placeholder; not sure
    how I'm going to do mapping yet for it
2016-03-13 11:22:14 +11:00
Tim Allen fc7d5991ce Update to v097r18 release.
byuu says:

Changelog:
- fixed SNES sprite priority regression from r17
- added nall/windows/guard.hpp to guard against global namespace
  pollution (similar to nall/xorg/guard.hpp)
- almost fixed Windows compilation (still accuracy profile only, sorry)
- finished porting all of gba/ppu's registers over to the new .bit,.bits
  format ... all GBA registers.cpp files gone now
- the "processors :=" line in the target-$(ui)/GNUmakefile is no longer
  required
  - processors += added to each emulator core
  - duplicates are removed using the new nall/GNUmakefile's $(unique)
    function
- SFC core can be compiled without the GB core now
  - "-DSFC_SUPERGAMEBOY" is required to build in SGB support now (it's
    set in target-tomoko/GNUmakefile)
- started once again on loki (higan/target-loki/) [as before, loki is
  Linux/BSD only on account of needing hiro::Console]

loki shouldn't be too horrendous ... I hope. I just have the base
skeleton ready for now. But the code from v094r08 should be mostly
copyable over to it. It's just that it's about 50KiB of incredibly
tricky code that has to be just perfect, so it's not going to be quick.
But at least with the skeleton, it'll be a lot easier to pick away at it
as I want.

Windows compilation fix: move hiro/windows/header.hpp line 18 (header
guard) to line 16 instead.
2016-03-13 11:22:14 +11:00
Tim Allen 29be18ce0c Update to v097r17 release.
byuu says:

Changelog:
- ruby: if DirectSoundCreate fails (no sound device present), return
  false from init instead of crashing
- nall: improved edge case return values for
  (basename,pathname,dirname,...)
- nall: renamed file_system_object class to inode
- nall: varuint_t replaced with VariadicNatural; which contains
  .bit,.bits,.byte ala Natural/Integer
- nall: fixed boolean compilation error on Windows
- WS: popa should not restore SP
- GBA: rewrote the CPU/APU cores to use the .bit,.bits functions;
  removed registers.cpp from each

Note that the GBA changes are extremely major. This is about five hours
worth of extremely delicate work. Any slight errors could break
emulation in extremely bad ways. Let's hold off on extensive testing
until the next WIP, after I do the same to the PPU.

So far ... endrift's SOUNDCNT_X I/O test is failing, although that code
didn't change, so clearly I messed up SOUNDCNT_H somehow ...

To compile on Windows:

1. change nall/string/platform.hpp line 47 to

    return slice(result, 0, 3);

2. change ruby/video.wgl.cpp line 72 to

    auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool {

3. add this line to the very top of hiro/windows/header.cpp:

    #define boolean FuckYouMicrosoft
2016-03-13 11:22:14 +11:00
Tim Allen 4b29f4bad7 Update to v097r15 release.
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.
2016-02-16 20:32:49 +11:00
Tim Allen ef65bb862a Update to 20160215 release.
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.
2016-02-16 20:27:55 +11:00
Tim Allen 6c83329cae Update to v097r13 release.
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.
2016-02-09 22:51:12 +11:00
Tim Allen 32a95a9761 Update to v097r12 release.
byuu says:

Nothing WS-related this time.

First, I fixed expansion port device mapping. On first load, it was
mapping the expansion port device too late, so it ended up not taking
effect. I had to spin out the logic for that into
Program::connectDevices(). This was proving to be quite annoying while
testing eBoot (SNES-Hook simulation.)

Second, I fixed the audio->set(Frequency, Latency) functions to take
(uint) parameters from the configuration file, so the weird behavior
around changing settings in the audio panel should hopefully be gone
now.

Third, I rewrote the interface->load,unload functions to call into the
(Emulator)::System::load,unload functions. And I have those call out to
Cartridge::load,unload. Before, this was inverted, and Cartridge::load()
was invoking System::load(), which I felt was kind of backward.

The Super Game Boy really didn't like this change, however. And it took
me a few hours to power through it. Before, I had the Game Boy core
dummying out all the interface->(load,save)Request calls, and having the
SNES core make them for it. This is because the folder paths and IDs
will be different between the two cores.

I've redesigned things so that ICD2's Emulator::Interface overloads
loadRequest and saveRequest, and translates the requests into new
requests for the SuperFamicom core. This allows the Game Boy code to do
its own loading for everything without a bunch of Super Game Boy special
casing, and without any awkwardness around powering on with no cartridge
inserted.

This also lets the SNES side of things simply call into higher-level
GameBoy::interface->load,save(id, stream) functions instead of stabbing
at the raw underlying state inside of various Game Boy core emulation
classes. So things are a lot better abstracted now.
2016-02-08 14:17:59 +11:00
Tim Allen 605a8aa3e9 Update to v097r05 release.
byuu says:

More V30MZ implemented, a lot more to go.

icarus now supports importing WS and WSC games. It expects them to have
the correct file extension, same for GB and GBC.

> Ugh, apparently HiDPI icarus doesn't let you press the check boxes.

I set the flag value in the plist to false for now. Forgot to do it for
higan, but hopefully I won't forget before release.
2016-01-30 17:40:35 +11:00
Tim Allen 344e63d928 Update to v097r02 release.
byuu says:

Note: balanced/performance profiles still broken, sorry.

Changelog:
- added nall/GNUmakefile unique() function; used on linking phase of
  higan
- added nall/unique_pointer
- target-tomoko and {System}::Video updated to use
  unique_pointer<ClassName> instead of ClassName* [1]
- locate() updated to search multiple paths [2]
- GB: pass gekkio's if_ie_registers and boot_hwio-G test ROMs
- FC, GB, GBA: merge video/ into the PPU cores
- ruby: fixed ~AudioXAudio2() typo

[1] I expected this to cause new crashes on exit due to changing the
order of destruction of objects (and deleting things that weren't
deleted before), but ... so far, so good. I guess we'll see what crops
up, especially on OS X (which is already crashing for unknown reasons on
exit.)

[2] right now, the search paths are: programpath(), {configpath(),
"higan/"}, {localpath(), "higan/"}; but we can add as many more as we
want, and we can also add platform-specific versions.
2016-01-25 22:27:18 +11:00
Tim Allen cec33c1d0f Update to v096r07 release.
byuu says:

Changelog:
- configuration files are now stored in localpath() instead of configpath()
- Video gamma/saturation/luminance sliders are gone now, sorry
- added Video Filter->Blur Emulation [1]
- added Video Filter->Scanline Emulation [2]
- improvements to GBA audio emulation (fixes Minish Cap) [Jonas Quinn]

[1] For the Famicom, this does nothing. For the Super Famicom, this
performs horizontal blending for proper pseudo-hires translucency. For
the Game Boy, Game Boy Color, and Game Boy Advance, this performs
interframe blending (each frame is the average of the current and
previous frame), which is important for things like the GBVideoPlayer.

[2] Right now, this only applies to the Super Famicom, but it'll come to
the Famicom in the future. For the Super Famicom, this option doesn't
just add scanlines, it simulates the phosphor decay that's visible in
interlace mode. If you observe an interlaced game like RPM Racing on
a real SNES, you'll notice that even on perfectly still screens, the
image appears to shake. This option emulates that effect.

Note 1: the buffering right now is a little sub-optimal, so there will
be a slight speed hit with this new support. Since the core is now
generating native ARGB8888 colors, it might as well call out to the
interface to lock/unlock/refresh the video, that way it can render
directly to the screen. Although ... that might not be such a hot idea,
since the GBx interframe blending reads from the target buffer, and that
tends to be a catastrophic option for performance.

Note 2: the balanced and performance profiles for the SNES are
completely busted again. This WIP took 6 1/2 hours, and I'm exhausted.
Very much not looking forward to working on those, since those two have
all kinds of fucked up speedup tricks for non-interlaced and/or
non-hires video modes.

Note 3: if you're on Windows and you saved your system folders somewhere
else, now'd be a good time to move them to %localappdata%/higan
2016-01-15 21:07:57 +11:00
Tim Allen 72b6a8b32e Update to v096r04 release.
byuu says:

Changelog:
- fixed S-DD1 RAM writes (Star Ocean audio fixed)
- applied all of the DMG test ROM fixes discussed earlier; passes many
  more test ROMs now
- at least until the GBVideoPlayer is working: for debugging purposes,
  CPU/PPU single-step now instead of sync just-in-time (~30% slower)
- fixed OS X crash on NSTextView (hopefully, would be very odd if not)

Unfortunately passing these test ROMs caused my favorite GB/GBC game to
break all of its graphics =(
Shin Megami Tensei - Devichil - Kuro no Sho (Japan) is all garbled now.
I'm really quite bummed by this ... but I guess I'll go through and
revert r04's fixes one at a time until I find what's causing it.

On the plus side, Astro Rabby is playable now. Still acts weird when
pressing B/A on the first screen, but the start button will start the
game.

EDIT: got it. Shin Megami Tensei - Devichil requires FF4F (VBK) to be
readable. Before, it was always returning 0x00. With my return 0xFF
patch, that broke. But it should be returning the VBK value, which also
fixes it. Also need to handle FF68/FF6A reads. Was really hoping that'd
help GBVideoPlayer too, but nope. It doesn't read any of those three
registers.
2016-01-11 21:31:30 +11:00
Tim Allen 47d4bd4d81 Update to v096r01 release.
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.
2015-12-30 17:54:59 +11:00
Tim Allen 4e2eb23835 Update to v093 release.
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.
2013-08-18 13:21:14 +10:00
Tim Allen 29ea5bd599 Update to v092r09 release.
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.
2013-05-05 19:21:30 +10:00
Tim Allen 75dab443b4 Update to v092r08 release.
byuu says:

Changelog:
- fixed cartridge load window focus on Windows
- lots of updates to nall, ruby and phoenix
- ethos and Emulator::Interface updated from "foo &bar" to "foo& bar"
  syntax (work-in-progress)

Before I had mixed the two ways to declare variables/arguments all over
the place, so the goal is to unify them all for consistency. So the
changelog for this release will be massive (750KB >.>) due to the syntax
change. Yeah, that's what I spent the last three days working on ...
2013-05-02 21:25:45 +10:00
Tim Allen bbc33fe05f Update to higan v092r01, ananke v02r01 and purify v03r01 releases.
byuu says:

higan changelog:
- compiler is set to g++-4.7, subst(cc,++) rule is gone, C files compile
  with $(compiler) -x c
- make throws an error when you specify an invalid profile or compile on
  an unsupported platform (instead of hanging forever)
- added unverified.png to resources (causes too big of a speed hit to
  actually check for folder/unverified file ... so disabled for now)
- fixed default browser paths for Game Boy, Sufami Turbo and BS-X
  Satellaview (have to delete paths.cfg to see this)
- browser home button seeks to configpath()/higan/library.cfg
- settings->driver is now settings->advanced, and it adds game library
  path setting and profile information
- emulation cores now load manifest files internally, manifest.bml is
  not required for a game folder to be recognized by higan as such
- BS-X Satellaview and Sufami Turbo slot cartridge handling moved out of
  sfc/chip and into sfc/slot
- Video::StartFullScreen only sets fullscreen when a game is specified
  on the command-line

purify and ananke changelog:
- library output path shown in purify window
- added button to change library path
- squelch firmware warning windows to prevent multi-threading crash, but
  only via purify (they show up in higan still)
2013-01-21 23:27:15 +11:00