2017-02-21 11:07:33 +00:00
|
|
|
auto PSG::write(uint8 data) -> void {
|
|
|
|
bool l = data.bit(7);
|
|
|
|
if(l) select = data.bits(4,6);
|
|
|
|
|
|
|
|
switch(select) {
|
|
|
|
|
|
|
|
case 0: {
|
|
|
|
if(l) tone0.pitch.bits(0,3) = data.bits(0,3);
|
|
|
|
else tone0.pitch.bits(4,9) = data.bits(0,5);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 1: {
|
|
|
|
tone0.volume = data.bits(0,3);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 2: {
|
|
|
|
if(l) tone1.pitch.bits(0,3) = data.bits(0,3);
|
|
|
|
else tone1.pitch.bits(4,9) = data.bits(0,5);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 3: {
|
|
|
|
tone1.volume = data.bits(0,3);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 4: {
|
|
|
|
if(l) tone2.pitch.bits(0,3) = data.bits(0,3);
|
|
|
|
else tone2.pitch.bits(4,9) = data.bits(0,5);
|
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
|
|
|
noise.pitch = tone2.pitch;
|
2017-02-21 11:07:33 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 5: {
|
|
|
|
tone2.volume = data.bits(0,3);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 6: {
|
|
|
|
noise.rate = data.bits(0,1);
|
|
|
|
noise.enable = data.bit(2);
|
|
|
|
noise.lfsr = 0x8000;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 7: {
|
|
|
|
noise.volume = data.bits(0,3);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Game Gear only
|
|
|
|
auto PSG::balance(uint8 data) -> void {
|
|
|
|
tone0.right = data.bit(0);
|
|
|
|
tone1.right = data.bit(1);
|
|
|
|
tone2.right = data.bit(2);
|
|
|
|
noise.right = data.bit(3);
|
|
|
|
tone0.left = data.bit(4);
|
|
|
|
tone1.left = data.bit(5);
|
|
|
|
tone2.left = data.bit(6);
|
|
|
|
noise.left = data.bit(7);
|
|
|
|
}
|