Commit Graph

234 Commits

Author SHA1 Message Date
Tim Allen 3517d5c4a4 Update to v103r02 release.
byuu says:

Changelog:

  - fc/apu: improved phase duty cycle emulation (mode 3 is 25% phase
    inverted; counter decrements)
  - md/apu: power/reset do not cancel 68K bus requests
  - md/apu: 68K is not granted bus access on Z80 power/reset
  - md/controller: replaced System::Peripherals with ControllerPort
    concept
  - md/controller: CTRL port is now read-write, maintains value across
    controller changes (and soon, soft resets)
  - md/psg: PSG sampling rate unintentionally modified¹
  - processor/spc700: improve cycle timing of (indirect),y instructions
    [Overload]
  - processor/spc700: idle() cycles actually read from the program
    counter; much like the 6502 [Overload]
      - some of the idle() cycles should read from other addresses; this
        still needs to be supported
  - processor/spc700: various cleanups to instruction function naming
  - processor/z80: prefix state (HL→IX,IY override) can now be
    serialized
  - icarus: fix install rule for certain platforms (it wasn't buggy on
    FreeBSD, but was on Linux?)

¹: the clock speed of the PSG is oscillator/15. But I was setting the
sampling rate to oscillator/15/16, which was around 223KHz. I am not
sure whether the PSG should be outputting at 3MHz or 223KHz. Amazingly
... I don't really hear a difference either way `o_O` I didn't actually
mean to make this change; I just noticed it after comparing the diff
between r01 and r02. If this turns out to be wrong, set

    stream = Emulator::audio.createStream(1, frequency() / 16.0);

in md/psg.cpp to revert this change.
2017-06-27 11:18:28 +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 b7006822bf Update to v103 WIP release.
byuu says (in the WIP forum):

Changelog:

  - higan: cheat codes accept = and ? separators now
      - the new preferred code format is: address=value or
        address=if-match?value
      - the old code format of address/value and address/if-match/value
        will continue to work
  - higan: cheats.bml is no longer included with the base distribution
      - mightymo stopped updating it in 2015, and it's not source code;
        it can still be pulled in from older releases
  - fc: improved PAL mode timing; use PAL APU timing tables; fix PAL
    noise period table [hex\_usr]
  - md: support aborting a Z80 bus wait in order to capture save states
    without freezing
      - note that this will violate accuracy; but in practice a slight
        desync is better than an emulator deadlock
  - sfc: revert DSP ENDX randomization for now (want to research it more
    before deploying in an official release)
  - sfc: fix Super Famicom.sys/manifest.bml APU RAM size [hex\_usr]
  - tomoko: cleaned up make install rules
  - hiro/cocoa: use ABGR for pixel data [Sintendo]

Note: I forgot to change the command-line and drag-and-drop separator
from : to | in this WIP. However, it is corrected in the v103 official
binary and source published on download.byuu.org. Sorry about that, I
know it makes the Git repository history more difficult. I'm not
concerned whether the : → | change is part of v103 or v103r01 in the
repository, and will leave this to your discretion, Screwtape.

I also still need to set the VDP bit to indicate PAL mode in the Mega
Drive core. This is what happens when I have 47 things I have to do,
given how lousy my memory is. I miss things.
2017-06-22 16:10:13 +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 e7806dd6e8 Update to v102r27 release.
byuu says:

Changelog:

  - processor/gsu: minor code cleanup
  - processor/hg51b: renamed reg(Read,Write) to register(Read,Write)
  - processor/lr35902: minor code cleanup
  - processor/spc700: completed code cleanup (sans disassembler)
      - no longer uses internal global state inside instructions
  - processor/spc700: will no longer hang the emulator if stuck in a WAI
    (SLEEP) or STP (STOP) instruction
  - processor/spc700: fixed bug in handling of OR1 and AND1 instructions
  - processor/z80: minor code cleanup
  - sfc/dsp: revert to initializing registers to 0x00; save for
    ENDX=random(), FLG=0xe0 [Jonas Quinn]

Major testing of the SNES game library would be appreciated, now that
its CPU cores have all been revised.

We know the DSP registers read back as randomized data ... mostly, but
there are apparently internal latches, which we can't emulate with the
current DSP design. So until we know which registers have separate
internal state that actually *is* initialized, I'm going to play it safe
and not break more games.

Thanks again to Jonas Quinn for the continued research into this issue.

EDIT: that said ... `MD works if((ENDX&0x30) > 0)` is only a 3:4 chance
that the game will work. That seems pretty unlikely that the odds of it
working are that low, given hardware testing by others in the past :/ I
thought if worked if `PITCH != 0` before, which would have been way more
likely.

The two remaining CPU cores that need major cleanup efforts are the
LR35902 and ARM cores. Both are very large, complicated, annoying cores
that will probably be better off as full rewrites from scratch. I don't
think I want to delay v103 in trying to accomplish that, however.

So I think it'll be best to focus on allowing the Mega Drive core to not
lock when processors are frozen waiting on a response from other
processors during a save state operation. Then we should be good for a
new release.
2017-06-19 12:07:54 +10:00
Tim Allen 50411a17d1 Update to v102r26 release.
byuu says:

Changelog:

  - md/ym2612: initialize DAC sample to center volume [Cydrak]
  - processor/arm: add accumulate mode extra cycle to mlal [Jonas
    Quinn]
  - processor/huc6280: split off algorithms, improve naming of functions
  - processor/mos6502: split off algorithms
  - processor/spc700: major revamp of entire core (~50% completed)
  - processor/wdc65816: fixed several bugs introduced by rewrite

For the SPC700, this turns out to be very old code as well, with global
object state variables, those annoying `{Boolean,Natural}BitField` types,
`under_case` naming conventions, heavily abbreviated function names, etc.
I'm working to get the code to be in the same design as the MOS6502,
HuC6280, WDC65816 cores, since they're all extremely similar in terms of
architectural design (the SPC700 is more of an off-label
reimplementation of a 6502 core, but still.)

The main thing left is that about 90% of the actual instructions still
need to be adapted to not use the internal state (`aa`, `rd`, `dp`,
`sp`, `bit` variables.) I wanted to finish this today, but ran out of
time before work.

I wouldn't suggest too much testing just yet. We should wait until the
SPC700 core is finished for that. However, if some does want to and
spots regressions, please let me know.
2017-06-16 10:06:17 +10:00
Tim Allen b73d918776 Update to v102r25 release.
byuu says:

Changelog:

  - processor/arm: corrected MUL instruction timings [Jonas Quinn]
  - processor/wdc65816: finished phase two of the rewrite

I'm really pleased with the visual results of the wdc65816 core rewrite.
I was able to eliminate all of the weird `{Boolean,Natural}BitRange`
templates, as well as the need to use unions/structs. Registers are now
just simple `uint24` or `uint16` types (technically they're `Natural<T>`
types, but then all of higan uses those), flags are now just bool types.
I also eliminated all of the implicit object state inside of the core
(aa, rd, dp, sp) and instead do all computations on the stack frame with
local variables. Through using macros to reference the registers and
individual parts of them, I was able to reduce the visual tensity of all
of the instructions. And by using normal types without implicit states,
I was able to eliminate about 15% of the instructions necessary, instead
reusing existing ones.

The final third phase of the rewrite will be to recode the disassembler.
That code is probably the oldest code in all of higan right now, still
using sprintf to generate the output. So it is very long overdue for a
cleanup.

And now for the bad news ... as with any large code cleanup, regression
errors have seeped in. Currently, no games are running at all. I've left
the old disassembler in for this reason: we can compare trace logs of
v102r23 against trace logs of v102r25. The second there's any
difference, we've spotted a buggy instruction and can correct it.

With any luck, this will be the last time I ever rewrite the wdc65816
core. My style has changed wildly over the ~10 years since I wrote this
core, but it's really solidifed in recent years.
2017-06-15 01:55:55 +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 cea64b9991 Update to v102r23 release.
byuu says:

Changelog:
  - rewrote the 6502 CPU core from scratch. Now called MOS6502,
    supported BCD mode
      - Famicom core disables BCD mode via MOS6502::BCD = 0;
  - renamed r65816 folder to wdc65816 (still need to rename the actual
    class, though ...)

Note: need to remove build rules for the now renamed r6502, r65816
objects from processor/GNUmakefile.

So this'll seem like a small WIP, but it was a solid five hours to
rewrite the entire 6502 core. The reason I wanted to do this was because
the old 6502 core was pretty sloppy. My coding style improved a lot, and
I really liked how the HuC6280 CPU core came out, so I wanted the 6502
core to be like that one.

The core can now support BCD mode, so hopefully that will prove useful
to hex\_usr and allow one core to run both the NES and his Atari 2600
cores at some point.

Note that right now, the core doesn't support any illegal instructions.
The old core supported a small number of them, but were mostly the no
operation ones. The goal is support all of the illegal instructions at
some point.

It's very possible the rewrite introduced some regressions, so thorough
testing of the NES core would be appreciated if anyone were up for it.
2017-06-11 11:51:53 +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 1ca4609079 Update to v102r18 release.
byuu says:

This WIP fixes all the critical pending issues I had open. I'm sure
there's many more that simply didn't make their way into said list. So
by all means, please report important issues you're aware of so they can
get fixed.

Changelog:

  - ruby: add variable texture support to GDI video driver [bug
    reported by Cydrak]
  - ruby: minor cleanups to XShm video driver
  - ruby: fix handling of up+down, left+right hat cases for XInput
    driver [bug reported by Cydrak]
  - nall: fixed vector class so that compilation with GCC 7.1 should
    succeed [SuperMikeMan]
  - sfc: initialize most DSP registers to random values to fix Magical
    Drop [Jonas Quinn]
  - sfc: lower PPU brightness when luma=0 from 50% scale to 25% scale;
    helps scenes like Final Fantasy III's intro
2017-05-30 17:48:41 +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 7e7003fd29 Update to v102r15 release.
byuu says:

Changelog:

  - nall: added DSP::IIR::OnePole (which is a first-order IIR filter)
  - FC/APU: removed strong highpass, weak hipass filters (and the
    dummied out lowpass filter)
  - MS,GG,MD/PSG: removed lowpass filter
  - MS,GG,MD/PSG: audio was not being centered properly; removed
    centering for now
  - MD/YM2612: fixed clipping of accumulator from 18 signed bits to 14
    signed bits (-0x2000 to +0x1fff) [Cydrak]
  - MD/YM2612: removed lowpass filter
  - PCE/PSG: audio was not being centered properly; removed centering
    for now

First thing is that I've removed all of the ad-hoc audio filtering.
Emulator::Stream intrinsically provides a three-pass, second-order
biquad IIR butterworth lowpass filter that clips frequencies above 20KHz
with very good attenuation (as good as IIR gets, anyway.)

It doesn't really make sense to have the various cores running
additional lowpass filters. If we want to filter frequencies below
20KHz, then I can adapt Emulator::Audio::createStream() to take a cutoff
frequency value, and we can do it all at once, with much better quality.

Right now, I don't know what frequencies are best to cut off the various
other audio cores, so they're just gone for now.

As for the highpass filters for the Famicom core, well ... you don't get
aliasing from resampling low frequencies. And generally speaking, too
low a frequency will be inaudible anyway. All these were doing was
killing possible bass (if they were too strong.) We can add them again,
but only if someone can convert Ryphecha's ad-hoc magic integers into a
frequency cutoff. In which case, I'll use my biquad IIR filter to do it
even better. On this note, it may prove useful to do this for the MD PSG
as well, to try and head off unnecessary clamping when mixing with the
YM2612.

Finally, there was the audio centering issue that affected the
MS,GG,MD,PCE,SG cores. It was flooring the "silent" audio level, which
was resulting in extremely heavy distortion if you tried listening to
higan and, say, audacious at the same time. Without the botched
centering, this distortion is completely gone now.

However, without any centering, we've halved the potential volume range.
This means the audio slider in higan's audio settings panel will start
clamping twice as quickly. So ultimately, we need to figure out how to
fix the centering. This isn't as simple as just subtracting less. We
will probably have to center every individual audio channel before
summing them to do this properly.

Results:

On the Mega Drive, Altered Beast sounds quite a bit better, a lot less
distortion now. But it's still not perfect, especially sound effects.
Further, Bare Knuckle / Streets of Rage still has really bad sound
effects. It looks like I broke something in Cydrak's code when trying to
adapt it to my style =(
2017-03-07 07:23:22 +11:00
Tim Allen 89d47914b9 Update to v102r14 release.
byuu says:

Changelog:

  - (MS,GG,MD)/PSG: flip output bit from noise channel [TmEE]
  - MD/YM2612: rewrite YM2612::Channel functions to
    YM2612::Channel::Operator functions¹
  - MD/YM2612: pitch/octave I/O registers should set reload, not value
    (fixes sound in most games)
  - MD/YM2612: don't try to sign-extend raw PCM values (fixes Shining
    Force opening music)
  - MD/YM2612: various algorithm simplifications; conversions from
    `*`, `/`, `%` to `<<`, `>>`; etc.

