2014-12-10 19:41:13 +00:00
//TODO hook up newer file ID stuff, think about how to combine it with the disc ID
//TODO not liking the name ShockFramebufferJob
//TODO change display manager to not require 0xFF alpha channel set on videoproviders. check gdi+ and opengl! this will get us a speedup in some places
//TODO Disc.Structure.Sessions[0].length_aba was 0
//looks like we can have (in NTSC) framebuffer dimensions like this:
//width: 280, 350, 700
//height: 240, 480
//mednafen's strategy is to put everything in a 320x240 and scale it up 3x to 960x720 by default (which is adequate to contain the largest PSX framebuffer)
//heres my strategy.
//1. we should have a native output mode, for debugging. but most users wont want it (massively distorted resolutions are common in games)
//2. do the right thing:
//always double a height of 240, and double a width of 280 or 350. For 280, float content in center screen.
//but lets not do this til we're on an upgraded mednafen
using System ;
2012-11-04 23:29:06 +00:00
using System.Runtime.InteropServices ;
using System.IO ;
using System.Collections.Generic ;
2013-11-04 01:39:19 +00:00
using BizHawk.Emulation.Common ;
2013-10-27 17:07:37 +00:00
#pragma warning disable 649 //adelikat: Disable dumb warnings until this file is complete
2013-11-13 23:36:21 +00:00
namespace BizHawk.Emulation.Cores.Sony.PSX
2012-11-04 23:29:06 +00:00
{
2014-04-25 01:19:57 +00:00
[ CoreAttributes (
2014-12-10 19:41:13 +00:00
"Octoshock" ,
2014-04-25 01:19:57 +00:00
"Ryphecha" ,
isPorted : true ,
isReleased : false
) ]
2014-11-24 01:17:05 +00:00
public unsafe class Octoshock : IEmulator , IVideoProvider , ISoundProvider
2012-11-04 23:29:06 +00:00
{
public string SystemId { get { return "NULL" ; } }
public static readonly ControllerDefinition NullController = new ControllerDefinition { Name = "Null Controller" } ;
2013-08-24 16:54:22 +00:00
public string BoardName { get { return null ; } }
2012-11-04 23:29:06 +00:00
private int [ ] frameBuffer = new int [ 0 ] ;
private Random rand = new Random ( ) ;
2012-12-10 00:43:43 +00:00
public CoreComm CoreComm { get ; private set ; }
2012-11-04 23:29:06 +00:00
public IVideoProvider VideoProvider { get { return this ; } }
public ISoundProvider SoundProvider { get { return this ; } }
public ISyncSoundProvider SyncSoundProvider { get { return new FakeSyncSound ( this , 735 ) ; } }
public bool StartAsyncSound ( ) { return true ; }
public void EndAsyncSound ( ) { }
//we can only have one active core at a time, due to the lib being so static.
//so we'll track the current one here and detach the previous one whenever a new one is booted up.
static Octoshock CurrOctoshockCore ;
2014-12-10 19:41:13 +00:00
IntPtr psx ;
DiscSystem . Disc disc ;
DiscInterface discInterface ;
2012-11-04 23:29:06 +00:00
bool disposed = false ;
public void Dispose ( )
{
if ( disposed ) return ;
2014-12-10 19:41:13 +00:00
OctoshockDll . shock_Destroy ( psx ) ;
psx = IntPtr . Zero ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
disposed = true ;
2012-11-04 23:29:06 +00:00
}
2014-12-10 19:41:13 +00:00
class DiscInterface : IDisposable
2012-11-04 23:29:06 +00:00
{
2014-12-10 19:41:13 +00:00
public DiscInterface ( DiscSystem . Disc disc )
{
this . Disc = disc ;
cbReadTOC = ShockDisc_ReadTOC ;
cbReadLBA = ShockDisc_ReadLBA2448 ;
OctoshockDll . shock_CreateDisc ( out OctoshockHandle , IntPtr . Zero , disc . LBACount , cbReadTOC , cbReadLBA , true ) ;
}
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
OctoshockDll . ShockDisc_ReadTOC cbReadTOC ;
OctoshockDll . ShockDisc_ReadLBA cbReadLBA ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
public DiscSystem . Disc Disc ;
public IntPtr OctoshockHandle ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
public void Dispose ( )
{
OctoshockDll . shock_DestroyDisc ( OctoshockHandle ) ;
OctoshockHandle = IntPtr . Zero ;
}
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
int ShockDisc_ReadTOC ( IntPtr opaque , OctoshockDll . ShockTOC * read_target , OctoshockDll . ShockTOCTrack * tracks101 )
{
read_target - > disc_type = 1 ; //hardcoded in octoshock
read_target - > first_track = ( byte ) Disc . TOCRaw . FirstRecordedTrackNumber ; //i _think_ thats what is meant here
read_target - > last_track = ( byte ) Disc . TOCRaw . LastRecordedTrackNumber ; //i _think_ thats what is meant here
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
tracks101 [ 0 ] . lba = tracks101 [ 0 ] . adr = tracks101 [ 0 ] . control = 0 ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
for ( int i = 1 ; i < 100 ; i + + )
{
var item = Disc . TOCRaw . TOCItems [ i ] ;
tracks101 [ i ] . adr = 1 ; //not sure what this is
tracks101 [ i ] . lba = ( uint ) item . LBATimestamp . Sector ;
tracks101 [ i ] . control = ( byte ) item . Control ;
}
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
////the lead-out track is to be synthesized
tracks101 [ read_target - > last_track + 1 ] . adr = 1 ;
tracks101 [ read_target - > last_track + 1 ] . control = 0 ;
tracks101 [ read_target - > last_track + 1 ] . lba = ( uint ) Disc . TOCRaw . LeadoutTimestamp . Sector ;
////laaaame
//tracks101[read_target->last_track + 1].lba =
// (uint)(
// Disc.Structure.Sessions[0].Tracks[read_target->last_track - 1].Start_ABA //AUGH. see comment in Start_ABA
// + Disc.Structure.Sessions[0].Tracks[read_target->last_track - 1].LengthInSectors
// - 150
// );
//element 100 is to be copied as the lead-out track
tracks101 [ 100 ] = tracks101 [ read_target - > last_track + 1 ] ;
return OctoshockDll . SHOCK_OK ;
2012-11-04 23:29:06 +00:00
}
2014-12-10 19:41:13 +00:00
byte [ ] SectorBuffer = new byte [ 2352 ] ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
int ShockDisc_ReadLBA2448 ( IntPtr opaque , int lba , void * dst )
{
//lets you check subcode generation by logging it and checking against the CCD subcode
bool subcodeLog = false ;
bool readLog = false ;
2013-12-21 18:00:38 +00:00
2014-12-10 19:41:13 +00:00
if ( subcodeLog ) Console . Write ( "{0}|" , lba ) ;
else if ( readLog ) Console . WriteLine ( "Read Sector: " + lba ) ;
2013-12-11 01:53:40 +00:00
2014-12-10 19:41:13 +00:00
Disc . ReadLBA_2352 ( lba , SectorBuffer , 0 ) ;
Marshal . Copy ( SectorBuffer , 0 , new IntPtr ( dst ) , 2352 ) ;
Disc . ReadLBA_SectorEntry ( lba ) . SubcodeSector . ReadSubcodeDeinterleaved ( SectorBuffer , 0 ) ;
Marshal . Copy ( SectorBuffer , 0 , new IntPtr ( ( byte * ) dst + 2352 ) , 96 ) ;
if ( subcodeLog )
2012-11-04 23:29:06 +00:00
{
2014-12-10 19:41:13 +00:00
for ( int i = 0 ; i < 24 ; i + + )
Console . Write ( "{0:X2}" , * ( ( byte * ) dst + 2352 + i ) ) ;
Console . WriteLine ( ) ;
2012-11-04 23:29:06 +00:00
}
2014-12-10 19:41:13 +00:00
return OctoshockDll . SHOCK_OK ;
2012-11-04 23:29:06 +00:00
}
2014-12-10 19:41:13 +00:00
}
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
public Octoshock ( CoreComm comm , DiscSystem . Disc disc )
{
ServiceProvider = new BasicServiceProvider ( this ) ;
var domains = new List < MemoryDomain > ( ) ;
CoreComm = comm ;
VirtualWidth = BufferWidth = 256 ;
BufferHeight = 192 ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
Attach ( ) ;
this . disc = disc ;
discInterface = new DiscInterface ( disc ) ;
//determine region of the provided disc
OctoshockDll . ShockDiscInfo discInfo ;
OctoshockDll . shock_AnalyzeDisc ( discInterface . OctoshockHandle , out discInfo ) ;
//try to acquire the appropriate firmware
string firmwareRegion = "U" ;
if ( discInfo . region = = OctoshockDll . eRegion . EU ) firmwareRegion = "E" ;
if ( discInfo . region = = OctoshockDll . eRegion . JP ) firmwareRegion = "J" ;
byte [ ] firmware = comm . CoreFileProvider . GetFirmware ( "PSX" , "U" , true , "A PSX `" + firmwareRegion + "` region bios file is required" ) ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
//create the instance
fixed ( byte * pFirmware = firmware )
OctoshockDll . shock_Create ( out psx , discInfo . region , pFirmware ) ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
OctoshockDll . shock_OpenTray ( psx ) ;
OctoshockDll . shock_SetDisc ( psx , discInterface . OctoshockHandle ) ;
OctoshockDll . shock_CloseTray ( psx ) ;
OctoshockDll . shock_PowerOn ( psx ) ;
2012-11-04 23:29:06 +00:00
}
2014-12-10 19:41:13 +00:00
public IEmulatorServiceProvider ServiceProvider { get ; private set ; }
void Attach ( )
2012-11-04 23:29:06 +00:00
{
2014-12-10 19:41:13 +00:00
//attach this core as the current
if ( CurrOctoshockCore ! = null )
CurrOctoshockCore . Dispose ( ) ;
CurrOctoshockCore = this ;
//the psx instance cant be created until the desired region is known, which needs a disc, so we need the dll static attached first
2012-11-04 23:29:06 +00:00
}
2014-12-10 19:41:13 +00:00
//public void LoadCuePath(string path)
//{
// Attach();
// DiscSystem.Disc.FromCCDPath
//}
static Octoshock ( )
2012-11-04 23:29:06 +00:00
{
}
2014-12-10 19:41:13 +00:00
2014-11-30 20:29:30 +00:00
[FeatureNotImplemented]
2013-11-03 16:29:51 +00:00
public void ResetCounters ( )
2012-11-04 23:29:06 +00:00
{
2012-11-25 15:41:40 +00:00
// FIXME when all this stuff is implemented
2012-11-04 23:29:06 +00:00
Frame = 0 ;
}
public void FrameAdvance ( bool render , bool rendersound )
{
2014-12-10 19:41:13 +00:00
OctoshockDll . shock_Step ( psx , OctoshockDll . eShockStep . Frame ) ;
OctoshockDll . ShockFramebufferJob fb = new OctoshockDll . ShockFramebufferJob ( ) ;
OctoshockDll . shock_GetFramebuffer ( psx , ref fb ) ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
//Console.WriteLine(fb.height);
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
if ( render = = false ) return ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
int w = fb . width ;
int h = fb . height ;
BufferWidth = w ;
2012-11-04 23:29:06 +00:00
BufferHeight = h ;
int len = w * h ;
if ( frameBuffer . Length ! = len )
2014-12-10 19:41:13 +00:00
{
Console . WriteLine ( "PSX FB size: {0},{1}" , fb . width , fb . height ) ;
2012-11-04 23:29:06 +00:00
frameBuffer = new int [ len ] ;
2014-12-10 19:41:13 +00:00
}
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
fixed ( int * ptr = frameBuffer )
{
fb . ptr = ptr ;
OctoshockDll . shock_GetFramebuffer ( psx , ref fb ) ;
//alpha channel is added in c++, right now. wish we didnt have to do it at all
}
2012-11-04 23:29:06 +00:00
}
2014-11-24 01:17:05 +00:00
[FeatureNotImplemented]
2012-11-04 23:29:06 +00:00
public ControllerDefinition ControllerDefinition { get { return NullController ; } }
2014-11-24 01:17:05 +00:00
[FeatureNotImplemented]
2012-11-04 23:29:06 +00:00
public IController Controller { get ; set ; }
2014-11-24 01:17:05 +00:00
public int Frame
{
[FeatureNotImplemented]
get ;
[FeatureNotImplemented]
set ;
}
[FeatureNotImplemented]
2012-11-04 23:29:06 +00:00
public bool DeterministicEmulation { get { return true ; } }
2014-11-24 01:17:05 +00:00
2012-11-04 23:29:06 +00:00
public int [ ] GetVideoBuffer ( ) { return frameBuffer ; }
public int VirtualWidth { get ; private set ; }
2014-04-30 23:48:37 +00:00
public int VirtualHeight { get { return BufferHeight ; } }
2012-11-04 23:29:06 +00:00
public int BufferWidth { get ; private set ; }
public int BufferHeight { get ; private set ; }
public int BackgroundColor { get { return 0 ; } }
public void GetSamples ( short [ ] samples ) { }
public void DiscardSamples ( ) { }
public int MaxVolume { get ; set ; }
}
}