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 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
2014-12-16 04:02:55 +00:00
//TODO mednafen 0.9.37 changed some disc region detection heuristics. analyze and apply in c# side. also the SCEX id handling changed, maybe simplified
2014-12-10 19:41:13 +00:00
2014-12-17 10:50:20 +00:00
//TODO - ok, think about this. we MUST load a state with the CDC completely intact. no quickly changing discs. thats madness.
//well, I could savestate the disc index and validate the disc collection when loading a state.
//the big problem is, it's completely at odds with the slider-based disc changing model.
//but, maybe it can be reconciled with that model by using the disc ejection to our advantage.
//perhaps moving the slider is meaningless if the disc is ejected--it only affects what disc is inserted when the disc gets inserted!! yeah! this might could save us!
//not exactly user friendly but maybe we can build it from there with a custom UI.. a disk-changer? dunno if that would help
2014-12-10 19:41:13 +00:00
using System ;
2014-12-14 08:48:23 +00:00
using System.ComponentModel ;
2012-11-04 23:29:06 +00:00
using System.Runtime.InteropServices ;
using System.IO ;
using System.Collections.Generic ;
2014-12-12 00:25:46 +00:00
using Newtonsoft.Json ;
2012-11-04 23:29:06 +00:00
2014-12-18 08:35:56 +00:00
2013-11-04 01:39:19 +00:00
using BizHawk.Emulation.Common ;
2014-12-14 08:48:23 +00:00
using BizHawk.Common ;
2013-11-04 01:39:19 +00:00
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-12-15 05:28:06 +00:00
public unsafe class Octoshock : IEmulator , IVideoProvider , ISyncSoundProvider , IMemoryDomains , ISaveRam , IStatable , IDriveLight , IInputPollable , ISettable < Octoshock . Settings , Octoshock . SyncSettings > , IDebuggable
2012-11-04 23:29:06 +00:00
{
2014-12-11 20:31:55 +00:00
public string SystemId { get { return "PSX" ; } }
2014-12-10 23:43:11 +00:00
2014-12-19 03:24:48 +00:00
public static readonly ControllerDefinition PSXControllerDefinition = new ControllerDefinition
2014-12-10 23:43:11 +00:00
{
Name = "DualShock Controller" ,
BoolButtons =
{
2014-12-15 21:54:51 +00:00
"P1 Up" , "P1 Down" , "P1 Left" , "P1 Right" , "P1 Select" , "P1 Start" , "P1 Square" , "P1 Triangle" , "P1 Circle" , "P1 Cross" , "P1 L1" ,
2014-12-16 23:44:23 +00:00
"P1 R1" , "P1 L2" , "P1 R2" , "P1 L3" , "P1 R3" , "P1 MODE" ,
"P2 Up" , "P2 Down" , "P2 Left" , "P2 Right" , "P2 Select" , "P2 Start" , "P2 Square" , "P2 Triangle" , "P2 Circle" , "P2 Cross" , "P2 L1" ,
"P2 R1" , "P2 L2" , "P2 R2" , "P2 L3" , "P2 R3" , "P2 MODE" ,
2014-12-19 03:24:48 +00:00
"Eject" , "Insert" , "Reset" ,
2014-12-10 23:43:11 +00:00
} ,
FloatControls =
{
2014-12-15 21:54:51 +00:00
"P1 LStick X" , "P1 LStick Y" , "P1 RStick X" , "P1 RStick Y" ,
2014-12-16 23:44:23 +00:00
"P2 LStick X" , "P2 LStick Y" , "P2 RStick X" , "P2 RStick Y" ,
2014-12-16 03:15:27 +00:00
"Disc Select" ,
2014-12-10 23:43:11 +00:00
} ,
FloatRanges =
{
2014-12-16 23:44:23 +00:00
new [ ] { 0.0f , 128.0f , 255.0f } ,
new [ ] { 255.0f , 128.0f , 0.0f } ,
new [ ] { 0.0f , 128.0f , 255.0f } ,
new [ ] { 255.0f , 128.0f , 0.0f } ,
2014-12-10 23:43:11 +00:00
new [ ] { 0.0f , 128.0f , 255.0f } ,
new [ ] { 255.0f , 128.0f , 0.0f } ,
new [ ] { 0.0f , 128.0f , 255.0f } ,
new [ ] { 255.0f , 128.0f , 0.0f } ,
2014-12-16 03:15:27 +00:00
new [ ] { 1.0f , 1.0f , 5.0f } ,
2014-12-19 03:24:48 +00:00
} ,
2014-12-10 23:43:11 +00:00
} ;
2012-11-04 23:29:06 +00:00
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 ; } }
//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-14 08:48:23 +00:00
2014-12-10 19:41:13 +00:00
IntPtr psx ;
2014-12-18 08:35:56 +00:00
TraceBuffer tracer = new TraceBuffer ( ) ;
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 ;
2014-12-16 10:47:50 +00:00
//TODO - dispose disc wrappers
//TODO - dispose discs
2012-11-04 23:29:06 +00:00
}
2014-12-11 08:30:37 +00:00
/// <summary>
/// Wraps the ShockDiscRef returned from the DLL and acts as a bridge between it and a DiscSystem disc
/// </summary>
2014-12-10 19:41:13 +00:00
class DiscInterface : IDisposable
2012-11-04 23:29:06 +00:00
{
2014-12-16 10:47:50 +00:00
public DiscInterface ( DiscSystem . Disc disc , Action < DiscInterface > cbActivity )
2014-12-10 19:41:13 +00:00
{
this . Disc = disc ;
cbReadTOC = ShockDisc_ReadTOC ;
cbReadLBA = ShockDisc_ReadLBA2448 ;
2014-12-10 23:48:47 +00:00
this . cbActivity = cbActivity ;
2014-12-10 19:41:13 +00:00
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 ;
2014-12-16 10:47:50 +00:00
Action < DiscInterface > cbActivity ;
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 )
{
2014-12-16 10:47:50 +00:00
cbActivity ( this ) ;
2014-12-10 23:48:47 +00:00
2014-12-10 19:41:13 +00:00
//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-16 10:47:50 +00:00
List < DiscInterface > discInterfaces = new List < DiscInterface > ( ) ;
DiscInterface currentDiscInterface ;
2014-12-10 23:48:47 +00:00
2014-12-17 02:54:43 +00:00
public OctoshockDll . eRegion SystemRegion { get ; private set ; }
public OctoshockDll . eVidStandard SystemVidStandard { get ; private set ; }
public System . Drawing . Size CurrentVideoSize { get ; private set ; }
2014-12-19 03:24:48 +00:00
public bool CurrentDiscEjected { get ; private set ; }
public int CurrentDiscIndexMounted { get ; private set ; }
public List < string > HackyDiscButtons = new List < string > ( ) ;
2014-12-17 01:23:24 +00:00
2014-12-10 21:56:12 +00:00
//note: its annoying that we have to have a disc before constructing this.
//might want to change that later. HOWEVER - we need to definitely have a region, at least
2014-12-19 03:24:48 +00:00
public Octoshock ( CoreComm comm , List < DiscSystem . Disc > discs , List < string > discNames , byte [ ] exe , object settings , object syncSettings )
2014-12-10 19:41:13 +00:00
{
ServiceProvider = new BasicServiceProvider ( this ) ;
2014-12-23 01:58:12 +00:00
( ServiceProvider as BasicServiceProvider ) . Register < ITraceable > ( tracer ) ;
2014-12-10 19:41:13 +00:00
CoreComm = comm ;
2014-12-19 03:24:48 +00:00
DriveLightEnabled = true ;
2012-11-04 23:29:06 +00:00
2014-12-14 08:48:23 +00:00
_Settings = ( Settings ) settings ? ? new Settings ( ) ;
_SyncSettings = ( SyncSettings ) syncSettings ? ? new SyncSettings ( ) ;
2014-12-10 19:41:13 +00:00
Attach ( ) ;
2014-12-19 03:24:48 +00:00
HackyDiscButtons . AddRange ( discNames ) ;
2014-12-17 01:23:24 +00:00
//assume this region for EXE and PSF, maybe not correct though
2014-12-10 19:41:13 +00:00
string firmwareRegion = "U" ;
2014-12-17 01:23:24 +00:00
SystemRegion = OctoshockDll . eRegion . NA ;
2014-12-11 08:30:37 +00:00
2014-12-16 10:47:50 +00:00
if ( discs ! = null )
{
2014-12-17 02:54:43 +00:00
foreach ( var disc in discs )
2014-12-16 10:47:50 +00:00
{
var discInterface = new DiscInterface ( disc ,
( di ) = >
{
//if current disc this delegate disc, activity is happening
if ( di = = currentDiscInterface )
DriveLightOn = true ;
} ) ;
discInterfaces . Add ( discInterface ) ;
}
}
else
{
//assume its NA region for test programs, for now. could it be read out of the ps-exe header?
}
if ( discInterfaces . Count ! = 0 )
2014-12-11 08:30:37 +00:00
{
2014-12-16 10:47:50 +00:00
//determine region of one of the discs
2014-12-11 08:30:37 +00:00
OctoshockDll . ShockDiscInfo discInfo ;
2014-12-16 10:47:50 +00:00
OctoshockDll . shock_AnalyzeDisc ( discInterfaces [ 0 ] . OctoshockHandle , out discInfo ) ;
2014-12-11 08:30:37 +00:00
//try to acquire the appropriate firmware
if ( discInfo . region = = OctoshockDll . eRegion . EU ) firmwareRegion = "E" ;
if ( discInfo . region = = OctoshockDll . eRegion . JP ) firmwareRegion = "J" ;
2014-12-17 01:23:24 +00:00
SystemRegion = discInfo . region ;
2014-12-11 08:30:37 +00:00
}
2014-12-17 01:23:24 +00:00
//see http://problemkaputt.de/psx-spx.htm
2014-12-17 02:54:43 +00:00
int CpuClock_n = 44100 * 768 ;
2014-12-17 01:23:24 +00:00
int CpuClock_d = 1 ;
2014-12-17 02:54:43 +00:00
int VidClock_n = CpuClock_n * 11 ;
int VidClock_d = CpuClock_d * 7 ;
2014-12-17 01:23:24 +00:00
if ( SystemRegion = = OctoshockDll . eRegion . EU )
{
CoreComm . VsyncNum = VidClock_n ;
CoreComm . VsyncDen = VidClock_d * 314 * 3406 ;
SystemVidStandard = OctoshockDll . eVidStandard . PAL ;
}
else
{
CoreComm . VsyncNum = VidClock_n ;
CoreComm . VsyncDen = VidClock_d * 263 * 3413 ;
SystemVidStandard = OctoshockDll . eVidStandard . NTSC ;
}
//TODO - known bad firmwares are a no-go. we should refuse to boot them. (thats the mednafen policy)
byte [ ] firmware = comm . CoreFileProvider . GetFirmware ( "PSX" , firmwareRegion , 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 )
2014-12-17 01:23:24 +00:00
OctoshockDll . shock_Create ( out psx , SystemRegion , pFirmware ) ;
2012-11-04 23:29:06 +00:00
2014-12-11 01:56:21 +00:00
SetMemoryDomains ( ) ;
2014-12-10 21:56:12 +00:00
2014-12-17 02:54:43 +00:00
//set a default framebuffer based on the first frame of emulation, to cut down on flickering or whatever
//this is probably quixotic, but we have to pick something
{
BufferWidth = 280 ;
BufferHeight = 240 ;
if ( SystemVidStandard = = OctoshockDll . eVidStandard . PAL )
{
BufferWidth = 280 ;
BufferHeight = 288 ;
}
CurrentVideoSize = new System . Drawing . Size ( BufferWidth , BufferHeight ) ;
var size = Octoshock . CalculateResolution ( SystemVidStandard , _Settings , BufferWidth , BufferHeight ) ;
BufferWidth = VirtualWidth = size . Width ;
BufferHeight = VirtualHeight = size . Height ;
frameBuffer = new int [ BufferWidth * BufferHeight ] ;
}
2014-12-12 00:40:15 +00:00
2014-12-19 03:24:48 +00:00
//TODO - should be able to cold boot system with disc isnerted
2014-12-16 10:47:50 +00:00
if ( discInterfaces . Count ! = 0 )
2014-12-11 08:30:37 +00:00
{
2014-12-19 03:24:48 +00:00
//start with first disc inserted and tray closed
CurrentDiscEjected = false ;
CurrentDiscIndexMounted = 1 ;
currentDiscInterface = discInterfaces [ CurrentDiscIndexMounted - 1 ] ;
OctoshockDll . shock_OpenTray ( psx ) ;
OctoshockDll . shock_SetDisc ( psx , currentDiscInterface . OctoshockHandle ) ;
OctoshockDll . shock_CloseTray ( psx ) ;
2014-12-11 08:30:37 +00:00
}
else
{
//must be an exe
fixed ( byte * pExeBuffer = exe )
OctoshockDll . shock_MountEXE ( psx , pExeBuffer , exe . Length ) ;
2014-12-19 03:24:48 +00:00
//start with no disc inserted and tray closed
CurrentDiscEjected = false ;
CurrentDiscIndexMounted = 0 ;
OctoshockDll . shock_CloseTray ( psx ) ;
2014-12-11 08:30:37 +00:00
}
2014-12-17 04:01:26 +00:00
//connect two dualshocks, thats all we're doing right now
2014-12-10 23:43:11 +00:00
OctoshockDll . shock_Peripheral_Connect ( psx , 0x01 , OctoshockDll . ePeripheralType . DualShock ) ;
2014-12-17 04:01:26 +00:00
OctoshockDll . shock_Peripheral_Connect ( psx , 0x02 , OctoshockDll . ePeripheralType . DualShock ) ;
2014-12-12 11:07:47 +00:00
//do this after framebuffers and peripherals and whatever crap are setup. kind of lame, but thats how it is for now
StudySaveBufferSize ( ) ;
2014-12-14 08:48:23 +00:00
2014-12-10 19:41:13 +00:00
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 ; }
2014-12-13 13:50:36 +00:00
public IInputCallbackSystem InputCallbacks { get { throw new NotImplementedException ( ) ; } }
2014-12-12 01:49:54 +00:00
public bool DriveLightEnabled { get ; private set ; }
public bool DriveLightOn { get ; private set ; }
2014-12-10 19:41:13 +00:00
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
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 ;
}
2014-12-10 23:43:11 +00:00
void SetInput ( )
{
uint buttons = 0 ;
2014-12-14 08:48:23 +00:00
2014-12-10 23:43:11 +00:00
//dualshock style
2014-12-16 04:02:55 +00:00
if ( Controller [ "P1 Select" ] ) buttons | = 1 ;
if ( Controller [ "P1 L3" ] ) buttons | = 2 ;
if ( Controller [ "P1 R3" ] ) buttons | = 4 ;
if ( Controller [ "P1 Start" ] ) buttons | = 8 ;
if ( Controller [ "P1 Up" ] ) buttons | = 16 ;
if ( Controller [ "P1 Right" ] ) buttons | = 32 ;
if ( Controller [ "P1 Down" ] ) buttons | = 64 ;
if ( Controller [ "P1 Left" ] ) buttons | = 128 ;
if ( Controller [ "P1 L2" ] ) buttons | = 256 ;
if ( Controller [ "P1 R2" ] ) buttons | = 512 ;
if ( Controller [ "P1 L1" ] ) buttons | = 1024 ;
if ( Controller [ "P1 R1" ] ) buttons | = 2048 ;
if ( Controller [ "P1 Triangle" ] ) buttons | = 4096 ;
if ( Controller [ "P1 Circle" ] ) buttons | = 8192 ;
if ( Controller [ "P1 Cross" ] ) buttons | = 16384 ;
if ( Controller [ "P1 Square" ] ) buttons | = 32768 ;
if ( Controller [ "P1 MODE" ] ) buttons | = 65536 ;
byte left_x = ( byte ) Controller . GetFloat ( "P1 LStick X" ) ;
byte left_y = ( byte ) Controller . GetFloat ( "P1 LStick Y" ) ;
byte right_x = ( byte ) Controller . GetFloat ( "P1 RStick X" ) ;
byte right_y = ( byte ) Controller . GetFloat ( "P1 RStick Y" ) ;
2014-12-10 23:43:11 +00:00
OctoshockDll . shock_Peripheral_SetPadInput ( psx , 0x01 , buttons , left_x , left_y , right_x , right_y ) ;
2014-12-17 04:01:26 +00:00
//dualshock style
buttons = 0 ;
if ( Controller [ "P2 Select" ] ) buttons | = 1 ;
if ( Controller [ "P2 L3" ] ) buttons | = 2 ;
if ( Controller [ "P2 R3" ] ) buttons | = 4 ;
if ( Controller [ "P2 Start" ] ) buttons | = 8 ;
if ( Controller [ "P2 Up" ] ) buttons | = 16 ;
if ( Controller [ "P2 Right" ] ) buttons | = 32 ;
if ( Controller [ "P2 Down" ] ) buttons | = 64 ;
if ( Controller [ "P2 Left" ] ) buttons | = 128 ;
if ( Controller [ "P2 L2" ] ) buttons | = 256 ;
if ( Controller [ "P2 R2" ] ) buttons | = 512 ;
if ( Controller [ "P2 L1" ] ) buttons | = 1024 ;
if ( Controller [ "P2 R1" ] ) buttons | = 2048 ;
if ( Controller [ "P2 Triangle" ] ) buttons | = 4096 ;
if ( Controller [ "P2 Circle" ] ) buttons | = 8192 ;
if ( Controller [ "P2 Cross" ] ) buttons | = 16384 ;
if ( Controller [ "P2 Square" ] ) buttons | = 32768 ;
if ( Controller [ "P2 MODE" ] ) buttons | = 65536 ;
left_x = ( byte ) Controller . GetFloat ( "P2 LStick X" ) ;
left_y = ( byte ) Controller . GetFloat ( "P2 LStick Y" ) ;
right_x = ( byte ) Controller . GetFloat ( "P2 RStick X" ) ;
right_y = ( byte ) Controller . GetFloat ( "P2 RStick Y" ) ;
OctoshockDll . shock_Peripheral_SetPadInput ( psx , 0x02 , buttons , left_x , left_y , right_x , right_y ) ;
2014-12-10 23:43:11 +00:00
}
2014-12-17 02:54:43 +00:00
/// <summary>
/// Calculates what the output resolution would be for the given input resolution and settings
/// </summary>
public static System . Drawing . Size CalculateResolution ( OctoshockDll . eVidStandard standard , Settings settings , int w , int h )
{
int virtual_width = settings . ClipHorizontalOverscan ? 768 : 800 ;
int scanline_start = standard = = OctoshockDll . eVidStandard . NTSC ? settings . ScanlineStart_NTSC : settings . ScanlineStart_PAL ;
int scanline_end = standard = = OctoshockDll . eVidStandard . NTSC ? settings . ScanlineEnd_NTSC : settings . ScanlineEnd_PAL ;
int scanline_num = scanline_end - scanline_start + 1 ;
int real_scanline_num = standard = = OctoshockDll . eVidStandard . NTSC ? 240 : 288 ;
int VirtualWidth = - 1 , VirtualHeight = - 1 ;
switch ( settings . ResolutionMode )
{
case eResolutionMode . Debug :
VirtualWidth = w ;
VirtualHeight = h ;
break ;
case eResolutionMode . Mednafen :
VirtualWidth = settings . ClipHorizontalOverscan ? 302 : 320 ;
VirtualHeight = scanline_num ;
break ;
case eResolutionMode . PixelPro :
VirtualWidth = virtual_width ;
VirtualHeight = scanline_num * 2 ;
break ;
case eResolutionMode . TweakedMednafen :
VirtualWidth = settings . ClipHorizontalOverscan ? 378 : 400 ;
VirtualHeight = ( int ) ( scanline_num * 300.0f / real_scanline_num ) ;
break ;
}
return new System . Drawing . Size ( VirtualWidth , VirtualHeight ) ;
}
2014-12-19 03:24:48 +00:00
void FrameAdvance_PrepDiscState ( )
2012-11-04 23:29:06 +00:00
{
2014-12-19 03:24:48 +00:00
//if eject is requested, and valid, apply it
if ( Controller [ "Eject" ] & & ! CurrentDiscEjected )
{
OctoshockDll . shock_OpenTray ( psx ) ;
CurrentDiscEjected = true ;
}
2014-12-10 23:43:11 +00:00
2014-12-19 03:24:48 +00:00
//change the disc if needed, and valid
//TODO - warning if zero time change?
int requestedDisc = ( int ) Controller . GetFloat ( "Disc Select" ) ;
if ( requestedDisc ! = CurrentDiscIndexMounted & & CurrentDiscEjected )
{
CurrentDiscIndexMounted = requestedDisc ;
if ( CurrentDiscIndexMounted = = 0 )
{
currentDiscInterface = null ;
OctoshockDll . shock_SetDisc ( psx , IntPtr . Zero ) ;
}
else
{
currentDiscInterface = discInterfaces [ CurrentDiscIndexMounted - 1 ] ;
OctoshockDll . shock_SetDisc ( psx , currentDiscInterface . OctoshockHandle ) ;
}
}
2014-12-16 10:47:50 +00:00
2014-12-19 03:24:48 +00:00
//if insert is requested, and valid, apply it
if ( Controller [ "Insert" ] & & CurrentDiscEjected )
2014-12-16 10:47:50 +00:00
{
2014-12-19 03:24:48 +00:00
OctoshockDll . shock_CloseTray ( psx ) ;
CurrentDiscEjected = false ;
2014-12-16 10:47:50 +00:00
}
2014-12-19 03:24:48 +00:00
}
2014-12-16 10:47:50 +00:00
2014-12-19 03:24:48 +00:00
public void FrameAdvance ( bool render , bool rendersound )
{
Frame + + ;
//clear drive light. itll get set to light up by sector-reading callbacks
//TODO - debounce this by a frame or so perhaps?
DriveLightOn = false ;
FrameAdvance_PrepDiscState ( ) ;
SetInput ( ) ;
2014-12-16 10:47:50 +00:00
2014-12-17 01:23:24 +00:00
var ropts = new OctoshockDll . ShockRenderOptions ( )
{
scanline_start = SystemVidStandard = = OctoshockDll . eVidStandard . NTSC ? _Settings . ScanlineStart_NTSC : _Settings . ScanlineStart_PAL ,
scanline_end = SystemVidStandard = = OctoshockDll . eVidStandard . NTSC ? _Settings . ScanlineEnd_NTSC : _Settings . ScanlineEnd_PAL ,
clipOverscan = _Settings . ClipHorizontalOverscan
} ;
OctoshockDll . shock_SetRenderOptions ( psx , ref ropts ) ;
2014-12-16 10:47:50 +00:00
2014-12-18 08:35:56 +00:00
//prep tracer
if ( tracer . Enabled )
OctoshockDll . shock_SetTraceCallback ( psx , IntPtr . Zero , ShockTraceCallback ) ;
else
OctoshockDll . shock_SetTraceCallback ( psx , IntPtr . Zero , null ) ;
//------------------------
2014-12-10 19:41:13 +00:00
OctoshockDll . shock_Step ( psx , OctoshockDll . eShockStep . Frame ) ;
2014-12-18 08:35:56 +00:00
//------------------------
2014-12-10 19:41:13 +00:00
2014-12-14 08:48:23 +00:00
//what happens to sound in this case?
if ( render = = false ) return ;
2012-11-04 23:29:06 +00:00
2014-12-14 08:48:23 +00:00
OctoshockDll . ShockFramebufferInfo fb = new OctoshockDll . ShockFramebufferInfo ( ) ;
2014-12-17 02:54:43 +00:00
//run this once to get current logical size
OctoshockDll . shock_GetFramebuffer ( psx , ref fb ) ;
CurrentVideoSize = new System . Drawing . Size ( fb . width , fb . height ) ;
2014-12-14 08:48:23 +00:00
if ( _Settings . ResolutionMode = = eResolutionMode . PixelPro )
fb . flags = OctoshockDll . eShockFramebufferFlags . Normalize ;
2012-11-04 23:29:06 +00:00
2014-12-14 08:48:23 +00:00
OctoshockDll . shock_GetFramebuffer ( psx , ref fb ) ;
2012-11-04 23:29:06 +00:00
2014-12-10 19:41:13 +00:00
int w = fb . width ;
int h = fb . height ;
2014-12-16 10:59:39 +00:00
BufferWidth = w ;
2012-11-04 23:29:06 +00:00
BufferHeight = h ;
2014-12-17 02:54:43 +00:00
var size = CalculateResolution ( this . SystemVidStandard , _Settings , w , h ) ;
VirtualWidth = size . Width ;
VirtualHeight = size . Height ;
2014-12-14 08:48:23 +00:00
int len = w * h ;
2012-11-04 23:29:06 +00:00
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 ) ;
}
2014-12-11 00:57:47 +00:00
fixed ( short * samples = sbuff )
{
2014-12-11 01:56:21 +00:00
sbuffcontains = OctoshockDll . shock_GetSamples ( psx , null ) ;
2014-12-11 00:57:47 +00:00
if ( sbuffcontains * 2 > sbuff . Length ) throw new InvalidOperationException ( "shock_GetSamples returned too many samples: " + sbuffcontains ) ;
2014-12-11 01:56:21 +00:00
OctoshockDll . shock_GetSamples ( psx , samples ) ;
2014-12-11 00:57:47 +00:00
}
2012-11-04 23:29:06 +00:00
}
2014-11-24 01:17:05 +00:00
2014-12-19 03:24:48 +00:00
public ControllerDefinition ControllerDefinition { get { return PSXControllerDefinition ; } }
2012-11-04 23:29:06 +00:00
public IController Controller { get ; set ; }
2014-12-12 00:25:46 +00:00
public int Frame { get ; private set ; }
public int LagCount { get ; set ; }
public bool IsLagFrame { get ; private set ; }
2014-11-24 01:17:05 +00:00
[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-12-10 21:56:12 +00:00
public int VirtualHeight { get ; private set ; }
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 ; } }
2014-12-11 00:57:47 +00:00
2014-12-11 01:56:21 +00:00
#region Debugging
unsafe void SetMemoryDomains ( )
{
var mmd = new List < MemoryDomain > ( ) ;
IntPtr ptr ;
int size ;
OctoshockDll . shock_GetMemData ( psx , out ptr , out size , OctoshockDll . eMemType . MainRAM ) ;
mmd . Add ( MemoryDomain . FromIntPtr ( "MainRAM" , size , MemoryDomain . Endian . Little , ptr , true ) ) ;
OctoshockDll . shock_GetMemData ( psx , out ptr , out size , OctoshockDll . eMemType . GPURAM ) ;
mmd . Add ( MemoryDomain . FromIntPtr ( "GPURAM" , size , MemoryDomain . Endian . Little , ptr , true ) ) ;
OctoshockDll . shock_GetMemData ( psx , out ptr , out size , OctoshockDll . eMemType . SPURAM ) ;
mmd . Add ( MemoryDomain . FromIntPtr ( "SPURAM" , size , MemoryDomain . Endian . Little , ptr , true ) ) ;
OctoshockDll . shock_GetMemData ( psx , out ptr , out size , OctoshockDll . eMemType . BiosROM ) ;
mmd . Add ( MemoryDomain . FromIntPtr ( "BiosROM" , size , MemoryDomain . Endian . Little , ptr , true ) ) ;
OctoshockDll . shock_GetMemData ( psx , out ptr , out size , OctoshockDll . eMemType . PIOMem ) ;
mmd . Add ( MemoryDomain . FromIntPtr ( "PIOMem" , size , MemoryDomain . Endian . Little , ptr , true ) ) ;
2014-12-15 05:28:06 +00:00
OctoshockDll . shock_GetMemData ( psx , out ptr , out size , OctoshockDll . eMemType . DCache ) ;
mmd . Add ( MemoryDomain . FromIntPtr ( "DCache" , size , MemoryDomain . Endian . Little , ptr , true ) ) ;
2014-12-11 01:56:21 +00:00
MemoryDomains = new MemoryDomainList ( mmd , 0 ) ;
}
public MemoryDomainList MemoryDomains { get ; private set ; }
#endregion
2014-12-11 00:57:47 +00:00
#region ISoundProvider
2014-12-17 01:23:24 +00:00
//private short[] sbuff = new short[1454 * 2]; //this is the most ive ever seen.. dont know why. two frames worth i guess
private short [ ] sbuff = new short [ 1611 * 2 ] ; //need this for pal
2014-12-11 00:57:47 +00:00
private int sbuffcontains = 0 ;
public ISoundProvider SoundProvider { get { throw new InvalidOperationException ( ) ; } }
public ISyncSoundProvider SyncSoundProvider { get { return this ; } }
public bool StartAsyncSound ( ) { return false ; }
public void EndAsyncSound ( ) { }
public void GetSamples ( out short [ ] samples , out int nsamp )
{
samples = sbuff ;
nsamp = sbuffcontains ;
}
public void DiscardSamples ( )
{
sbuffcontains = 0 ;
}
#endregion
2014-12-11 07:27:21 +00:00
#region ISaveRam
public byte [ ] CloneSaveRam ( )
{
var buf = new byte [ 128 * 1024 ] ;
fixed ( byte * pbuf = buf )
{
var transaction = new OctoshockDll . ShockMemcardTransaction ( ) ;
transaction . buffer128k = pbuf ;
transaction . transaction = OctoshockDll . eShockMemcardTransaction . Read ;
OctoshockDll . shock_Peripheral_MemcardTransact ( psx , 0x01 , ref transaction ) ;
}
return buf ;
}
public void StoreSaveRam ( byte [ ] data )
{
fixed ( byte * pbuf = data )
{
var transaction = new OctoshockDll . ShockMemcardTransaction ( ) ;
transaction . buffer128k = pbuf ;
transaction . transaction = OctoshockDll . eShockMemcardTransaction . Write ;
OctoshockDll . shock_Peripheral_MemcardTransact ( psx , 0x01 , ref transaction ) ;
}
}
public bool SaveRamModified
{
get
{
var transaction = new OctoshockDll . ShockMemcardTransaction ( ) ;
transaction . transaction = OctoshockDll . eShockMemcardTransaction . CheckDirty ;
return OctoshockDll . shock_Peripheral_MemcardTransact ( psx , 0x01 , ref transaction ) = = OctoshockDll . SHOCK_TRUE ;
}
}
#endregion //ISaveRam
2014-12-12 00:25:46 +00:00
#region Savestates
//THIS IS STILL AWFUL
JsonSerializer ser = new JsonSerializer ( ) { Formatting = Formatting . Indented } ;
class TextStateData
{
public int Frame ;
public int LagCount ;
public bool IsLagFrame ;
2014-12-19 03:24:48 +00:00
public bool CurrentDiscEjected ;
public int CurrentDiscIndexMounted ;
2014-12-12 00:25:46 +00:00
}
public void SaveStateText ( TextWriter writer )
{
var s = new TextState < TextStateData > ( ) ;
s . Prepare ( ) ;
var transaction = new OctoshockDll . ShockStateTransaction ( )
{
transaction = OctoshockDll . eShockStateTransaction . TextSave ,
ff = s . GetFunctionPointersSave ( )
} ;
int result = OctoshockDll . shock_StateTransaction ( psx , ref transaction ) ;
if ( result ! = OctoshockDll . SHOCK_OK )
throw new InvalidOperationException ( "eShockStateTransaction.TextSave returned error!" ) ;
s . ExtraData . IsLagFrame = IsLagFrame ;
s . ExtraData . LagCount = LagCount ;
s . ExtraData . Frame = Frame ;
2014-12-19 03:24:48 +00:00
s . ExtraData . CurrentDiscEjected = CurrentDiscEjected ;
s . ExtraData . CurrentDiscIndexMounted = CurrentDiscIndexMounted ;
2014-12-12 00:25:46 +00:00
ser . Serialize ( writer , s ) ;
// TODO write extra copy of stuff we don't use (WHY?)
}
public void LoadStateText ( TextReader reader )
{
var s = ( TextState < TextStateData > ) ser . Deserialize ( reader , typeof ( TextState < TextStateData > ) ) ;
s . Prepare ( ) ;
var transaction = new OctoshockDll . ShockStateTransaction ( )
{
transaction = OctoshockDll . eShockStateTransaction . TextLoad ,
2014-12-12 11:07:47 +00:00
ff = s . GetFunctionPointersLoad ( )
2014-12-12 00:25:46 +00:00
} ;
2014-12-14 08:48:23 +00:00
2014-12-12 00:25:46 +00:00
int result = OctoshockDll . shock_StateTransaction ( psx , ref transaction ) ;
if ( result ! = OctoshockDll . SHOCK_OK )
throw new InvalidOperationException ( "eShockStateTransaction.TextLoad returned error!" ) ;
IsLagFrame = s . ExtraData . IsLagFrame ;
LagCount = s . ExtraData . LagCount ;
Frame = s . ExtraData . Frame ;
2014-12-19 03:24:48 +00:00
CurrentDiscEjected = s . ExtraData . CurrentDiscEjected ;
CurrentDiscIndexMounted = s . ExtraData . CurrentDiscIndexMounted ;
2014-12-12 00:25:46 +00:00
}
byte [ ] savebuff ;
2014-12-13 08:44:39 +00:00
byte [ ] savebuff2 ;
2014-12-12 00:25:46 +00:00
void StudySaveBufferSize ( )
{
var transaction = new OctoshockDll . ShockStateTransaction ( ) ;
transaction . transaction = OctoshockDll . eShockStateTransaction . BinarySize ;
int size = OctoshockDll . shock_StateTransaction ( psx , ref transaction ) ;
savebuff = new byte [ size ] ;
2014-12-19 03:24:48 +00:00
savebuff2 = new byte [ savebuff . Length + 4 + 4 + 4 + 1 + 1 + 4 ] ;
2014-12-12 00:25:46 +00:00
}
public void SaveStateBinary ( BinaryWriter writer )
{
fixed ( byte * psavebuff = savebuff )
{
var transaction = new OctoshockDll . ShockStateTransaction ( )
{
transaction = OctoshockDll . eShockStateTransaction . BinarySave ,
buffer = psavebuff ,
bufferLength = savebuff . Length
} ;
2014-12-14 08:48:23 +00:00
2014-12-12 00:25:46 +00:00
int result = OctoshockDll . shock_StateTransaction ( psx , ref transaction ) ;
if ( result ! = OctoshockDll . SHOCK_OK )
throw new InvalidOperationException ( "eShockStateTransaction.BinarySave returned error!" ) ;
writer . Write ( savebuff . Length ) ;
writer . Write ( savebuff ) ;
2014-12-13 08:44:39 +00:00
// other variables
writer . Write ( IsLagFrame ) ;
writer . Write ( LagCount ) ;
writer . Write ( Frame ) ;
2014-12-19 03:24:48 +00:00
writer . Write ( CurrentDiscEjected ) ;
writer . Write ( CurrentDiscIndexMounted ) ;
2014-12-12 00:25:46 +00:00
}
}
public void LoadStateBinary ( BinaryReader reader )
{
fixed ( byte * psavebuff = savebuff )
{
var transaction = new OctoshockDll . ShockStateTransaction ( )
{
transaction = OctoshockDll . eShockStateTransaction . BinaryLoad ,
buffer = psavebuff ,
bufferLength = savebuff . Length
} ;
int length = reader . ReadInt32 ( ) ;
if ( length ! = savebuff . Length )
throw new InvalidOperationException ( "Save buffer size mismatch!" ) ;
reader . Read ( savebuff , 0 , length ) ;
int ret = OctoshockDll . shock_StateTransaction ( psx , ref transaction ) ;
if ( ret ! = OctoshockDll . SHOCK_OK )
throw new InvalidOperationException ( "eShockStateTransaction.BinaryLoad returned error!" ) ;
2014-12-13 08:44:39 +00:00
// other variables
IsLagFrame = reader . ReadBoolean ( ) ;
LagCount = reader . ReadInt32 ( ) ;
Frame = reader . ReadInt32 ( ) ;
2014-12-19 03:24:48 +00:00
CurrentDiscEjected = reader . ReadBoolean ( ) ;
CurrentDiscIndexMounted = reader . ReadInt32 ( ) ;
//TODO - need a method to sneak the required disc, without having to do a proper eject sequence
2014-12-12 00:25:46 +00:00
}
}
public byte [ ] SaveStateBinary ( )
{
2014-12-13 08:44:39 +00:00
//this are objectionable shenanigans, but theyre required to get the extra info in the stream. we need a better approach.
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-12-12 00:25:46 +00:00
}
public bool BinarySaveStatesPreferred
{
get { return true ; }
}
#endregion
2014-12-14 08:48:23 +00:00
#region Settings
Settings _Settings = new Settings ( ) ;
SyncSettings _SyncSettings ;
public enum eResolutionMode
{
PixelPro , Debug ,
Mednafen , TweakedMednafen
}
public class SyncSettings
{
public SyncSettings Clone ( )
{
return ( SyncSettings ) MemberwiseClone ( ) ;
}
}
public class Settings
{
[DisplayName("Resolution Mode")]
2014-12-17 01:23:24 +00:00
[Description("Stuff")]
2014-12-14 08:48:23 +00:00
[DefaultValue(eResolutionMode.PixelPro)]
public eResolutionMode ResolutionMode { get ; set ; }
2014-12-17 01:23:24 +00:00
[DisplayName("ScanlineStart_NTSC")]
[DefaultValue(0)]
public int ScanlineStart_NTSC { get ; set ; }
[DisplayName("ScanlineEnd_NTSC")]
[DefaultValue(239)]
public int ScanlineEnd_NTSC { get ; set ; }
[DisplayName("ScanlineStart_PAL")]
[DefaultValue(0)]
public int ScanlineStart_PAL { get ; set ; }
[DisplayName("ScanlineEnd_PAL")]
[DefaultValue(287)]
public int ScanlineEnd_PAL { get ; set ; }
[DisplayName("Clip Horizontal Overscan")]
[DefaultValue(false)]
public bool ClipHorizontalOverscan { get ; set ; }
public void Validate ( )
{
if ( ScanlineStart_NTSC < 0 ) ScanlineStart_NTSC = 0 ;
if ( ScanlineStart_PAL < 0 ) ScanlineStart_PAL = 0 ;
if ( ScanlineEnd_NTSC > 239 ) ScanlineEnd_NTSC = 239 ;
if ( ScanlineEnd_PAL > 287 ) ScanlineEnd_PAL = 287 ;
//make sure theyre not in the wrong order
if ( ScanlineEnd_NTSC < ScanlineStart_NTSC )
{
int temp = ScanlineEnd_NTSC ;
ScanlineEnd_NTSC = ScanlineStart_NTSC ;
ScanlineStart_NTSC = temp ;
}
if ( ScanlineEnd_PAL < ScanlineStart_PAL )
{
int temp = ScanlineEnd_PAL ;
ScanlineEnd_PAL = ScanlineStart_PAL ;
ScanlineStart_PAL = temp ;
}
}
2014-12-14 08:48:23 +00:00
public Settings ( )
{
SettingsUtil . SetDefaultValues ( this ) ;
}
public Settings Clone ( )
{
return ( Settings ) MemberwiseClone ( ) ;
}
}
public Settings GetSettings ( )
{
return _Settings . Clone ( ) ;
}
public SyncSettings GetSyncSettings ( )
{
return _SyncSettings . Clone ( ) ;
}
public bool PutSettings ( Settings o )
{
2014-12-17 01:23:24 +00:00
_Settings . Validate ( ) ;
2014-12-14 08:48:23 +00:00
_Settings = o ;
//TODO
//var native = _Settings.GetNativeSettings();
//BizSwan.bizswan_putsettings(Core, ref native);
return false ;
}
public bool PutSyncSettings ( SyncSettings o )
{
_SyncSettings = o ;
return false ;
}
#endregion
2014-12-15 05:28:06 +00:00
#region IDebuggable
2014-12-20 03:19:33 +00:00
// TODO: don't cast to int, and are any of these not 32 bit?
2014-12-20 13:16:15 +00:00
public IDictionary < string , RegisterValue > GetCpuFlagsAndRegisters ( )
2014-12-15 05:28:06 +00:00
{
2014-12-20 13:16:15 +00:00
Dictionary < string , RegisterValue > ret = new Dictionary < string , RegisterValue > ( ) ;
2014-12-15 05:28:06 +00:00
var regs = new OctoshockDll . ShockRegisters_CPU ( ) ;
OctoshockDll . shock_GetRegisters_CPU ( psx , ref regs ) ;
ret [ "r1" ] = ( int ) regs . GPR [ 1 ] ; ret [ "r2" ] = ( int ) regs . GPR [ 2 ] ; ret [ "r3" ] = ( int ) regs . GPR [ 3 ] ;
ret [ "r4" ] = ( int ) regs . GPR [ 4 ] ; ret [ "r5" ] = ( int ) regs . GPR [ 5 ] ; ret [ "r6" ] = ( int ) regs . GPR [ 6 ] ; ret [ "r7" ] = ( int ) regs . GPR [ 7 ] ;
ret [ "r8" ] = ( int ) regs . GPR [ 8 ] ; ret [ "r9" ] = ( int ) regs . GPR [ 9 ] ; ret [ "r10" ] = ( int ) regs . GPR [ 10 ] ; ret [ "r11" ] = ( int ) regs . GPR [ 11 ] ;
ret [ "r12" ] = ( int ) regs . GPR [ 12 ] ; ret [ "r13" ] = ( int ) regs . GPR [ 13 ] ; ret [ "r14" ] = ( int ) regs . GPR [ 14 ] ; ret [ "r15" ] = ( int ) regs . GPR [ 15 ] ;
ret [ "r16" ] = ( int ) regs . GPR [ 16 ] ; ret [ "r17" ] = ( int ) regs . GPR [ 17 ] ; ret [ "r18" ] = ( int ) regs . GPR [ 18 ] ; ret [ "r19" ] = ( int ) regs . GPR [ 19 ] ;
ret [ "r20" ] = ( int ) regs . GPR [ 20 ] ; ret [ "r21" ] = ( int ) regs . GPR [ 21 ] ; ret [ "r22" ] = ( int ) regs . GPR [ 22 ] ; ret [ "r23" ] = ( int ) regs . GPR [ 23 ] ;
ret [ "r24" ] = ( int ) regs . GPR [ 24 ] ; ret [ "r25" ] = ( int ) regs . GPR [ 25 ] ; ret [ "r26" ] = ( int ) regs . GPR [ 26 ] ; ret [ "r27" ] = ( int ) regs . GPR [ 27 ] ;
ret [ "r28" ] = ( int ) regs . GPR [ 28 ] ; ret [ "r29" ] = ( int ) regs . GPR [ 29 ] ; ret [ "r30" ] = ( int ) regs . GPR [ 30 ] ; ret [ "r31" ] = ( int ) regs . GPR [ 31 ] ;
ret [ "at" ] = ( int ) regs . GPR [ 1 ] ;
ret [ "v0" ] = ( int ) regs . GPR [ 2 ] ; ret [ "v1" ] = ( int ) regs . GPR [ 3 ] ;
ret [ "a0" ] = ( int ) regs . GPR [ 4 ] ; ret [ "a1" ] = ( int ) regs . GPR [ 5 ] ; ret [ "a2" ] = ( int ) regs . GPR [ 6 ] ; ret [ "a3" ] = ( int ) regs . GPR [ 7 ] ;
ret [ "t0" ] = ( int ) regs . GPR [ 8 ] ; ret [ "t1" ] = ( int ) regs . GPR [ 9 ] ; ret [ "t2" ] = ( int ) regs . GPR [ 10 ] ; ret [ "t3" ] = ( int ) regs . GPR [ 11 ] ;
ret [ "t4" ] = ( int ) regs . GPR [ 12 ] ; ret [ "t5" ] = ( int ) regs . GPR [ 13 ] ; ret [ "t6" ] = ( int ) regs . GPR [ 14 ] ; ret [ "t7" ] = ( int ) regs . GPR [ 15 ] ;
ret [ "s0" ] = ( int ) regs . GPR [ 16 ] ; ret [ "s1" ] = ( int ) regs . GPR [ 17 ] ; ret [ "s2" ] = ( int ) regs . GPR [ 18 ] ; ret [ "s3" ] = ( int ) regs . GPR [ 19 ] ;
ret [ "s4" ] = ( int ) regs . GPR [ 20 ] ; ret [ "s5" ] = ( int ) regs . GPR [ 21 ] ; ret [ "s6" ] = ( int ) regs . GPR [ 22 ] ; ret [ "s7" ] = ( int ) regs . GPR [ 23 ] ;
ret [ "t8" ] = ( int ) regs . GPR [ 24 ] ; ret [ "t9" ] = ( int ) regs . GPR [ 25 ] ;
ret [ "k0" ] = ( int ) regs . GPR [ 26 ] ; ret [ "k1" ] = ( int ) regs . GPR [ 27 ] ;
ret [ "gp" ] = ( int ) regs . GPR [ 28 ] ;
ret [ "sp" ] = ( int ) regs . GPR [ 29 ] ;
ret [ "fp" ] = ( int ) regs . GPR [ 30 ] ;
ret [ "ra" ] = ( int ) regs . GPR [ 31 ] ;
2014-12-18 08:21:48 +00:00
ret [ "pc" ] = ( int ) regs . PC ;
ret [ "lo" ] = ( int ) regs . LO ;
ret [ "hi" ] = ( int ) regs . HI ;
2014-12-18 11:30:06 +00:00
ret [ "sr" ] = ( int ) regs . SR ;
ret [ "cause" ] = ( int ) regs . CAUSE ;
ret [ "epc" ] = ( int ) regs . EPC ;
2014-12-18 08:21:48 +00:00
2014-12-15 05:28:06 +00:00
return ret ;
}
static Dictionary < string , int > CpuRegisterIndices = new Dictionary < string , int > ( ) {
{ "r1" , 1 } , { "r2" , 2 } , { "r3" , 3 } , { "r4" , 4 } , { "r5" , 5 } , { "r6" , 6 } , { "r7" , 7 } ,
{ "r8" , 8 } , { "r9" , 9 } , { "r10" , 10 } , { "r11" , 11 } , { "r12" , 12 } , { "r13" , 13 } , { "r14" , 14 } , { "r15" , 15 } ,
{ "r16" , 16 } , { "r17" , 17 } , { "r18" , 18 } , { "r19" , 19 } , { "r20" , 20 } , { "r21" , 21 } , { "r22" , 22 } , { "r23" , 23 } ,
{ "r24" , 24 } , { "r25" , 25 } , { "r26" , 26 } , { "r27" , 27 } , { "r28" , 28 } , { "r29" , 29 } , { "r30" , 30 } , { "r31" , 31 } ,
{ "at" , 1 } , { "v0" , 2 } , { "v1" , 3 } ,
{ "a0" , 4 } , { "a1" , 5 } , { "a2" , 6 } , { "a3" , 7 } ,
{ "t0" , 8 } , { "t1" , 9 } , { "t2" , 10 } , { "t3" , 11 } ,
{ "t4" , 12 } , { "t5" , 13 } , { "t6" , 14 } , { "t7" , 15 } ,
{ "s0" , 16 } , { "s1" , 17 } , { "s2" , 18 } , { "s3" , 19 } ,
{ "s4" , 20 } , { "s5" , 21 } , { "s6" , 22 } , { "s7" , 23 } ,
{ "t8" , 24 } , { "t9" , 25 } ,
{ "k0" , 26 } , { "k1" , 27 } ,
2014-12-18 08:21:48 +00:00
{ "gp" , 28 } , { "sp" , 29 } , { "fp" , 30 } , { "ra" , 31 } ,
{ "pc" , 32 } ,
//33 - PC_NEXT
//34 - IN_BD_SLOT
{ "lo" , 35 } ,
{ "hi" , 36 } ,
{ "sr" , 37 } ,
{ "cause" , 38 } ,
{ "epc" , 39 } ,
2014-12-15 05:28:06 +00:00
} ;
public void SetCpuRegister ( string register , int value )
{
int index = CpuRegisterIndices [ register ] ;
OctoshockDll . shock_SetRegister_CPU ( psx , index , ( uint ) value ) ;
}
2014-12-23 01:58:12 +00:00
public ITraceable Tracer { get { return tracer ; } }
2014-12-18 08:35:56 +00:00
public int ShockTraceCallback ( IntPtr opaque , uint PC , uint inst , string dis )
{
Tracer . Put ( dis ) ;
return OctoshockDll . SHOCK_OK ;
}
2014-12-15 05:28:06 +00:00
[FeatureNotImplemented]
public IMemoryCallbackSystem MemoryCallbacks { get { throw new NotImplementedException ( ) ; } }
2014-12-20 13:29:57 +00:00
public bool CanStep ( StepType type ) { return false ; }
2014-12-15 05:28:06 +00:00
[FeatureNotImplemented]
2014-12-15 22:19:10 +00:00
public void Step ( StepType type ) { throw new NotImplementedException ( ) ; }
2014-12-15 05:28:06 +00:00
#endregion //IDebuggable
2012-11-04 23:29:06 +00:00
}
}