I'm trying to extract the memory/bus interface, and pass it in at
the start of each cycle instead of having the BusPort permanently
embedded, which will allow migrating to emulator-hal.
The functional way would be argument drilling; passing an extra argument
to each function in the entire execution core. The problem is that it's
messy, so a solution that is still functional is to implement all of the
execution logic on a newtype that contains a reference to the mutable
state and the owned cycle data, and at the end of the cycle, decompose
the M68kCycleGuard that holds the reference, and keep the cycle data for
debugging purposes.
The debug loop that reads a command and does something is part of the
frontend's main loop, so that it can potentially update, even though
it doesn't actually work for minifb because the command input is a
blocking call. It's also not implemented in the pixels frontend.
At some point I'll make a web frontend.
Now it's up to 99% tests passing, 15362 are still failing, but many
of those are the unimplemented IN/OUT instructions, which the Genesis
doesn't seem to use
Special thanks to raddad772 https://github.com/raddad772
Also added some fixes to the Z80 for panicking math operations, but
it still won't complete due to an unimplemented instruction
It now actually checks the clock and tries to mix the audio in sync
relative to the clock, but the cpal output doesn't yet try to sync
to the StreamInstant time. Sound seems a lot better on chrome in
wasm, but and kind of better on firefox despite frame skipping not
being supported yet, but it's way slower for some reason (12fps)
- The envelope generator wasn't working as it should have, minor issues
with the limits and whether to use 10-bit or 12-bit values (more to come)
- fixed issues with sustain level where it was always set to 0
- fixed release rate and levels to make them 5-bit and 10-bit numbers
respectively, so they match the others
- switched from SineWave to SquareWave and this alone made it go from
terrible and muddy to not that far off. I probably need to completely
change the output
- also included an attempt at removing HostData, still needed for an
interrupt that is triggered by user input
The hope was that this would reduce the amount of copying and bit
shifting required by the frontend to get the data on screen, but
it doesn't seem to offer much advantage, surprisingly. I'll leave
it in though. There are a few other minor tweaks included here to
try to improve the performance a bit
If the sim is running slower than 60Hz, it was using the frame limiter
to not apply because no frame was drawn, and so it would end up running
at full speed. Minifb can save the last frame without cloning it, and
redraw the same frame if no new frame is ready, which allows the limiter
to still delay the next frame, so slower speeds work. This was also
preventing things that didn't update the screen from allowing inputs
including escape to have any effect
AddressRepeater now takes the range it should repeat over, which only
really affects its reported size.
AddressAdapter is now AddressRightShifter, which is literally the operation
it performs, where the input is still the bits to shift the address right by
It turns out to not be too much of a performance issue to allocate
a new frame each time one is produced, so to reduce lock contention
I added a queue where frames are added to and taken from without
locking the frame for the whole update. I'm hoping this will give
more flexibility to frontend implementations, which can simply
skip or repeat frames if needed.
Mortal Kombat 2 was working but somewhere while getting the harte
tests to work, I fixed interrupts to change the flags before they're
pushed to the stack, in order to match the expected behaviour from
the tests when an address error occurs (sr is changed and the stack
push causes the error). I correctly saved the state of sr in the
function for group0 interrupts, to push to the stack later, but the
normal interrupts was saving sr *after* the flags were changed...
Now it saves sr beforehand
I also included some changes to the gfx interface to allow taking
frames, to fix a compile error introduced by the last commit.