Overall ... Sonic the Hedgehog sounds really, really great. Almost
perfect, but there's a bit of clamping going on in the special zones.
Langrisser II sounds really great. Shining Force sounds pretty much
perfect. Bare Knucles (Streets of Rage) does pretty badly ... punches
sound more like dinging a salad fork on a wine glass, heh. Altered Beast
is extremely broken ... no music at the title screen, very distorted
in-game music. I suspect a bug outside of the YM2612 is affecting this
game.

So, the YM2612 emulation isn't perfect, but it's a really good start to
the most complex sound chip in all of higan. Hopefully the VRC7 and
YM2413 will prove to be less ferocious ... not that I'm in any rush to
work on either. The former is going to need the NES mapper rewrite to be
done first, and the latter is cool but not very necessary since all
those games have fallbacks to the inferior PSG audio.

But really ... I can't thank Cydrak enough for doing this for me. It
would have probably taken me months to parse through all of the
documentation on this chip (most of which is in a 55-page thread on
spritesmind that is filled with wrong/outdated information at the start,
and corrections as you go deeper.) Not to mention, learning about what
the hell detuning, low-frequency oscillation, tremolo, vibrato, etc were
all about. Or how those algorithms to compute the final output work. Or
the dozens of special cases littered in there to make everything sound
good. Fierce, nasty chip that.

Now the last real problem is save states ... the Mega Drive is going to
be the trickiest of all to implement with libco. There are lots of areas
where one chip will deadlock another chip while it completes some
operation. We don't have a choice but to force those stalls to abort
anyway, in order to let libco reach the start of its entry point once
again. I don't know what kind of impact that'll have on states ... I
suspect they'll work almost as reliably as the SNES does, but I can't
know that until I implement it. It's going to be pretty nasty, though.

¹: this basically removes a lot of unnecessary op. prefixes and the
need to capture `auto& op = operators[index]` at the start of every
function.

I wanted to have subfunctions like
`YM2612::Channel::Operator::Envelope::run()`, etc but unfortunately,
pretty much all of the envelope, phase, pitch, level functions need to
access each other's state.
2017-03-03 21:45:07 +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 4c3f9b93e7 Update to v102r12 release.
byuu says:

Changelog:

  - MD/PSG: fixed 68K bus Z80 status read address location
  - MS, GG, MD/PSG: channels post-decrement their counters, not
    pre-decrement [Cydrak]¹
  - MD/VDP: cache screen width registers once per scanline; screen
    height registers once per frame
  - MD/VDP: support 256-width display mode (used in Shining Force, etc)
  - MD/YM2612: implemented timers²
  - MD/YM2612: implemented 8-bit PCM DAC²
  - 68000: TRAP instruction should index the vector location by 32 (eg
    by 128 bytes), fixes Shining Force
  - nall: updated hex(), octal(), binary() functions to take uintmax
    instead of template<typename T> parameter³

¹: this one makes an incredible difference. Sie noticed that lots of
games set a period of 0, which would end up being a really long period
with pre-decrement. By fixing this, noise shows up in many more games,
and sounds way better in games even where it did before. You can hear
extra sound on Lunar - Sanposuru Gakuen's title screen, the noise in
Sonic The Hedgehog (Mega Drive) sounds better, etc.

²: this also really helps sound. The timers allow PSG music to play
back at the correct speed instead of playing back way too quickly. And
the PCM DAC lets you hear a lot of drum effects, as well as the
"Sega!!" sound at the start of Sonic the Hedgehog, and the infamous,
"Rise from your grave!" line from Altered Beast.

Still, most music on the Mega Drive comes from the FM channels, so
there's still not a whole lot to listen to.

I didn't implement Cydrak's $02c test register just yet. Sie wasn't 100%
certain on how the extended DAC bit worked, so I'd like to play it a
little conservative and get sound working, then I'll go back and add a
toggle or something to enable undocumented registers, that way we can
use that to detect any potential problems they might be causing.

³: unfortunately we lose support for using hex() on nall/arithmetic
types. If I have a const Pair& version of the function, then the
compiler gets confused on whether Natural<32> should use uintmax or
const Pair&, because compilers are stupid, and you can't have explicit
arguments in overloaded functions. So even though either function would
work, it just decides to error out instead >_>

This is actually really annoying, because I want hex() to be useful for
printing out nall/crypto keys and hashes directly.

But ... this change had to be made. Negative signed integers would crash
programs, and that was taking out my 68000 disassembler.
2017-02-27 19:45:51 +11:00
Tim Allen 1cab2dfeb8 Update to v102r11 release.
byuu says:

Changelog:

  - MD: connected 32KB cartridge RAM up to every Genesis game under 2MB
    loaded¹
  - MS, GG, MD: improved PSG noise channel emulation, hopefully²
  - MS, GG, MD: lowered PSG volume so that the lowpass doesn't clamp
    samples³
  - MD: added read/write handlers for VRAM, VSRAM, CRAM
  - MD: block VRAM copy when CD4 is clear⁴
  - MD: rewrote VRAM fill, VRAM copy to be byte-based⁵
  - MD: VRAM fill byte set should fall through to regular data port
    write handler⁶

¹: the header parsing for backup RAM is really weird. It's spaces
when not used, and seems to be 0x02000001-0x02003fff for the Shining
games. I don't understand why it starts at 0x02000001 instead of
0x02000000. So I'm just forcing every game to have 32KB of RAM for now.
There's also special handling for ROMs > 2MB that also have RAM
(Phantasy Star IV, etc) where there's a toggle to switch between ROM and
RAM. For now, that's not emulated.

I was hoping the Shining games would run after this, but they're still
dead-locking on me :(

²: Cydrak pointed out some flaws in my attempt to implement what he
had. I was having trouble understanding what he meant, so I went back
and read the docs on the sound chip and tried implementing the counter
the way the docs describe. Hopefully I have this right, but I don't know
of any good test ROMs to make sure my noise emulation is correct. The
docs say the shifted-out value goes to the output instead of the low bit
of the LFSR, so I made that change as well.

I think I hear the noise I'm supposed to in Sonic Marble Zone now, but
it seems like it's not correct in Green Hill Zone, adding a bit of an
annoying buzz to the background music. Maybe it sounds better with the
YM2612, but more likely, I still screwed something up :/

³: it's set to 50% range for both cores right now. For the MD, it
will need to be 25% once YM2612 emulation is in.

⁴: technically, this deadlocks the VDP until a hard reset. I could
emulate this, but for now I just don't do the VRAM copy in this case.

⁵: VSRAM fill and CRAM fill not supported in this new mode. They're
technically undocumented, and I don't have good notes on how they work.
I've been seeing conflicting notes on whether the VRAM fill buffer is
8-bits or 16-bits (I chose 8-bits), and on whether you write the low
byte and then high byte of each words, or the high byte and then low
byte (I chose the latter.)

The VRAM copy improvements fix the opening text in Langrisser II, so
that's great.

⁶: Langrisser II sets the transfer length to one less than needed to
fill the background letter tile on the scenario overview screen. After
moving to byte-sized transfers, a black pixel was getting stuck there.
So effectively, VRAM fill length becomes DMA length + 1, and the first
byte uses the data port so it writes a word value instead of just a byte
value. Hopefully this is all correct, although it probably gets way more
complicated with the VDP FIFO.
2017-02-25 22:11:46 +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 8071da4c6a Update to v102r09 release.
byuu says:

Changelog:

  - MD: restructured DMA to a subclass of VDP
  - MD: implemented VRAM copy mode (fixes Langrisser II ... mostly)
  - MS: implemened PSG support [Cydrak]
  - GG: implemented PSG stereo sound support
  - MS: use the new struct Model {} design that other cores use

The MS/GG PSG should be feature complete, but I don't have good tests
for Game Gear stereo mode, nor for the noise channel. There's also a
really weird behavior with when to reload the channel counters on volume
register writes. I can confirm what Cydrak observed in that following
the docs and reloading always creates serious audio distortion problems.
So, more research is needed there.

To get the correct sound out of the PSG, I have to run it at 3.58MHz /
16, which seems really weird to me. The docs make it sound like it's
supposed to run at the full 3.58MHz. If we can really run it at
223.7KHz, then that's help reduce the overhead of PSG emulation, which
will definitely come in handy for Mega Drive, and possibly later Mega
CD, emulation.

I have not implemented the PSG into the Mega Drive just yet. Nor have I
implemented save states or cheat code support into the MS/GG cores yet.
The latter is next on my list.
2017-02-21 22:07:33 +11:00
Tim Allen d76c0c7e82 Update to v102r08 release.
byuu says:

Changelog:

  - PCE: restructured VCE, VDCs to run one scanline at a time
  - PCE: bound VDCs to 1365x262 timing (in order to decouple the VDCs
    from the VCE)
  - PCE: the two changes above allow save states to function; also
    grants a minor speed boost
  - PCE: added cheat code support (uses 21-bit bus addressing; compare
    byte will be useful here)
  - 68K: fixed `mov *,ccr` to read two bytes instead of one [Cydrak]
  - Z80: emulated /BUSREQ, /BUSACK; allows 68K to suspend the Z80
    [Cydrak]
  - MD: emulated the Z80 executing instructions [Cydrak]
  - MD: emulated Z80 interrupts (triggered during each Vblank period)
    [Cydrak]
  - MD: emulated Z80 memory map [Cydrak]
  - MD: added stubs for PSG, YM2612 accesses [Cydrak]
  - MD: improved bus emulation [Cydrak]

The PCE core is pretty much ready to go. The only major feature missing
is FM modulation.

The Mega Drive improvements let us start to see the splash screens for
Langrisser II, Shining Force, Shining in the Darkness. I was hoping I
could get them in-game, but no such luck. My Z80 implementation is
probably flawed in some way ... now that I think about it, I believe I
missed the BusAPU::reset() check for having been granted access to the
Z80 first. But I doubt that's the problem.

Next step is to implement Cydrak's PSG core into the Master System
emulator. Once that's in, I'm going to add save states and cheat code
support to the Master System core.

Next, I'll add the PSG core into the Mega Drive. Then I'll add the
'easy' PCM part of the YM2612. Then the rest of the beastly YM2612 core.
Then finally, cap things off with save state and cheat code support.

Should be nearing a new release at that point.
2017-02-20 19:13:10 +11:00
Tim Allen 7c9b78b7bb Update to v102r07 release.
byuu says:

Changelog:

  - PCE: emulated PSG volume controls (vastly enhances audio quality)
  - PCE: emulated PSG noise as a square wave (somewhat enhances audio
    quality)
  - PCE: added save state support (currently broken and deadlocks the
    emulator though)

Thankfully, MAME had some rather easy to read code on how the volume
adjustment works, which they apparently ripped out of expired patents.
Hooray!

The two remaining sound issues are:

1. the random number generator for the noise channel is definitely not
hardware accurate. But it won't affect the sound quality at all. You'd
only be able to tell the difference by looking at hex bytes of a stream
rip.
2. I have no clue how to emulate the LFO (frequency modulation). A comment
in MAME's code (they also don't emulate it) advises that they aren't
aware of any games that even use it. But I'm there has to be at least one?

Given LFO not being used, and the RNG not really mattering all that much
... the sound's pretty close to perfect now.
2017-02-13 10:09:03 +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 bf70044edc Update to v102r05 release.
byuu says:

Changelog:

  - higan: added Makefile option,
    `build=(release|debug|instrument|optimize)` , defaults to release
  - PCE: added preliminary PSG (sound) emulation

The Makefile thing is just to make it easier to build debug releases
without having to hand-edit the Makefile. Just say "gmake build=debug"
and you'll get -g, otherwise you'll get -O3 -s. I'll probably start
adding these build= blocks to my other projects. Or maybe I'll put it
into nall, in which case release will need a different name ... a stable
-01, and a fast -03 mode. I also want to add a mode to generate
profiling information (via gprof.)

Unfortunately, the existing documentation on the PCE's PSG is as
barebones as humanly possible.

Right now, I support waveform mode, direct D/A mode, and noise
generation mode. However for noise, I'm not actually generating a proper
square wave, and I don't know the PRNG algorithm used for choosing the
random values. So for now, I'm just feeding in nall::random() values to
it.

