bsnes/higan/md/ym2612/ym2612.cpp

188 lines
4.7 KiB
C++
Raw Normal View History

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 04:21:37 +00:00
#include <md/md.hpp>
namespace MegaDrive {
YM2612 ym2612;
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 08:13:10 +00:00
#include "io.cpp"
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 08:45:51 +00:00
#include "timer.cpp"
#include "channel.cpp"
#include "constants.cpp"
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
#include "serialization.cpp"
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 04:21:37 +00:00
auto YM2612::Enter() -> void {
while(true) scheduler.synchronize(), ym2612.main();
}
auto YM2612::main() -> void {
sample();
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 08:45:51 +00:00
timerA.run();
timerB.run();
if(lfo.enable && ++lfo.divider == lfoDividers[lfo.rate]) {
lfo.divider = 0;
lfo.clock++;
for(auto& channel : channels) {
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 10:45:07 +00:00
for(auto& op : channel.operators) {
op.updatePhase(); //due to vibrato
op.updateLevel(); //due to tremolo
}
}
}
if(++envelope.divider == 3) {
envelope.divider = 0;
envelope.clock++;
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 10:45:07 +00:00
}
for(auto& channel : channels) {
for(auto& op : channel.operators) {
op.runPhase();
if(envelope.divider) continue;
op.runEnvelope();
}
}
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 08:45:51 +00:00
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
step(144);
}
auto YM2612::sample() -> void {
int left = 0;
int right = 0;
for(auto& channel : channels) {
auto& op = channel.operators;
const int modMask = -(1 << 1);
const int sumMask = -(1 << 5);
const int outMask = -(1 << 5);
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 10:45:07 +00:00
auto old = [&](uint n) -> int { return op[n].prior & modMask; };
auto mod = [&](uint n) -> int { return op[n].output & modMask; };
auto out = [&](uint n) -> int { return op[n].output & sumMask; };
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 10:45:07 +00:00
auto wave = [&](uint n, uint modulation) -> int {
int x = (modulation >> 1) + (op[n].phase.value >> 10);
int y = sine[x & 0x3ff] + op[n].outputLevel;
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 10:45:07 +00:00
return y < 0x2000 ? pow2[y & 0x1ff] << 2 >> (y >> 9) : 0;
};
int feedback = modMask & op[0].output + op[0].prior >> 9 - channel.feedback;
int accumulator = 0;
for(auto n : range(4)) op[n].prior = op[n].output;
op[0].output = wave(0, feedback * (channel.feedback > 0));
if(channel.algorithm == 0) {
//0 -> 1 -> 2 -> 3
op[1].output = wave(1, mod(0));
op[2].output = wave(2, old(1));
op[3].output = wave(3, mod(2));
accumulator += out(3);
}
if(channel.algorithm == 1) {
//(0 + 1) -> 2 -> 3
op[1].output = wave(1, 0);
op[2].output = wave(2, mod(0) + old(1));
op[3].output = wave(3, mod(2));
accumulator += out(3);
}
if(channel.algorithm == 2) {
//0 + (1 -> 2) -> 3
op[1].output = wave(1, 0);
op[2].output = wave(2, old(1));
op[3].output = wave(3, mod(0) + mod(2));
accumulator += out(3);
}
if(channel.algorithm == 3) {
//(0 -> 1) + 2 -> 3
op[1].output = wave(1, mod(0));
op[2].output = wave(2, 0);
op[3].output = wave(3, mod(1) + mod(2));
accumulator += out(3);
}
if(channel.algorithm == 4) {
//(0 -> 1) + (2 -> 3)
op[1].output = wave(1, mod(0));
op[2].output = wave(2, 0);
op[3].output = wave(3, mod(2));
accumulator += out(1) + out(3);
}
if(channel.algorithm == 5) {
//0 -> (1 + 2 + 3)
op[1].output = wave(1, mod(0));
op[2].output = wave(2, old(0));
op[3].output = wave(3, mod(0));
accumulator += out(1) + out(2) + out(3);
}
if(channel.algorithm == 6) {
//(0 -> 1) + 2 + 3
op[1].output = wave(1, mod(0));
op[2].output = wave(2, 0);
op[3].output = wave(3, 0);
accumulator += out(1) + out(2) + out(3);
}
if(channel.algorithm == 7) {
//0 + 1 + 2 + 3
op[1].output = wave(1, 0);
op[2].output = wave(2, 0);
op[3].output = wave(3, 0);
accumulator += out(0) + out(1) + out(2) + out(3);
}
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-06 20:23:22 +00:00
int voiceData = sclamp<14>(accumulator) & outMask;
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 10:23:29 +00:00
if(dac.enable && (&channel == &channels[5])) voiceData = (int)dac.sample - 0x80 << 6;
if(channel.leftEnable ) left += voiceData;
if(channel.rightEnable) right += voiceData;
}
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-06 20:23:22 +00:00
stream->sample(sclamp<16>(left) / 32768.0, sclamp<16>(right) / 32768.0);
}
auto YM2612::step(uint clocks) -> void {
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 01:07:04 +00:00
Thread::step(clocks);
synchronize(cpu);
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 08:45:51 +00:00
synchronize(apu);
}
auto YM2612::power() -> void {
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
create(YM2612::Enter, system.colorburst() * 15.0 / 7.0);
stream = Emulator::audio.createStream(2, frequency() / 144.0);
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 08:45:51 +00:00
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-06 20:23:22 +00:00
io = {};
lfo = {};
dac = {};
envelope = {};
timerA = {};
timerB = {};
for(auto& channel : channels) channel.power();
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 10:45:07 +00:00
const uint positive = 0;
const uint negative = 1;
for(int x = 0; x <= 0xff; x++) {
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 10:45:07 +00:00
int y = -256 * log(sin((2 * x + 1) * Math::Pi / 1024)) / log(2) + 0.5;
sine[0x000 + x] = positive + (y << 1);
sine[0x1ff - x] = positive + (y << 1);
sine[0x200 + x] = negative + (y << 1);
sine[0x3ff - x] = negative + (y << 1);
}
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 08:45:51 +00:00
for(int y = 0; y <= 0xff; y++) {
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 10:45:07 +00:00
int z = 1024 * pow(2, (0xff - y) / 256.0) + 0.5;
pow2[positive + (y << 1)] = +z;
pow2[negative + (y << 1)] = ~z; //not -z
}
}
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 04:21:37 +00:00
}