2012-10-23 03:33:57 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
2013-11-04 00:36:15 +00:00
|
|
|
|
|
|
|
|
|
using BizHawk.Common;
|
2013-11-04 01:06:36 +00:00
|
|
|
|
using BizHawk.Emulation.Common;
|
2012-10-23 03:33:57 +00:00
|
|
|
|
using EMU7800.Core;
|
|
|
|
|
|
2012-12-12 18:17:30 +00:00
|
|
|
|
namespace BizHawk.Emulation
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
|
|
|
|
public partial class Atari7800 : IEmulator
|
|
|
|
|
{
|
2012-12-16 18:16:50 +00:00
|
|
|
|
// TODO:
|
|
|
|
|
// some things don't work when you try to plug in a 2600 game
|
|
|
|
|
|
2012-12-12 01:32:58 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-16 18:16:50 +00:00
|
|
|
|
public string SystemId { get { return "A78"; } } // TODO 2600?
|
2012-10-23 03:33:57 +00:00
|
|
|
|
public GameInfo game;
|
|
|
|
|
|
2013-08-24 16:54:22 +00:00
|
|
|
|
public string BoardName { get { return null; } }
|
|
|
|
|
|
2012-10-23 03:33:57 +00:00
|
|
|
|
public void FrameAdvance(bool render, bool rendersound)
|
|
|
|
|
{
|
|
|
|
|
_frame++;
|
|
|
|
|
|
2012-12-16 15:15:54 +00:00
|
|
|
|
if (Controller["Power"])
|
|
|
|
|
{
|
|
|
|
|
// it seems that theMachine.Reset() doesn't clear ram, etc
|
|
|
|
|
// this should leave hsram intact but clear most other things
|
|
|
|
|
HardReset();
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-15 02:36:38 +00:00
|
|
|
|
ControlAdapter.Convert(Controller, theMachine.InputState);
|
2012-12-12 01:32:58 +00:00
|
|
|
|
theMachine.ComputeNextFrame(avProvider.framebuffer);
|
2012-12-12 15:36:17 +00:00
|
|
|
|
|
2012-12-16 01:34:02 +00:00
|
|
|
|
_islag = theMachine.InputState.Lagged;
|
2012-12-15 02:36:38 +00:00
|
|
|
|
|
2012-10-23 03:33:57 +00:00
|
|
|
|
if (_islag)
|
|
|
|
|
{
|
|
|
|
|
LagCount++;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-12 01:32:58 +00:00
|
|
|
|
avProvider.FillFrameBuffer();
|
2012-12-12 16:24:14 +00:00
|
|
|
|
|
2012-10-23 03:33:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-10 00:43:43 +00:00
|
|
|
|
public CoreComm CoreComm { get; private set; }
|
2012-10-23 03:33:57 +00:00
|
|
|
|
public bool DeterministicEmulation { get; set; }
|
2012-12-16 18:02:39 +00:00
|
|
|
|
private List<MemoryDomain> _MemoryDomains;
|
2013-11-06 02:15:29 +00:00
|
|
|
|
public MemoryDomainList MemoryDomains { get; private set; }
|
2012-10-23 03:33:57 +00:00
|
|
|
|
|
|
|
|
|
public int Frame { get { return _frame; } set { _frame = value; } }
|
|
|
|
|
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
|
|
|
|
public bool IsLagFrame { get { return _islag; } }
|
|
|
|
|
private bool _islag = true;
|
|
|
|
|
private int _lagcount = 0;
|
|
|
|
|
private int _frame = 0;
|
|
|
|
|
|
2012-12-16 18:16:50 +00:00
|
|
|
|
#region saveram
|
2012-12-12 03:47:05 +00:00
|
|
|
|
public byte[] ReadSaveRam()
|
2012-12-12 15:36:17 +00:00
|
|
|
|
{
|
2012-12-12 03:47:05 +00:00
|
|
|
|
return (byte[])hsram.Clone();
|
|
|
|
|
}
|
|
|
|
|
public void StoreSaveRam(byte[] data)
|
2012-12-12 15:36:17 +00:00
|
|
|
|
{
|
2012-12-12 03:47:05 +00:00
|
|
|
|
Buffer.BlockCopy(data, 0, hsram, 0, data.Length);
|
|
|
|
|
}
|
|
|
|
|
public void ClearSaveRam()
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < hsram.Length; i++)
|
|
|
|
|
hsram[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
public bool SaveRamModified
|
2012-12-12 15:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
2012-12-12 03:47:05 +00:00
|
|
|
|
return GameInfo.MachineType == MachineType.A7800PAL || GameInfo.MachineType == MachineType.A7800NTSC;
|
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("No one ever uses this, and it won't work with the way MainForm is set up.");
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-12-16 18:16:50 +00:00
|
|
|
|
#endregion
|
2012-12-12 03:47:05 +00:00
|
|
|
|
|
2012-12-12 01:32:58 +00:00
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
if (avProvider != null)
|
|
|
|
|
{
|
|
|
|
|
avProvider.Dispose();
|
|
|
|
|
avProvider = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-12-12 15:36:17 +00:00
|
|
|
|
|
2012-10-23 03:33:57 +00:00
|
|
|
|
|
2013-11-03 16:29:51 +00:00
|
|
|
|
public void ResetCounters()
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
|
|
|
|
_frame = 0;
|
2012-11-25 15:41:40 +00:00
|
|
|
|
_lagcount = 0;
|
|
|
|
|
_islag = false;
|
2012-10-23 03:33:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-16 18:16:50 +00:00
|
|
|
|
#region savestates
|
|
|
|
|
public void SaveStateText(TextWriter writer) { SyncState(new Serializer(writer)); }
|
|
|
|
|
public void LoadStateText(TextReader reader) { SyncState(new Serializer(reader)); }
|
|
|
|
|
public void SaveStateBinary(BinaryWriter bw) { SyncState(new Serializer(bw)); }
|
|
|
|
|
public void LoadStateBinary(BinaryReader br) { SyncState(new Serializer(br)); }
|
2012-10-23 03:33:57 +00:00
|
|
|
|
public byte[] SaveStateBinary()
|
|
|
|
|
{
|
|
|
|
|
MemoryStream ms = new MemoryStream();
|
|
|
|
|
BinaryWriter bw = new BinaryWriter(ms);
|
|
|
|
|
SaveStateBinary(bw);
|
|
|
|
|
bw.Flush();
|
|
|
|
|
return ms.ToArray();
|
|
|
|
|
}
|
2013-05-06 20:51:28 +00:00
|
|
|
|
|
|
|
|
|
public bool BinarySaveStatesPreferred { get { return true; } }
|
|
|
|
|
|
2012-12-16 18:16:50 +00:00
|
|
|
|
void SyncState(Serializer ser)
|
|
|
|
|
{
|
|
|
|
|
byte[] core = null;
|
|
|
|
|
if (ser.IsWriter)
|
|
|
|
|
{
|
|
|
|
|
var ms = new MemoryStream();
|
|
|
|
|
theMachine.Serialize(new BinaryWriter(ms));
|
|
|
|
|
ms.Close();
|
|
|
|
|
core = ms.ToArray();
|
|
|
|
|
}
|
|
|
|
|
ser.BeginSection("Atari7800");
|
|
|
|
|
ser.Sync("core", ref core, false);
|
|
|
|
|
ser.Sync("Lag", ref _lagcount);
|
|
|
|
|
ser.Sync("Frame", ref _frame);
|
|
|
|
|
ser.Sync("IsLag", ref _islag);
|
|
|
|
|
ser.EndSection();
|
|
|
|
|
if (ser.IsReader)
|
|
|
|
|
{
|
|
|
|
|
theMachine = MachineBase.Deserialize(new BinaryReader(new MemoryStream(core, false)));
|
|
|
|
|
avProvider.ConnectToMachine(theMachine);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
2012-10-23 03:33:57 +00:00
|
|
|
|
|
2012-12-15 02:36:38 +00:00
|
|
|
|
Atari7800Control ControlAdapter;
|
|
|
|
|
|
|
|
|
|
public ControllerDefinition ControllerDefinition { get; private set; }
|
2012-10-23 03:33:57 +00:00
|
|
|
|
public IController Controller { get; set; }
|
2012-12-16 18:16:50 +00:00
|
|
|
|
|
2012-10-23 03:33:57 +00:00
|
|
|
|
|
2012-12-10 21:29:50 +00:00
|
|
|
|
class ConsoleLogger : ILogger
|
|
|
|
|
{
|
|
|
|
|
public void WriteLine(string format, params object[] args)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine(format, args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void WriteLine(object value)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Write(string format, params object[] args)
|
|
|
|
|
{
|
|
|
|
|
Console.Write(format, args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Write(object value)
|
|
|
|
|
{
|
|
|
|
|
Console.Write(value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-12 03:40:18 +00:00
|
|
|
|
public Atari7800(CoreComm comm, GameInfo game, byte[] rom, byte[] ntsc_bios, byte[] pal_bios, byte[] highscoreBIOS, string GameDBfn)
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
2012-12-10 00:43:43 +00:00
|
|
|
|
CoreComm = comm;
|
|
|
|
|
|
2012-12-12 03:40:18 +00:00
|
|
|
|
if (EMU7800.Win.GameProgramLibrary.EMU7800DB == null)
|
|
|
|
|
{
|
|
|
|
|
EMU7800.Win.GameProgramLibrary.EMU7800DB = new EMU7800.Win.GameProgramLibrary(new StreamReader(GameDBfn));
|
|
|
|
|
}
|
2012-12-15 16:06:35 +00:00
|
|
|
|
|
|
|
|
|
if (rom.Length % 1024 == 128)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("Trimming 128 byte .a78 header...");
|
|
|
|
|
byte[] newrom = new byte[rom.Length - 128];
|
|
|
|
|
Buffer.BlockCopy(rom, 128, newrom, 0, newrom.Length);
|
|
|
|
|
rom = newrom;
|
|
|
|
|
}
|
2012-12-12 03:40:18 +00:00
|
|
|
|
GameInfo = EMU7800.Win.GameProgramLibrary.EMU7800DB.TryRecognizeRom(rom);
|
|
|
|
|
CoreComm.RomStatusDetails = GameInfo.ToString();
|
|
|
|
|
Console.WriteLine("Rom Determiniation from 7800DB:");
|
|
|
|
|
Console.WriteLine(GameInfo.ToString());
|
|
|
|
|
|
2012-10-23 03:33:57 +00:00
|
|
|
|
this.rom = rom;
|
|
|
|
|
this.game = game;
|
|
|
|
|
this.hsbios = highscoreBIOS;
|
2012-12-12 03:40:18 +00:00
|
|
|
|
this.bios = GameInfo.MachineType == MachineType.A7800PAL ? pal_bios : ntsc_bios;
|
2013-08-24 02:49:46 +00:00
|
|
|
|
if (bios == null)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidDataException("The BIOS corresponding to the region of the game you loaded is required to run Atari 7800 games.");
|
|
|
|
|
}
|
2012-10-23 03:33:57 +00:00
|
|
|
|
HardReset();
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-16 15:15:54 +00:00
|
|
|
|
void HardReset()
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
2012-12-12 03:40:18 +00:00
|
|
|
|
cart = Cart.Create(rom, GameInfo.CartType);
|
2012-12-10 21:29:50 +00:00
|
|
|
|
ILogger logger = new ConsoleLogger();
|
2012-12-27 22:24:42 +00:00
|
|
|
|
|
|
|
|
|
HSC7800 hsc7800 = null;
|
|
|
|
|
if (hsbios != null)
|
|
|
|
|
{
|
|
|
|
|
hsc7800 = new HSC7800(hsbios, hsram);
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-12 03:40:18 +00:00
|
|
|
|
Bios7800 bios7800 = new Bios7800(bios);
|
|
|
|
|
theMachine = MachineBase.Create
|
|
|
|
|
(GameInfo.MachineType,
|
|
|
|
|
cart,
|
|
|
|
|
bios7800,
|
|
|
|
|
hsc7800,
|
|
|
|
|
GameInfo.LController,
|
|
|
|
|
GameInfo.RController,
|
|
|
|
|
logger);
|
2012-12-12 15:36:17 +00:00
|
|
|
|
|
2012-12-11 23:01:01 +00:00
|
|
|
|
theMachine.Reset();
|
2012-12-15 02:36:38 +00:00
|
|
|
|
|
|
|
|
|
ControlAdapter = new Atari7800Control(theMachine);
|
|
|
|
|
if (ControlAdapter.ControlType.Name != "Atari 7800 ProLine Joystick Controller")
|
|
|
|
|
throw new Exception("For now, only Atari 7800 ProLine Joystick games are supported.");
|
|
|
|
|
ControllerDefinition = ControlAdapter.ControlType;
|
|
|
|
|
|
2012-12-12 15:36:17 +00:00
|
|
|
|
avProvider.ConnectToMachine(theMachine);
|
2012-12-12 03:40:18 +00:00
|
|
|
|
// to sync exactly with audio as this emulator creates and times it, the frame rate should be exactly 60:1 or 50:1
|
|
|
|
|
CoreComm.VsyncNum = theMachine.FrameHZ;
|
|
|
|
|
CoreComm.VsyncDen = 1;
|
2012-12-16 18:02:39 +00:00
|
|
|
|
|
|
|
|
|
// reset memory domains
|
|
|
|
|
if (_MemoryDomains == null)
|
|
|
|
|
{
|
|
|
|
|
_MemoryDomains = new List<MemoryDomain>();
|
|
|
|
|
if (theMachine is Machine7800)
|
|
|
|
|
{
|
|
|
|
|
_MemoryDomains.Add(new MemoryDomain(
|
2013-11-04 02:11:40 +00:00
|
|
|
|
"RAM1", 0x800, MemoryDomain.Endian.Unknown,
|
2012-12-16 18:02:39 +00:00
|
|
|
|
delegate(int addr)
|
|
|
|
|
{
|
|
|
|
|
return ((Machine7800)theMachine).RAM1[(ushort)addr];
|
|
|
|
|
},
|
|
|
|
|
delegate(int addr, byte val)
|
|
|
|
|
{
|
|
|
|
|
((Machine7800)theMachine).RAM1[(ushort)addr] = val;
|
|
|
|
|
}));
|
|
|
|
|
_MemoryDomains.Add(new MemoryDomain(
|
2013-11-04 02:11:40 +00:00
|
|
|
|
"RAM2", 0x800, MemoryDomain.Endian.Unknown,
|
2012-12-16 18:02:39 +00:00
|
|
|
|
delegate(int addr)
|
|
|
|
|
{
|
|
|
|
|
return ((Machine7800)theMachine).RAM2[(ushort)addr];
|
|
|
|
|
},
|
|
|
|
|
delegate(int addr, byte val)
|
|
|
|
|
{
|
|
|
|
|
((Machine7800)theMachine).RAM2[(ushort)addr] = val;
|
|
|
|
|
}));
|
|
|
|
|
_MemoryDomains.Add(new MemoryDomain(
|
2013-11-04 02:11:40 +00:00
|
|
|
|
"BIOS ROM", bios.Length, MemoryDomain.Endian.Unknown,
|
2012-12-16 18:02:39 +00:00
|
|
|
|
delegate(int addr)
|
|
|
|
|
{
|
|
|
|
|
return bios[addr];
|
|
|
|
|
},
|
|
|
|
|
delegate(int addr, byte val)
|
|
|
|
|
{
|
|
|
|
|
}));
|
2012-12-27 22:24:42 +00:00
|
|
|
|
if (hsc7800 != null)
|
|
|
|
|
{
|
|
|
|
|
_MemoryDomains.Add(new MemoryDomain(
|
2013-11-04 02:11:40 +00:00
|
|
|
|
"HSC ROM", hsbios.Length, MemoryDomain.Endian.Unknown,
|
2012-12-27 22:24:42 +00:00
|
|
|
|
delegate(int addr)
|
|
|
|
|
{
|
|
|
|
|
return hsbios[addr];
|
|
|
|
|
},
|
|
|
|
|
delegate(int addr, byte val)
|
|
|
|
|
{
|
|
|
|
|
}));
|
|
|
|
|
_MemoryDomains.Add(new MemoryDomain(
|
2013-11-04 02:11:40 +00:00
|
|
|
|
"HSC RAM", hsram.Length, MemoryDomain.Endian.Unknown,
|
2012-12-27 22:24:42 +00:00
|
|
|
|
delegate(int addr)
|
|
|
|
|
{
|
|
|
|
|
return hsram[addr];
|
|
|
|
|
},
|
|
|
|
|
delegate(int addr, byte val)
|
|
|
|
|
{
|
|
|
|
|
hsram[addr] = val;
|
|
|
|
|
}));
|
|
|
|
|
}
|
2012-12-16 18:02:39 +00:00
|
|
|
|
_MemoryDomains.Add(new MemoryDomain(
|
2013-11-04 02:11:40 +00:00
|
|
|
|
"System Bus", 65536, MemoryDomain.Endian.Unknown,
|
2012-12-16 18:02:39 +00:00
|
|
|
|
delegate(int addr)
|
|
|
|
|
{
|
|
|
|
|
return theMachine.Mem[(ushort)addr];
|
|
|
|
|
},
|
|
|
|
|
delegate(int addr, byte val)
|
|
|
|
|
{
|
|
|
|
|
theMachine.Mem[(ushort)addr] = val;
|
|
|
|
|
}));
|
|
|
|
|
}
|
2012-12-16 18:16:50 +00:00
|
|
|
|
else // todo 2600?
|
2012-12-16 18:02:39 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
2013-11-06 02:15:29 +00:00
|
|
|
|
MemoryDomains = new MemoryDomainList(_MemoryDomains);
|
2012-12-16 18:02:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-23 03:33:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-16 18:16:50 +00:00
|
|
|
|
#region audio\video
|
|
|
|
|
|
|
|
|
|
public ISyncSoundProvider SyncSoundProvider { get { return avProvider; } }
|
|
|
|
|
public bool StartAsyncSound() { return false; }
|
|
|
|
|
public void EndAsyncSound() { }
|
|
|
|
|
public IVideoProvider VideoProvider { get { return avProvider; } }
|
|
|
|
|
public ISoundProvider SoundProvider { get { return null; } }
|
2012-10-23 03:33:57 +00:00
|
|
|
|
|
2012-12-12 15:36:17 +00:00
|
|
|
|
MyAVProvider avProvider = new MyAVProvider();
|
2012-10-23 03:33:57 +00:00
|
|
|
|
|
2012-12-12 01:32:58 +00:00
|
|
|
|
class MyAVProvider : IVideoProvider, ISyncSoundProvider, IDisposable
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
2012-12-12 01:32:58 +00:00
|
|
|
|
public FrameBuffer framebuffer { get; private set; }
|
2012-12-12 15:36:17 +00:00
|
|
|
|
public void ConnectToMachine(MachineBase m)
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
2012-12-12 01:32:58 +00:00
|
|
|
|
framebuffer = m.CreateFrameBuffer();
|
|
|
|
|
BufferWidth = framebuffer.VisiblePitch;
|
|
|
|
|
BufferHeight = framebuffer.Scanlines;
|
|
|
|
|
vidbuffer = new int[BufferWidth * BufferHeight];
|
|
|
|
|
|
2012-12-12 16:24:14 +00:00
|
|
|
|
uint newsamplerate = (uint)m.SoundSampleFrequency;
|
|
|
|
|
if (newsamplerate != samplerate)
|
|
|
|
|
{
|
2012-12-16 15:15:54 +00:00
|
|
|
|
// really shouldn't happen (after init), but if it does, we're ready
|
2012-12-12 16:24:14 +00:00
|
|
|
|
if (resampler != null)
|
|
|
|
|
resampler.Dispose();
|
|
|
|
|
resampler = new Emulation.Sound.Utilities.SpeexResampler(3, newsamplerate, 44100, newsamplerate, 44100, null, null);
|
|
|
|
|
samplerate = newsamplerate;
|
|
|
|
|
dcfilter = Emulation.Sound.Utilities.DCFilter.DetatchedMode(256);
|
|
|
|
|
}
|
2012-10-23 03:33:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-12 16:24:14 +00:00
|
|
|
|
uint samplerate;
|
2012-12-12 01:32:58 +00:00
|
|
|
|
int[] vidbuffer;
|
|
|
|
|
Emulation.Sound.Utilities.SpeexResampler resampler;
|
|
|
|
|
Emulation.Sound.Utilities.DCFilter dcfilter;
|
2012-10-23 03:33:57 +00:00
|
|
|
|
|
2012-12-12 00:30:36 +00:00
|
|
|
|
public void FillFrameBuffer()
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
2012-12-12 01:32:58 +00:00
|
|
|
|
unsafe
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
2012-12-16 16:57:16 +00:00
|
|
|
|
fixed (byte* src_ = framebuffer.VideoBuffer)
|
2013-07-31 00:33:02 +00:00
|
|
|
|
fixed (int* dst_ = vidbuffer)
|
|
|
|
|
fixed (int* pal = TIATables.NTSCPalette)
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
2013-07-31 00:33:02 +00:00
|
|
|
|
byte* src = src_;
|
|
|
|
|
int* dst = dst_;
|
|
|
|
|
for (int i = 0; i < vidbuffer.Length; i++)
|
2012-12-12 00:23:01 +00:00
|
|
|
|
{
|
2013-07-31 00:33:02 +00:00
|
|
|
|
*dst++ = pal[*src++];
|
2012-12-12 00:23:01 +00:00
|
|
|
|
}
|
2012-10-23 03:33:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int[] GetVideoBuffer()
|
|
|
|
|
{
|
2012-12-12 01:32:58 +00:00
|
|
|
|
return vidbuffer;
|
2012-10-23 03:33:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int VirtualWidth { get { return BufferWidth; } }
|
2012-12-12 00:30:36 +00:00
|
|
|
|
public int BufferWidth { get; private set; }
|
|
|
|
|
public int BufferHeight { get; private set; }
|
|
|
|
|
public int BackgroundColor { get { return unchecked((int)0xff000000); } }
|
2012-10-23 03:33:57 +00:00
|
|
|
|
|
2012-12-12 01:32:58 +00:00
|
|
|
|
public void GetSamples(out short[] samples, out int nsamp)
|
2012-10-23 20:21:55 +00:00
|
|
|
|
{
|
2012-12-12 01:32:58 +00:00
|
|
|
|
int nsampin = framebuffer.SoundBufferByteLength;
|
|
|
|
|
unsafe
|
|
|
|
|
{
|
2012-12-16 16:57:16 +00:00
|
|
|
|
fixed (byte* src = framebuffer.SoundBuffer)
|
2012-12-12 01:32:58 +00:00
|
|
|
|
{
|
2012-12-12 15:36:17 +00:00
|
|
|
|
for (int i = 0; i < nsampin; i++)
|
|
|
|
|
{
|
2012-12-12 16:24:14 +00:00
|
|
|
|
// the buffer values don't really get very large at all,
|
|
|
|
|
// so this doesn't overflow
|
|
|
|
|
short s = (short)(src[i] * 200);
|
2012-12-12 15:36:17 +00:00
|
|
|
|
resampler.EnqueueSample(s, s);
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-12 01:32:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
resampler.GetSamples(out samples, out nsamp);
|
|
|
|
|
dcfilter.PushThroughSamples(samples, nsamp * 2);
|
2012-10-23 20:21:55 +00:00
|
|
|
|
}
|
2012-12-12 01:32:58 +00:00
|
|
|
|
|
2012-10-23 03:33:57 +00:00
|
|
|
|
public void DiscardSamples()
|
|
|
|
|
{
|
2012-12-12 16:24:14 +00:00
|
|
|
|
if (resampler != null)
|
|
|
|
|
resampler.DiscardSamples();
|
2012-10-23 03:33:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-12 01:32:58 +00:00
|
|
|
|
public void Dispose()
|
2012-10-23 03:33:57 +00:00
|
|
|
|
{
|
2012-12-12 01:32:58 +00:00
|
|
|
|
if (resampler != null)
|
|
|
|
|
{
|
|
|
|
|
resampler.Dispose();
|
|
|
|
|
resampler = null;
|
|
|
|
|
}
|
2012-10-23 03:33:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-12-16 18:16:50 +00:00
|
|
|
|
#endregion
|
2012-10-23 03:33:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|