2016-08-17 12:31:22 +00:00
|
|
|
#include <ms/ms.hpp>
|
|
|
|
|
|
|
|
namespace MasterSystem {
|
|
|
|
|
|
|
|
PSG psg;
|
2017-02-21 11:07:33 +00:00
|
|
|
#include "io.cpp"
|
|
|
|
#include "tone.cpp"
|
|
|
|
#include "noise.cpp"
|
Update to v102r10 release.
byuu says:
Changelog:
- removed Emulator::Interface::Capabilities¹
- MS: improved the PSG emulation a bit
- MS: added cheat code support
- MS: added save state support²
- MD: emulated the PSG³
¹: there's really no point to it anymore. I intend to add cheat codes
to the GBA core, as well as both cheat codes and save states to the Mega
Drive core. I no longer intend to emulate any new systems, so these
values will always be true. Further, the GUI doesn't respond to these
values to disable those features anymore ever since the hiro rewrite, so
they're double useless.
²: right now, the Z80 core is using a pointer for HL-\>(IX,IY)
overrides. But I can't reliably serialize pointers, so I need to convert
the Z80 core to use an integer here. The save states still appear to
work fine, but there's the potential for an instruction to execute
incorrectly if you're incredibly unlucky, so this needs to be fixed as
soon as possible. Further, I still need a way to serialize
array<T, Size> objects, and I should also add nall::Boolean
serialization support.
³: I don't have a system in place to share identical sound chips. But
this chip is so incredibly simple that it's not really much trouble to
duplicate it. Further, I can strip out the stereo sound support code
from the Game Gear portion, so it's even tinier.
Note that the Mega Drive only just barely uses the PSG. Not at all in
Altered Beast, and only for a tiny part of the BGM music on Sonic 1,
plus his jump sound effect.
2017-02-22 21:25:01 +00:00
|
|
|
#include "serialization.cpp"
|
2016-08-17 12:31:22 +00:00
|
|
|
|
|
|
|
auto PSG::Enter() -> void {
|
|
|
|
while(true) scheduler.synchronize(), psg.main();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto PSG::main() -> void {
|
2017-02-21 11:07:33 +00:00
|
|
|
tone0.run();
|
|
|
|
tone1.run();
|
|
|
|
tone2.run();
|
|
|
|
noise.run();
|
|
|
|
|
|
|
|
int left = 0;
|
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
|
|
|
left += levels[tone0.volume] * tone0.output * tone0.left;
|
|
|
|
left += levels[tone1.volume] * tone1.output * tone1.left;
|
|
|
|
left += levels[tone2.volume] * tone2.output * tone2.left;
|
|
|
|
left += levels[noise.volume] * noise.output * noise.left;
|
2017-02-21 11:07:33 +00:00
|
|
|
|
|
|
|
int right = 0;
|
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
|
|
|
right += levels[tone0.volume] * tone0.output * tone0.right;
|
|
|
|
right += levels[tone1.volume] * tone1.output * tone1.right;
|
|
|
|
right += levels[tone2.volume] * tone2.output * tone2.right;
|
|
|
|
right += levels[noise.volume] * noise.output * noise.right;
|
2017-02-21 11:07:33 +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
|
|
|
stream->sample(sclamp<16>(left) / 32768.0, sclamp<16>(right) / 32768.0);
|
Update to v102r10 release.
byuu says:
Changelog:
- removed Emulator::Interface::Capabilities¹
- MS: improved the PSG emulation a bit
- MS: added cheat code support
- MS: added save state support²
- MD: emulated the PSG³
¹: there's really no point to it anymore. I intend to add cheat codes
to the GBA core, as well as both cheat codes and save states to the Mega
Drive core. I no longer intend to emulate any new systems, so these
values will always be true. Further, the GUI doesn't respond to these
values to disable those features anymore ever since the hiro rewrite, so
they're double useless.
²: right now, the Z80 core is using a pointer for HL-\>(IX,IY)
overrides. But I can't reliably serialize pointers, so I need to convert
the Z80 core to use an integer here. The save states still appear to
work fine, but there's the potential for an instruction to execute
incorrectly if you're incredibly unlucky, so this needs to be fixed as
soon as possible. Further, I still need a way to serialize
array<T, Size> objects, and I should also add nall::Boolean
serialization support.
³: I don't have a system in place to share identical sound chips. But
this chip is so incredibly simple that it's not really much trouble to
duplicate it. Further, I can strip out the stereo sound support code
from the Game Gear portion, so it's even tinier.
Note that the Mega Drive only just barely uses the PSG. Not at all in
Altered Beast, and only for a tiny part of the BGM music on Sonic 1,
plus his jump sound effect.
2017-02-22 21:25:01 +00:00
|
|
|
step(1);
|
2016-08-17 12:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto PSG::step(uint clocks) -> void {
|
|
|
|
Thread::step(clocks);
|
2016-08-19 14:11:26 +00:00
|
|
|
synchronize(cpu);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto PSG::power() -> void {
|
2017-02-21 11:07:33 +00:00
|
|
|
//Master System is monaural; Game Gear is stereo
|
|
|
|
//use stereo mode for both; output same sample to both channels for Master System
|
|
|
|
create(PSG::Enter, system.colorburst() / 16.0);
|
|
|
|
stream = Emulator::audio.createStream(2, frequency());
|
Update to v103r01 release.
byuu says:
Changelog:
- nall/dsp: improve one pole coefficient calculations [Fatbag]
- higan/audio: reworked filters to support selection of either one
pole (first-order) or biquad (second-order) filters
- note: the design is not stable yet; so forks should not put too
much effort into synchronizing with this change yet
- fc: added first-order filters as per NESdev wiki (90hz lowpass +
440hz lowpass + 14khz highpass)
- fc: created separate NTSC-J and NTSC-U regions
- NESdev wiki says the Japanese Famicom uses a separate audio
filtering strategy, but details are fuzzy
- there's also cartridge audio output being disabled on NES units;
and differences with controllers
- this stuff will be supported in the future, just adding the
support for it now
- gba: corrected serious bugs in PSG wave channel emulation [Cydrak]
- note that if there are still bugs here, it's my fault
- md/psg,ym2612: added first-order low-pass 2840hz filter to match
VA3-VA6 Mega Drives
- md/psg: lowered volume relative to the YM2612
- using 0x1400; multiple people agreed it was the closest to the
hardware recordings against a VA6
- ms,md/psg: don't serialize the volume levels array
- md/vdp: Hblank bit acts the same during Vblank as outside of it (it
isn't always set during Vblank)
- md/vdp: return isPAL in bit 0 of control port reads
- tomoko: change command-line option separator from : to |
- [Editor's note: This change was present in the public v103,
but it's in this changelog because it was made after the v103 WIP]
- higan/all: change the 20hz high-pass filters from second-order
three-pass to first-order one-pass
- these filters are meant to remove DC bias, but I honestly can't
hear a difference with or without them
- so there's really no sense wasting CPU power with an extremely
powerful filter here
Things I did not do:
- change icarus install rule
- work on 8-bit Mega Drive SRAM
- work on Famicom or Mega Drive region detection heuristics in icarus
My long-term dream plan is to devise a special user-configurable
filtering system where you can set relative volumes and create your own
list of filters (any number of them in any order at any frequency), that
way people can make the systems sound however they want.
Right now, the sanest place to put this information is inside the
$system.sys/manifest.bml files. But that's not very user friendly, and
upgrading to new versions will lose these changes if you don't copy them
over manually. Of course, cluttering the GUI with a fancy filter editor
is probably supreme overkill for 99% of users, so maybe that's fine.
2017-06-26 01:41:58 +00:00
|
|
|
stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0);
|
|
|
|
stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3);
|
2017-02-21 11:07:33 +00:00
|
|
|
|
|
|
|
select = 0;
|
|
|
|
for(auto n : range(15)) {
|
Update to v102r11 release.
byuu says:
Changelog:
- MD: connected 32KB cartridge RAM up to every Genesis game under 2MB
loaded¹
- MS, GG, MD: improved PSG noise channel emulation, hopefully²
- MS, GG, MD: lowered PSG volume so that the lowpass doesn't clamp
samples³
- MD: added read/write handlers for VRAM, VSRAM, CRAM
- MD: block VRAM copy when CD4 is clear⁴
- MD: rewrote VRAM fill, VRAM copy to be byte-based⁵
- MD: VRAM fill byte set should fall through to regular data port
write handler⁶
¹: the header parsing for backup RAM is really weird. It's spaces
when not used, and seems to be 0x02000001-0x02003fff for the Shining
games. I don't understand why it starts at 0x02000001 instead of
0x02000000. So I'm just forcing every game to have 32KB of RAM for now.
There's also special handling for ROMs > 2MB that also have RAM
(Phantasy Star IV, etc) where there's a toggle to switch between ROM and
RAM. For now, that's not emulated.
I was hoping the Shining games would run after this, but they're still
dead-locking on me :(
²: Cydrak pointed out some flaws in my attempt to implement what he
had. I was having trouble understanding what he meant, so I went back
and read the docs on the sound chip and tried implementing the counter
the way the docs describe. Hopefully I have this right, but I don't know
of any good test ROMs to make sure my noise emulation is correct. The
docs say the shifted-out value goes to the output instead of the low bit
of the LFSR, so I made that change as well.
I think I hear the noise I'm supposed to in Sonic Marble Zone now, but
it seems like it's not correct in Green Hill Zone, adding a bit of an
annoying buzz to the background music. Maybe it sounds better with the
YM2612, but more likely, I still screwed something up :/
³: it's set to 50% range for both cores right now. For the MD, it
will need to be 25% once YM2612 emulation is in.
⁴: technically, this deadlocks the VDP until a hard reset. I could
emulate this, but for now I just don't do the VRAM copy in this case.
⁵: VSRAM fill and CRAM fill not supported in this new mode. They're
technically undocumented, and I don't have good notes on how they work.
I've been seeing conflicting notes on whether the VRAM fill buffer is
8-bits or 16-bits (I chose 8-bits), and on whether you write the low
byte and then high byte of each words, or the high byte and then low
byte (I chose the latter.)
The VRAM copy improvements fix the opening text in Langrisser II, so
that's great.
⁶: Langrisser II sets the transfer length to one less than needed to
fill the background letter tile on the scenario overview screen. After
moving to byte-sized transfers, a black pixel was getting stuck there.
So effectively, VRAM fill length becomes DMA length + 1, and the first
byte uses the data port so it writes a word value instead of just a byte
value. Hopefully this is all correct, although it probably gets way more
complicated with the VDP FIFO.
2017-02-25 11:11:46 +00:00
|
|
|
levels[n] = 0x2000 * pow(2, n * -2.0 / 6.0) + 0.5;
|
2017-02-21 11:07:33 +00:00
|
|
|
}
|
|
|
|
levels[15] = 0;
|
|
|
|
|
|
|
|
tone0.power();
|
|
|
|
tone1.power();
|
|
|
|
tone2.power();
|
|
|
|
noise.power();
|
2016-08-17 12:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|