I'm also not sure about the noise mode's frequency counter. Magic Kit is
implying it's 64*~frequency, but that results in an 11-bit period. It
seems only logical that we'd want a 12-bit period. So my guess is that
it's actually 12-bit, and halfway through it alternates between two
randomly generated values every 32 samples, and the two values are
generated every time the period hits zero.

Next up, it's not clear when the period counter is reloaded, either for
the waveform or the noise mode. So for now, when enabling the channel, I
reload the waveform period. And when enabling noise mode, I reload the
noise period. I don't know if you need to do it when writing to the
frequency registers or not.

Next, it's not clear whether the period is a decrement-and-compare, or a
compare-and-decrement, and whether we reload with frequency,
frequency-1, or frequency+1. There's this cryptic note in
pcetext.txt:

> The PSG channel frequency is 12 bits, $001 is the highest frequency,
> $FFF is the next to lowest frequency, and $000 is the lowest frequency.

As best I can tell, he's trying to say that it's decrement-and-compare.

Whatever the case, there's periodic popping noises every few seconds. I
thought it might be because this is the first system with a fractional
sampling rate (~3.57MHz), but rounding the frequency to a whole number
doesn't help at all, and emulator/audio should be able to handle
fractional resampling rates anyway.

The popping noises could also be due to PSG writes being cycle-timed,
and my HuC6280 cycle timings not being very great yet. The PSG has no
kind of interrupts, so I think careful timing is the only way to do
certain things, especially D/A mode.

Next up, I really don't understand the frequency modulation mode at all.
I don't have any idea whatsoever how to support that. It also has a
frequency value that we'll need to understand how the period works and
reloads. Basic idea though is the channel 1 output turns into a value to
modulate channel 0's frequency by, and channel 1's output gets muted.

Next up, I don't know how the volume controls work at all. There's a
master volume left+right, per-channel volume left+right, and per-channel
overall volume. The documentation lists their effects in terms of
decibels. I have no fucking clue how to turn decibels into multiply-by
values. Let alone how to stack THREE levels of audio volume controls
>_>

Next, it looks like the output is always 5-bit unsigned per-channel, but
there's also all the volume adjustments. So I don't know the final
bit-depth of the final output to normalize the value into a signed
floating point value between -1.0 and +1.0. So for now, half the
potential speaker range (anything below zero) isn't used in the
generated output.

As bad as all this sounds, and it is indeed bad ... the audio's about
~75% correct, so you can definitely play games like this, it just won't
be all that much fun.
2017-02-10 08:56:59 +11:00
Tim Allen ee7662a8be Update to v102r04 release.
byuu says:

Changelog:
  - Super Game Boy support is functional once again
  - new GameBoy::SuperGameBoyInterface class
  - system.(dmg,cgb,sgb) is now Model::(Super)GameBoy(Color) ala the PC
    Engine
  - merged WonderSwanInterface, WonderSwanColorInterface shared
    functions to WonderSwan::Interface
  - merged GameBoyInterface, GameBoyColorInterface shared functions to
    GameBoy::Interface
  - Interface::unload() now calls Interface::save() for Master System,
    Game Gear, Mega Drive, PC Engine, SuperGrafx
  - PCE: emulated PCE-CD backup RAM; stored per-game as save.ram (2KiB
    file)
      - this means you can now save your progress in games like Neutopia
      - the PCE-CD I/O registers like BRAM write protect are not
        emulated yet
  - PCE: IRQ sources now hold the IRQ line state, instead of the CPU
    holding it
      - this fixes most SuperGrafx games, which were fighting over the
        VDC IRQ line previously
  - PCE: CPU I/O $14xx should return the pending IRQ bits even if IRQs
    are disabled
  - PCE: VCE and the VDCs now synchronize to each other; fixes pixel
    widths in all games
  - PCE: greatly increased the accuracy of the VPC priority selection
    code (windows may be buggy still)
  - HuC6280: PLA, PLX, PLY should set Z, N flags; fixes many game bugs
    [Jonas Quinn]

The big thing I wanted to do was enslave the VDC(s) to the VCE. But
unfortunately, I forgot about the asynchronous DMA channels that each
VDC supports, so this isn't going to be possible I'm afraid.

In the most demanding case, Daimakaimura in-game, we're looking at 85fps
on my Xeon E3 1276v3. So ... not great, and we don't even have sound
connected yet.

We are going to have to profile and optimize this code once sound
emulation and save states are in.

Basically, think of it like this: the VCE, VDC0, and VDC1 all have the
same overhead, scheduling wise (which is the bulk of the performance
loss) as the dot-renderer for the SNES core. So it's like there's three
bsnes-accuracy PPU threads running just for video.

-----

Oh, just a fair warning ... the hooks for the SGB are a work in
progress.

If anyone is working on higan or a fork and want to do something similar
to it, don't use it as a template, at least not yet.

Right now, higan looks like this:

  - Emulator::Video handles the platform→videoRefresh calls
  - Emulator::Audio handles the platform→audioSample calls
  - each core hard-codes the platform→inputPoll, inputRumble calls
  - each core hard-codes calls to path, open, load to process files
  - dipSettings and notify are specialty hacks, neither are even hooked
    up right now to anything

With the SGB, it's an emulation core inside an emulation core, so
ideally you want to hook all of those functions. Emulator::Video and
Emulator::Audio aren't really abstractions over that, as the GB core
calls them and we have to special case not calling them in SGB mode.

The path, open, load can be implemented without hooks, thanks to the UI
only using one instance of Emulator::Platform for all cores. All we have
to do is override the folder path ID for the "Game Boy.sys" folder, so
that it picks "Super Game Boy.sfc/" and loads its boot ROM instead.
That's just a simple argument to GameBoy::System::load() and we're done.

dipSettings, notify and inputRumble don't matter. But we do also have to
hook inputPoll as well.

The nice idea would be for SuperFamicom::ICD2 to inherit from
Emulator::Platform and provide the desired functions that we need to
overload. After that, we'd just need the GB core to keep an abstraction
over the global Emulator::platform\* handle, to select between the UI
version and the SFC::ICD2 version.

However ... that doesn't work because of Emulator::Video and
Emulator::Audio. They would also have to gain an abstraction over
Emulator::platform\*, and even worse ... you'd have to constantly swap
between the two so that the SFC core uses the UI, and the GB core uses
the ICD2.

And so, for right now, I'm checking Model::SuperGameBoy() -> bool
everywhere, and choosing between the UI and ICD2 targets that way. And
as such, the ICD2 doesn't really need Emulator::Platform inheritance,
although it certainly could do that and just use the functions it needs.

But the SGB is even weirder, because we need additional new signals
beyond just Emulator::Platform, like joypWrite(), etc.

I'd also like to work on the Emulator::Stream for the SGB core. I don't
see why we can't have the GB core create its own stream, and let the
ICD2 just use that instead. We just have to be careful about the ICD2's
CPU soft reset function, to make sure the GB core's Stream object
remains valid. What I think that needs is a way to release an
Emulator::Stream individually, rather than calling
Emulator::Audio::reset() to do it. They are shared\_pointer objects, so
I think if I added a destructor function to remove it from
Emulator::Audio::streams, then that should work.
2017-01-26 12:06:06 +11:00
Tim Allen 186f008574 Update to v102r03 release.
byuu says:

Changelog:

  - PCE: split VCE from VDC
  - HuC6280: changed bus from (uint21 addr) to (uint8 bank, uint13 addr)
  - added SuperGrafx emulation (adds secondary VDC, plus new VPC)

The VDC now has no concept of the actual display raster timing, and
instead is driven by Vpulse (start of frame) and Hpulse (start of
scanline) signals from the VCE. One still can't render the start of the
next scanline onto the current scanline through overly aggressive
timings, but it shouldn't be too much more difficult to allow that to
occur now. This process incurs quite a major speed hit, so low-end
systems with Atom CPUs can't run things at 60fps anymore.

The timing needs a lot of work. The pixels end up very jagged if the VCE
doesn't output batches of 2-4 pixels at a time. But this should not be a
requirement at all, so I'm not sure what's going wrong there.

Yo, Bro and the 512-width mode of TV Sports Basketball is now broken as
a result of these changes, and I'm not sure why.

To load SuperGrafx games, you're going to have to change the .pce
extensions to .sg or .sgx. Or you can manually move the games from the
PC Engine folder to the SuperGrafx folder and change the game folder
extensions. I have no way to tell the games apart. Mednafen uses CRC32
comparisons, and I may consider that since there's only five games, but
I'm not sure yet.

The only SuperGrafx game that's playable right now is Aldynes. And the
priorities are all screwed up. I don't understand how the windows or the
priorities work at all from sgxtech.txt, so ... yeah. It's pretty
broken, but it's a start.

I could really use some help with this, as I'm very lost right now with
rendering :/

-----

Note that the SuperGrafx is technically its own system, it's not an
add-on.

As such, I'm giving it a separate .sys folder, and a separate library.

There's debate over how to name this thing. "SuperGrafx" appears more
popular than "Super Grafx". And you might also call it the "PC Engine
SuperGrafx", but I decided to leave off the prefix so it appears more
distinct.
2017-01-24 08:18:54 +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 c40e9754bc Update to v102r01 release.
byuu says:

Changelog:

  - MS, MD, PCE: remove controllers from scheduler in destructor
    [hex_usr]
  - PCE: no controller should return all bits set (still causing errant
    key presses when swapping gamepads)
  - PCE: emulate MDR for hardware I/O $0800-$17ff
  - PCE: change video resolution to 1140x242
  - PCE: added tertiary background Vscroll register (secondary cache)
  - PCE: create classes out of VDC VRAM, SATB, CRAM for cleaner access
    and I/O registers
  - PCE: high bits of CRAM read should be set
  - PCE: partially emulated VCE display registers: color frequency, HDS,
    HDW, VDS, VDW
  - PCE: 32-width sprites now split to two 16-width sprites to handle
    overflow properly
  - PCE: hopefully emulated sprite zero hit correctly (it's not well
    documented, and not often used)
  - PCE: trigger line coincidence interrupts during the previous
    scanline's Hblank period
  - tomoko: raise viewport from 320x240 to 326x242 to accommodate PC
    Engine's max resolution
  - nall: workaround for Clang compilation bug that can't figure out
    that a char is an integral data type
2017-01-22 11:33:36 +11:00
Tim Allen ae5968cfeb Update to v102 release.
byuu says (in the public announcement):

This release adds very preliminary emulation of the Sega Master System
(Mark III), Sega Game Gear, Sega Mega Drive (Genesis), and NEC PC Engine
(Turbografx-16). These cores do not yet offer sound emulation, save
states or cheat codes.

I'm always very hesitant to release a new emulation core in its alpha
stages, as in the past this has resulted in lasting bad impressions
of cores that have since improved greatly. For instance, the Game Boy
Advance emulation offered today is easily the second most accurate around,
yet it is still widely judged by its much older alpha implementation.

However, it's always been tradition with higan to not hold onto code
in secret. Rather than delay future releases for another year or two,
I'll put my faith in you all to understand that the emulation of these
systems will improve over time.

I hope that by releasing things as they are now, I might be able to
receive some much needed assistance in improving these cores, as the
documentation for these new systems is very much less than ideal.

byuu says (in the WIP forum):

Changelog:

  - PCE: latch background scroll registers (fixes Neutopia scrolling)
  - PCE: clip background attribute table scrolling (fixes Blazing Lazers
    scrolling)
  - PCE: support background/sprite enable/disable bits
  - PCE: fix large sprite indexing (fixes Blazing Lazers title screen
    sprites)
  - HuC6280: wrap zeropage accesses to never go beyond $20xx
  - HuC6280: fix alternating addresses for block move instructions
    (fixes Neutopia II)
  - HuC6280: block move instructions save and restore A,X,Y registers
  - HuC6280: emulate BCD mode (may not be 100% correct, based on SNES
    BCD) (fixes Blazing Lazers scoring)
2017-01-20 08:01:15 +11:00
Tim Allen b03563426f Update to v101r35 release.
byuu says:

Changelog:
  - PCE: added 384KB HuCard ROM mirroring mode
  - PCE: corrected D-pad polling order
  - PCE: corrected palette color ordering (GRB, not RGB -- yes,
    seriously)
  - PCE: corrected SATB DMA -- should write to SATB, not to VRAM
  - PCE: broke out Background, Sprite VDC settings to separate
    subclasses
  - PCE: emulated VDC backgrounds
  - PCE: emulated VDC sprites
  - PCE: emulated VDC sprite overflow, collision interrupts
  - HuC6280: fixed disassembler output for STi instructions
  - HuC6280: added missing LastCycle check to interrupt()
  - HuC6280: fixed BIT, CMP, CPX, CPY, TRB, TSB, TST flag testing and
    result
  - HuC6280: added extra cycle delays to the block move instructions
  - HuC6280: fixed ordering for flag set/clear instructions (happens
    after LastCycle check)
  - HuC6280: removed extra cycle from immediate instructions
  - HuC6280: fixed indirectLoad, indirectYStore absolute addressing
  - HuC6280: fixed BBR, BBS zeropage value testing
  - HuC6280: fixed stack push/pull direction

