1. 24 Jul, 2017 1 commit
    • Update to v103r20 release. · d5c09c9a
      byuu says:
        - ruby/audio/xaudio2: ported to new ruby API
        - ruby/video/cgl: ported to new ruby API (untested, won't compile)
        - ruby/video/directdraw: ported to new ruby API
        - ruby/video/gdi: ported to new ruby API
        - ruby/video/glx: ported to new ruby API
        - ruby/video/wgl: ported to new ruby API
        - ruby/video/opengl: code cleanups
      The macOS CGL driver is sure to have compilation errors. If someone will
      post the compilation error log, I can hopefully fix it in one or two
      iterations of WIPs.
      I am unable to test the Xorg GLX driver, because my FreeBSD desktop
      video card drivers do not support OpenGL 3.2. If the driver doesn't
      work, I'm going to need help tracking down what broke from the older
      The real fun is still yet to come ... all the Linux-only drivers, where
      I don't have a single Linux machine to test with.
        - libco/fiber
        - libco/ucontext (I should really just delete this)
        - tomoko: hide main UI window when in exclusive fullscreen mode
      Screwtape committed
  2. 23 Jul, 2017 1 commit
    • Update to v103r19 release. · 8be474b0
      byuu says:
        - tomoko: Application::onMain assigned at end of Program::Program()
        - libco: add `#define _XOPEN_SOURCE 500` to fix compilation of sjlj.c
        - ruby/audio/openal: fixed device driver string list enumeration
        - ruby/audio/wasapi: changing device re-initializes the driver now
        - ruby/audio/wasapi: probably a pointless change, but don't fill the
          buffer beyond the queue size with silence
        - ruby/video/xvideo: renamed from ruby/video/xv
        - ruby/video/xvideo: check to see if `XV_AUTOPAINT_COLORKEY` exists
          before setting it [SuperMikeMan]
        - ruby/video/xvideo: align buffer sizes to be evenly divisible by four
        - ruby/video/xvideo: fail nicely without crashing (hopefully)
        - ruby/video/xvideo: add support for YV12 and I420 12-bit planar YUV
      ¹: prevents crashes when drivers fail to initialize from running the
      main loop that polls input drivers before the input driver is
      initialized (or fails to initialize itself.) Some drivers still don't
      block their main functions when initialization fails, so they will still
      crash, but I'll work to fix them.
      ²: this was a **major** pain in the ass, heh. You only get one chroma
      sample for every four luma samples, so the color reproduction is even
      worse than UYVY and YUYV (which is two to four chroma to luma.) Further,
      the planar format took forever to figure out. Apparently it doesn't care
      what portion of the image you specify in XvShmPutImage, it expects you
      to use the buffer dimensions to locate the U and V portions of the data.
      This is probably the most thorough X-Video driver in existence now.
        - forgot to rename the configuration settings dialog window title to
          just "Settings"
      Screwtape committed
  3. 20 Jul, 2017 1 commit
    • Update to v103r18 release. · 284e4c04
      byuu says:
        - tomoko: improved handling of changing audio devices on the audio
          settings panel
        - ruby/audio/wasapi: added device enumeration and selection support¹
        - ruby/audio/wasapi: release property store handle from audio device
        - ruby/audio/wasapi: fix exclusive mode buffer filling
        - ruby/video/glx2: ported to new API -- tested and confirmed working
        - ruby/video/sdl: fixed initialization -- tested and confirmed working
          on FreeBSD now³
        - ruby/video/xv: ported to new API -- tested and mostly working great,
          sans fullscreen mode⁴
        - accidentally changed "Driver Settings" label to "Driver" on the
          audio settings tab because I deleted the line and forgot the
          "Settings" part
        - need to use "return initialize();" from setDevice() in the WASAPI
          driver, instead of "return true;", so device selection is currently
          not functioning in this WIP for said driver
      ¹: for now, this will likely end up selecting the first available
      endpoint device, which is probably wrong. I need to come up with a
      system to expose good 'default values' when selecting new audio drivers,
      or changing audio device settings.
      ²: glx2 is a fallback driver for system with only OpenGL 2.0 and no
      OpenGL 3.2 drivers, such as FreeBSD 10.1 with AMD graphics cards.
      ³: although I really should track down why InputManager::poll() is
      crashing the emulator when Video::ready() returns false ...
      ⁴: really bizarrely, when entering fullscreen mode, it looks like the
      image was a triangle strip, and the bottom right triange is missing, and
      the top left triangle skews the entire image into it. I'm suspecting
      this is a Radeon driver bug when trying to create a 2560x1600 X-Video
      surface. The glitch persists when exiting fullscreen, too.
      If anyone can test the X-Video driver on their Linux/BSD system, it'd be
      appreciated. If it's just my video card, I'll ignore it. If not,
      hopefully someone can find the cause of the issue :|
      Screwtape committed
  4. 19 Jul, 2017 1 commit
    • Update to v103r17 release. · 0b4e7fb5
      byuu says:
        - tomoko: re-hid the video sync option¹
        - tomoko: removed " Settings" duplication on all the individual
          settings tab options
        - ruby/audio/wasapi: finished port to new syntax; adapted to an
          event-driven model; support 32-bit integral audio²
        - ruby/video/sdl: ported to new syntax; disabled driver on FreeBSD³
      ¹: still contemplating a synchronize submenu of {none, video, audio},
      but ... the fact that video can't work on PAL, WonderSwan games is a
      real limitation for it
      ²: this driver actually received a ton of work. There's also a new
      ring-buffer queue, and I added special handling for when exclusive mode
      fails because the latency requested is lower than the hardware can
      support. It'll pick the closest latency to the minimum that is possible
      in this case.
      On my Audigy Rx, the results for non-exclusive mode are the same. For
      exclusive mode, the framerate drops from 60fps to ~50fps for smaller
      buffers, and ~55fps for larger buffers (no matter how big, it never hits
      60fps.) This is a lot better than before where it was hitting ~15fps,
      but unfortunately it's the best I can do.
      The event system used by WASAPI is really stupid. It just uses SetEvent
      at some arbitrary time, and you have to query to see how many samples
      it's waiting on. This makes it unknowable how many samples we should
      buffer before calling `WaitForSingleObject(INFINITE)`, and it's also
      unclear how we should handle cases where there's more samples available
      than our queue has: either we can fill it with zeroes, or we can write
      less samples. The former should prevent audio looping effects when
      running too slowly, whereas the latter could potentially be too
      ambitious when the audio could've recovered from a minor stall.
      It's shocking to me how there's as many ways to send audio to a sound
      card as there are sound card APIs, when all that's needed is a simple
      double buffer and a callback event from another thread to do it right.
      It's also terrifying how unbelievably shitty nearly all sound card
      drivers apparently are.
      Also, I don't know if cards can output an actual 24-bit mode with three
      byte audio samples, or if they always just take 32-bit samples and
      ignore the lower 8-bits. Whatever, it's all nonsense for the final
      output to be >16-bits anyway (hi, `double[]` input from ruby.)
      ³: unfortunately, this driver always crashes on FreeBSD (even before
      the rewrite), so I'll need someone on Linux to test it and make sure it
      actually works. I'll also need testing for a lot of the other drivers as
      well, once they're ported over (I don't have X-video, PulseAudio, ALSA,
      or udev.)
      Note that I forgot to set `_ready=true` at the end of `initialize()`,
      and `_ready=false` in `terminate()`, but it shouldn't actually matter
      beyond showing you a false warning message on startup about it failing
      to initialize.
      Screwtape committed
  5. 17 Jul, 2017 2 commits
    • Update to v103r16 release. · f87c6b7e
      byuu says:
        - emulator/audio: added the ability to change the output frequency at
          run-time without emulator reset
        - tomoko: display video synchronize option again¹
        - tomoko: Settings→Configuration expanded to Settings→{Video,
          Audio, Input, Hotkey, Advanced} Settings²
        - tomoko: fix default population of audio settings tab
        - ruby: Audio::frequency is a double now (to match both
          Emulator::Audio and ASIO)³
        - tomoko: changing the audio device will repopulate the frequency and
          latency lists
        - tomoko: changing the audio frequency can now be done in real-time
        - ruby/audio/asio: added missing device() information, so devices can
          be changed now
        - ruby/audio/openal: ported to new API; added device selection support
        - ruby/audio/wasapi: ported to new API, but did not test yet (it's
          assuredly still broken)⁴
      ¹: I'm uneasy about this ... but, I guess if people want to disable
      audio and just have smooth scrolling video ... so be it. With
      Screwtape's documentation, hopefully that'll help people understand that
      video synchronization always breaks audio synchronization. I may change
      this to a child menu that lets you pick between {no synchronization,
      video synchronization, audio synchronization} as a radio selection.
      ²: given how much more useful the video and audio tabs are now, I
      felt that four extra menu items were worth saving a click and going
      right to the tab you want. This also matches the behavior of the Tools
      menu displaying all tool options and taking you directly to each tab.
      This is kind of a hard change to get used to ... but I think it's for
      the better.
      ³: kind of stupid because I've never seen a hardware sound card where
      floor(frequency) != frequency, but whatever. Yay consistency.
      ⁴: I'm going to move it to be event-driven, and try to support 24-bit
      sample formats if possible. Who knows which cards that'll fix and which
      cards that'll break. I may end up making multiple WASAPI drivers so
      people can find one that actually works for them. We'll see.
      Screwtape committed
    • Update to v103r15 release. · 4129630d
      byuu says:
        - ruby: rewrote the API interfaces for Video, Audio, Input
        - ruby/audio: can now select the number of output channels (not useful
          to higan, sorry)
        - ruby/asio: various improvements
        - tomoko: audio settings panel can now select separate audio devices
          (for ASIO, OSS so far)
        - tomoko: audio settings panel frequency and latency lists are
          dynamically populated now
      Note: due to the ruby API rewrite, most drivers will not compile. Right
      now, the following work:
        - video: Direct3D, XShm
        - audio: ASIO, OSS
        - input: Windows, SDL, Xlib
      It takes a really long time to rewrite these (six hours to do the
      above), so it's going to be a while before we're back at 100%
      functionality again.
        - ASIO needs device(), setDevice()
        - need to call setDevice() at program startup to populate
          frequency/latency settings properly
        - changing the device and/or frequency needs to update the emulator
          resampler rates
      The really hard part is going to be the last one: the only way to change
      the emulator frequency is to flush all the audio streams and then
      recompute all the coefficients for the resamplers. If this is called
      during emulation, all audio streams will be erased and thus no sound
      will be output. I'll most likely be forced to simply ignore
      device/frequency changes until the user loads another game. It is at
      least possible to toggle the latency dynamically.
      Screwtape committed
  6. 15 Jul, 2017 1 commit
    • Update to v103r14 release. · 17697317
      byuu says:
        - tomoko: by popular choice, default to adaptive mode on new installs
        - hiro/windows: fix bug that was preventing the escape key from
          closing some dialog windows
        - nall/registry: use "\\\\" as separator instead of "/" ... because
          some registry keys contain "/" in them >_>
        - ruby: add ASIO driver stub (so far it can only initialize and grab
          the driver name/version information)
      Screwtape committed
  7. 12 Jul, 2017 1 commit
    • Update to v103r13 release. · ed5ec585
      byuu says:
        - gb/interface: fix Game Boy Color extension to be "gbc" and not "gb"
        - ms/interface: move Master System hardware controls below controller
        - sfc/ppu: improve latching behavior of BGnHOFS registers (not
          hardware verified) [AWJ]
        - tomoko/input: rework port/device mapping to support non-sequential
          ports and devices¹
            - todo: should add move() to inputDevice.mappings.append and
            - note: there's a weird GCC 4.9 bug with brace initialization of
              InputEmulator; have to assign each field separately
        - tomoko: all windows sans the main presentation window can be
          dismissed with the escape key
        - icarus: the single file selection dialog ("Load ROM Image...") can
          be dismissed with the escape key
        - tomoko: do not pause emulation when FocusLoss/Pause is set during
          exclusive fullscreen mode
        - hiro/(windows,gtk,qt): implemented Window::setDismissable() function
          (missing from cocoa port, sorry)
        - nall/string: fixed printing of largest possible negative numbers (eg
          `INT_MIN`) [Sintendo]
            - only took eight months! :D
      ¹: When I tried to move the Master System hardware port below the
      controller ports, I ran into a world of pain.
      The input settings list expects every item in the
      `InputEmulator<InputPort<InputDevice<InputMapping>>>>` arrays to be
      populated with valid results. But these would be sparsely populated
      based on the port and device IDs from inside higan. And that is done so
      that the Interface::inputPoll can have O(1) lookup of ports and devices.
      This worked because all the port and device IDs were sequential (they
      left no gaps in the maps upon creating the lists.)
      Unfortunately by changing the expectation of port ID to how it appears
      in the list, inputs would not poll correctly. By leaving them alone and
      just moving Hardware to the third position, the Game Gear would be
      missing port IDs of 0 and 1 (the controller ports of the Master System).
      Even by trying to make separate MasterSystemHardware and
      GameGearHardware ports, things still fractured when the devices were no
      longer contigious.
      I got pretty sick of this and just decided to give up on O(1)
      port/device lookup, and moved to O(n) lookup. It only knocked the
      framerate down by maybe one frame per second, enough to be in the margin
      of error. Inputs aren't polled *that* often for loops that usually
      terminate after 1-2 cycles to be too detrimental to performance.
      So the new input system now allows non-sequential port and device IDs.
      Remember that I killed input IDs a while back. There's never any reason
      for those to need IDs ... it was easier to just order the inputs in the
      order you want to see them in the user interface. So the input lookup is
      still O(1). Only now, everything's safer and I return a
      maybe<InputMapping&>, and won't crash out the program trying to use a
      mapping that isn't found for some reason.
      Errata: the escape key isn't working on the browser/message dialogs on
      Windows, because of course nothing can ever just be easy and work for
      me. If anyone else wouldn't mind looking into that, I'd greatly
      appreciate it.
      Having the `WM_KEYDOWN` test inside the main `Application_sharedProc`, it
      seems to not respond to the escape key on modal dialogs. If I put the
      `WM_KEYDOWN` test in the main window proc, then it doesn't seem to get
      called for `VK_ESCAPE` at all, and doesn't get called period for modal
      windows. So I'm at a loss and it's past 4AM here >_>
      Screwtape committed
  8. 09 Jul, 2017 1 commit
    • Update to v103r12 release. · 434e303f
      byuu says:
        - ruby/video: cleaned up Direct3D9 driver and fixed catastrophic
          memory leak
        - ruby/video: added fullscreen exclusive mode support to the Direct3D9
        - ruby/video: minor cosmetic code cleanups to various drivers
        - tomoko: added support to always allow input when in fullscreen
          exclusive mode
        - tomoko: fixed window to not remove resizability flag when exiting
          fullscreen mode
      ¹: I am assuming that exclusive mode will try to capture the primary
      monitor. I don't know what will happen in multi-monitor setups, however,
      as I don't use such a setup here.
      Also, I am using `D3DPRESENT_DISCARD` instead of `D3DPRESENT_FLIP`. I'm
      not sure if this will prove better or worse, but I've heard it will
      waste less memory, and having a BackBufferCount of 1 should still result
      in page flipping anyway. The difference is supposedly just that you
      can't rely on the back buffer being a valid copy of the previous frame
      like you can with FLIP.
      Lastly, if you want Vsync, you can edit the configuration file to enable
      that, and then turn off audio sync.
      Errata: "pause emulation when focus is lost" is not working with
      exclusive mode. I need to add a check to never auto-pause when in
      exclusive mode. Thanks to bun for catching that one.
      Screwtape committed
  9. 08 Jul, 2017 1 commit
    • Update to v103r11 release. · ee982f09
      byuu says:
        - tomoko: removed "Settings→Video Emulation→Overscan Mask" setting¹
        - tomoko: remove a few unnecessary calls to resizeViewport on startup
        - tomoko: only resize main window from video settings when in adaptive
          or toggling adaptive mode²
        - hiro/windows: add `SWP_NOACTIVATE` flag to prevent focus stealing on
          resizing invisible windows³
        - hiro/windows: suppress spurious API-generated `onSize()` callback
          when calling `setVisible()`
      ¹: it just seemed like bad design to default to overscan masking
      being disabled with overscan masks of 8 horizontal, 8 vertical out of
      the box. Users would adjust the sliders and not see anything happening.
      Instead, I've set the default masks to zero. If you want to turn off
      overscan masking, simply slide those to zero again.
      ²: I figure the only way we're going to be able to fairly evaluate
      Screwtape's suggestion is to try it both ways. And I will admit, I kind
      of like the way this works as well ... a lot more so than I thought I
      would, so I think it was a great suggestion. Still, now's the time if
      people have strong opinions on this. Be sure to try both r10 and r11 to
      compare. Barring no other feedback, I'm going to keep it this way.
      ³: this fixes the blinking of the main window on startup.
      Screwtape, thanks again for the improvement suggestions. At this point
      though, I am not using a tiling window manager. If you are able to patch
      hiro/gtk and/or hiro/qt (I mostly use GTK) to work with tiling window
      managers better, I wouldn't mind applying said patches, so long as they
      don't break things on my own Xfce desktop with xfwm4.
      Also, I noticed one issue with Xfce ... if the window is maximized and I
      try to call `Window::setSize()`, it's not actually removing the maximize
      flag. We'll need to look into how to add that to GTK, but I don't think
      it's a huge issue. A similar glitch happens on windows where the icon
      still reflects being maximized, but it does actually shrink, it just
      sticks to the top left corner of the screen. So this isn't really a
      critical bug, but would be extra polish.
      Screwtape committed
  10. 07 Jul, 2017 1 commit
    • Update to v103r10 release. · cbbf5ec1
      byuu says:
        - tomoko: video scaling options are now resolutions in the
          configuration file, eg "640x480", "960x720", "1280x960"
        - tomoko: main window is now always resizable instead of fixed width
          (also supports maximizing)
        - tomoko: added support for non-integral scaling in windowed mode
        - tomoko: made the quick/managed state messaging more consistent
        - tomoko: hide "Find Codes ..." button from the cheat editor window if
          the cheat database is not present
        - tomoko: per-game cheats.bml file now goes into the higan/ subfolder
          instead of the root folder
      So the way the new video system works is you have the following options
      on the video settings panel:
      Windowed mode: { Aspect correction, Integral scaling, Adaptive }
      Fullscreen mode: { Aspect correction, Integral scaling } (and one day,
      hopefully Exclusive will be added here)
      Whenever you adjust the overscan masking, or you change any of the
      windowed or fullscreen mode settings, or you choose a different video
      scale from the main menu, or you load a new game, or you unload a game,
      or you rotate the display of an emulated system, the resizeViewport
      logic will be invoked. This logic will remember the last option you
      chose for video scale, and base the new window size on that value as an
      upper limit of the new window size.
      If you are in windowed mode and have adaptive enabled, it will shrink
      the window to fit the contents of the emulated system's video output.
      Otherwise, if you are not in integral scaling mode, it will scale the
      video as large as possible to fit into the video scaled size you have
      selected. Otherwise, it will perform an integral scale and center the
      video inside of the viewport.
      If you are in fullscreen mode, it's much the same, only there is no
      adaptive mode.
      A major problem with Xorg is that it's basically impossible to change
      the resizability attribute of a window post-creation. You can do it, but
      all kinds of crazy issues start popping up. Like if you toggle
      fullscreen, then you'll find that the window won't grow past a certain
      fairly small size that it's already at, and cannot be shrunk. And the
      multipliers will stop expanding the window as large as they should. And
      sometimes the UI elements won't be placed in the correct position, or
      the video will draw over them. It's a big mess. So I have to keep the
      main window always resizable. Also, note that this is not a limitation
      of hiro. It's just totally broken in Xorg itself. No amount of fiddling
      has ever allowed this to work reliably for me on either GTK+ 2 or Qt 4.
      So what this means is ... the adaptive mode window is also resizable.
      What happens here is, whenever you drag the corners of the main window
      to resize it, or toggle the maximize window button, higan will bypass
      the video scale resizing code and instead act as though the adaptive
      scaling mode were disabled. So if integral scaling is checked, it'll
      begin scaling in integral mode. Otherwise, it'll begin scaling in
      non-integral mode.
      And because of this flexibility, it no longer made sense for the video
      scale menu to be a radio box. I know, it sucks to not see what the
      active selection is anymore, but ... say you set the scale to small,
      then you accidentally resized the window a little, but want it snapped
      back to the proper small resolution dimensions. If it were a radio item,
      you couldn't reselect the same option again, because it's already active
      and events don't propagate in said case. By turning them into regular
      menu options, the video scale menu can be used to restore window sizing.
      On Windows, the main window blinks a few times on first load. The fix
      for that is a safeguard in the video settings code, roughly like so ...
      but note you'd need to make a few other changes for this to work against
          auto VideoSettings::updateViewport(bool firstRun) -> void {
            if(!firstRun) presentation->resizeViewport();
      That'll get it down to one blink, as with v103 official. Not sure I can
      eliminate that one extra blink.
      I forgot to remove the setResizable toggle on fullscreen mode exit. On
      Windows, the main window will end up unresizable after toggling
      fullscreen. I missed that one because like I said, toggling resizability
      is totally broken on Xorg. You can fix that with the below change:
          auto Presentation::toggleFullScreen() -> void {
            if(!fullScreen()) {
              if(!input->acquired()) input->acquire();
            } else {
              if(input->acquired()) input->release();
      Windows is stealing focus on calls to resizeViewport(), so we need to
      deal with that somehow ...
      I'm not really concerned about the behavior of shrinking the viewport
      below the smallest multiplier for a given system. It might make sense to
      snap it to the window size and forego all other scaling, but honestly
      ... meh. I don't really care. Nobody sane is going to play like that.
      Screwtape committed
  11. 06 Jul, 2017 1 commit
    • Update to v103r09 release. · 7af270aa
      byuu says:
        - gba/apu: fixed wave RAM nibble ordering (fixes audio in Castlevania,
        - 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.
      Screwtape committed
  12. 05 Jul, 2017 2 commits
    • Update to v103r08 release. · 191a71b2
      byuu says:
        - 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
        - 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
      Screwtape committed
    • Update to v103r07 release. · d4876a83
      byuu says:
        - 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
          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--;
          auto CPU::DMA::run() -> bool {
            if(cpu.stopped() || !active || waiting) return false;
            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.
      Screwtape committed
  13. 03 Jul, 2017 1 commit
    • Update to v103r06 release. · 16f73630
      byuu says:
        - processor/spc700: restored fetch/load/store/pull/push shorthand
        - processor/spc700: split functions that tested the algorithm used (`op
          != &SPC700:...`) to separate instructions
            - mostly for code clarity over code size: it was awkward having
              cycle counts change based on a function parameter
        - processor/spc700: implemented Overload's new findings on which
          cycles are truly internal (no bus reads)
        - sfc/smp: TEST register emulation has been vastly improved¹
      ¹: it turns out that TEST.d4,d5 is the external clock divider (used
      when accessing RAM through the DSP), and TEST.d6,d7 is the internal
      clock divider (used when accessing IPLROM, IO registers, or during idle
      The DSP (24576khz) feeds its clock / 12 through to the SMP (2048khz).
      The clock divider setting further divides the clock by 2, 4, 8, or 16.
      Since 8 and 16 are not cleanly divislbe by 12, the SMP cycle count
      glitches out and seems to take 10 and 2 clocks instead of 8 or 16. This
      can on real hardware either cause the SMP to run very slowly, or more
      likely, crash the SMP completely until reset.
      What's even stranger is the timers aren't affected by this. They still
      clock by 2, 4, 8, or 16.
      Note that technically I could divide my own clock counters by 24 and
      reduce these to {1,2,5,10} and {1,2,4,8}, I instead chose to divide by
      12 to better illustrate this hardware issue and better model that the
      SMP clock runs at 2048khz and not 1024khz.
      Further, note that things aren't 100% perfect yet. This seems to throw
      off some tests, such as blargg's `test_timer_speed`. I can't tell how
      far off I am because blargg's test tragically doesn't print out fail
      values. But you can see the improvements in that higan is now passing
      all of Revenant's tests that were obviously completely wrong before.
      Screwtape committed
  14. 01 Jul, 2017 1 commit
    • Update to v103r05 release. · 40802b0b
      byuu says:
        - fc/controller: added ControllerPort class; removed Peripherals class
        - md/controller/gamepad: removed X,Y,Z buttons since this isn't a
          6-button controller
        - ms/controller: added ControllerPort class (not used in Game Gear
          mode); removed Peripherals class
        - pce/controller: added ControllerPort class; removed Peripherals
        - processor/spc700: idle(address) is part of SMP class again, contains
          flag to detect mov (x)+ edge case
        - sfc/controller/super-scope,justifier: use CPU frequency instead of
          hard-coding NTSC frequency
        - sfc/cpu: move 4x8-bit SMP ports to SMP class
        - sfc/smp: move APU RAM to DSP class
        - sfc/smp: improved emulation of TEST registers bits 4-7 [information
          from nocash]
            - d4,d5 is RAM wait states (1,2,5,10)
            - d6,d7 is ROM/IO wait states (1,2,5,10)
        - sfc/smp: code cleanup to new style (order from lowest to highest
          bits; use .bit(s) functions)
        - sfc/smp: $00f8,$00f9 are P4/P5 auxiliary ports; named the registers
      Screwtape committed
  15. 30 Jun, 2017 1 commit
    • Update to v103r04 release. · ff3750de
      byuu says:
        - fc/apu: $4003,$4007 writes initialize duty counter to 0 instead of 7
        - fc/apu: corrected duty table entries for use with decrementing duty
        - processor/spc700: emulated the behavior of cycle 3 of (x)+
          instructions to not read I/O registers
            - specifically, this prevents reads from $fd-ff from resetting the
              timers, as observed on real hardware
        - sfc/controller: added ControllerPort class to match Mega Drive
        - sfc/expansion: added ExpansionPort class to match Mega Drive design
        - sfc/system: removed Peripherals class
        - sfc/system: changed `colorburst()` to `cpuFrequency()`; added
        - sfc: replaced calls to `system.region == System::Region::*` with
        - sfc/expansion: remove thread from scheduler when device is destroyed
        - sfc/smp: `{read,write}Port` now use a separate 4x8-bit buffer instead
          of underlying APU RAM [hex\_usr]
      Screwtape committed
  16. 28 Jun, 2017 1 commit
    • Update to v103r03 release. · 78f34148
      byuu says:
        - md/psg: fixed output frequency rate regression from v103r02
        - processor/m68k: fixed calculations for ABCD, NBCD, SBCD [hex\_usr,
        - processor/spc700: renamed abbreviated instructions to functional
          descriptions (eg `XCN` → `ExchangeNibble`)
        - processor/spc700: removed memory.cpp shorthand functions (fetch,
          load, store, pull, push)
        - processor/spc700: updated all instructions to follow cycle behavior
          as documented by Overload with a logic analyzer
      Once again, the changes to the SPC700 core are really quite massive. And
      this time it's not just cosmetic: the idle cycles have been updated to
      pull from various memory addresses. This is why I removed the shorthand
      functions -- so that I could handle the at-times very bizarre addresses
      the SPC700 has on its address bus during its idle cycles.
      There is one behavior Overload mentioned that I don't emulate ... one of
      the cycles of the (X) transfer functions seems to not actually access
      the $f0-ff internal SMP registers? I don't fully understand what
      Overload is getting at, so I haven't tried to support it just yet.
      Also, there are limits to logic analyzers. In many cases the same
      address is read from twice consecutively. It is unclear which of the two
      reads the SPC700 actually utilizes. I tried to choose the most logical
      values (usually the first one), but ... I don't know that we'll be able
      to figure this one out. It's going to be virtually impossible to test
      this through software, because the PC can't really execute out of
      registers that have side effects on reads.
      Screwtape committed
  17. 27 Jun, 2017 1 commit
    • Update to v103r02 release. · 3517d5c4
      byuu says:
        - fc/apu: improved phase duty cycle emulation (mode 3 is 25% phase
          inverted; counter decrements)
        - md/apu: power/reset do not cancel 68K bus requests
        - md/apu: 68K is not granted bus access on Z80 power/reset
        - md/controller: replaced System::Peripherals with ControllerPort
        - md/controller: CTRL port is now read-write, maintains value across
          controller changes (and soon, soft resets)
        - md/psg: PSG sampling rate unintentionally modified¹
        - processor/spc700: improve cycle timing of (indirect),y instructions
        - processor/spc700: idle() cycles actually read from the program
          counter; much like the 6502 [Overload]
            - some of the idle() cycles should read from other addresses; this
              still needs to be supported
        - processor/spc700: various cleanups to instruction function naming
        - processor/z80: prefix state (HL→IX,IY override) can now be
        - icarus: fix install rule for certain platforms (it wasn't buggy on
          FreeBSD, but was on Linux?)
      ¹: the clock speed of the PSG is oscillator/15. But I was setting the
      sampling rate to oscillator/15/16, which was around 223KHz. I am not
      sure whether the PSG should be outputting at 3MHz or 223KHz. Amazingly
      ... I don't really hear a difference either way `o_O` I didn't actually
      mean to make this change; I just noticed it after comparing the diff
      between r01 and r02. If this turns out to be wrong, set
          stream = Emulator::audio.createStream(1, frequency() / 16.0);
      in md/psg.cpp to revert this change.
      Screwtape committed
  18. 26 Jun, 2017 1 commit
    • Update to v103r01 release. · ecc7e899
      byuu says:
        - 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.
      Screwtape committed
  19. 22 Jun, 2017 4 commits
    • Don't bundle the cheats database in built artifacts. · a2baea24
      As of v103, higan no longer includes the cheat database.
      Screwtape committed
    • Update to v103 final release. · 561c6413
      byuu says (in the public annoucement):
      With this release, PC Engine, Master System, Game Gear, Mega Drive and
      the newly added SuperGrafx support are now quite usable! They're far
      from the best emulators for these systems, but with many bugfixes, full
      sound emulation, and save state support ... many games are now fully
      playable with decent accuracy. The Game Boy Advance emulation is also
      now substantially improved with vastly improved sound quality and a new
      dot-based PPU renderer. With that change, every single component in
      higan is now cycle-based. Regrettably, these changes do carry a ~20%
      performance penalty compared to GBA emulation in v102.
      Changelog (since the previous release):
        - added SuperGrafx emulation
        - improved audio band-pass filtering for all emulated systems
        - screen rotation is now a hotkey; automatically rotates control
        - screen rotation now supported on the Game Boy Advance as well (used
          by a small number of games)
        - massive improvements to Mega Drive emulation
        - massive code cleanups and rewrites to many CPU emulation cores
          (MOS6502, WDC65816, SPC700, etc)
        - Famicom, Master System, Mega Drive: added PAL emulation support
        - PC Engine, SuperGrafx, Master System, Game Gear, Mega Drive: added
          save state support
        - PC Engine, SuperGrafx: added PSG sound emulation
        - Master System, Game Gear: added PSG sound emulation
        - Mega Drive: added Z80 APU emulation [with help from Cydrak]
        - Mega Drive: added PSG sound emulation
        - Mega Drive: added YM2612 sound emulation [Cydrak]
        - Super Famicom: fixed Super Game Boy emulation
        - PC Engine: added save RAM support (using per-game PCE-CD backup RAM)
        - Game Boy Advance: substantial improvements to audio emulation
        - Game Boy Advance: convert scanline-based PPU renderer to a dot-based
        - Game Boy Advance: properly initialize CPU state (fixes Classic NES
          Series games)
        - Game Boy Advance: MUL timing corrected [Jonas Quinn]
        - Mega Drive: emulate special mappers for Phantasy Star IV, Super
          Street Fighter II, etc.
        - Super Famicom: use darker luma for INIDISP=0 (large improvement to
          Final Fantasy III opening)
        - Super Famicom: fixed bugs in SMP OR1,AND1 instructions
        - cheat code database regrettably removed from official releases; will
          be made available separately
        - Famicom: PAL emulation improvements [hex\_usr]
      Screwtape committed
    • Update to v103 WIP release. · b7006822
      byuu says (in the WIP forum):
        - higan: cheat codes accept = and ? separators now
            - the new preferred code format is: address=value or
            - the old code format of address/value and address/if-match/value
              will continue to work
        - higan: cheats.bml is no longer included with the base distribution
            - mightymo stopped updating it in 2015, and it's not source code;
              it can still be pulled in from older releases
        - fc: improved PAL mode timing; use PAL APU timing tables; fix PAL
          noise period table [hex\_usr]
        - md: support aborting a Z80 bus wait in order to capture save states
          without freezing
            - note that this will violate accuracy; but in practice a slight
              desync is better than an emulator deadlock
        - sfc: revert DSP ENDX randomization for now (want to research it more
          before deploying in an official release)
        - sfc: fix Super Famicom.sys/manifest.bml APU RAM size [hex\_usr]
        - tomoko: cleaned up make install rules
        - hiro/cocoa: use ABGR for pixel data [Sintendo]
      Note: I forgot to change the command-line and drag-and-drop separator
      from : to | in this WIP. However, it is corrected in the v103 official
      binary and source published on download.byuu.org. Sorry about that, I
      know it makes the Git repository history more difficult. I'm not
      concerned whether the : → | change is part of v103 or v103r01 in the
      repository, and will leave this to your discretion, Screwtape.
      I also still need to set the VDP bit to indicate PAL mode in the Mega
      Drive core. This is what happens when I have 47 things I have to do,
      given how lousy my memory is. I miss things.
      Screwtape committed
  20. 20 Jun, 2017 1 commit
    • Update to v102r28 release. · 8476f351
      byuu says:
        - 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
      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.
      Screwtape committed
  21. 19 Jun, 2017 1 commit
    • Update to v102r27 release. · e7806dd6
      byuu says:
        - processor/gsu: minor code cleanup
        - processor/hg51b: renamed reg(Read,Write) to register(Read,Write)
        - processor/lr35902: minor code cleanup
        - processor/spc700: completed code cleanup (sans disassembler)
            - no longer uses internal global state inside instructions
        - processor/spc700: will no longer hang the emulator if stuck in a WAI
          (SLEEP) or STP (STOP) instruction
        - processor/spc700: fixed bug in handling of OR1 and AND1 instructions
        - processor/z80: minor code cleanup
        - sfc/dsp: revert to initializing registers to 0x00; save for
          ENDX=random(), FLG=0xe0 [Jonas Quinn]
      Major testing of the SNES game library would be appreciated, now that
      its CPU cores have all been revised.
      We know the DSP registers read back as randomized data ... mostly, but
      there are apparently internal latches, which we can't emulate with the
      current DSP design. So until we know which registers have separate
      internal state that actually *is* initialized, I'm going to play it safe
      and not break more games.
      Thanks again to Jonas Quinn for the continued research into this issue.
      EDIT: that said ... `MD works if((ENDX&0x30) > 0)` is only a 3:4 chance
      that the game will work. That seems pretty unlikely that the odds of it
      working are that low, given hardware testing by others in the past :/ I
      thought if worked if `PITCH != 0` before, which would have been way more
      The two remaining CPU cores that need major cleanup efforts are the
      LR35902 and ARM cores. Both are very large, complicated, annoying cores
      that will probably be better off as full rewrites from scratch. I don't
      think I want to delay v103 in trying to accomplish that, however.
      So I think it'll be best to focus on allowing the Mega Drive core to not
      lock when processors are frozen waiting on a response from other
      processors during a save state operation. Then we should be good for a
      new release.
      Screwtape committed
  22. 16 Jun, 2017 1 commit
    • Update to v102r26 release. · 50411a17
      byuu says:
        - md/ym2612: initialize DAC sample to center volume [Cydrak]
        - processor/arm: add accumulate mode extra cycle to mlal [Jonas
        - processor/huc6280: split off algorithms, improve naming of functions
        - processor/mos6502: split off algorithms
        - processor/spc700: major revamp of entire core (~50% completed)
        - processor/wdc65816: fixed several bugs introduced by rewrite
      For the SPC700, this turns out to be very old code as well, with global
      object state variables, those annoying `{Boolean,Natural}BitField` types,
      `under_case` naming conventions, heavily abbreviated function names, etc.
      I'm working to get the code to be in the same design as the MOS6502,
      HuC6280, WDC65816 cores, since they're all extremely similar in terms of
      architectural design (the SPC700 is more of an off-label
      reimplementation of a 6502 core, but still.)
      The main thing left is that about 90% of the actual instructions still
      need to be adapted to not use the internal state (`aa`, `rd`, `dp`,
      `sp`, `bit` variables.) I wanted to finish this today, but ran out of
      time before work.
      I wouldn't suggest too much testing just yet. We should wait until the
      SPC700 core is finished for that. However, if some does want to and
      spots regressions, please let me know.
      Screwtape committed
  23. 14 Jun, 2017 1 commit
    • Update to v102r25 release. · b73d9187
      byuu says:
        - processor/arm: corrected MUL instruction timings [Jonas Quinn]
        - processor/wdc65816: finished phase two of the rewrite
      I'm really pleased with the visual results of the wdc65816 core rewrite.
      I was able to eliminate all of the weird `{Boolean,Natural}BitRange`
      templates, as well as the need to use unions/structs. Registers are now
      just simple `uint24` or `uint16` types (technically they're `Natural<T>`
      types, but then all of higan uses those), flags are now just bool types.
      I also eliminated all of the implicit object state inside of the core
      (aa, rd, dp, sp) and instead do all computations on the stack frame with
      local variables. Through using macros to reference the registers and
      individual parts of them, I was able to reduce the visual tensity of all
      of the instructions. And by using normal types without implicit states,
      I was able to eliminate about 15% of the instructions necessary, instead
      reusing existing ones.
      The final third phase of the rewrite will be to recode the disassembler.
      That code is probably the oldest code in all of higan right now, still
      using sprintf to generate the output. So it is very long overdue for a
      And now for the bad news ... as with any large code cleanup, regression
      errors have seeped in. Currently, no games are running at all. I've left
      the old disassembler in for this reason: we can compare trace logs of
      v102r23 against trace logs of v102r25. The second there's any
      difference, we've spotted a buggy instruction and can correct it.
      With any luck, this will be the last time I ever rewrite the wdc65816
      core. My style has changed wildly over the ~10 years since I wrote this
      core, but it's really solidifed in recent years.
      Screwtape committed
  24. 13 Jun, 2017 1 commit
    • Update to v102r24 release. · 6e840629
      byuu says
        - 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
        - SFC: massive, eight-hour cleanup of WDC65816 CPU core ... still not
      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
      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.
      Screwtape committed
  25. 11 Jun, 2017 1 commit
    • Update to v102r23 release. · cea64b99
      byuu says:
        - rewrote the 6502 CPU core from scratch. Now called MOS6502,
          supported BCD mode
            - Famicom core disables BCD mode via MOS6502::BCD = 0;
        - renamed r65816 folder to wdc65816 (still need to rename the actual
          class, though ...)
      Note: need to remove build rules for the now renamed r6502, r65816
      objects from processor/GNUmakefile.
      So this'll seem like a small WIP, but it was a solid five hours to
      rewrite the entire 6502 core. The reason I wanted to do this was because
      the old 6502 core was pretty sloppy. My coding style improved a lot, and
      I really liked how the HuC6280 CPU core came out, so I wanted the 6502
      core to be like that one.
      The core can now support BCD mode, so hopefully that will prove useful
      to hex\_usr and allow one core to run both the NES and his Atari 2600
      cores at some point.
      Note that right now, the core doesn't support any illegal instructions.
      The old core supported a small number of them, but were mostly the no
      operation ones. The goal is support all of the illegal instructions at
      some point.
      It's very possible the rewrite introduced some regressions, so thorough
      testing of the NES core would be appreciated if anyone were up for it.
      Screwtape committed
  26. 08 Jun, 2017 1 commit
    • Update to v102r22 release. · 8af3e4a6
      byuu says:
        - 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
            - 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
        - 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
      Screwtape committed
  27. 06 Jun, 2017 2 commits
    • Update to v102r21 release. · a4629e1f
      byuu says:
        - 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--
      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.
      Screwtape committed
    • Update to v102r20 release. · 3bcf3c24
      byuu says:
        - 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
        - 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
            - 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 ...
      Screwtape committed
  28. 04 Jun, 2017 1 commit
    • Update to v102r19 release. · 2461293f
      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 ;)
        - GBA: rewrote PPU from a scanline-based renderer to a pixel-based
        - 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.
      Screwtape committed
  29. 30 May, 2017 1 commit
    • Update to v102r18 release. · 1ca46090
      byuu says:
      This WIP fixes all the critical pending issues I had open. I'm sure
      there's many more that simply didn't make their way into said list. So
      by all means, please report important issues you're aware of so they can
      get fixed.
        - ruby: add variable texture support to GDI video driver [bug
          reported by Cydrak]
        - ruby: minor cleanups to XShm video driver
        - ruby: fix handling of up+down, left+right hat cases for XInput
          driver [bug reported by Cydrak]
        - nall: fixed vector class so that compilation with GCC 7.1 should
          succeed [SuperMikeMan]
        - sfc: initialize most DSP registers to random values to fix Magical
          Drop [Jonas Quinn]
        - sfc: lower PPU brightness when luma=0 from 50% scale to 25% scale;
          helps scenes like Final Fantasy III's intro
      Screwtape committed
  30. 10 Mar, 2017 1 commit
    • Update to v102r17 release. · 82c58527
      byuu says:
        - 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
        - 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
            - 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
        - need to serialize the new cartridge ramEnable, ramWritable, bank
      ¹: 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
      ⁴: 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.
      Screwtape committed
  31. 08 Mar, 2017 1 commit
    • Update to v102r16 release. · 04072b27
      byuu says:
        - Emulator::Stream now allows adding low-pass and high-pass filters
            - 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;
        - 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.
      Screwtape committed
  32. 06 Mar, 2017 1 commit
    • Update to v102r15 release. · 7e7003fd
      byuu says:
        - nall: added DSP::IIR::OnePole (which is a first-order IIR filter)
        - FC/APU: removed strong highpass, weak hipass filters (and the
          dummied out lowpass filter)
        - MS,GG,MD/PSG: removed lowpass filter
        - MS,GG,MD/PSG: audio was not being centered properly; removed
          centering for now
        - MD/YM2612: fixed clipping of accumulator from 18 signed bits to 14
          signed bits (-0x2000 to +0x1fff) [Cydrak]
        - MD/YM2612: removed lowpass filter
        - PCE/PSG: audio was not being centered properly; removed centering
          for now
      First thing is that I've removed all of the ad-hoc audio filtering.
      Emulator::Stream intrinsically provides a three-pass, second-order
      biquad IIR butterworth lowpass filter that clips frequencies above 20KHz
      with very good attenuation (as good as IIR gets, anyway.)
      It doesn't really make sense to have the various cores running
      additional lowpass filters. If we want to filter frequencies below
      20KHz, then I can adapt Emulator::Audio::createStream() to take a cutoff
      frequency value, and we can do it all at once, with much better quality.
      Right now, I don't know what frequencies are best to cut off the various
      other audio cores, so they're just gone for now.
      As for the highpass filters for the Famicom core, well ... you don't get
      aliasing from resampling low frequencies. And generally speaking, too
      low a frequency will be inaudible anyway. All these were doing was
      killing possible bass (if they were too strong.) We can add them again,
      but only if someone can convert Ryphecha's ad-hoc magic integers into a
      frequency cutoff. In which case, I'll use my biquad IIR filter to do it
      even better. On this note, it may prove useful to do this for the MD PSG
      as well, to try and head off unnecessary clamping when mixing with the
      Finally, there was the audio centering issue that affected the
      MS,GG,MD,PCE,SG cores. It was flooring the "silent" audio level, which
      was resulting in extremely heavy distortion if you tried listening to
      higan and, say, audacious at the same time. Without the botched
      centering, this distortion is completely gone now.
      However, without any centering, we've halved the potential volume range.
      This means the audio slider in higan's audio settings panel will start
      clamping twice as quickly. So ultimately, we need to figure out how to
      fix the centering. This isn't as simple as just subtracting less. We
      will probably have to center every individual audio channel before
      summing them to do this properly.
      On the Mega Drive, Altered Beast sounds quite a bit better, a lot less
      distortion now. But it's still not perfect, especially sound effects.
      Further, Bare Knuckle / Streets of Rage still has really bad sound
      effects. It looks like I broke something in Cydrak's code when trying to
      adapt it to my style =(
      Screwtape committed
  33. 03 Mar, 2017 1 commit
    • Update to v102r14 release. · 89d47914
      byuu says:
        - (MS,GG,MD)/PSG: flip output bit from noise channel [TmEE]
        - MD/YM2612: rewrite YM2612::Channel functions to
          YM2612::Channel::Operator functions¹
        - MD/YM2612: pitch/octave I/O registers should set reload, not value
          (fixes sound in most games)
        - MD/YM2612: don't try to sign-extend raw PCM values (fixes Shining
          Force opening music)
        - MD/YM2612: various algorithm simplifications; conversions from
          `*`, `/`, `%` to `<<`, `>>`; etc.
      Overall ... Sonic the Hedgehog sounds really, really great. Almost
      perfect, but there's a bit of clamping going on in the special zones.
      Langrisser II sounds really great. Shining Force sounds pretty much
      perfect. Bare Knucles (Streets of Rage) does pretty badly ... punches
      sound more like dinging a salad fork on a wine glass, heh. Altered Beast
      is extremely broken ... no music at the title screen, very distorted
      in-game music. I suspect a bug outside of the YM2612 is affecting this
      So, the YM2612 emulation isn't perfect, but it's a really good start to
      the most complex sound chip in all of higan. Hopefully the VRC7 and
      YM2413 will prove to be less ferocious ... not that I'm in any rush to
      work on either. The former is going to need the NES mapper rewrite to be
      done first, and the latter is cool but not very necessary since all
      those games have fallbacks to the inferior PSG audio.
      But really ... I can't thank Cydrak enough for doing this for me. It
      would have probably taken me months to parse through all of the
      documentation on this chip (most of which is in a 55-page thread on
      spritesmind that is filled with wrong/outdated information at the start,
      and corrections as you go deeper.) Not to mention, learning about what
      the hell detuning, low-frequency oscillation, tremolo, vibrato, etc were
      all about. Or how those algorithms to compute the final output work. Or
      the dozens of special cases littered in there to make everything sound
      good. Fierce, nasty chip that.
      Now the last real problem is save states ... the Mega Drive is going to
      be the trickiest of all to implement with libco. There are lots of areas
      where one chip will deadlock another chip while it completes some
      operation. We don't have a choice but to force those stalls to abort
      anyway, in order to let libco reach the start of its entry point once
      again. I don't know what kind of impact that'll have on states ... I
      suspect they'll work almost as reliably as the SNES does, but I can't
      know that until I implement it. It's going to be pretty nasty, though.
      ¹: this basically removes a lot of unnecessary op. prefixes and the
      need to capture `auto& op = operators[index]` at the start of every
      I wanted to have subfunctions like
      `YM2612::Channel::Operator::Envelope::run()`, etc but unfortunately,
      pretty much all of the envelope, phase, pitch, level functions need to
      access each other's state.
      Screwtape committed
  34. 01 Mar, 2017 1 commit
    • Update to v102r13 release. · 0bf2c9d4
      byuu says:
        - removed Emulator::Interface::videoFrequency(), audioFrequency()¹
        - (MS,GG,MD)/PSG: removed inversion on noise channel LFSR update
        - 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.
      Screwtape committed