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;
|
Update to v097r02 release.
byuu says:
Note: balanced/performance profiles still broken, sorry.
Changelog:
- added nall/GNUmakefile unique() function; used on linking phase of
higan
- added nall/unique_pointer
- target-tomoko and {System}::Video updated to use
unique_pointer<ClassName> instead of ClassName* [1]
- locate() updated to search multiple paths [2]
- GB: pass gekkio's if_ie_registers and boot_hwio-G test ROMs
- FC, GB, GBA: merge video/ into the PPU cores
- ruby: fixed ~AudioXAudio2() typo
[1] I expected this to cause new crashes on exit due to changing the
order of destruction of objects (and deleting things that weren't
deleted before), but ... so far, so good. I guess we'll see what crops
up, especially on OS X (which is already crashing for unknown reasons on
exit.)
[2] right now, the search paths are: programpath(), {configpath(),
"higan/"}, {localpath(), "higan/"}; but we can add as many more as we
want, and we can also add platform-specific versions.
2016-01-25 11:27:18 +00:00
|
|
|
#include "audio.cpp"
|
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 {
|
2010-08-09 13:28:56 +00:00
|
|
|
clock += clocks;
|
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::synchronizeSMP() -> void {
|
2016-02-09 11:51:12 +00:00
|
|
|
if(SMP::Threaded) {
|
|
|
|
if(clock >= 0 && !scheduler.synchronizing()) co_switch(smp.thread);
|
Updated to v067r21 release.
byuu says:
This moves toward a profile-selection mode. Right now, it is incomplete.
There are three binaries, one for each profile. The GUI selection
doesn't actually do anything yet. There will be a launcher in a future
release that loads each profile's respective binary.
I reverted away from blargg's SMP library for the time being, in favor
of my own. This will fix most of the csnes/bsnes-performance bugs. This
causes a 10% speed hit on 64-bit platforms, and a 15% speed hit on
32-bit platforms. I hope to be able to regain that speed in the future,
I may also experiment with creating my own fast-SMP core which drops bus
hold delays and TEST register support (never used by anything, ever.)
Save states now work in all three cores, but they are not
cross-compatible. The profile name is stored in the description field of
the save states, and it won't load a state if the profile name doesn't
match.
The debugger only works on the research target for now. Give it time and
it will return for the other targets.
Other than that, let's please resume testing on all three once again.
See how far we get this time :)
I can confirm the following games have issues on the performance
profile:
- Armored Police Metal Jacket (minor logo flickering, not a big deal)
- Chou Aniki (won't start, so obviously unplayable)
- Robocop vs The Terminator (major in-game flickering, unplayable)
Anyone still have that gigantic bsnes thread archive from the ZSNES
forum? Maybe I posted about how to fix those two broken games in there,
heh.
I really want to release this as v1.0, but my better judgment says we
need to give it another week. Damn.
2010-10-20 11:22:44 +00:00
|
|
|
} else {
|
2016-02-09 11:51:12 +00:00
|
|
|
while(clock >= 0) smp.main();
|
Updated to v067r21 release.
byuu says:
This moves toward a profile-selection mode. Right now, it is incomplete.
There are three binaries, one for each profile. The GUI selection
doesn't actually do anything yet. There will be a launcher in a future
release that loads each profile's respective binary.
I reverted away from blargg's SMP library for the time being, in favor
of my own. This will fix most of the csnes/bsnes-performance bugs. This
causes a 10% speed hit on 64-bit platforms, and a 15% speed hit on
32-bit platforms. I hope to be able to regain that speed in the future,
I may also experiment with creating my own fast-SMP core which drops bus
hold delays and TEST register support (never used by anything, ever.)
Save states now work in all three cores, but they are not
cross-compatible. The profile name is stored in the description field of
the save states, and it won't load a state if the profile name doesn't
match.
The debugger only works on the research target for now. Give it time and
it will return for the other targets.
Other than that, let's please resume testing on all three once again.
See how far we get this time :)
I can confirm the following games have issues on the performance
profile:
- Armored Police Metal Jacket (minor logo flickering, not a big deal)
- Chou Aniki (won't start, so obviously unplayable)
- Robocop vs The Terminator (major in-game flickering, unplayable)
Anyone still have that gigantic bsnes thread archive from the ZSNES
forum? Maybe I posted about how to fix those two broken games in there,
heh.
I really want to release this as v1.0, but my better judgment says we
need to give it another week. Damn.
2010-10-20 11:22:44 +00:00
|
|
|
}
|
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);
|
2015-10-10 02:16:12 +00:00
|
|
|
synchronizeSMP();
|
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 */
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::power() -> void {
|
|
|
|
for(auto& r : state.regs) r = 0;
|
|
|
|
state.echoHistoryOffset = 0;
|
|
|
|
state.everyOtherSample = false;
|
2010-08-09 13:28:56 +00:00
|
|
|
state.kon = 0;
|
|
|
|
state.noise = 0;
|
|
|
|
state.counter = 0;
|
2015-10-10 02:16:12 +00:00
|
|
|
state.echoOffset = 0;
|
|
|
|
state.echoLength = 0;
|
|
|
|
state.konBuffer = 0;
|
|
|
|
state.endxBuffer = 0;
|
|
|
|
state.envxBuffer = 0;
|
|
|
|
state.outxBuffer = 0;
|
|
|
|
state._pmon = 0;
|
|
|
|
state._non = 0;
|
|
|
|
state._eon = 0;
|
|
|
|
state._dir = 0;
|
|
|
|
state._koff = 0;
|
|
|
|
state._brrNextAddress = 0;
|
|
|
|
state._adsr0 = 0;
|
|
|
|
state._brrHeader = 0;
|
|
|
|
state._brrByte = 0;
|
|
|
|
state._srcn = 0;
|
|
|
|
state._esa = 0;
|
|
|
|
state._echoDisabled = 0;
|
|
|
|
state._dirAddress = 0;
|
|
|
|
state._pitch = 0;
|
|
|
|
state._output = 0;
|
|
|
|
state._looped = 0;
|
|
|
|
state._echoPointer = 0;
|
|
|
|
state._mainOut[0] = state._mainOut[1] = 0;
|
|
|
|
state._echoOut[0] = state._echoOut[1] = 0;
|
|
|
|
state._echoIn[0] = state._echoIn[1] = 0;
|
|
|
|
|
|
|
|
for(auto n : range(8)) {
|
|
|
|
voice[n].bufferOffset = 0;
|
|
|
|
voice[n].gaussianOffset = 0;
|
|
|
|
voice[n].brrAddress = 0;
|
|
|
|
voice[n].brrOffset = 1;
|
|
|
|
voice[n].vbit = 1 << n;
|
|
|
|
voice[n].vidx = n * 0x10;
|
|
|
|
voice[n].konDelay = 0;
|
|
|
|
voice[n].envelopeMode = EnvelopeRelease;
|
|
|
|
voice[n].envelope = 0;
|
|
|
|
voice[n].hiddenEnvelope = 0;
|
|
|
|
voice[n]._envxOut = 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2016-01-23 07:29:34 +00:00
|
|
|
|
|
|
|
audio.coprocessorEnable(false);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
auto DSP::reset() -> void {
|
2015-11-10 11:02:29 +00:00
|
|
|
create(Enter, system.apuFrequency());
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-10-10 02:16:12 +00:00
|
|
|
REG(FLG) = 0xe0;
|
|
|
|
state.noise = 0x4000;
|
|
|
|
state.echoHistoryOffset = 0;
|
|
|
|
state.everyOtherSample = 1;
|
|
|
|
state.echoOffset = 0;
|
|
|
|
state.counter = 0;
|
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
|
|
|
}
|