Neutopia looks okay until the main title screen, then there's some
gibberish on the bottom. The game also locks up with some gibberish once
you actually start a new game. So, still not playable just yet =(
2017-01-19 19:38:57 +11:00
Tim Allen f500426158 Update to v101r34 release.
byuu says:

Changelog:

  - PCE: emulated gamepad polling
  - PCE: emulated CPU interrupt sources
  - PCE: emulated timer
  - PCE: smarter emulation of ST0,ST1,ST2 instructions
  - PCE: better structuring of CPU, VDP IO registers
  - PCE: connected palette generation to the interface
  - PCE: emulated basic VDC timing
  - PCE: emulated VDC Vblank, Coincidence, and DMA completion IRQs
  - PCE: emulated VRAM, SATB DMA transfers
  - PCE: emulated VDC I/O registers

Everything I've implemented today likely has lots of bugs, and is
untested for obvious reasons.

So basically, after I fix many horrendous bugs, it should now be
possible to implement the VDC and start getting graphical output.
2017-01-17 08:02:56 +11:00
Tim Allen 8499c64756 Update to v101r33 release.
byuu says:

Changelog:

  - PCE: HuC6280 core completed

There's bound to be a countless stream of bugs, and the cycle counts are
almost certainly not exact yet, but ... all instructions are implemented.

So at this point, I can start comparing trace logs against Mednafen's
debugger output.

Of course, we're very likely to immediately slam into a wall of needing
I/O registers implemented for the VDC in order to proceed further.
2017-01-15 11:58:47 +11:00
Tim Allen 26bd7590ad Update to v101r32 release.
byuu says:

Changelog:

  - SMS: fixed controller connection bug
  - SMS: fixed Z80 reset bug
  - PCE: emulated HuC6280 MMU
  - PCE: emulated HuC6280 RAM
  - PCE: emulated HuCard ROM reading
  - PCE: implemented 178 instructions
  - tomoko: removed "soft reset" functionality
  - tomoko: moved "power cycle" to just above "unload" option

I'm not sure of the exact number of HuC6280 instructions, but it's less
than 260.

Many of the ones I skipped are HuC6280-originals that I don't know how
to emulate just yet.

I'm also really unsure about the zero page stuff. I believe we should be
adding 0x2000 to the addresses to hit page 1, which is supposed to be
mapped to the zero page (RAM). But when I look at turboEMU's source, I
have no clue how the hell it could possibly be doing that. It looks to
be reading from page 0, which is almost always ROM, which would be ...
really weird.

I also don't know if I've emulated the T mode opcodes correctly or not.
The documentation on them is really confusing.
2017-01-14 10:59:38 +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 0ad70a30f8 Update to v101r30 release.
byuu says:

Changelog:

  - SMS: added cartridge ROM/RAM mirroring (fixes Alex Kidd)
  - SMS: fixed 8x16 sprite mode (fixes Wonder Boy, Ys graphics)
  - Z80: emulated "ex (sp),hl" instruction
  - Z80: fixed INx NF (should be set instead of cleared)
  - Z80: fixed loop condition check for CPxR, INxR, LDxR, OTxR (fixes
    walking in Wonder Boy)
  - SFC: removed Debugger and sfc/debugger.hpp
  - icarus: connected MS, GG, MD importing to the scan dialog
  - PCE: added emulation skeleton to higan and icarus

At this point, Master System games are fairly highly compatible, sans
audio. Game Gear games are running, but I need to crop the resolution
and support the higher color palette that they can utilize. It's really
something else the way they handled the resolution shrink on that thing.

The last change is obviously going to be the biggest news.

I'm very well aware it's not an ideal time to start on a new emulation
core, with the MS and MD cores only just now coming to life with no
audio support.

But, for whatever reason, my heart's really set on working on the PC
Engine. I wanted to write the final higan skeleton core, and get things
ready so that whenever I'm in the mood to work on the PCE, I can do so.

The skeleton is far and away the most tedious and obnoxious part of the
emulator development, because it's basically all just lots of
boilerplate templated code, lots of new files to create, etc.

I really don't know how things are going to proceed ... but I can say
with 99.9% certainty that this will be the final brand new core ever
added to higan -- at least one written by me, that is. This was
basically the last system from my childhood that I ever cared about.
It's the last 2D system with games that I really enjoy playing. No other
system is worth dividing my efforts and reducing the quality and amount
of time to work on the systems I have.

In the future, there will be potential for FDS, Mega CD and PCE-CD
support. But those will all be add-ons, and they'll all be really
difficult and challenge the entire design of higan's UI (it's entirely
cartridge-driven at this time.) None of them will be entirely new cores
like this one.
2017-01-12 07:27:30 +11:00
Tim Allen 79c83ade70 Update to v101r29 release.
byuu says:

