[pce] Fix ADPCM more and code cleanup

This commit is contained in:
beirich 2011-09-07 03:31:32 +00:00
parent 45609f4e88
commit 41de458ec6
3 changed files with 119 additions and 73 deletions

View File

@ -3,7 +3,7 @@ using BizHawk.Emulation.Sound;
namespace BizHawk.Emulation.Consoles.TurboGrafx
{
public sealed class ADPCM
public sealed class ADPCM : ISoundProvider
{
public ushort IOAddress;
public ushort ReadAddress;
@ -15,17 +15,58 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public bool ReadPending, WritePending;
public byte[] RAM = new byte[0x10000];
public MetaspuSoundProvider SoundProvider = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
float Playback44khzTimer;
ScsiCDBus SCSI;
PCEngine pce;
MetaspuSoundProvider SoundProvider = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
// ***************************************************************************
public bool AdpcmIsPlaying { get; private set; }
public bool AdpcmBusyWriting { get { return AdpcmCdDmaRequested; } }
public bool AdpcmBusyReading { get { return ReadPending; } }
public bool AdpcmCdDmaRequested { get { return (Port180B & 3) != 0; } }
public byte Port180A
{
set
{
WriteBuffer = value;
WriteTimer = 24;
WritePending = true;
}
get
{
ReadPending = true;
ReadTimer = 24;
return ReadBuffer;
}
}
public byte Port180B;
public byte Port180D;
byte port180E;
public byte Port180E
{
get { return port180E; }
set
{
port180E = value;
float khz = 32 / (16 - (Port180E & 0x0F));
destSamplesPerSourceSample = 44.1f / khz;
}
}
// ***************************************************************************
public ADPCM(PCEngine pcEngine, ScsiCDBus scsi)
{
pce = pcEngine;
SCSI = scsi;
MaxVolume = 16384;
}
public void AdpcmControlWrite(byte value)
@ -33,7 +74,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
//Log.Error("CD","ADPCM CONTROL WRITE {0:X2}",value);
if ((Port180D & 0x80) != 0 && (value & 0x80) == 0)
{
Log.Note("CD", "Reset ADPCM!");
ReadAddress = 0;
WriteAddress = 0;
IOAddress = 0;
@ -72,9 +112,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if ((value & 0x40) == 0)
Console.WriteLine("a thing thats normally set is not set");
Console.WriteLine("Start playing! READ {0:X4} LENGTH {1:X4}", ReadAddress, AdpcmLength);
//Console.WriteLine("Start playing! READ {0:X4} LENGTH {1:X4}", ReadAddress, AdpcmLength);
AdpcmIsPlaying = true;
// nibble = true;
playingSample = 2048;
magnitude = 0;
Playback44khzTimer = 0;
@ -83,10 +122,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
Port180D = value;
}
public bool AdpcmIsPlaying { get; private set; }
public bool AdpcmBusyWriting { get { return AdpcmCdDmaRequested; } }
public bool AdpcmBusyReading { get { return ReadPending; } }
public void Think(int cycles)
{
Playback44khzTimer -= cycles;
@ -130,7 +165,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (SCSI.DataTransferInProgress == false)
{
Port180B = 0;
Console.WriteLine(" ADPCM DMA COMPLETED");
//Console.WriteLine(" ADPCM DMA COMPLETED");
}
}
@ -138,57 +173,67 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (AdpcmIsPlaying == false) pce.IRQ2Monitor |= 0x08;
pce.RefreshIRQ2();
}
public bool AdpcmCdDmaRequested { get { return (Port180B & 3) != 0; } }
public byte Port180A
{
set
{
WriteBuffer = value;
WriteTimer = 24;
WritePending = true;
}
get
{
ReadPending = true;
ReadTimer = 24;
return ReadBuffer;
}
}
public byte Port180B;
public byte Port180D;
byte port180E;
public byte Port180E
{
get { return port180E; }
set
{
port180E = value;
float khz = 32 / (16 - (Port180E & 0x0F));
destSamplesPerSourceSample = 44.1f / khz;
}
}
// ***************************************************************************
// Playback Functions
// ***************************************************************************
static readonly int[] StepSize =
{
16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 140, 143,
157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449,
494, 544, 598, 658, 724, 796, 876, 963,1060,1166,1282,1411,
1552
0x0002, 0x0006, 0x000A, 0x000E, 0x0012, 0x0016, 0x001A, 0x001E,
0x0002, 0x0006, 0x000A, 0x000E, 0x0013, 0x0017, 0x001B, 0x001F,
0x0002, 0x0006, 0x000B, 0x000F, 0x0015, 0x0019, 0x001E, 0x0022,
0x0002, 0x0007, 0x000C, 0x0011, 0x0017, 0x001C, 0x0021, 0x0026,
0x0002, 0x0007, 0x000D, 0x0012, 0x0019, 0x001E, 0x0024, 0x0029,
0x0003, 0x0009, 0x000F, 0x0015, 0x001C, 0x0022, 0x0028, 0x002E,
0x0003, 0x000A, 0x0011, 0x0018, 0x001F, 0x0026, 0x002D, 0x0034,
0x0003, 0x000A, 0x0012, 0x0019, 0x0022, 0x0029, 0x0031, 0x0038,
0x0004, 0x000C, 0x0015, 0x001D, 0x0026, 0x002E, 0x0037, 0x003F,
0x0004, 0x000D, 0x0016, 0x001F, 0x0029, 0x0032, 0x003B, 0x0044,
0x0005, 0x000F, 0x0019, 0x0023, 0x002E, 0x0038, 0x0042, 0x004C,
0x0005, 0x0010, 0x001B, 0x0026, 0x0032, 0x003D, 0x0048, 0x0053,
0x0006, 0x0012, 0x001F, 0x002B, 0x0038, 0x0044, 0x0051, 0x005D,
0x0006, 0x0013, 0x0021, 0x002E, 0x003D, 0x004A, 0x0058, 0x0065,
0x0007, 0x0016, 0x0025, 0x0034, 0x0043, 0x0052, 0x0061, 0x0070,
0x0008, 0x0018, 0x0029, 0x0039, 0x004A, 0x005A, 0x006B, 0x007B,
0x0009, 0x001B, 0x002D, 0x003F, 0x0052, 0x0064, 0x0076, 0x0088,
0x000A, 0x001E, 0x0032, 0x0046, 0x005A, 0x006E, 0x0082, 0x0096,
0x000B, 0x0021, 0x0037, 0x004D, 0x0063, 0x0079, 0x008F, 0x00A5,
0x000C, 0x0024, 0x003C, 0x0054, 0x006D, 0x0085, 0x009D, 0x00B5,
0x000D, 0x0027, 0x0042, 0x005C, 0x0078, 0x0092, 0x00AD, 0x00C7,
0x000E, 0x002B, 0x0049, 0x0066, 0x0084, 0x00A1, 0x00BF, 0x00DC,
0x0010, 0x0030, 0x0051, 0x0071, 0x0092, 0x00B2, 0x00D3, 0x00F3,
0x0011, 0x0034, 0x0058, 0x007B, 0x00A0, 0x00C3, 0x00E7, 0x010A,
0x0013, 0x003A, 0x0061, 0x0088, 0x00B0, 0x00D7, 0x00FE, 0x0125,
0x0015, 0x0040, 0x006B, 0x0096, 0x00C2, 0x00ED, 0x0118, 0x0143,
0x0017, 0x0046, 0x0076, 0x00A5, 0x00D5, 0x0104, 0x0134, 0x0163,
0x001A, 0x004E, 0x0082, 0x00B6, 0x00EB, 0x011F, 0x0153, 0x0187,
0x001C, 0x0055, 0x008F, 0x00C8, 0x0102, 0x013B, 0x0175, 0x01AE,
0x001F, 0x005E, 0x009D, 0x00DC, 0x011C, 0x015B, 0x019A, 0x01D9,
0x0022, 0x0067, 0x00AD, 0x00F2, 0x0139, 0x017E, 0x01C4, 0x0209,
0x0026, 0x0072, 0x00BF, 0x010B, 0x0159, 0x01A5, 0x01F2, 0x023E,
0x002A, 0x007E, 0x00D2, 0x0126, 0x017B, 0x01CF, 0x0223, 0x0277,
0x002E, 0x008A, 0x00E7, 0x0143, 0x01A1, 0x01FD, 0x025A, 0x02B6,
0x0033, 0x0099, 0x00FF, 0x0165, 0x01CB, 0x0231, 0x0297, 0x02FD,
0x0038, 0x00A8, 0x0118, 0x0188, 0x01F9, 0x0269, 0x02D9, 0x0349,
0x003D, 0x00B8, 0x0134, 0x01AF, 0x022B, 0x02A6, 0x0322, 0x039D,
0x0044, 0x00CC, 0x0154, 0x01DC, 0x0264, 0x02EC, 0x0374, 0x03FC,
0x004A, 0x00DF, 0x0175, 0x020A, 0x02A0, 0x0335, 0x03CB, 0x0460,
0x0052, 0x00F6, 0x019B, 0x023F, 0x02E4, 0x0388, 0x042D, 0x04D1,
0x005A, 0x010F, 0x01C4, 0x0279, 0x032E, 0x03E3, 0x0498, 0x054D,
0x0063, 0x012A, 0x01F1, 0x02B8, 0x037F, 0x0446, 0x050D, 0x05D4,
0x006D, 0x0148, 0x0223, 0x02FE, 0x03D9, 0x04B4, 0x058F, 0x066A,
0x0078, 0x0168, 0x0259, 0x0349, 0x043B, 0x052B, 0x061C, 0x070C,
0x0084, 0x018D, 0x0296, 0x039F, 0x04A8, 0x05B1, 0x06BA, 0x07C3,
0x0091, 0x01B4, 0x02D8, 0x03FB, 0x051F, 0x0642, 0x0766, 0x0889,
0x00A0, 0x01E0, 0x0321, 0x0461, 0x05A2, 0x06E2, 0x0823, 0x0963,
0x00B0, 0x0210, 0x0371, 0x04D1, 0x0633, 0x0793, 0x08F4, 0x0A54,
0x00C2, 0x0246, 0x03CA, 0x054E, 0x06D2, 0x0856, 0x09DA, 0x0B5E
};
static readonly int[] StepFactor = { -1, -1, -1, -1, 2, 4, 6, 8 };
float Playback44khzTimer;
int playingSample;
float nextSampleTimer = 0;
float destSamplesPerSourceSample;
@ -221,19 +266,14 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
void DecodeAdpcmSample()
{
// get sample. it's one nibble.
byte sample = ReadNibble();
bool positive = (sample & 8) == 0;
int mag = sample & 7;
int m = StepFactor[mag];
int adjustment = StepSize[(magnitude * 8) + mag];
magnitude = AddClamped(magnitude, m, 0, 48);
int adjustment = StepSize[magnitude];
if (positive == false) adjustment *= -1;
playingSample = AddClamped(playingSample, adjustment, 0, 4095);
//Console.WriteLine("decode: {0:X} sample: {1} ad_ref_index: {2}", sample,playingSample, magnitude);
}
void AdpcmEmitSample()
@ -242,9 +282,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
SoundProvider.buffer.enqueue_sample(0, 0);
else
{
int rate = 16 - (Port180E & 0x0F);
float khz = 32 / rate;
if (nextSampleTimer <= 0)
{
DecodeAdpcmSample();
@ -257,9 +294,21 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
AdpcmIsPlaying = false;
}
short adjustedSample = (short)((playingSample - 2048) << 3);
short adjustedSample = (short)((playingSample - 2048) * MaxVolume / 2048);
SoundProvider.buffer.enqueue_sample(adjustedSample, adjustedSample);
}
}
public void GetSamples(short[] samples)
{
SoundProvider.GetSamples(samples);
}
public void DiscardSamples()
{
SoundProvider.DiscardSamples();
}
public int MaxVolume { get; set; }
}
}
}

