2012-04-29 06:16:44 +00:00
|
|
|
#include <sfc/sfc.hpp>
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2012-04-26 10:51:13 +00:00
|
|
|
namespace SuperFamicom {
|
2010-08-09 13:28:56 +00:00
|
|
|
|
Update to v085r03 release.
byuu says:
Changelog:
- fixed cursor being visible under Metacity window manager (hopefully
doesn't cause regression with other WMs)
- show normal cursor when using SDL video driver
- added menu accelerators (meh, why not?)
- removed debugvirtual, ChipDebugger and chip/debugger functionality
entirely
- alt/smp disassembler moved up
- fixed alt/smp incw/decw instructions (unsigned->uint16 for internal
variables)
My plan going forward for a debugger is not to hardcode functionality
that causes the 10-15% slowdown right into the emulator itself.
Instead, I'm going to make a callback class, which will be a specialized
version of nall::function:
- can call function even if not assigned (results in no-op, return type
must have a trivial default constructor)
- if compiled without #define DEBUGGER, the entire thing turns into
a huge no-op; and will be eliminated entirely when compiled
- strategically place the functions: cb_step, cb_read, cb_write, etc.
From here, the ui-debugger GUI will bind the callbacks, implement
breakpoint checking, usage table generation, etc itself.
I'll probably have to add some breakout commands to exit the emulation
core prior to a frame event in some cases as well.
I didn't initially want any debugger-related stuff in the base cores,
but the #if debugger sCPUDebugger #else sCPU #endif stuff was already
more of a burden than this will be.
2012-02-04 09:23:53 +00:00
|
|
|
DSP dsp;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
#define REG(n) state.regs[n]
|
|
|
|
#define VREG(n) state.regs[v.vidx + n]
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
#include "gaussian.cpp"
|
|
|
|
#include "counter.cpp"
|
|
|
|
#include "envelope.cpp"
|
|
|
|
#include "brr.cpp"
|
|
|
|
#include "misc.cpp"
|
|
|
|
#include "voice.cpp"
|
|
|
|
#include "echo.cpp"
|
2016-01-23 07:29:34 +00:00
|
|
|
#include "serialization.cpp"
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
DSP::DSP() {
|
Update to v097r14 release.
byuu says:
This is a few days old, but oh well.
This WIP changes nall,hiro,ruby,icarus back to (u)int(8,16,32,64)_t.
I'm slowly pushing for (u)int(8,16,32,64) to use my custom
Integer<Size>/Natural<Size> classes instead. But it's going to be one
hell of a struggle to get that into higan.
2016-02-16 09:11:58 +00:00
|
|
|
static_assert(sizeof(int) >= 32 / 8, "int >= 32-bits");
|
|
|
|
static_assert((int8_t)0x80 == -0x80, "8-bit sign extension");
|
|
|
|
static_assert((int16_t)0x8000 == -0x8000, "16-bit sign extension");
|
|
|
|
static_assert((uint16_t)0xffff0000 == 0, "16-bit unsigned clip");
|
|
|
|
static_assert((-1 >> 1) == -1, "arithmetic shift right");
|
2015-10-10 02:16:12 +00:00
|
|
|
|
|
|
|
//-0x8000 <= n <= +0x7fff
|
|
|
|
assert(sclamp<16>(+0x8000) == +0x7fff);
|
|
|
|
assert(sclamp<16>(-0x8001) == -0x8000);
|
|
|
|
}
|
|
|
|
|
2010-08-09 13:28:56 +00:00
|
|
|
/* timing */
|
|
|
|
|
2016-02-09 11:51:12 +00:00
|
|
|
auto DSP::step(uint clocks) -> void {
|
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 03:56:12 +00:00
|
|
|
Thread::step(clocks);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2016-02-09 11:51:12 +00:00
|
|
|
auto DSP::Enter() -> void {
|
|
|
|
while(true) scheduler.synchronize(), dsp.main();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto DSP::main() -> void {
|
|
|
|
voice5(voice[0]);
|
|
|
|
voice2(voice[1]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice6(voice[0]);
|
|
|
|
voice3(voice[1]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice7(voice[0]);
|
|
|
|
voice4(voice[1]);
|
|
|
|
voice1(voice[3]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice8(voice[0]);
|
|
|
|
voice5(voice[1]);
|
|
|
|
voice2(voice[2]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice9(voice[0]);
|
|
|
|
voice6(voice[1]);
|
|
|
|
voice3(voice[2]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice7(voice[1]);
|
|
|
|
voice4(voice[2]);
|
|
|
|
voice1(voice[4]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice8(voice[1]);
|
|
|
|
voice5(voice[2]);
|
|
|
|
voice2(voice[3]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice9(voice[1]);
|
|
|
|
voice6(voice[2]);
|
|
|
|
voice3(voice[3]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice7(voice[2]);
|
|
|
|
voice4(voice[3]);
|
|
|
|
voice1(voice[5]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice8(voice[2]);
|
|
|
|
voice5(voice[3]);
|
|
|
|
voice2(voice[4]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice9(voice[2]);
|
|
|
|
voice6(voice[3]);
|
|
|
|
voice3(voice[4]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice7(voice[3]);
|
|
|
|
voice4(voice[4]);
|
|
|
|
voice1(voice[6]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice8(voice[3]);
|
|
|
|
voice5(voice[4]);
|
|
|
|
voice2(voice[5]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice9(voice[3]);
|
|
|
|
voice6(voice[4]);
|
|
|
|
voice3(voice[5]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice7(voice[4]);
|
|
|
|
voice4(voice[5]);
|
|
|
|
voice1(voice[7]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice8(voice[4]);
|
|
|
|
voice5(voice[5]);
|
|
|
|
voice2(voice[6]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice9(voice[4]);
|
|
|
|
voice6(voice[5]);
|
|
|
|
voice3(voice[6]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice1(voice[0]);
|
|
|
|
voice7(voice[5]);
|
|
|
|
voice4(voice[6]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice8(voice[5]);
|
|
|
|
voice5(voice[6]);
|
|
|
|
voice2(voice[7]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice9(voice[5]);
|
|
|
|
voice6(voice[6]);
|
|
|
|
voice3(voice[7]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice1(voice[1]);
|
|
|
|
voice7(voice[6]);
|
|
|
|
voice4(voice[7]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice8(voice[6]);
|
|
|
|
voice5(voice[7]);
|
|
|
|
voice2(voice[0]);
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice3a(voice[0]);
|
|
|
|
voice9(voice[6]);
|
|
|
|
voice6(voice[7]);
|
|
|
|
echo22();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice7(voice[7]);
|
|
|
|
echo23();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice8(voice[7]);
|
|
|
|
echo24();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice3b(voice[0]);
|
|
|
|
voice9(voice[7]);
|
|
|
|
echo25();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
echo26();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
misc27();
|
|
|
|
echo27();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
misc28();
|
|
|
|
echo28();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
misc29();
|
|
|
|
echo29();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
misc30();
|
|
|
|
voice3c(voice[0]);
|
|
|
|
echo30();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
voice4(voice[0]);
|
|
|
|
voice1(voice[2]);
|
|
|
|
tick();
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::tick() -> void {
|
2010-08-09 13:28:56 +00:00
|
|
|
step(3 * 8);
|
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 03:56:12 +00:00
|
|
|
synchronize(smp);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* register interface for S-SMP $00f2,$00f3 */
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::mute() const -> bool {
|
|
|
|
return REG(FLG) & 0x40;
|
2012-05-29 12:20:46 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::read(uint8 addr) -> uint8 {
|
|
|
|
return REG(addr);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::write(uint8 addr, uint8 data) -> void {
|
|
|
|
REG(addr) = data;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
if((addr & 0x0f) == ENVX) {
|
|
|
|
state.envxBuffer = data;
|
|
|
|
} else if((addr & 0x0f) == OUTX) {
|
|
|
|
state.outxBuffer = data;
|
|
|
|
} else if(addr == KON) {
|
|
|
|
state.konBuffer = data;
|
|
|
|
} else if(addr == ENDX) {
|
2010-08-09 13:28:56 +00:00
|
|
|
//always cleared, regardless of data written
|
2015-10-10 02:16:12 +00:00
|
|
|
state.endxBuffer = 0;
|
|
|
|
REG(ENDX) = 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialization */
|
|
|
|
|
2016-06-25 08:53:11 +00:00
|
|
|
auto DSP::load(Markup::Node node) -> bool {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::power() -> void {
|
2017-06-30 04:17:23 +00:00
|
|
|
create(Enter, system.apuFrequency());
|
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-08 20:20:40 +00:00
|
|
|
stream = Emulator::audio.createStream(2, frequency() / 768.0);
|
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-22 21:04:26 +00:00
|
|
|
|
2017-08-24 14:24:34 +00:00
|
|
|
random.array(apuram, sizeof(apuram));
|
Update to v103r05 release.
byuu says:
Changelog:
- fc/controller: added ControllerPort class; removed Peripherals class
- md/controller/gamepad: removed X,Y,Z buttons since this isn't a
6-button controller
- ms/controller: added ControllerPort class (not used in Game Gear
mode); removed Peripherals class
- pce/controller: added ControllerPort class; removed Peripherals
class
- processor/spc700: idle(address) is part of SMP class again, contains
flag to detect mov (x)+ edge case
- sfc/controller/super-scope,justifier: use CPU frequency instead of
hard-coding NTSC frequency
- sfc/cpu: move 4x8-bit SMP ports to SMP class
- sfc/smp: move APU RAM to DSP class
- sfc/smp: improved emulation of TEST registers bits 4-7 [information
from nocash]
- d4,d5 is RAM wait states (1,2,5,10)
- d6,d7 is ROM/IO wait states (1,2,5,10)
- sfc/smp: code cleanup to new style (order from lowest to highest
bits; use .bit(s) functions)
- sfc/smp: $00f8,$00f9 are P4/P5 auxiliary ports; named the registers
better
2017-07-01 06:15:27 +00:00
|
|
|
|
Update to v098r04 release.
byuu says:
Changelog:
- SFC: fixed behavior of 21fx $21fe register when no device is connected
(must return zero)
- SFC: reduced 21fx buffer size to 1024 bytes in both directions to
mirror the FT232H we are using
- SFC: eliminated dsp/modulo-array.hpp [1]
- higan: implemented higan/video interface and migrated all cores to it
[2]
[1] the echo history buffer was 8-bytes, so there was no need for it at
all here. Not sure what I was thinking. The BRR buffer was 12-bytes, and
has very weird behavior ... but there's only a single location in the
code where it actually writes to this buffer. It's much easier to just
write to the buffer three times there instead of implementing an entire
class just to abstract away two lines of code. This change actually
boosted the speed from ~124.5fps to around ~127.5fps, but that's within
the margin of error for GCC. I doubt it's actually faster this way.
The DSP core could really use a ton of work. It comes from a port of
blargg's spc_dsp to my coding style, but he was extremely fond of using
32-bit signed integers everywhere. There's a lot of opportunity to
remove red tape masking by resizing the variables to their actual state
sizes.
I really need to find where I put spc_dsp6.sfc from blargg. It's a great
test to verify if I've made any mistakes in my implementation that would
cause regressions. Don't suppose anyone has it?
[2] so again, the idea is that higan/audio and higan/video are going to
sit between the emulation cores and the user interfaces. The hope is to
output raw encoding data from the emulation cores without having to
worry about the video display format (generally 24-bit RGB) of the host
display. And also to avoid having to repeat myself with eg three
separate implementations of interframe blending, and so on.
Furthermore, the idea is that the user interface can configure its side
of the settings, and the emulation cores can configure their sides.
Thus, neither has to worry about the other end. And now we can spin off
new user interfaces much easier without having to mess with all of these
things.
Right now, I've implemented color emulation, interframe blending and
SNES horizontal color bleed. I did not implement scanlines (and
interlace effects for them) yet, but I probably will at some point.
Further, for right now, the WonderSwan/Color screen rotation is busted
and will only show games in the horizontal orientation. Obviously this
must be fixed before the next official release, but I'll want to think
about how to implement it.
Also, the SNES light gun pointers are missing for now.
Things are a bit messy right now as I've gone through several revisions
of how to handle these things, so a good house cleaning is in order once
everything is feature-complete again. I need to sit down and think
through how and where I want to handle things like light gun cursors,
LCD icons, and maybe even rasterized text messages.
And obviously ... higan/audio is still just nall::DSP's headers. I need
to revamp that whole interface. I want to make it quite powerful with
a true audio mixer so I can handle things like
SNES+SGB+MSU1+Voicer-Kun+SNES-CD (five separate audio streams at once.)
The video system has the concept of "effects" for things like color
bleed and interframe blending. I want to extend on this with useful
other effects, such as NTSC simulation, maybe bringing back my mini-HQ2x
filter, etc. I'd also like to restore the saturation/gamma/luma
adjustment sliders ... I always liked allowing people to compensate for
their displays without having to change settings system-wide. Lastly,
I've always wanted to see some audio effects. Although I doubt we'll
ever get my dream of CoreAudio-style profiles, I'd like to get some
basic equalizer settings and echo/reverb effects in there.
2016-04-11 21:29:56 +00:00
|
|
|
memory::fill(&state, sizeof(State));
|
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-22 21:04:26 +00:00
|
|
|
state.noise = 0x4000;
|
|
|
|
state.echoHistoryOffset = 0;
|
|
|
|
state.everyOtherSample = 1;
|
|
|
|
state.echoOffset = 0;
|
|
|
|
state.counter = 0;
|
2015-10-10 02:16:12 +00:00
|
|
|
|
|
|
|
for(auto n : range(8)) {
|
Update to v098r04 release.
byuu says:
Changelog:
- SFC: fixed behavior of 21fx $21fe register when no device is connected
(must return zero)
- SFC: reduced 21fx buffer size to 1024 bytes in both directions to
mirror the FT232H we are using
- SFC: eliminated dsp/modulo-array.hpp [1]
- higan: implemented higan/video interface and migrated all cores to it
[2]
[1] the echo history buffer was 8-bytes, so there was no need for it at
all here. Not sure what I was thinking. The BRR buffer was 12-bytes, and
has very weird behavior ... but there's only a single location in the
code where it actually writes to this buffer. It's much easier to just
write to the buffer three times there instead of implementing an entire
class just to abstract away two lines of code. This change actually
boosted the speed from ~124.5fps to around ~127.5fps, but that's within
the margin of error for GCC. I doubt it's actually faster this way.
The DSP core could really use a ton of work. It comes from a port of
blargg's spc_dsp to my coding style, but he was extremely fond of using
32-bit signed integers everywhere. There's a lot of opportunity to
remove red tape masking by resizing the variables to their actual state
sizes.
I really need to find where I put spc_dsp6.sfc from blargg. It's a great
test to verify if I've made any mistakes in my implementation that would
cause regressions. Don't suppose anyone has it?
[2] so again, the idea is that higan/audio and higan/video are going to
sit between the emulation cores and the user interfaces. The hope is to
output raw encoding data from the emulation cores without having to
worry about the video display format (generally 24-bit RGB) of the host
display. And also to avoid having to repeat myself with eg three
separate implementations of interframe blending, and so on.
Furthermore, the idea is that the user interface can configure its side
of the settings, and the emulation cores can configure their sides.
Thus, neither has to worry about the other end. And now we can spin off
new user interfaces much easier without having to mess with all of these
things.
Right now, I've implemented color emulation, interframe blending and
SNES horizontal color bleed. I did not implement scanlines (and
interlace effects for them) yet, but I probably will at some point.
Further, for right now, the WonderSwan/Color screen rotation is busted
and will only show games in the horizontal orientation. Obviously this
must be fixed before the next official release, but I'll want to think
about how to implement it.
Also, the SNES light gun pointers are missing for now.
Things are a bit messy right now as I've gone through several revisions
of how to handle these things, so a good house cleaning is in order once
everything is feature-complete again. I need to sit down and think
through how and where I want to handle things like light gun cursors,
LCD icons, and maybe even rasterized text messages.
And obviously ... higan/audio is still just nall::DSP's headers. I need
to revamp that whole interface. I want to make it quite powerful with
a true audio mixer so I can handle things like
SNES+SGB+MSU1+Voicer-Kun+SNES-CD (five separate audio streams at once.)
The video system has the concept of "effects" for things like color
bleed and interframe blending. I want to extend on this with useful
other effects, such as NTSC simulation, maybe bringing back my mini-HQ2x
filter, etc. I'd also like to restore the saturation/gamma/luma
adjustment sliders ... I always liked allowing people to compensate for
their displays without having to change settings system-wide. Lastly,
I've always wanted to see some audio effects. Although I doubt we'll
ever get my dream of CoreAudio-style profiles, I'd like to get some
basic equalizer settings and echo/reverb effects in there.
2016-04-11 21:29:56 +00:00
|
|
|
memory::fill(&voice[n], sizeof(Voice));
|
2015-10-10 02:16:12 +00:00
|
|
|
voice[n].brrOffset = 1;
|
|
|
|
voice[n].vbit = 1 << n;
|
|
|
|
voice[n].vidx = n * 0x10;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
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 02:07:54 +00:00
|
|
|
//note: memory is pseudo-random at startup; but internal state is less so
|
|
|
|
//exact differences are unknown. need to separate memory from internal state
|
|
|
|
for(auto r : range(0x80)) REG(r) = 0x00;
|
2015-10-10 02:16:12 +00:00
|
|
|
REG(FLG) = 0xe0;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
Update to v085r03 release.
byuu says:
Changelog:
- fixed cursor being visible under Metacity window manager (hopefully
doesn't cause regression with other WMs)
- show normal cursor when using SDL video driver
- added menu accelerators (meh, why not?)
- removed debugvirtual, ChipDebugger and chip/debugger functionality
entirely
- alt/smp disassembler moved up
- fixed alt/smp incw/decw instructions (unsigned->uint16 for internal
variables)
My plan going forward for a debugger is not to hardcode functionality
that causes the 10-15% slowdown right into the emulator itself.
Instead, I'm going to make a callback class, which will be a specialized
version of nall::function:
- can call function even if not assigned (results in no-op, return type
must have a trivial default constructor)
- if compiled without #define DEBUGGER, the entire thing turns into
a huge no-op; and will be eliminated entirely when compiled
- strategically place the functions: cb_step, cb_read, cb_write, etc.
From here, the ui-debugger GUI will bind the callbacks, implement
breakpoint checking, usage table generation, etc itself.
I'll probably have to add some breakout commands to exit the emulation
core prior to a frame event in some cases as well.
I didn't initially want any debugger-related stuff in the base cores,
but the #if debugger sCPUDebugger #else sCPU #endif stuff was already
more of a burden than this will be.
2012-02-04 09:23:53 +00:00
|
|
|
#undef REG
|
|
|
|
#undef VREG
|
|
|
|
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|