7800: speed up framebuffer blits, and add audio output

This commit is contained in:
goyuken 2012-12-12 01:32:58 +00:00
parent c22ad34844
commit a43ecbf6aa
1 changed files with 77 additions and 39 deletions

View File

@ -7,6 +7,15 @@ namespace BizHawk
{ {
public partial class Atari7800 : IEmulator public partial class Atari7800 : IEmulator
{ {
static Atari7800()
{
// add alpha bits to palette tables
for (int i = 0; i < TIATables.NTSCPalette.Length; i++)
TIATables.NTSCPalette[i] |= unchecked((int)0xff000000);
for (int i = 0; i < TIATables.PALPalette.Length; i++)
TIATables.PALPalette[i] |= unchecked((int)0xff000000);
}
public string SystemId { get { return "A78"; } } //TODO: are we going to allow this core to do 2600 games? public string SystemId { get { return "A78"; } } //TODO: are we going to allow this core to do 2600 games?
public GameInfo game; public GameInfo game;
@ -15,20 +24,20 @@ namespace BizHawk
_frame++; _frame++;
_islag = true; _islag = true;
theMachine.ComputeNextFrame(videoProvider.fb); theMachine.ComputeNextFrame(avProvider.framebuffer);
if (_islag) if (_islag)
{ {
LagCount++; LagCount++;
} }
videoProvider.FillFrameBuffer(); avProvider.FillFrameBuffer();
} }
/* TODO */ /* TODO */
public CoreComm CoreComm { get; private set; } public CoreComm CoreComm { get; private set; }
public ISyncSoundProvider SyncSoundProvider { get { return null; } } public ISyncSoundProvider SyncSoundProvider { get { return avProvider; } }
public bool StartAsyncSound() { return true; } public bool StartAsyncSound() { return false; }
public void EndAsyncSound() { } public void EndAsyncSound() { }
public bool DeterministicEmulation { get; set; } public bool DeterministicEmulation { get; set; }
public void SaveStateText(TextWriter writer) { } public void SaveStateText(TextWriter writer) { }
@ -51,9 +60,16 @@ namespace BizHawk
public void StoreSaveRam(byte[] data) { } public void StoreSaveRam(byte[] data) { }
public void ClearSaveRam() { } public void ClearSaveRam() { }
public bool SaveRamModified { get; set; } public bool SaveRamModified { get; set; }
public void Dispose() { } public void Dispose()
public IVideoProvider VideoProvider { get { return videoProvider; } } {
public ISoundProvider SoundProvider { get { return soundProvider; } } if (avProvider != null)
{
avProvider.Dispose();
avProvider = null;
}
}
public IVideoProvider VideoProvider { get { return avProvider; } }
public ISoundProvider SoundProvider { get { return null; } }
public void ResetFrameCounter() public void ResetFrameCounter()
@ -121,7 +137,6 @@ namespace BizHawk
this.hsbios = highscoreBIOS; this.hsbios = highscoreBIOS;
NTSC_BIOS = new Bios7800(ntsc_bios); NTSC_BIOS = new Bios7800(ntsc_bios);
PAL_BIOS = new Bios7800(pal_bios); PAL_BIOS = new Bios7800(pal_bios);
soundProvider = new MySoundProvider(this); //TODO
HardReset(); HardReset();
} }
@ -149,7 +164,7 @@ namespace BizHawk
//theMachine = new Machine7800NTSC(cart, null, null, logger); //theMachine = new Machine7800NTSC(cart, null, null, logger);
//TODO: clean up, the hs and bios are passed in, the bios has an object AND byte array in the core, and naming is inconsistent //TODO: clean up, the hs and bios are passed in, the bios has an object AND byte array in the core, and naming is inconsistent
theMachine.Reset(); theMachine.Reset();
videoProvider = new MyVideoProvider(theMachine.CreateFrameBuffer()); avProvider = new MyAVProvider(theMachine);
} }
void SyncState(Serializer ser) //TODO void SyncState(Serializer ser) //TODO
@ -164,36 +179,44 @@ namespace BizHawk
theMachine.Reset(); theMachine.Reset();
} }
MyVideoProvider videoProvider; MyAVProvider avProvider;
class MyVideoProvider : IVideoProvider class MyAVProvider : IVideoProvider, ISyncSoundProvider, IDisposable
{ {
public FrameBuffer fb { get; private set; } public FrameBuffer framebuffer { get; private set; }
public MyVideoProvider(FrameBuffer fb) public MyAVProvider(MachineBase m)
{ {
this.fb = fb; framebuffer = m.CreateFrameBuffer();
BufferWidth = fb.VisiblePitch; BufferWidth = framebuffer.VisiblePitch;
BufferHeight = fb.Scanlines; BufferHeight = framebuffer.Scanlines;
buffer = new int[BufferWidth * BufferHeight]; vidbuffer = new int[BufferWidth * BufferHeight];
uint samplerate = (uint)m.SoundSampleFrequency;
resampler = new Emulation.Sound.Utilities.SpeexResampler(3, samplerate, 44100, samplerate, 44100, null, null);
dcfilter = Emulation.Sound.Utilities.DCFilter.DetatchedMode(256);
} }
int[] buffer; int[] vidbuffer;
Emulation.Sound.Utilities.SpeexResampler resampler;
Emulation.Sound.Utilities.DCFilter dcfilter;
public void FillFrameBuffer() public void FillFrameBuffer()
{ {
int s = 0; unsafe
int t = 0;
for (int i = 0; i < 262; i++)
{ {
for (int j = 0; j < 320; j++) fixed (BufferElement *src_ = framebuffer.VideoBuffer)
{ {
buffer[(i * fb.VisiblePitch) + j] = TIATables.NTSCPalette[fb.VideoBuffer[s][t]] | unchecked((int)0xff000000); fixed (int* dst_ = vidbuffer)
t++;
if (t == 4)
{ {
t = 0; fixed (int* pal = TIATables.NTSCPalette)
s++; {
byte* src = (byte*)src_;
int* dst = dst_;
for (int i = 0; i < vidbuffer.Length; i++)
{
*dst++ = pal[*src++];
}
}
} }
} }
} }
@ -201,31 +224,46 @@ namespace BizHawk
public int[] GetVideoBuffer() public int[] GetVideoBuffer()
{ {
return buffer; return vidbuffer;
} }
public int VirtualWidth { get { return BufferWidth; } } public int VirtualWidth { get { return BufferWidth; } }
public int BufferWidth { get; private set; } public int BufferWidth { get; private set; }
public int BufferHeight { get; private set; } public int BufferHeight { get; private set; }
public int BackgroundColor { get { return unchecked((int)0xff000000); } } public int BackgroundColor { get { return unchecked((int)0xff000000); } }
}
MySoundProvider soundProvider; public void GetSamples(out short[] samples, out int nsamp)
class MySoundProvider : ISoundProvider
{
Atari7800 emu;
public MySoundProvider(Atari7800 emu)
{ {
this.emu = emu; int nsampin = framebuffer.SoundBufferByteLength;
unsafe
{
fixed (BufferElement* src_ = framebuffer.SoundBuffer)
{
byte* src = (byte*)src_;
for (int i = 0; i < nsampin; i++)
{
short s = (short)(src[i] * 200 - 25500);
resampler.EnqueueSample(s, s);
}
}
}
resampler.GetSamples(out samples, out nsamp);
dcfilter.PushThroughSamples(samples, nsamp * 2);
} }
public int MaxVolume { get { return 0; } set { } }
public void DiscardSamples() public void DiscardSamples()
{ {
resampler.DiscardSamples();
} }
public void GetSamples(short[] samples) public void Dispose()
{ {
if (resampler != null)
{
resampler.Dispose();
resampler = null;
}
} }
} }