View File

@ -2,8 +2,7 @@
* Turbo CD Issues *
******************************************************
- Baby Jo, a totally terrible game.
- Download 2, eventually has issues. Seems like waiting on ADPCM interrupts or flags.
- Download 2: 2nd level jacked up, like the level is garbage, and garbage is imba
- Similar in Dragon Slayer
- Dungeon Explorer II quite desperately need ADPCM audio
+ and a gross corruption issue at teh end of the intro. and then it freezes. :(
@ -12,7 +11,8 @@
- Macross 2036.. seems impossible to start/play the game. :(
- Rayxanber 2 weird issues at the end of first level with cd audio player
- rtype, end of level 4 dies with unrecognized scsi command ff
- Rtype, end of level 4 dies with unrecognized scsi command ff, or maybe freezes before then
- Snatcher dies at startup while polling subcode, demonstrating the incorrectness of subcode polling code.. yeah that hangs together
- Startling Odyssey does the reset-at-new-game-screen thats rather odd :(
- Super Darius II : at 1st Boss, game freezes waiting for adpcm
- Ys 1, start new game, death by adpcm probably ** shit it works now.
@ -30,7 +30,7 @@ General:
Right now the emulator is simply displaying a framebuffer. Eventually, we will do an update that emulates NTSC.
But for now we're letting this be. There's no intermediate step between emulating a framebuffer and emulating a TV.
Eagan's Rendered Sprite Demo - demonstrates sprites that shouldnt be displayed
Eagan's Rendered Sprite Demo - demonstrates sprites that shouldnt be displayed (so does Turbo Engine!)
===================================
Games that need TV Emulation (to varying degrees)
@ -45,8 +45,8 @@ Yo, Bro - Mid-frame res changes (hax to make playable) (IF YOU CAN CAL
Lesser degrees:
Aero Blaster - Bottom of Screen extends too many lines - like 3 extra or so
Alice - Screen too tall; glitches when scrolling up, but in pcejin also,
but not ootake; ergo probably a timing artifact
Alice - Screen too tall; glitches when scrolling up, but in mednafen in turboengine also,
but not Ootake; could be a timing artifact, or Ootake is cutting off the top
Dead Moon - Screen is too tall
Jack Nicholas Golf- Some screens are too tall and reveal bad gfx below the intended visible screen
Legend of Hero Ton- Slight gfx issue on top of screen
@ -67,9 +67,6 @@ Stuff I Fixed That's Not In Other Docs:
+ There is a one-instruction delay on changes to the I flag taking effect
- Affects (Not a complete list): Blodia, Body Conquest 2, Champions Forever Boxing,
Cross Wiber, Jackie Chan, Jigoku Meguri, New Adventure Island, World Beach volley
- Actually, I'm not at all convinced there's always a 1-instruction delay on the I-flag.
But this fixes several games; clearly there are delays in some scenarios. But it's not clear
to me that this delay is ALWAYS present.
+ Writing to the SATB location register of the VDC requests a VRAM->SAT DMA even if the SAT DMA
bit is disabled in the DCR.
+ This is in other docs, but Fighting Run requires full MWR register emulation including the various

View File

@ -110,7 +110,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
Cpu.WriteVDC = VDC1.WriteVDC;
CDAudio = new CDAudio(disc);
PSG.MaxVolume = short.MaxValue * 3 / 4;
SoundMixer = new SoundMixer(PSG, CDAudio, ADPCM.SoundProvider);
SoundMixer = new SoundMixer(PSG, CDAudio, ADPCM);
SoundSynchronizer = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
soundProvider = SoundSynchronizer;
Cpu.ThinkAction = (cycles) => { SCSI.Think(); ADPCM.Think(cycles); };