Changelog:

  - SMS: background VDP clips partial tiles on the left (math may not be
    right ... it's hard to reason about)
  - SMS: fix background VDP scroll locks
  - SMS: fix VDP sprite coordinates
  - SMS: paint black after the end of the visible display
      - todo: shouldn't be a brute force at the end of the main VDP
        loop, should happen in each rendering unit
  - higan: removed emulator/debugger.hpp
  - higan: removed privileged: access specifier
  - SFC: removed debugger hooks
      - todo: remove sfc/debugger.hpp
  - Z80: fixed disassembly of (fd,dd) cb (displacement) (opcode)
    instructions
  - Z80: fix to prevent interrupts from firing between ix/iy prefixes
    and opcodes
      - todo: this is a rather hacky fix that could, if exploited, crash
        the stack frame
  - Z80: fix BIT flags
  - Z80: fix ADD hl,reg flags
  - Z80: fix CPD, CPI flags
  - Z80: fix IND, INI flags
  - Z80: fix INDR, INIT loop flag check
  - Z80: fix OUTD, OUTI flags
  - Z80: fix OTDR, OTIR loop flag check
2017-01-10 08:27:13 +11:00
Tim Allen a3aea95e6b Update to v101r28 release.
byuu says:

Changelog:

  - SMS: emulated the remaining 240 instructions in the (0xfd, 0xdd)
    0xcb (displacement) (opcode) set
      - 1/8th of these were "legal" instructions, and apparently games
        use them a lot
  - SMS: emulated the standard gamepad controllers
      - reset button not emulated yet

The reset button is tricky. In every other case, reset is a hardware
thing that instantly reboots the entire machine.

But on the SMS, it's more like a gamepad button that's attached to the
front of the device. When you press it, it fires off a reset vector
interrupt and the gamepad polling routine lets you query the status of
the button.

Just having a reset option in the "Master System" hardware menu is not
sufficient to fully emulate the behavior. Even more annoying is that the
Game Gear doesn't have such a button, yet the core information structs
aren't flexible enough for the Master System to have it, and the Game
Gear to not have it, in the main menu. But that doesn't matter anyway,
since it won't work having it in the menu for the Master System.

So as a result, I'm going to have to have a new "input device" called
"Hardware" that has the "Reset" button listed under there. And for the
sake of consistency, I'm not sure if we should treat the other systems
the same way or not :/
2017-01-09 07:55:02 +11:00
Tim Allen 569f5abc28 Update to v101r27 release.
byuu says:

Changelog:

  - SMS: emulated the generic Sega memory mapper (none of the more
    limited forms of it yet)
      - (missing ROM shift, ROM write enable emulation -- no commercial
        games use either, though)
  - SMS: bus I/O returns 0xff instead of 0x00 so games don't think every
    key is being pressed at once
      - (this is a hack until I implement proper controller pad reading)
  - SMS: very limited protection against reading/writing past the end of
    ROM/RAM (todo: should mirror)
  - SMS: VDP background HSCROLL subtracts, rather than adds, to the
    offset (unlike VSCROLL)
  - SMS: VDP VSCROLL is 9-bit, modulates voffset+vscroll to 224 in
    192-line mode (32x28 tilemap)
  - SMS: VDP tiledata for backgrounds and sprites use `7-(x&7)` rather
    than `(x&7)`
  - SMS: fix output color to be 6-bit rather than 5-bit
  - SMS: left clip uses register `#7`, not palette color `#7`
      - (todo: do we want `color[reg7]` or `color[16 + reg7]`?)
  - SMS: refined handling of 0xcb, 0xed prefixes in the Z80 core and its
    disassembler
  - SMS: emulated (0xfd, 0xdd) 0xcb opcodes 0x00-0x0f (still missing
    0x10-0xff)
  - SMS: fixed 0xcb 0b-----110 opcodes to use direct HL and never allow
    (IX,IY)+d
  - SMS: fixed major logic bug in (IX,IY)+d displacement
      - (was using `read(x)` instead of `operand()` for the displacement
        byte fetch before)
  - icarus: fake there always being 32KiB of RAM in all SMS cartridges
    for the time being
      - (not sure how to detect this stuff yet; although I've read it's
        not even really possible `>_>`)

TODO: remove processor/z80/dissassembler.cpp code block at line 396 (as it's unnecessary.)

Lots of commercial games are starting to show trashed graphical output now.
2017-01-06 19:11:38 +11:00
Tim Allen 5bdf55f08f Update to v101r25 release.
byuu says:

Changelog:

  - SMS: emulated VDP mode 4 graphical output (background, sprites)
  - added $(windres) to icarus as well

I'm sure the VDP emulation is still really, really buggy, but
essentially I handle:

  - mode 4 rendering
  - background scrolling
  - background hscroll lock
  - background vscroll lock
  - background nametable relocation
  - sprite nametable relocation
  - sprite tiledata relocation
  - sprite 192-line y=0xd0 edge case (end sprite rendering)
  - sprite 8-pixel x-coordinate displacement
  - sprite extended size (height only in mode 4)
  - sprite overflow
  - sprite collision
  - left column masking
  - display disable
  - backdrop color
  - 192, 224, 240 height

I do not support:

  - mode 2 rendering
  - sprite zoom
  - disallowing 240 height in NTSC mode
  - PAL mode
  - probably lots more
2016-12-30 18:24:35 +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 bab2ac812a Update to v101r24 release.
byuu says:

Changelog:

  - SMS: extended bus mapping of in/out ports: now decoding them fully
    inside ms/bus
  - SMS: moved Z80 disassembly code from processor/z80 to ms/cpu
    (cosmetic)
  - SMS: hooked up non-functional silent PSG sample generation, so I can
    cap the framerate at 60fps
  - SMS: hooked up the VDP main loop: 684 clocks/scanline, 262
    scanlines/frame (no PAL support yet)
  - SMS: emulated the VDP Vcounter and Hcounter polling ... hopefully
    it's right, as it's very bizarre
  - SMS: emulated VDP in/out ports (data read, data write, status read,
    control write, register write)
  - SMS: decoding and caching all VDP register flags (variable names
    will probably change)
  - nall: \#undef IN on Windows port (prevent compilation warning on
    processor/z80)

Watching Sonic the Hedgehog, I can definitely see some VDP register
writes going through, which is a good sign.

Probably the big thing that's needed before I can get enough into the
VDP to start showing graphics is interrupt support. And interrupts are
never fun to figure out :/

What really sucks on this front is I'm flying blind on the Z80 CPU core.
Without a working VDP, I can't run any Z80 test ROMs to look for CPU
bugs. And the CPU is certainly too buggy still to run said test ROM
anyway. I can't find any SMS emulators with trace logging from reset.
Such logs vastly accelerate tracking down CPU logic bugs, so without
them, it's going to take a lot longer.
2016-12-17 22:31:34 +11:00
Tim Allen 1d7b674dd4 Update to v101r23 release.
byuu says:

This is a really tiny WIP. Just wanted to add the known fixes before I start debugging it against Mednafen in a fork.

Changelog:

  - Z80: fixed flag calculations on 8-bit ADC, ADD, SBC, SUB
  - Z80: fixed flag calculations on 16-bit ADD
  - Z80: simplified DAA logic \[AWJ\]
  - Z80: RETI sets IFF1=IFF2 (same as RETN)
2016-11-15 18:20:42 +11:00
Tim Allen c2c957a9da Update to v101r22 release.
byuu says:

Changelog:
- Z80: all 25 remaining instructions implemented

Now onto the debugging ... :/
2016-11-01 22:42:25 +11:00
Tim Allen 8cf20dabbf Update to v101r21 release.
byuu says:

Changelog:

- Z80: emulated 83 new instructions
- Z80: timing improvements

DAA is a skeleton implementation to complete the normal opcode set. Also
worth noting that I don't know exactly what the hell RETI is doing,
so for now it acts like RET. RETN probably needs some special handling
besides just setting IFF1=IFF2 as well.

I'm now missing 24 ED-prefix instructions, plus DAA, for a total of 25
opcodes remaining. And then, of course, several weeks worth of debugging
all of the inevitable bugs in the core.
2016-11-01 08:10:33 +11:00
Tim Allen 2707c5316d Update to v101r20 release.
byuu says:

Changelog:
- Z80: emulated 272 new instructions
- hiro/GTK: fixed v101r19 Linux regression [thanks, SuperMikeMan!]
2016-10-29 11:33:30 +11:00
Tim Allen f3e67da937 Update to v101r19 release.
byuu says:

Changelog:

-   added \~130 new PAL games to icarus (courtesy of Smarthuman
    and aquaman)
-   added all three Korean-localized games to icarus
-   sfc: removed SuperDisc emulation (it was going nowhere)
-   sfc: fixed MSU1 regression where the play/repeat flags were not
    being cleared on track select
-   nall: cryptography support added; will be used to sign future
    databases (validation will always be optional)
-   minor shims to fix compilation issues due to nall changes

The real magic is that we now have 25-30% of the PAL SNES library in
icarus!

Signing will be tricky. Obviously if I put the public key inside the
higan archive, then all anyone has to do is change that public key for
their own releases. And if you download from my site (which is now over
HTTPS), then you don't need the signing to verify integrity. I may just
put the public key on my site on my site and leave it at that, we'll
see.
2016-10-28 08:16:58 +11:00
Tim Allen c6fc15f8d2 Update to v101r18 release.
byuu says:

Changelog:

  - added 30 new PAL games to icarus (courtesy of Mikerochip)
  - new version of libco no longer requires mprotect nor W|X permissions
  - nall: default C compiler to -std=c11 instead of -std=c99
  - nall: use `-fno-strict-aliasing` during compilation
  - updated nall/certificates (hopefully for the last time)
  - updated nall/http to newer coding conventions
  - nall: improve handling of range() function

I didn't really work on higan at all, this is mostly just a release
because lots of other things have changed.

The most interesting is `-fno-strict-aliasing` ... basically, it joins
`-fwrapv` as being "stop the GCC developers from doing *really* evil
shit that could lead to security vulnerabilities or instabilities."

For the most part, it's a ~2% speed penalty for higan. Except for the
Sega Genesis, where it's a ~10% speedup. I have no idea how that's
possible, but clearly something's going very wrong with strict aliasing
on the Genesis core.

So ... it is what it is. If you need the performance for the non-Genesis
cores, you can turn it off in your builds. But I'm getting quite sick of
C++'s "surprises" and clever compiler developers, so I'm keeping it on
in all of my software going forward.
2016-09-14 21:55:53 +10:00
Tim Allen d6e9d94ec3 Update to v101r17 release.
byuu says:

Changelog:

  - Z80: added most opcodes between 0x00 and 0x3f (two or three hard
    ones missing still)
  - Z80: redid register declaration *again* to handle AF', BC', DE',
    HL' (ugggggh, the fuck? Alternate registers??)
      - basically, using `#define <register name>` values to get around
        horrendously awful naming syntax
  - Z80: improved handling of displace() so that it won't ever trigger
    on (BC) or (DE)
2016-09-06 23:53:14 +10:00
Tim Allen 2fbbccf985 Update to v101r16 release.
byuu says:

Changelog:

  - Z80: implemented 113 new instructions (all the easy
    LD/ADC/ADD/AND/OR/SBC/SUB/XOR ones)
  - Z80: used alternative to castable<To, With> type (manual cast inside
    instruction() register macros)
  - Z80: debugger: used register macros to reduce typing and increase
    readability
  - Z80: debugger: smarter way of handling multiple DD/FD prefixes
    (using gotos, yay!)
  - ruby: fixed crash with Windows input driver on exit (from SuperMikeMan)

I have no idea how the P/V flag is supposed to work on AND/OR/XOR, so
that's probably wrong for now. HALT is also mostly a dummy function for
now. But I typically implement those inside instruction(), so it
probably won't need to be changed? We'll see.
2016-09-06 10:09:33 +10:00
Tim Allen 4c3f58150c Update to v101r15 release.
byuu says:

Changelog:

  - added (poorly-named) castable<To, With> template
  - Z80 debugger rewritten to make declaring instructions much simpler
  - Z80 has more instructions implemented; supports displacement on
    (IX), (IY) now
  - added `Processor::M68K::Bus` to mirror `Processor::Z80::Bus`
      - it does add a pointer indirection; so I'm not sure if I want to
        do this for all of my emulator cores ...
2016-09-04 23:51:27 +10:00
Tim Allen d91f3999cc Update to v101r14 release.
byuu says:
Changelog:

  - rewrote the Z80 core to properly handle 0xDD (IX0 and 0xFD (IY)
    prefixes
  - added Processor::Z80::Bus as a new type of abstraction
  - all of the instructions implemented have their proper T-cycle counts
    now
  - added nall/certificates for my public keys

The goal of `Processor::Z80::Bus` is to simulate the opcode fetches being
2-read + 2-wait states; operand+regular reads/writes being 3-read. For
now, this puts the cycle counts inside the CPU core. At the moment, I
can't think of any CPU core where this wouldn't be appropriate. But it's
certainly possible that such a case exists. So this may not be the
perfect solution.

The reason for having it be a subclass of Processor::Z80 instead of
virtual functions for the MasterSystem::CPU core to define is due to
naming conflicts. I wanted the core to say `in(addr)` and have it take
the four clocks. But I also wanted a version of the function that didn't
consume time when called. One way to do that would be for the core to
call `Z80::in(addr)`, which then calls the regular `in(addr)` that goes to
`MasterSystem::CPU::in(addr)`. But I don't want to put the `Z80::`
prefix on all of the opcodes. Very easy to forget it, and then end up not
consuming any time. Another is to use uglier names in the
`MasterSystem::CPU` core, like `read_`, `write_`, `in_`, `out_`, etc. But,
yuck.

So ... yeah, this is an experiment. We'll see how it goes.
2016-09-03 21:26:04 +10:00
Tim Allen 7c96826eb0 Update to v101r13 release.
byuu says:

Changelog:

  - MS: added ms/bus
  - Z80: implemented JP/JR/CP/DI/IM/IN instructions
  - MD/VDP: added window layer emulation
  - MD/controller/gamepad: fixed d2,d3 bits (Altered Beast requires
    this)

The Z80 is definitely a lot nastier than the LR35902. There's a lot of
table duplication with HL→IX→IY; and two of them nest two levels deep
(eg FD CB xx xx), so the design may change as I implement more.
2016-08-27 14:48:21 +10:00
Tim Allen 5df717ff2a Update to v101r12 release.
byuu says:

Changelog:

  - new md/bus/ module for bus reads/writes
      - abstracts byte/word accesses wherever possible (everything but
        RAM; forces all but I/O to word, I/O to byte)
      - holds the system RAM since that's technically not part of the
        CPU anyway
  - added md/controller and md/system/peripherals
  - added emulation of gamepads
  - added stub PSG audio output (silent) to cap the framerate at 60fps
    with audio sync enabled
  - fixed VSRAM reads for plane vertical scrolling (two bugs here: add
    instead of sub; interlave plane A/B)
  - mask nametable read offsets (can't exceed 8192-byte nametables
    apparently)
  - emulated VRAM/VSRAM/CRAM reads from VDP data port
  - fixed sprite width/height size calculations
  - added partial emulation of 40-tile per scanline limitation (enough
    to fix Sonic's title screen)
  - fixed off-by-one sprite range testing
  - fixed sprite tile indexing
  - Vblank happens at Y=224 with overscan disabled
      - unsure what happens when you toggle it between Y=224 and Y=240
        ... probably bad things
  - fixed reading of address register for ADDA, CMPA, SUBA
  - fixed sign extension for MOVEA effect address reads
  - updated MOVEM to increment the read addresses (but not writeback)
    for (aN) mode

With all of that out of the way, we finally have Sonic the Hedgehog
(fully?) playable. I played to stage 1-2 and through the special stage,
at least. EDIT: yeah, we probably need HIRQs for Labyrinth Zone.

Not much else works, of course. Most games hang waiting on the Z80, and
those that don't (like Altered Beast) are still royally screwed. Tons of
features still missing; including all of the Z80/PSG/YM2612.

A note on the perihperals this time around: the Mega Drive EXT port is
basically identical to the regular controller ports. So unlike with the
Famicom and Super Famicom, I'm inheriting the exension port from the
controller class.
2016-08-22 08:11:24 +10:00
Tim Allen f7ddbfc462 Update to v101r11 release.
byuu says:

Changelog:

  - 68K: fixed NEG/NEGX operand order
  - 68K: fixed bug in disassembler that was breaking trace logging
  - VDP: improved sprite rendering (still 100% broken)
  - VDP: added horizontal/vertical scrolling (90% broken)

Forgot:

  - 68K: fix extension word sign bit on indexed modes for disassembler
    as well
  - 68K: emulate STOP properly (use r.stop flag; clear on IRQs firing)

I'm really wearing out fast here. The Genesis documentation is somehow
even worse than Game Boy documentation, but this is a far more complex
system.

It's a massive time sink to sit here banging away at every possible
combination of how things could work, only to see no positive
improvements. Nothing I do seems to get sprites to do a goddamn thing.

squee says the sprite Y field is 10-bits, X field is 9-bits. genvdp says
they're both 10-bits. BlastEm treats them like they're both 10-bits,
then masks off the upper bit so it's effectively 9-bits anyway.

Nothing ever bothers to tell you whether the horizontal scroll values
are supposed to add or subtract from the current X position. Probably
the most basic detail you could imagine for explaining horizontal
scrolling and yet ... nope. Nothing.

I can't even begin to understand how the VDP FIFO functionality works,
or what the fuck is meant by "slots".

I'm completely at a loss as how how in the holy hell the 68K works with
8-bit accesses. I don't know whether I need byte/word handlers for every
device, or if I can just hook it right into the 68K core itself. This
one's probably the most major design detail. I need to know this before
I go and implement the PSG/YM2612/IO ports-\>gamepads/Z80/etc.

Trying to debug the 68K is murder because basically every game likes to
start with a 20,000,000-instruction reset phase of checksumming entire
games, and clearing out the memory as agonizingly slowly as humanly
possible. And like the ARM, there's too many registers so I'd need three
widescreen monitors to comfortably view the entire debugger output lines
onscreen.

I can't get any test ROMs to debug functionality outside of full games
because every **goddamned** test ROM coder thinks it's acceptable to tell
people to go fetch some toolchain from a link that died in the late '90s
and only works on MS-DOS 6.22 to build their fucking shit, because god
forbid you include a 32KiB assembled ROM image in your fucking archives.

... I may have to take a break for a while. We'll see.
2016-08-21 12:50:05 +10:00
Tim Allen 0b70a01b47 Update to v101r10 release.
byuu says:
Changelog:

  - 68K: MOVEQ is 8-bit signed
  - 68K: disassembler was print EOR for OR instructions
  - 68K: address/program-counter indexed mode had the signed-word/long
    bit backward
  - 68K: ADDQ/SUBQ #n,aN always works in long mode; regardless of size
  - 68K→VDP DMA needs to use `mode.bit(0)<<22|dmaSource`; increment by
    one instead of two
  - Z80: added registers and initial two instructions
  - MS: hooked up enough to load and start running games
      - Sonic the Hedgehog can execute exactly one instruction... whoo.
2016-08-20 00:11:26 +10:00
Tim Allen 4d2e17f9c0 Update to v101r09 release.
byuu says:

Sorry, two WIPs in one day. Got excited and couldn't wait.

Changelog:

  - ADDQ, SUBQ shouldn't update flags when targeting an address register
  - ADDA should sign extend effective address reads
  - JSR was pushing the PC too early
  - some improvements to 8-bit register reads on the VDP (still needs
    work)
  - added H/V counter reads to the VDP IO port region
  - icarus: added support for importing Master System and Game Gear ROMs
  - tomoko: added library sub-menus for each manufacturer
      - still need to sort Game Gear after Mega Drive somehow ...

The sub-menu system actually isn't all that bad. It is indeed a bit more
annoying, but not as annoying as I thought it was going to be. However,
it looks a hell of a lot nicer now.
2016-08-18 08:05:50 +10:00
Tim Allen 043f6a8b33 Update to v101r08 release.
byuu says:

Changelog:

  - 68K: fixed read-modify-write instructions
  - 68K: fixed ADDX bug (using wrong target)
  - 68K: fixed major bug with SUB using wrong argument ordering
  - 68K: fixed sign extension when reading address registers from
    effective addressing
  - 68K: fixed sign extension on CMPA, SUBA instructions
  - VDP: improved OAM sprite attribute table caching behavior
  - VDP: improved DMA fill operation behavior
  - added Master System / Game Gear stubs (needed for developing the Z80
    core)
2016-08-17 22:31:22 +10:00
Tim Allen ffd150735b Update to v101r07 release.
byuu says:

Added VDP sprite rendering. Can't get any games far enough in to see if
it actually works. So in other words, it doesn't work at all and is 100%
completely broken.

Also added 68K exceptions and interrupts. So far only the VDP interrupt
is present. It definitely seems to be firing in commercial games, so
that's promising. But the implementation is almost certainly completely
wrong. There is fuck all of nothing for documentation on how interrupts
actually work. I had to find out the interrupt vector numbers from
reading the comments from the Sonic the Hedgehog disassembly. I have
literally no fucking clue what I0-I2 (3-bit integer priority value in
the status register) is supposed to do. I know that Vblank=6, Hblank=4,
Ext(gamepad)=2. I know that at reset, SR.I=7. I don't know if I'm
supposed to block interrupts when I is >, >=, <, <= to the interrupt
level. I don't know what level CPU exceptions are supposed to be.

Also implemented VDP regular DMA. No idea if it works correctly since
none of the commercial games run far enough to use it. So again, it's
horribly broken for usre.

Also improved VDP fill mode. But I don't understand how it takes
byte-lengths when the bus is 16-bit. The transfer times indicate it's
actually transferring at the same speed as the 68K->VDP copy, strongly
suggesting it's actually doing 16-bit transfers at a time. In which case,
what happens when you set an odd transfer length?

Also, both DMA modes can now target VRAM, VSRAM, CRAM. Supposedly there's
all kinds of weird shit going on when you target VSRAM, CRAM with VDP
fill/copy modes, but whatever. Get to that later.

Also implemented a very lazy preliminary wait mechanism to to stall out
a processor while another processor exerts control over the bus. This
one's going to be a major work in progress. For one, it totally breaks
the model I use to do save states with libco. For another, I don't
know if a 68K->VDP DMA instantly locks the CPU, or if it the CPU could
actually keep running if it was executing out of RAM when it started
the DMA transfer from ROM (eg it's a bus busy stall, not a hard chip
stall.) That'll greatly change how I handle the waiting.

Also, the OSS driver now supports Audio::Latency. Sound should be
even lower latency now. On FreeBSD when set to 0ms, it's absolutely
incredible. Cannot detect latency whatsoever. The Mario jump sound seems
to happen at the very instant I hear my cherry blue keyswitch activate.
2016-08-15 14:56:38 +10: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 ac2d0ba1cf Update to v101r05 release.
byuu says:

Changelog:

  - 68K: fixed bug that affected BSR return address
  - VDP: added very preliminary emulation of planes A, B, W (W is
    entirely broken though)
  - VDP: added command/address stuff so you can write to VRAM, CRAM,
    VSRAM
  - VDP: added VRAM fill DMA

I would be really surprised if any commercial games showed anything at
all, so I'd probably recommend against wasting your time trying, unless
you're really bored :P

Also, I wanted to add: I am accepting patches\! So if anyone wants to
look over the 68K core for bugs, that would save me untold amounts of
time in the near future :D
2016-08-13 09:47:30 +10:00
Tim Allen 1df2549d18 Update to v101r04 release.
byuu says:

Changelog:

  - pulled the (u)intN type aliases into higan instead of leaving them
    in nall
  - added 68K LINEA, LINEF hooks for illegal instructions
  - filled the rest of the 68K lambda table with generic instance of
    ILLEGAL
  - completed the 68K disassembler effective addressing modes
      - still unsure whether I should use An to decode absolute
        addresses or not
      - pro: way easier to read where accesses are taking place
      - con: requires An to be valid; so as a disassembler it does a
        poor job
      - making it optional: too much work; ick
  - added I/O decoding for the VDP command-port registers
  - added skeleton timing to all five processor cores
  - output at 1280x480 (needed for mixed 256/320 widths; and to handle
    interlace modes)

The VDP, PSG, Z80, YM2612 are all stepping one clock at a time and
syncing; which is the pathological worst case for libco. But they also
have no logic inside of them. With all the above, I'm averaging around
250fps with just the 68K core actually functional, and the VDP doing a
dumb "draw white pixels" loop. Still way too early to tell how this
emulator is going to perform.

Also, the 320x240 mode of the Genesis means that we don't need an aspect
correction ratio. But we do need to ensure the output window is a
multiple 320x240 so that the scale values work correctly. I was
hard-coding aspect correction to stretch the window an additional \*8/7.
But that won't work anymore so ... the main higan window is now 640x480,
960x720, or 1280x960. Toggling aspect correction only changes the video
width inside the window.

It's a bit jarring ... the window is a lot wider, more black space now
for most modes. But for now, it is what it is.
2016-08-12 11:07:04 +10:00
Tim Allen 9b8c3ff8c0 Update to v101r03 release.
byuu says:

The 68K core now implements all 88 instructions. It ended up being 111
instructions in my core due to splitting up opcodes with the same name
but different addressing modes or directions (removes conditions at the
expense of more code.)

Technically, I don't have exceptions actually implemented yet, and
RESET/STOP don't do anything but set flags. So there's still more to
go. But ... close enough for statistics time!

The M68K core source code is 124,712 bytes in size. The next largest
core is the ARM7 core at 70,203 bytes in size.

The M68K object size is 942KiB; with the next largest being the V30MZ
core at 173KiB.

There are a total of 19,656 invalid opcodes in the 68000 revision (unless
of course I've made mistakes in my mappings, which is very probably.)

Now the fun part ... figuring out how to fix bugs in this core without
VDP emulation :/
2016-08-11 08:02:02 +10:00
Tim Allen 0a57cac70c Update to v101r02 release.
byuu says:

Changelog:

  - Emulator: use `(uintmax)-1 >> 1` for the units of time
  - MD: implemented 13 new 68K instructions (basically all of the
    remaining easy ones); 21 remain
  - nall: replaced `(u)intmax_t` (64-bit) with *actual* `(u)intmax` type
    (128-bit where available)
      - this extends to everything: atoi, string, etc. You can even
        print 128-bit variables if you like

22,552 opcodes still don't exist in the 68K map. Looking like quite a
few entries will be blank once I finish.
2016-08-09 21:07:18 +10:00
Tim Allen 8bdf8f2a55 Update to v101r01 release.
byuu says:

Changelog:

  - added eight more 68K instructions
  - split ADD(direction) into two separate ADD functions

I now have 54 out of 88 instructions implemented (thus, 34 remaining.)
The map is missing 25,182 entries out of 65,536. Down from 32,680 for
v101.00

Aside: this version number feels really silly. r10 and r11 surely will
as well ...
2016-08-08 20:12:03 +10:00
Tim Allen e39987a3e3 Update to v101 release.
byuu says (in the public announcement):

Not a large changelog this time, sorry. This release is mostly to fix
the SA-1 issue, and to get some real-world testing of the new scheduler
model. Most of the work in the past month has gone into writing a 68000
CPU core; yet it's still only about half-way finished.

Changelog (since the previous release):

  - fixed SNES SA-1 IRQ regression (fixes Super Mario RPG level-up
    screen)
  - new scheduler for all emulator cores (precision of 2^-127)
  - icarus database adds nine new SNES games
  - added Input/Frequency to settings file (allows simulation of
    latency)

byuu says (in the WIP forum):

Changelog:

  - in 32-bit mode, Thread uses uint64\_t with 2^-63 time units (10^-7
    precision in the worst case)
      - nearly ten times the precision of an attosecond
  - in 64-bit mode, Thread uses uint128\_t with 2^-127 time units
    (10^-26 precision in the worst case)
      - far more accurate than yoctoseconds; almost closing in on planck
        time

Note: a quartz crystal is accurate to 10^-4 or 10^-5. A cesium fountain
atomic clock is accurate to 10^-15. So ... yeah. 2^-63 was perfectly
fine; but there was no speed penalty whatsoever for using uint128\_t in
64-bit mode, so why not?
2016-08-08 20:04:15 +10:00
Tim Allen f5e5bf1772 Update to v100r16 release.
byuu says:

(Windows users may need to include <sys/time.h> at the top of
nall/chrono.hpp, not sure.)

Unchangelog:
- forgot to add the Scheduler clock=0 fix because I have the memory of
  a goldfish

Changelog:
- new icarus database with nine additional games
- hiro(GTK,Qt) won't constantly write its settings.bml file to disk
  anymore
- added latency simulator for fun (settings.bml => Input/Latency in
  milliseconds)

So the last one ... I wanted to test out nall::chrono, and I was also
thinking that by polling every emulated frame, it's pretty wasteful when
you are using Fast Forward and hitting 200+fps. As I've said before,
calls to ruby::input::poll are not cheap.

So to get around this, I added a limiter so that if you called the
hardware poll function within N milliseconds, it'll return without
doing any actual work. And indeed, that increases my framerate of Zelda
3 uncapped from 133fps to 142fps. Yay. But it's not a "real" speedup,
as it only helps you when you exceed 100% speed (theoretically, you'd
need to crack 300% speed since the game itself will poll at 16ms at 100%
speed, but yet it sped up Zelda 3, so who am I to complain?)

I threw the latency value into the settings file. It should be 16,
but I set it to 5 since that was the lowest before it started negatively
impacting uncapped speeds. You're wasting your time and CPU cycles setting
it lower than 5, but if people like placebo effects it might work. Maybe
I should let it be a signed integer so people can set it to -16 and think
it's actually faster :P (I'm only joking. I took out the 96000hz audio
placebo effect as well. Not really into psychological tricks anymore.)

But yeah seriously, I didn't do this to start this discussion again for
the billionth time. Please don't go there. And please don't tell me this
WIP has higher/lower latency than before. I don't want to hear it.

The only reason I bring it up is for the fun part that is worth
discussing: put up or shut up time on how sensitive you are to
latency! You can set the value above 5 to see how games feel.

I personally can't really tell a difference until about 50. And I can't
be 100% confident it's worse until about 75. But ... when I set it to
150, games become "extra difficult" ... the higher it goes, the worse
it gets :D

For this WIP, I've left no upper limit cap. I'll probably set a cap of
something like 500ms or 1000ms for the official release. Need to balance
user error/trolling with enjoyability. I'll think about it.

[...]

Now, what I worry about is stupid people seeing it and thinking it's an
"added latency" setting, as if anyone would intentionally make things
worse by default. This is a limiter. So if 5ms have passed since the
game last polled, and that will be the case 99.9% of the time in games,
the next poll will happen just in time, immediately when the game polls
the inputs. Thus, a value below 1/<framerate>ms is not only pointless,
if you go too low it will ruin your fast forward max speeds.

I did say I didn't want to resort to placebo tricks, but I also don't
want to spark up public discussion on this again either. So it might
be best to default Input/Latency to 0ms, and internally have a max(5,
latency) wrapper around the value.
2016-08-03 22:32:40 +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 306cac2b54 Update to v100r13 release.
byuu says:

Changelog: M68K improvements, new instructions added.
2016-07-26 20:46:43 +10:00
Tim Allen f230d144b5 Update to v100r12 release.
byuu says:

All of the above fixes, plus I added all 24 variations on the shift
opcodes, plus SUBQ, plus fixes to the BCC instruction.

I can now run 851,767 instructions into Sonic the Hedgehog before hitting
an unimplemented instruction (SUB).

The 68K core is probably only ~35% complete, and yet it's already within
4KiB of being the largest CPU core, code size wise, in all of higan. Fuck
this chip.
2016-07-25 23:15:54 +10:00
Tim Allen 7ccfbe0206 Update to v100r11 release.
byuu says:

I split the Register class and read/write handlers into DataRegister and
AddressRegister, given that they have different behaviors on byte/word
accesses (data tends to preserve the upper bits; address tends to
sign-extend things.)

I expanded EA to EffectiveAddress. No sense in abbreviating things
to death.

I've now implemented 26 instructions. But the new ones are just all the
stupid from/to ccr/sr instructions.

Ryphecha confirmed that you can't set the undefined bits, so I don't
think the BitField concept is appropriate for the CCR/SR. Instead, I'm
just storing direct flags and have (read,write)(CCR,SR) instead. This
isn't like the 65816 where you have subroutines that push and pop the
flag register. It's much more common to access individual flags. Doesn't
match the consistency angle of the other CPU cores, but ... I think this
is the right thing to for the 68K specifically.
2016-07-23 12:32:35 +10:00
Tim Allen 4b897ba791 Update to v100r10 release.
byuu says:

Redesigned the handling of reading/writing registers to be about eight
times faster than the old system. More work may be needed ... it seems
data registers tend to preserve their upper bits upon assignment; whereas
address registers tend to sign-extend values into them. It may make
sense to have DataRegister and AddressRegister classes with separate
read/write handlers. I'd have to hold two Register objects inside the
EffectiveAddress (EA) class if we do that.

Implemented 19 opcodes now (out of somewhere between 60 and 90.) That gets
the first ~530,000 instructions in Sonic the Hedgehog running (though
probably wrong. But we can run a lot thanks to large initialization
loops.)

If I force the core to loop back to the reset vector on an invalid opcode,
I'm getting about 1500fps with a dumb 320x240 blit 60 times a second and
just the 68K running alone (no Z80, PSG, VDP, YM2612.) I don't know if
that's good or not. I guess we'll find out.

I had to stop tonight because the final opcode I execute is an RTS
(return from subroutine) that's branching back to address 0; which is
invalid ... meaning something went terribly wrong and the system crashed.
2016-07-22 22:03:25 +10:00
Tim Allen be3f6ac0d5 Update to v100r09 release.
byuu says:

Another six hours in ...

I have all of the opcodes, memory access functions, disassembler mnemonics
and table building converted over to the new template<uint Size> format.

Certainly, it would be quite easy for this nightmare chip to throw me
another curveball, but so far I can handle:

- MOVE (EA to, EA from) case
  - read(from) has to update register index for +/-(aN) mode
- MOVEM (EA from) case
  - when using +/-(aN), RA can't actually be updated until the transfer
    is completed
- LEA (EA from) case
  - doesn't actually perform the final read; just returns the address
    to be read from
- ANDI (EA from-and-to) case
  - same EA has to be read from and written to
  - for -(aN), the read has to come from aN-2, but can't update aN yet;
    so that the write also goes to aN-2
- no opcode can ever fetch the extension words more than once
- manually control the order of extension word fetching order for proper
  opcode decoding

To do all of that without a whole lot of duplicated code (or really
bloating out every single instruction with red tape), I had to bring
back the "bool valid / uint32 address" variables inside the EA struct =(

If weird exceptions creep in like timing constraints only on certain
opcodes, I can use template flags to the EA read/write functions to
handle that.
2016-07-19 19:12:05 +10:00
Tim Allen 92fe5b0813 Update to v100r08 release.
byuu says:

Six and a half hours this time ... one new opcode, and all old opcodes
now in a deprecated format. Hooray, progress!

For building the table, I've decided to move from:

    for(uint opcode : range(65536)) {
      if(match(...)) bind(opNAME, ...);
    }

To instead having separate for loops for each supported opcode. This
lets me specialize parts I want with templates.

And to this aim, I'm moving to replace all of the
(read,write)(size, ...) functions with (read,write)<Size>(...) functions.

This will amount to the ~70ish instructions being triplicated ot ~210ish
instructions; but I think this is really important.

When I was getting into flag calculations, a ton of conditionals
were needed to mask sizes to byte/word/long. There was also lots of
conditionals in all the memory access handlers.

The template code is ugly, but we eliminate a huge amount of branch
conditions this way.
2016-07-18 08:11:29 +10:00
Tim Allen 059347e575 Update to v100r07 release.
byuu says:

Four and a half hours of work and ... zero new opcodes implemented.

This was the best job I could do refining the effective address
computations. Should have all twelve 68000 modes implemented now. Still
have a billion questions about when and how I'm supposed to perform
certain edge case operations, though.
2016-07-17 13:24:28 +10:00
Tim Allen 0d6a09f9f8 Update to v100r06 release.
byuu says:

Up to ten 68K instructions out of somewhere between 61 and 88, depending
upon which PDF you look at. Of course, some of them aren't 100% completed
yet, either. Lots of craziness with MOVEM, and BCC has a BSR variant
that needs stack push/pop functions.

This WIP actually took over eight hours to make, going through every
possible permutation on how to design the core itself. The updated design
now builds both the instruction decoder+dispatcher and the disassembler
decoder into the same main loop during M68K's constructor.

The special cases are also really psychotic on this processor, and
I'm afraid of missing something via the fallthrough cases. So instead,
I'm ordering the instructions alphabetically, and including exclusion
cases to ignore binding invalid cases. If I end up remapping an existing
register, then it'll throw a run-time assertion at program startup.

I wanted very much to get rid of struct EA (EffectiveAddress), but
it's too difficult to keep track of the internal effective address
without it. So I split out the size to a separate parameter, since
every opcode only has one size parameter, and otherwise it was getting
duplicated in opcodes that take two EAs, and was also awkward with the
flag testing. It's a bit more typing, but I feel it's more clean this way.

Overall, I'm really worried this is going to be too slow. I don't want
to turn the EA stuff into templates, because that will massively bloat
out compilation times and object sizes, and will also need a special DSL
preprocessor since C++ doesn't have a static for loop. I can definitely
optimize a lot of EA's address/read/write functions away once the core
is completed, but it's never going to hold a candle to a templatized
68K core.

----

Forgot to include the SA-1 regression fix. I always remember immediately
after I upload and archive the WIP. Will try to get that in next time,
I guess.
2016-07-16 18:39:44 +10:00
Tim Allen b72f35a13e Update to v100r05 release.
byuu says:

Alright, I'm definitely going to need to find some people willing to
tolerate my questions on this chip, so I'm going to go ahead and announce
I'm working on this I guess.

This core is way too big for a surprise like the NES and WS cores
were. It'll probably even span multiple v10x releases before it's
even ready.
2016-07-13 08:47:04 +10:00
Tim Allen 1c0ef793fe Update to v100r04 release.
byuu says:

I now have enough of three instructions implemented to get through the
first four instructions in Sonic the Hedgehog.

But they're far from complete. The very first instruction uses EA
addressing, which is similar to x86's ModRM in terms of how disgustingly
complex it is. And it also accesses Z80 control registers, which obviously
isn't going to do anything yet.

The slow speed was me being stupid again. It's not 7.6MHz per frame,
it's 7.67MHz per second. So yeah, speed is so far acceptable again. But
we'll see how things go as I keep emulating more. The 68K decode is not
pretty at all.
2016-07-12 20:19:31 +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 3dd1aa9c1b Update to v100r02 release.
byuu says:

Sigh ... I'm really not a good person. I'm inherently selfish.

My responsibility and obligation right now is to work on loki, and
then on the Tengai Makyou Zero translation, and then on improving the
Famicom emulation.

And yet ... it's not what I really want to do. That shouldn't matter;
I should work on my responsibilities first.

Instead, I'm going to be a greedy, self-centered asshole, and work on
what I really want to instead.

I'm really sorry, guys. I'm sure this will make a few people happy,
and probably upset even more people.

I'm also making zero guarantees that this ever gets finished. As always,
I wish I could keep these things secret, so if I fail / give up, I could
just drop it with no shame. But I would have to cut everyone out of the
WIP process completely to make it happen. So, here goes ...

This WIP adds the initial skeleton for Sega Mega Drive / Genesis
emulation. God help us.

(minor note: apparently the new extension for Mega Drive games is .md,
neat. That's what I chose for the folders too. I thought it was .smd,
so that'll be fixed in icarus for the next WIP.)

(aside: this is why I wanted to get v100 out. I didn't want this code in
a skeleton state in v100's source. Nor did I want really broken emulation,
which the first release is sure to be, tarring said release.)

...

So, basically, I've been ruminating on the legacy I want to leave behind
with higan. 3D systems are just plain out. I'm never going to support
them. They're too complex for my abilities, and they would run too slowly
with my design style. I'm not willing to compromise my design ideals. And
I would never want to play a 3D game system at native 240p/480i resolution
... but 1080p+ upscaling is not accurate, so that's a conflict I want
to avoid entirely. It's also never going to emulate computer systems
(X68K, PC-98, FM-Towns, etc) because holy shit that would completely
destroy me. It's also never going emulate arcade machines.

So I think of higan as a collection of 2D emulators for consoles
and handhelds. I've gone over every major 2D gaming system there is,
looking for ones with games I actually care about and enjoy. And I
basically have five of those systems supported already. Looking at the
remaining list, I see only three systems left that I have any interest
in whatsoever: PC-Engine, Master System, Mega Drive. Again, I'm not in
any way committing to emulating any of these, but ... if I had all of
those in higan, I think I'd be content to really, truly, finally stop
writing more emulators for the rest of my life.

And so I decided to tackle the most difficult system first. If I'm
successful, the Z80 core should cover a lot of the work on the SMS. And
the HuC6280 should land somewhere between the NES and SNES in terms of
difficulty ... closer to the NES.

The systems that just don't appeal to me at all, which I will never touch,
include, but are not limited to:
* Atari 2600/5200/7800
* Lynx
* Jaguar
* Vectrex
* Colecovision
* Commodore 64
* Neo-Geo
* Neo-Geo Pocket / Color
* Virtual Boy
* Super A'can
* 32X
* CD-i
* etc, etc, etc.

And really, even if something were mildly interesting in there ... we
have to stop. I can't scale infinitely. I'm already way past my limit,
but I'm doing this anyway. Too many cores bloats everything and kills
quality on everything. I don't want higan to become MESS v2.

I don't know what I'll do about the Famicom Disk System, PC-Engine CD,
and Mega CD. I don't think I'll be able to achieve 60fps emulating the
Mega CD, even if I tried to.

I don't know what's going to happen here with even the Mega Drive. Maybe
I'll get driven crazy with the documentation and quit. Maybe it'll end
up being too complicated and I'll quit. Maybe the emulation will end up
way too slow and I'll give up. Maybe it'll take me seven years to get
any games playable at all. Maybe Steve Snake, AamirM and Mike Pavone
will pool money to hire a hitman to come after me. Who knows.

But this is what I want to do, so ... here goes nothing.
2016-07-09 14:21:37 +10:00
Tim Allen 88c79e56a0 Update to v100r01 release.
[This version, with the internal version number changed back to "v100",
replaced the original v100 source archive on byuu.org soon after v100's
release, because it fixes important bugs in that version. --Ed]

byuu says:

Changelog:
- fixed default paths for Sufami Turbo slotted games
- moved WonderSwan orientation controls to the port rather than the device
  - I do like hex_usr's idea here; but that'll need more consideration;
    so this is a temporary fix
- added new debugger interface (see the public topic for more on that)
2016-07-08 22:31:35 +10:00
Tim Allen 07995c05a5 Update to v100 release.
byuu says:

higan has finally reached v100!

I feel it's important to stress right away that this is not "version
1.00", nor is it a major milestone release. Rather than arbitrary version
numbers, all of my software simply bumps version numbers by one for each
official release. As such, higan v100 is simply higan's 100th release.

That said, the primary focus of this release has been code
clean-ups. These are always somewhat dangerous in that regressions are
possible. We've tested through sixteen WIP revisions, one of which was
open to the public, to try and minimize any regressions. But all the same,
please report any regressions if you discover any.

Changelog (since v099):
FC: render during pixels 1-256 instead of 0-255 [hex_usr]
FC: rewrote controller emulation code
SFC: 8% speedup over the previous release thanks to PPU optimizations
SFC: fixed nasty DB address wrapping regression from v099
SFC: USART developer controller removed; superseded by 21fx
SFC: Super Multitap option removed from controller port 1; ports
    renamed 2-5
SFC: hidden option to experiment with 128KB VRAM (strictly for novelty)
higan: audio volume no longer divided by number of audio streams
higan: updated controller polling code to fix possible future mapping
    issues
higan: replaced nall/stream with nall/vfs for file-loading subsystem
tomoko: can now load multi-slotted games via command-line
tomoko: synchronize video removed from UI; still available in the
    settings file
tomoko, icarus: can navigate to root drive selection on Windows
all: major code cleanups and refactoring (~1MB diff against v099)

Note 1: the audio volume change means that SGB and MSU1 games won't
lose half the volume on the SNES sounds anymore. However, if one goes
overboard and drives the sound all the way to max volume with the MSU1,
clamping may occur. The obvious solution is not to drive volume that high
(it will vastly overpower the SNES audio, which usually never exceeds
25% volume.) Another option is to lower the volume in the audio settings
panel to 50%. In general, neither is likely to ever be necessary.

Note 2: the synchronize video option was hidden from the UI because it
is no longer useful. With the advent of compositors, the loss of the
complicated timing settings panel, support for the WonderSwan and its
75hz display, the need to emulate variable refresh rate behaviors in the
Game Boy, the unfortunate latency spike and audio distortion caused by
long Vsync pauses, and the arrival of adaptive sync technology ... it
no longer makes sense to present this option. However, as stated, you
can edit settings.bml to enable this option anyway if you insist and
understand the aforementioned risks.

Changelog (since v099r16 open beta):

- fixed MSU1 audio sign extension
- fixed compilation with SGB support disabled
- icarus can now navigate to root directory
- fixed compilation issues with OS X port
- (hopefully) fixed label height issue with hiro that affected icarus
  import dialog
- (mostly) fixed BS Memory, Sufami Turbo slot loading

Errata:

- forgot to remove the " - Slot A", " - Slot B" suffixes for Sufami
  Turbo slot loading
  - this means you have to navigate up one folder and then into Sufami
    Turbo/ to load games for this system
- moving WonderSwan orientation controls to the device slot is causing
  some nastiness
  - can now select orientation from the main menu, but it doesn't rotate
    the display
2016-07-08 22:04:59 +10:00
Tim Allen 13ad9644a2 Update to v099r16 release (public beta).
byuu says:

Changelog:
- hiro: BrowserDialog can navigate up to drive selection on Windows
- nall: (file,path,dir,base,prefix,suffix)name =>
  Location::(file,path,dir,base,prefix,suffix)
- higan/tomoko: rename audio filter label from "Sinc" to "IIR - Biquad"
- higan/tomoko: allow loading files via icarus on the command-line
  once again
- higan/tomoko: (begrudging) quick hack to fix presentation window focus
  on startup
- higan/audio: don't divide output audio volume by number of streams
- processor/r65816: fix a regression in (read,write)DB; fixes Taz-Mania
- fixed compilation regressions on Windows and Linux

I'm happy with where we are at with code cleanups and stability, so I'd
like to release v100. But even though I'm not assigning any special
significance to this version, we should probably test it more thoroughly
first.
2016-07-04 21:53:24 +10:00
Tim Allen 8d5cc0c35e Update to v099r15 release.
byuu says:

Changelog:
- nall::lstring -> nall::string_vector
- added IntegerBitField<type, lo, hi> -- hopefully it works correctly...
- Multitap 1-4 -> Super Multitap 2-5
- fixed SFC PPU CGRAM read regression
- huge amounts of SFC PPU IO register cleanups -- .bits really is lovely
- re-added the read/write(VRAM,OAM,CGRAM) helpers for the SFC PPU
  - but they're now optimized to the realities of the PPU (16-bit data
    sizes / no address parameter / where appropriate)
  - basically used to get the active-display overrides in a unified place;
    but also reduces duplicate code in (read,write)IO
2016-07-04 21:48:17 +10:00
Tim Allen 82293c95ae Update to v099r14 release.
byuu says:

Changelog:
- (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel
  like they were contributing enough to be worth it]
- cleaned up nall::integer,natural,real functionality
  - toInteger, toNatural, toReal for parsing strings to numbers
  - fromInteger, fromNatural, fromReal for creating strings from numbers
  - (string,Markup::Node,SQL-based-classes)::(integer,natural,real)
    left unchanged
  - template<typename T> numeral(T value, long padding, char padchar)
    -> string for print() formatting
    - deduces integer,natural,real based on T ... cast the value if you
      want to override
    - there still exists binary,octal,hex,pointer for explicit print()
      formatting
- lstring -> string_vector [but using lstring = string_vector; is
  declared]
  - would be nice to remove the using lstring eventually ... but that'd
    probably require 10,000 lines of changes >_>
- format -> string_format [no using here; format was too ambiguous]
- using integer = Integer<sizeof(int)*8>; and using natural =
  Natural<sizeof(uint)*8>; declared
  - for consistency with boolean. These three are meant for creating
    zero-initialized values implicitly (various uses)
- R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees
  up struct IO {} io; naming]
- SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {}
  (status,registers); now
  - still some CPU::Status status values ... they didn't really fit into
    IO functionality ... will have to think about this more
- SFC CPU, PPU, SMP now use step() exclusively instead of addClocks()
  calling into step()
- SFC CPU joypad1_bits, joypad2_bits were unused; killed them
- SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it
- SFC PPU OAM moved into PPU::Object; since nothing else uses it
  - the raw uint8[544] array is gone. OAM::read() constructs values from
    the OAM::Object[512] table now
  - this avoids having to determine how we want to sub-divide the two
    OAM memory sections
  - this also eliminates the OAM::synchronize() functionality
- probably more I'm forgetting

The FPS fluctuations are driving me insane. This WIP went from 128fps to
137fps. Settled on 133.5fps for the final build. But nothing I changed
should have affected performance at all. This level of fluctuation makes
it damn near impossible to know whether I'm speeding things up or slowing
things down with changes.
2016-07-01 21:50:32 +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 7a68059f78 Update to v099r12 release.
byuu says:

Changelog:
- fixed FC AxROM / VRC7 regression
- BitField split to BooleanBitField/NaturalBitField (in preparation
  for IntegerBitField)
- BitFieldReference removed
- GB CPU cleaned up
- GB Cartridge + Mappers cleaned up
- SFC CGRAM is now emulated as uint15[256] instead of uint[512]
- sfc/ppu/memory.cpp no longer needed; removed
- purged SFC Debugger hooks for now (some of the operator[] calls were
  bypassing them anyway)

Unfortunately, for reasons that defy all semblance of logic, the CGRAM
change caused a slight speed hit. As have the last few changes. We're
now down to around 129.5fps compared to 123.fps for v099 and 134.5fps
at our peak (v099r01-r02).

I really like the style I came up with for the Game Boy mappers to settle
the purpose(ROM,RAM) vs (rom,ram)Purpose naming convention. If I ever get
around to redoing the NES mappers, that's likely the approach I'll take.
2016-06-28 20:43:47 +10:00
Tim Allen 3e807946b8 Update to v099r11 release.
byuu says:

Changelog:
- NES PPU core updated to use BitFields (absolutely massive improvement
  in code readability)
- NES APU core updated to new coding style
- NES cartridge/board and cartridge/chip updated to new coding style
- pushed NES PPU rendering one dot forward (doesn't fix King's Quest V
  yet, sadly)
- fixed SNES PPU BG tilemask for 128KiB VRAM mode (doesn't fix Yoshi's
  Island, though)

So ... I kind of went overboard with the fc/cartridge changes. This WIP
diff is 185KiB >_>
I didn't realize it was going to be as big a task as it was, but once
I started everything broke in a chain reaction, so I had to do it all
at once.

There's a massive chance we've broken a bunch of NES things. Any typos
in this WIP are going to be absolutely insidious to track down =(

But ... supposing I pulled it off, this means the Famicom core is now
fully converted to the new coding style as well. That leaves only the
GB and GBA cores. Once those are finished, then we'll finally be free
of these gigantic hellspawn diffs.
2016-06-27 23:07:57 +10:00
Tim Allen a816998122 Update to v099r10 release.
byuu says:

Changelog:
- higan/profile/ => higan/systems/ [temporary; unless we can't think of
  a better base folder name]
- god-damn-better-have fixed the input polling bug
- re-added command-line and drag-and-drop loading
  - command-line loading can now load multiple folders at once (SGB+GB
    game; Sufami Turbo+Slot A+Slot B; etc)
  - if you load just the base cart, it'll present you with a dialog to
    optionally load slotted cart(s)
- MSU1 now goes through nall/vfs instead of directly accessing the
  filesystem
- Famicom Cartridge, PPU cores updated to newer programming style
  - there's countless opportunity for BitField and .bits() in the PPU
    ... but I'm worried about breaking things

If anyone has a working MSU1 game and can test the changes out, that'd
be appreciated. I still don't have a test ROM on my dev box.

I wouldn't worry too much about extensively testing the Famicom PPU
changes just yet ... I'm still struggling with what to name the structs
inside the classes between all of my emulators, and the BitField/.bits()
changes will be much more important to test at a later date.

The only use case left for Emulator::Interface::path(uint id) is for
21fx emulation. This peripheral loads a DLL/SO via LoadLibrary/dlopen,
which do not have any official ways to open a file in RAM. I'm
very hesitant to use the portable trick of writing the memory to a
temporary file, loading it, and deleting the temporary file once done
... it's a real waste of disk activity. I might make something like
vfs::file::isVirtual->bool,path()->string to get around this. But even
once I do, the underlying LoadLibrary/dlopen call is still going to be
direct disk access.
2016-06-26 18:54:12 +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 875f031182 Update to v099r06 release.
byuu says:

Changelog:
- Super Famicom core converted to use nall/vfs
  - excludes Super Game Boy; since that's invoked from inside the GB core

This was definitely the major obstacle to test nall/vfs'
applicability. Things worked out pretty great in the end.

We went from 22.0KiB (cartridge) + 18.6KiB (interface) to 24.5KiB
(cartridge) + 11.4KiB (interface). Or 40.7KiB to 36.0KiB. This removes
a very large source of indirection. Before it was: "coprocessor <=>
cartridge <=> interface" for loading and saving data, and now it's just
"coprocessor <=> cartridge". And it may make sense to eventually turn
this into just "cartridge -> coprocessor" by making each coprocessor
class handle its own markup parsing.

It's nice to have all the manifest parsing in one location (well, sans
MSU1); but it's also nice for loading/unloading to be handled by each
coprocessor itself. So I'll have to think longer about that one.

I've also started handling Interface::save() differently. Instead of
keeping track of memory IDs and filenames, and iterating through that
vector of objects ... instead I now have a system that mirrors the markup
parsing on loading, but handles saving instead. This was actually the
reason the code size savings weren't more significant, but I like this
style more. As before, it removes an extra level of indirection.

So ... next up, I need to port over the GB, then GBA, then WS
cores. These shouldn't take too long since they're all very simple with
just ROM+RAM(+RTC) right now. Then get the SGB callbacks using vfs. Then
after that, gut all the old stream stuff from nall and higan. Kill the
(load,save)Request stuff, rename the load(Gamepak)Request to something
simpler, and then we should be good.

Anyway ... these are some huge changes.
2016-06-24 22:01:03 +10:00
Tim Allen f04d9d58f5 Update to v099r05 release.
byuu says:

Changelog:
- added nall/vfs
- converted Famicom core to use nall/vfs interface instead of nall/stream
  interface
2016-06-20 21:00:32 +10:00
Tim Allen 40abcfc4a5 Update to v099r04 release.
byuu says:

Changelog:
- lots of code cleanups to processor/r6502 (the switch.cpp file is only
  halfway done ...)
- lots of code cleanups to fc/cpu
- removed fc/input
- implemented fc/controller

hex_usr, you may not like this, but I want to keep the controller port
and expansion port interface separate, like I do with the SNES. I realize
the NES' is used more for controllers, and the SNES' more for hardware
expansions, but ... they're not compatible pinouts and you can't really
connect one to the other.

Right now, I've only implemented the controller portion. I'll have to
get to the peripheral portion later.

Also, the gamepad implementation there now may be wrong. It's based off
the Super Famicom version obviously. I'm not sure if the Famicom has
different behavior with latching $4016 writes, or not. But, it works in
Mega Man II, so it's a start.

Everyone, be sure to remap your controls, and then set port 1 -> gamepad
after loading your first Famicom game with the new WIP.
2016-06-18 16:04:32 +10:00
Tim Allen 44a8c5a2b4 Update to v099r03 release.
byuu says:

Changelog:
- finished cleaning up the SFC core to my new coding conventions
- removed sfc/controller/usart (superseded by 21fx)
- hid Synchronize Video option from the menu (still in the configuration
  file)

Pretty much the only minor detail left is some variable names in the
SA-1 core that really won't look good at all if I move to camelCase,
so I'll have to rethink how I handle those. It's probably a good area
to attempt using BitFields, to see how it impacts performance. But I'll
do that in a test branch first.

But for the most part, this should be the end of the gigantic diffs (this
one was 174KiB), at least for the SFC/WS cores. Still have the FC/GB/GBA
cores to clean up more fully. Assuming we don't spot any new regressions,
we should be ~95% out of the woods on code cleanups breaking things.
2016-06-17 23:03:54 +10:00
Tim Allen f1a80075fa Update to v099r02 release.
byuu says:

Changelog:
- renamed sfc/ppu/sprite (OAM oam;) to sfc/ppu/object (Object obj;) [hex_usr]
- renamed sfc/ppu's memory {vram, oam, cgram} to just vram, oam, cgram
- fixed addr&=~1 regression [hex_usr]
- fixed 8bpp tiledata regression [hex_usr]
2016-06-15 21:32:17 +10:00