2014-08-08 00:55:33 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.IO ;
using BizHawk.Common.BufferExtensions ;
using BizHawk.Emulation.Common ;
2014-08-08 20:01:09 +00:00
using Newtonsoft.Json ;
2014-08-13 20:33:59 +00:00
using System.ComponentModel ;
using BizHawk.Common ;
2014-08-08 00:55:33 +00:00
namespace BizHawk.Emulation.Cores.Nintendo.GBA
{
2014-08-24 14:11:30 +00:00
[CoreAttributes("VBA-Next", "many authors", true, true, "cd508312a29ed8c29dacac1b11c2dce56c338a54", "https://github.com/libretro/vba-next")]
2014-12-12 01:58:12 +00:00
[ServiceNotApplicable(typeof(IDriveLight))]
2014-11-30 20:29:30 +00:00
public class VBANext : IEmulator , IVideoProvider , ISyncSoundProvider , IInputPollable ,
2014-11-30 16:42:58 +00:00
IGBAGPUViewable , IMemoryDomains , ISaveRam , IStatable , IDebuggable , ISettable < object , VBANext . SyncSettings >
2014-08-08 00:55:33 +00:00
{
IntPtr Core ;
2014-08-23 19:06:37 +00:00
[CoreConstructor("GBA")]
2014-09-12 15:39:04 +00:00
public VBANext ( byte [ ] file , CoreComm comm , GameInfo game , bool deterministic , object syncsettings )
2014-08-08 00:55:33 +00:00
{
2014-12-13 21:49:15 +00:00
var ser = new BasicServiceProvider ( this ) ;
ser . Register < IDisassemblable > ( new ArmV4Disassembler ( ) ) ;
ServiceProvider = ser ;
2014-08-23 19:06:37 +00:00
CoreComm = comm ;
2014-12-05 01:56:45 +00:00
2014-08-08 00:55:33 +00:00
byte [ ] biosfile = CoreComm . CoreFileProvider . GetFirmware ( "GBA" , "Bios" , true , "GBA bios file is mandatory." ) ;
2014-09-12 15:39:04 +00:00
if ( file . Length > 32 * 1024 * 1024 )
2014-08-08 00:55:33 +00:00
throw new ArgumentException ( "ROM is too big to be a GBA ROM!" ) ;
if ( biosfile . Length ! = 16 * 1024 )
throw new ArgumentException ( "BIOS file is not exactly 16K!" ) ;
2014-08-13 20:33:59 +00:00
LibVBANext . FrontEndSettings FES = new LibVBANext . FrontEndSettings ( ) ;
2014-08-23 19:06:37 +00:00
FES . saveType = ( LibVBANext . FrontEndSettings . SaveType ) game . GetInt ( "saveType" , 0 ) ;
FES . flashSize = ( LibVBANext . FrontEndSettings . FlashSize ) game . GetInt ( "flashSize" , 0x10000 ) ;
FES . enableRtc = game . GetInt ( "rtcEnabled" , 0 ) ! = 0 ;
FES . mirroringEnable = game . GetInt ( "mirroringEnabled" , 0 ) ! = 0 ;
2014-08-13 21:49:28 +00:00
Console . WriteLine ( "GameDB loaded settings: saveType={0}, flashSize={1}, rtcEnabled={2}, mirroringEnabled={3}" ,
FES . saveType , FES . flashSize , FES . enableRtc , FES . mirroringEnable ) ;
2014-08-13 20:33:59 +00:00
2014-08-23 19:06:37 +00:00
_SyncSettings = ( SyncSettings ) syncsettings ? ? new SyncSettings ( ) ;
2014-08-13 20:33:59 +00:00
DeterministicEmulation = deterministic ;
FES . skipBios = _SyncSettings . SkipBios ;
FES . RTCUseRealTime = _SyncSettings . RTCUseRealTime ;
FES . RTCwday = ( int ) _SyncSettings . RTCInitialDay ;
FES . RTCyear = _SyncSettings . RTCInitialTime . Year % 100 ;
FES . RTCmonth = _SyncSettings . RTCInitialTime . Month - 1 ;
FES . RTCmday = _SyncSettings . RTCInitialTime . Day ;
FES . RTChour = _SyncSettings . RTCInitialTime . Hour ;
FES . RTCmin = _SyncSettings . RTCInitialTime . Minute ;
FES . RTCsec = _SyncSettings . RTCInitialTime . Second ;
if ( DeterministicEmulation )
{
2014-08-27 22:19:26 +00:00
// FES.skipBios = false; // this is OK; it is deterministic and probably accurate
2014-08-13 20:33:59 +00:00
FES . RTCUseRealTime = false ;
}
2014-08-12 00:34:19 +00:00
2014-08-08 00:55:33 +00:00
Core = LibVBANext . Create ( ) ;
if ( Core = = IntPtr . Zero )
throw new InvalidOperationException ( "Create() returned nullptr!" ) ;
try
{
2014-09-12 15:39:04 +00:00
if ( ! LibVBANext . LoadRom ( Core , file , ( uint ) file . Length , biosfile , ( uint ) biosfile . Length , FES ) )
2014-08-08 00:55:33 +00:00
throw new InvalidOperationException ( "LoadRom() returned false!" ) ;
2014-08-08 20:01:09 +00:00
2014-12-05 00:05:40 +00:00
Tracer = new TraceBuffer ( ) ;
2014-08-08 20:01:09 +00:00
CoreComm . VsyncNum = 262144 ;
CoreComm . VsyncDen = 4389 ;
CoreComm . NominalWidth = 240 ;
CoreComm . NominalHeight = 160 ;
2014-09-12 15:39:04 +00:00
GameCode = Encoding . ASCII . GetString ( file , 0xac , 4 ) ;
2014-08-11 15:29:53 +00:00
Console . WriteLine ( "Game code \"{0}\"" , GameCode ) ;
2014-08-08 20:01:09 +00:00
savebuff = new byte [ LibVBANext . BinStateSize ( Core ) ] ;
savebuff2 = new byte [ savebuff . Length + 13 ] ;
2014-08-16 05:45:31 +00:00
InitMemoryDomains ( ) ;
2014-08-21 23:51:25 +00:00
InitRegisters ( ) ;
2014-08-24 00:04:57 +00:00
InitCallbacks ( ) ;
2014-08-17 20:05:56 +00:00
// todo: hook me up as a setting
SetupColors ( ) ;
2014-08-08 00:55:33 +00:00
}
catch
{
Dispose ( ) ;
throw ;
}
}
2014-12-04 03:38:30 +00:00
public IEmulatorServiceProvider ServiceProvider { get ; private set ; }
2014-08-08 00:55:33 +00:00
public void FrameAdvance ( bool render , bool rendersound = true )
{
Frame + + ;
if ( Controller [ "Power" ] )
LibVBANext . Reset ( Core ) ;
2014-12-05 02:27:39 +00:00
SyncTraceCallback ( ) ;
2014-08-24 00:04:57 +00:00
2014-08-17 20:05:56 +00:00
IsLagFrame = LibVBANext . FrameAdvance ( Core , GetButtons ( ) , videobuff , soundbuff , out numsamp , videopalette ) ;
2014-08-08 00:55:33 +00:00
if ( IsLagFrame )
LagCount + + ;
}
public int Frame { get ; private set ; }
public int LagCount { get ; set ; }
public bool IsLagFrame { get ; private set ; }
2014-12-05 00:05:40 +00:00
public ITracer Tracer { get ; private set ; }
2014-08-08 00:55:33 +00:00
public string SystemId { get { return "GBA" ; } }
2014-08-13 20:33:59 +00:00
public bool DeterministicEmulation { get ; private set ; }
2014-08-08 00:55:33 +00:00
public void ResetCounters ( )
{
Frame = 0 ;
LagCount = 0 ;
IsLagFrame = false ;
}
2014-08-11 15:29:53 +00:00
public string BoardName { get { return null ; } }
/// <summary>
/// set in the ROM internal header
/// </summary>
public string GameCode { get ; private set ; }
2014-08-08 00:55:33 +00:00
public CoreComm CoreComm { get ; private set ; }
public void Dispose ( )
{
if ( Core ! = IntPtr . Zero )
{
LibVBANext . Destroy ( Core ) ;
Core = IntPtr . Zero ;
}
}
#region SaveRam
2014-08-13 17:52:13 +00:00
public byte [ ] CloneSaveRam ( )
2014-08-08 00:55:33 +00:00
{
2014-08-13 20:33:59 +00:00
byte [ ] data = new byte [ LibVBANext . SaveRamSize ( Core ) ] ;
if ( ! LibVBANext . SaveRamSave ( Core , data , data . Length ) )
throw new InvalidOperationException ( "SaveRamSave() failed!" ) ;
return data ;
2014-08-08 00:55:33 +00:00
}
public void StoreSaveRam ( byte [ ] data )
{
2014-08-13 20:33:59 +00:00
// internally, we try to salvage bad-sized saverams
if ( ! LibVBANext . SaveRamLoad ( Core , data , data . Length ) )
throw new InvalidOperationException ( "SaveRamLoad() failed!" ) ;
2014-08-08 00:55:33 +00:00
}
public bool SaveRamModified
{
get
{
2014-08-13 20:33:59 +00:00
return LibVBANext . SaveRamSize ( Core ) ! = 0 ;
2014-08-08 00:55:33 +00:00
}
}
#endregion
#region SaveStates
2014-08-08 20:01:09 +00:00
JsonSerializer ser = new JsonSerializer ( ) { Formatting = Formatting . Indented } ;
byte [ ] savebuff ;
byte [ ] savebuff2 ;
class TextStateData
{
public int Frame ;
public int LagCount ;
public bool IsLagFrame ;
}
2014-08-08 00:55:33 +00:00
public void SaveStateText ( TextWriter writer )
{
2014-08-08 20:01:09 +00:00
var s = new TextState < TextStateData > ( ) ;
s . Prepare ( ) ;
var ff = s . GetFunctionPointersSave ( ) ;
LibVBANext . TxtStateSave ( Core , ref ff ) ;
s . ExtraData . IsLagFrame = IsLagFrame ;
s . ExtraData . LagCount = LagCount ;
s . ExtraData . Frame = Frame ;
ser . Serialize ( writer , s ) ;
// write extra copy of stuff we don't use
writer . WriteLine ( ) ;
writer . WriteLine ( "Frame {0}" , Frame ) ;
//Console.WriteLine(BizHawk.Common.BufferExtensions.BufferExtensions.HashSHA1(SaveStateBinary()));
2014-08-08 00:55:33 +00:00
}
public void LoadStateText ( TextReader reader )
{
2014-08-08 20:01:09 +00:00
var s = ( TextState < TextStateData > ) ser . Deserialize ( reader , typeof ( TextState < TextStateData > ) ) ;
s . Prepare ( ) ;
var ff = s . GetFunctionPointersLoad ( ) ;
LibVBANext . TxtStateLoad ( Core , ref ff ) ;
IsLagFrame = s . ExtraData . IsLagFrame ;
LagCount = s . ExtraData . LagCount ;
Frame = s . ExtraData . Frame ;
2014-08-08 00:55:33 +00:00
}
public void SaveStateBinary ( BinaryWriter writer )
{
2014-08-08 20:01:09 +00:00
if ( ! LibVBANext . BinStateSave ( Core , savebuff , savebuff . Length ) )
throw new InvalidOperationException ( "Core's BinStateSave() returned false!" ) ;
writer . Write ( savebuff . Length ) ;
writer . Write ( savebuff ) ;
// other variables
writer . Write ( IsLagFrame ) ;
writer . Write ( LagCount ) ;
writer . Write ( Frame ) ;
2014-08-08 00:55:33 +00:00
}
public void LoadStateBinary ( BinaryReader reader )
{
2014-08-08 20:01:09 +00:00
int length = reader . ReadInt32 ( ) ;
if ( length ! = savebuff . Length )
throw new InvalidOperationException ( "Save buffer size mismatch!" ) ;
reader . Read ( savebuff , 0 , length ) ;
if ( ! LibVBANext . BinStateLoad ( Core , savebuff , savebuff . Length ) )
throw new InvalidOperationException ( "Core's BinStateLoad() returned false!" ) ;
// other variables
IsLagFrame = reader . ReadBoolean ( ) ;
LagCount = reader . ReadInt32 ( ) ;
Frame = reader . ReadInt32 ( ) ;
2014-08-08 00:55:33 +00:00
}
public byte [ ] SaveStateBinary ( )
{
2014-08-08 20:01:09 +00:00
var ms = new MemoryStream ( savebuff2 , true ) ;
var bw = new BinaryWriter ( ms ) ;
SaveStateBinary ( bw ) ;
bw . Flush ( ) ;
if ( ms . Position ! = savebuff2 . Length )
throw new InvalidOperationException ( ) ;
ms . Close ( ) ;
return savebuff2 ;
2014-08-08 00:55:33 +00:00
}
public bool BinarySaveStatesPreferred
{
get { return true ; }
}
#endregion
#region Debugging
2014-08-24 00:04:57 +00:00
LibVBANext . StandardCallback padcb ;
LibVBANext . AddressCallback fetchcb ;
LibVBANext . AddressCallback readcb ;
LibVBANext . AddressCallback writecb ;
2014-11-19 02:24:33 +00:00
LibVBANext . TraceCallback tracecb ;
2014-08-24 00:04:57 +00:00
2014-12-05 02:27:39 +00:00
private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem ( ) ;
public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks ; } }
private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem ( ) ;
public IMemoryCallbackSystem MemoryCallbacks { get { return _memorycallbacks ; } }
2014-11-19 03:16:36 +00:00
string Trace ( uint addr , uint opcode )
{
return
2014-11-19 03:33:09 +00:00
string . Format ( "{0:x8} {1} {2}" ,
2014-11-19 03:16:36 +00:00
opcode ,
2014-11-19 03:33:09 +00:00
( Emulation . Cores . Components . ARM . Darm . DisassembleStuff ( addr , opcode ) ? ? "" ) . PadRight ( 30 ) ,
regs . TraceString ( ) ) ;
2014-11-19 03:16:36 +00:00
}
2014-08-24 00:04:57 +00:00
void InitCallbacks ( )
{
2014-12-04 00:43:12 +00:00
padcb = new LibVBANext . StandardCallback ( ( ) = > InputCallbacks . Call ( ) ) ;
2014-12-07 18:53:56 +00:00
fetchcb = new LibVBANext . AddressCallback ( ( addr ) = > MemoryCallbacks . CallExecutes ( addr ) ) ;
readcb = new LibVBANext . AddressCallback ( ( addr ) = > MemoryCallbacks . CallReads ( addr ) ) ;
writecb = new LibVBANext . AddressCallback ( ( addr ) = > MemoryCallbacks . CallWrites ( addr ) ) ;
2014-12-05 00:05:40 +00:00
tracecb = new LibVBANext . TraceCallback ( ( addr , opcode ) = > Tracer . Put ( Trace ( addr , opcode ) ) ) ;
2014-12-04 01:46:59 +00:00
_inputCallbacks . ActiveChanged + = SyncPadCallback ;
2014-12-05 02:27:39 +00:00
_memorycallbacks . ActiveChanged + = SyncMemoryCallbacks ;
2014-12-04 01:46:59 +00:00
}
void SyncPadCallback ( )
{
2014-12-05 02:27:39 +00:00
LibVBANext . SetPadCallback ( Core , InputCallbacks . Any ( ) ? padcb : null ) ;
2014-08-24 00:04:57 +00:00
}
2014-12-05 02:27:39 +00:00
void SyncMemoryCallbacks ( )
2014-08-24 00:04:57 +00:00
{
2014-12-05 01:56:45 +00:00
LibVBANext . SetFetchCallback ( Core , MemoryCallbacks . HasExecutes ? fetchcb : null ) ;
LibVBANext . SetReadCallback ( Core , MemoryCallbacks . HasReads ? readcb : null ) ;
LibVBANext . SetWriteCallback ( Core , MemoryCallbacks . HasWrites ? writecb : null ) ;
2014-12-05 02:27:39 +00:00
}
2014-12-05 02:39:42 +00:00
void SyncTraceCallback ( )
2014-12-05 02:27:39 +00:00
{
2014-12-05 00:05:40 +00:00
LibVBANext . SetTraceCallback ( Core , Tracer . Enabled ? tracecb : null ) ;
2014-08-24 00:04:57 +00:00
}
2014-08-17 19:02:10 +00:00
LibVBANext . StandardCallback scanlinecb ;
GBAGPUMemoryAreas IGBAGPUViewable . GetMemoryAreas ( )
{
var s = new LibVBANext . MemoryAreas ( ) ;
LibVBANext . GetMemoryAreas ( Core , s ) ;
return new GBAGPUMemoryAreas
{
mmio = s . mmio ,
oam = s . oam ,
palram = s . palram ,
vram = s . vram
} ;
}
void IGBAGPUViewable . SetScanlineCallback ( Action callback , int scanline )
{
if ( scanline < 0 | | scanline > 227 )
{
throw new ArgumentOutOfRangeException ( "Scanline must be in [0, 227]!" ) ;
}
if ( callback = = null )
{
scanlinecb = null ;
LibVBANext . SetScanlineCallback ( Core , scanlinecb , 0 ) ;
}
else
{
scanlinecb = new LibVBANext . StandardCallback ( callback ) ;
LibVBANext . SetScanlineCallback ( Core , scanlinecb , scanline ) ;
}
}
2014-08-16 05:45:31 +00:00
void InitMemoryDomains ( )
2014-08-08 00:55:33 +00:00
{
2014-08-16 05:45:31 +00:00
var mm = new List < MemoryDomain > ( ) ;
var s = new LibVBANext . MemoryAreas ( ) ;
var l = MemoryDomain . Endian . Little ;
LibVBANext . GetMemoryAreas ( Core , s ) ;
mm . Add ( MemoryDomain . FromIntPtr ( "IWRAM" , 32 * 1024 , l , s . iwram ) ) ;
mm . Add ( MemoryDomain . FromIntPtr ( "EWRAM" , 256 * 1024 , l , s . ewram ) ) ;
mm . Add ( MemoryDomain . FromIntPtr ( "BIOS" , 16 * 1024 , l , s . bios , false ) ) ;
mm . Add ( MemoryDomain . FromIntPtr ( "PALRAM" , 1024 , l , s . palram , false ) ) ;
mm . Add ( MemoryDomain . FromIntPtr ( "VRAM" , 96 * 1024 , l , s . vram ) ) ;
mm . Add ( MemoryDomain . FromIntPtr ( "OAM" , 1024 , l , s . oam ) ) ;
mm . Add ( MemoryDomain . FromIntPtr ( "ROM" , 32 * 1024 * 1024 , l , s . rom ) ) ;
2014-10-31 15:46:13 +00:00
2014-08-16 05:45:31 +00:00
mm . Add ( new MemoryDomain ( "BUS" , 0x10000000 , l ,
delegate ( int addr )
{
if ( addr < 0 | | addr > = 0x10000000 )
throw new ArgumentOutOfRangeException ( ) ;
return LibVBANext . SystemBusRead ( Core , addr ) ;
} ,
delegate ( int addr , byte val )
{
if ( addr < 0 | | addr > = 0x10000000 )
throw new ArgumentOutOfRangeException ( ) ;
LibVBANext . SystemBusWrite ( Core , addr , val ) ;
} ) ) ;
2014-08-17 20:32:08 +00:00
// special combined ram memory domain
{
var ew = mm [ 1 ] ;
var iw = mm [ 0 ] ;
MemoryDomain cr = new MemoryDomain ( "Combined WRAM" , ( 256 + 32 ) * 1024 , MemoryDomain . Endian . Little ,
delegate ( int addr )
{
if ( addr < 0 | | addr > = ( 256 + 32 ) * 1024 )
throw new IndexOutOfRangeException ( ) ;
if ( addr > = 256 * 1024 )
return iw . PeekByte ( addr & 32767 ) ;
else
return ew . PeekByte ( addr ) ;
} ,
delegate ( int addr , byte val )
{
if ( addr < 0 | | addr > = ( 256 + 32 ) * 1024 )
throw new IndexOutOfRangeException ( ) ;
if ( addr > = 256 * 1024 )
iw . PokeByte ( addr & 32767 , val ) ;
else
ew . PokeByte ( addr , val ) ;
} ) ;
mm . Add ( cr ) ;
}
2014-08-16 05:45:31 +00:00
MemoryDomains = new MemoryDomainList ( mm , 0 ) ;
2014-08-08 00:55:33 +00:00
}
2014-08-16 05:45:31 +00:00
public MemoryDomainList MemoryDomains { get ; private set ; }
2014-08-21 23:51:25 +00:00
VBARegisterHelper regs ;
void InitRegisters ( )
{
regs = new VBARegisterHelper ( Core ) ;
}
2014-11-23 16:22:02 +00:00
public IDictionary < string , int > GetCpuFlagsAndRegisters ( )
2014-08-08 00:55:33 +00:00
{
2014-08-21 23:51:25 +00:00
return regs . GetAllRegisters ( ) ;
2014-08-08 00:55:33 +00:00
}
public void SetCpuRegister ( string register , int value )
{
2014-08-21 23:51:25 +00:00
regs . SetRegister ( register , value ) ;
2014-08-08 00:55:33 +00:00
}
2014-12-14 18:58:16 +00:00
[FeatureNotImplemented]
public void StepInto ( ) { throw new NotImplementedException ( ) ; }
[FeatureNotImplemented]
public void StepOut ( ) { throw new NotImplementedException ( ) ; }
[FeatureNotImplemented]
public void StepOver ( ) { throw new NotImplementedException ( ) ; }
2014-08-08 00:55:33 +00:00
#endregion
#region Settings
public object GetSettings ( )
{
return null ;
}
2014-10-19 01:22:47 +00:00
public SyncSettings GetSyncSettings ( )
2014-08-08 00:55:33 +00:00
{
2014-08-13 20:33:59 +00:00
return _SyncSettings . Clone ( ) ;
2014-08-08 00:55:33 +00:00
}
2014-08-13 20:33:59 +00:00
SyncSettings _SyncSettings ;
2014-08-08 00:55:33 +00:00
public bool PutSettings ( object o )
{
return false ;
}
2014-10-19 01:22:47 +00:00
public bool PutSyncSettings ( SyncSettings o )
2014-08-08 00:55:33 +00:00
{
2014-10-19 01:22:47 +00:00
bool ret = SyncSettings . NeedsReboot ( o , _SyncSettings ) ;
_SyncSettings = o ;
2014-08-13 20:33:59 +00:00
return ret ;
}
public class SyncSettings
{
[DisplayName("Skip BIOS")]
2014-08-27 22:19:26 +00:00
[Description("Skips the BIOS intro. A BIOS file is still required.")]
2014-08-24 17:33:23 +00:00
[DefaultValue(true)]
2014-08-13 20:33:59 +00:00
public bool SkipBios { get ; set ; }
[DisplayName("RTC Use Real Time")]
[Description("Causes the internal clock to reflect your system clock. Only relevant when a game has an RTC chip. Forced to false for movie recording.")]
[DefaultValue(true)]
public bool RTCUseRealTime { get ; set ; }
[DisplayName("RTC Initial Time")]
[Description("The initial time of emulation. Only relevant when a game has an RTC chip and \"RTC Use Real Time\" is false.")]
[DefaultValue(typeof(DateTime), "2010-01-01")]
public DateTime RTCInitialTime { get ; set ; }
public enum DayOfWeek
{
Sunday = 0 ,
Monday ,
Tuesday ,
Wednesday ,
Thursday ,
Friday ,
Saturday
}
[DisplayName("RTC Initial Day")]
[Description("The day of the week to go with \"RTC Initial Time\". Due to peculiarities in the RTC chip, this can be set indepedently of the year, month, and day of month.")]
[DefaultValue(DayOfWeek.Friday)]
public DayOfWeek RTCInitialDay { get ; set ; }
public SyncSettings ( )
{
SettingsUtil . SetDefaultValues ( this ) ;
}
public static bool NeedsReboot ( SyncSettings x , SyncSettings y )
{
return ! DeepEquality . DeepEquals ( x , y ) ;
}
public SyncSettings Clone ( )
{
return ( SyncSettings ) MemberwiseClone ( ) ;
}
2014-08-08 00:55:33 +00:00
}
#endregion
#region Controller
public ControllerDefinition ControllerDefinition { get { return GBA . GBAController ; } }
public IController Controller { get ; set ; }
private LibVBANext . Buttons GetButtons ( )
{
LibVBANext . Buttons ret = 0 ;
foreach ( string s in Enum . GetNames ( typeof ( LibVBANext . Buttons ) ) )
{
if ( Controller [ s ] )
ret | = ( LibVBANext . Buttons ) Enum . Parse ( typeof ( LibVBANext . Buttons ) , s ) ;
}
return ret ;
}
#endregion
#region VideoProvider
int [ ] videobuff = new int [ 240 * 160 ] ;
2014-08-17 20:05:56 +00:00
int [ ] videopalette = new int [ 65536 ] ;
2014-08-08 00:55:33 +00:00
public IVideoProvider VideoProvider { get { return this ; } }
public int [ ] GetVideoBuffer ( ) { return videobuff ; }
public int VirtualWidth { get { return 240 ; } }
public int VirtualHeight { get { return 160 ; } }
public int BufferWidth { get { return 240 ; } }
public int BufferHeight { get { return 160 ; } }
public int BackgroundColor { get { return unchecked ( ( int ) 0xff000000 ) ; } }
2014-08-17 20:05:56 +00:00
void SetupColors ( )
{
int [ ] tmp = BizHawk . Emulation . Cores . Nintendo . Gameboy . GBColors . GetLut ( Gameboy . GBColors . ColorType . vivid ) ;
// reorder
for ( int i = 0 ; i < 32768 ; i + + )
{
int j = i & 0x3e0 | ( i & 0x1f ) < < 10 | i > > 10 & 0x1f ;
videopalette [ i ] = tmp [ j ] ;
}
// duplicate
Array . Copy ( videopalette , 0 , videopalette , 32768 , 32768 ) ;
}
2014-08-08 00:55:33 +00:00
#endregion
#region SoundProvider
short [ ] soundbuff = new short [ 2048 ] ;
2014-08-08 04:09:50 +00:00
int numsamp ;
2014-08-08 00:55:33 +00:00
public ISoundProvider SoundProvider { get { return null ; } }
public ISyncSoundProvider SyncSoundProvider { get { return this ; } }
public bool StartAsyncSound ( ) { return false ; }
public void EndAsyncSound ( ) { }
public void GetSamples ( out short [ ] samples , out int nsamp )
{
samples = soundbuff ;
2014-08-08 04:09:50 +00:00
nsamp = numsamp ;
2014-08-08 00:55:33 +00:00
}
public void DiscardSamples ( )
{
}
#endregion
}
}