2014-06-29 00:57:33 +00:00
using System ;
using System.Collections.Generic ;
2013-11-30 02:20:34 +00:00
namespace BizHawk.Client.Common
{
public class PlatformFrameRates
{
2019-11-15 21:15:13 +00:00
// these are political numbers, designed to be in accord with tasvideos.org tradition. they're not necessarily mathematical factualities (although they may be in some cases)
// it would be nice if we could turn this into a rational expression natively, and also, to write some comments about the derivation and ideal values (since this seems to be where they're all collected)
2014-02-04 03:08:20 +00:00
// are we collecting them anywhere else? for avi-writing code perhaps?
2015-09-28 21:52:23 +00:00
// just some constants, according to specs
2017-05-18 16:36:38 +00:00
private static readonly double PALCarrier = ( 15625 * 283.75 ) + 25 ; // 4.43361875 MHz
private static readonly double NTSCCarrier = 4500000 * 227.5 / 286 ; // 3.579545454... MHz
private static readonly double PALNCarrier = ( 15625 * 229.25 ) + 25 ; // 3.58205625 MHz
2015-09-28 21:52:23 +00:00
2017-05-18 16:36:38 +00:00
private static readonly Dictionary < string , double > Rates = new Dictionary < string , double >
{
["NES"] = 60.098813897440515532 , // discussion here: http://forums.nesdev.com/viewtopic.php?t=492 ; a rational expression would be (19687500 / 11) / ((341*262-0.529780.5)/3) -> (118125000 / 1965513) -> 60.098813897440515529533511098629 (so our chosen number is very close)
["NES_PAL"] = 50.006977968268290849 ,
["FDS"] = 60.098813897440515532 ,
["FDS_PAL"] = 50.006977968268290849 ,
2020-01-24 21:55:48 +00:00
["SNES"] = 21477272.0 / ( 4 * 341 * 262 ) , // 60.098475521
["SNES_PAL"] = 21281370.0 / ( 4 * 341 * 312 ) , // 50.0069789082
["SGB"] = 21477272.0 / ( 4 * 341 * 262 ) , // 60.098475521
["SGB_PAL"] = 21281370.0 / ( 4 * 341 * 312 ) , // 50.0069789082
2017-05-18 16:36:38 +00:00
["PCE"] = ( 7159090.90909090 / 455 / 263 ) , // 59.8261054535
["PCECD"] = ( 7159090.90909090 / 455 / 263 ) , // 59.8261054535
["SMS"] = ( 3579545 / 262.0 / 228.0 ) , // 59.9227434043
["SMS_PAL"] = ( 3546893 / 313.0 / 228.0 ) , // 49.7014320946
["GG"] = ( 3579545 / 262.0 / 228.0 ) , // 59.9227434043
["GG_PAL"] = ( 3546893 / 313.0 / 228.0 ) , // 49.7014320946
["SG"] = ( 3579545 / 262.0 / 228.0 ) , // 59.9227434043
["SG_PAL"] = ( 3546893 / 313.0 / 228.0 ) , // 49.7014320946
["NGP"] = ( 6144000.0 / ( 515 * 198 ) ) , // 60.2530155928
2017-05-30 22:42:09 +00:00
["VB"] = ( 20000000.0 / ( 259 * 384 * 4 ) ) , // 50.2734877735
2017-05-18 16:36:38 +00:00
["Lynx"] = 16000000.0 / ( 16 * 105 * 159 ) , // 59.89817310572028
["WSWAN"] = ( 3072000.0 / ( 159 * 256 ) ) , // 75.4716981132
["GB"] = 262144.0 / 4389.0 , // 59.7275005696
["GBC"] = 262144.0 / 4389.0 , // 59.7275005696
2020-02-08 12:36:06 +00:00
["GB_Clock"] = 2097152.0 ,
2017-05-18 16:36:38 +00:00
["GBA"] = 262144.0 / 4389.0 , // 59.7275005696
["GEN"] = 53693175 / ( 3420.0 * 262 ) ,
["GEN_PAL"] = 53203424 / ( 3420.0 * 313 ) ,
// while the number of scanlines per frame is software controlled and variable, we
// enforce exactly 262 (NTSC) 312 (PAL) per reference time frame
["A26"] = 315000000.0 / 88.0 / 262.0 / 228.0 , // 59.922751013550531429197560173856
// this pal clock ref is exact
["A26_PAL"] = 3546895.0 / 312.0 / 228.0 , // 49.860759671614934772829509671615
["A78"] = 59.9227510135505 ,
["Coleco"] = 59.9227510135505 ,
// according to http://problemkaputt.de/psx-spx.htm
["PSX"] = 44100.0 * 768 * 11 / 7 / 263 / 3413 , // 59.292862562
["PSX_PAL"] = 44100.0 * 768 * 11 / 7 / 314 / 3406 , // 49.7645593576
["C64_PAL"] = PALCarrier * 2 / 9 / 312 / 63 ,
["C64_NTSC"] = NTSCCarrier * 2 / 7 / 263 / 65 ,
["C64_NTSC_OLD"] = NTSCCarrier * 2 / 7 / 262 / 64 ,
["C64_DREAN"] = PALNCarrier * 2 / 7 / 312 / 65 ,
2018-05-08 20:57:19 +00:00
["INTV"] = 59.92 ,
2019-11-04 01:55:38 +00:00
["ZXSpectrum_PAL"] = 50.080128205 ,
["AmstradCPC_PAL"] = 50.08012820512821 ,
2017-05-18 16:36:38 +00:00
2019-11-04 01:55:38 +00:00
// according to ryphecha, using
// clocks[2] = { 53.693182e06, 53.203425e06 }; //ntsc console, pal console
2019-11-15 21:15:13 +00:00
// lpf[2][2] = { { 263, 262.5 }, { 314, 312.5 } }; //ntsc,pal; non-interlaced, interlaced
2019-11-04 01:55:38 +00:00
// cpl[2] = { 3412.5, 3405 }; //ntsc mode, pal mode
// PAL PS1: 0, PAL Mode: 0, Interlaced: 0 --- 59.826106 (53.693182e06/(263*3412.5))
// PAL PS1: 0, PAL Mode: 0, Interlaced: 1 --- 59.940060 (53.693182e06/(262.5*3412.5))
// PAL PS1: 1, PAL Mode: 1, Interlaced: 0 --- 49.761427 (53.203425e06/(314*3405))
// PAL PS1: 1, PAL Mode: 1, Interlaced: 1 --- 50.000282(53.203425e06/(312.5*3405))
} ;
2014-02-04 03:08:20 +00:00
public double this [ string systemId , bool pal ]
{
get
{
2017-05-10 11:45:23 +00:00
var key = systemId + ( pal ? "_PAL" : "" ) ;
2020-03-01 21:49:48 +00:00
return Rates . ContainsKey ( key ) ? Rates [ key ] : 60.0 ;
2014-02-04 03:08:20 +00:00
}
}
2014-06-29 00:57:33 +00:00
public TimeSpan MovieTime ( IMovie movie )
{
2019-11-15 21:15:13 +00:00
var dblSeconds = GetSeconds ( movie ) ;
var seconds = ( int ) ( dblSeconds % 60 ) ;
2014-06-29 00:57:33 +00:00
var days = seconds / 86400 ;
var hours = seconds / 3600 ;
var minutes = ( seconds / 60 ) % 60 ;
2019-11-15 21:15:13 +00:00
var milliseconds = ( int ) ( ( dblSeconds - seconds ) * 1000 ) ;
2014-06-29 00:57:33 +00:00
return new TimeSpan ( days , hours , minutes , seconds , milliseconds ) ;
}
private double Fps ( IMovie movie )
{
2020-03-01 22:36:47 +00:00
var system = movie . HeaderEntries [ HeaderKeys . Platform ] ;
var core = movie . HeaderEntries [ HeaderKeys . Core ] ;
var pal = movie . HeaderEntries . ContainsKey ( HeaderKeys . Pal )
& & movie . HeaderEntries [ HeaderKeys . Pal ] = = "1" ;
2014-06-29 00:57:33 +00:00
2020-03-01 22:36:47 +00:00
if ( movie . HeaderEntries . ContainsKey ( HeaderKeys . CycleCount ) & & core = = "Gambatte" )
2020-02-08 12:36:06 +00:00
{
system = "GB_Clock" ;
}
2019-11-15 21:15:13 +00:00
return this [ system , pal ] ;
2014-06-29 00:57:33 +00:00
}
private double GetSeconds ( IMovie movie )
{
2019-06-21 21:58:13 +00:00
double frames = movie . TimeLength ;
2014-06-29 00:57:33 +00:00
if ( frames < 1 )
{
return 0 ;
}
return frames / Fps ( movie ) ;
}
2013-11-30 02:20:34 +00:00
}
}