BizHawk/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs

283 lines
8.7 KiB
C#
Raw Normal View History

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
using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
#pragma warning disable 649 //adelikat: Disable dumb warnings until this file is complete
namespace BizHawk.Emulation.Cores.Sony.PSX
{
[CoreAttributes(
2014-12-10 19:41:13 +00:00
"Octoshock",
"Ryphecha",
isPorted: true,
isReleased: false
)]
public unsafe class Octoshock : IEmulator, IVideoProvider, ISoundProvider
{
public string SystemId { get { return "NULL"; } }
public static readonly ControllerDefinition NullController = new ControllerDefinition { Name = "Null Controller" };
public string BoardName { get { return null; } }
private int[] frameBuffer = new int[0];
private Random rand = new Random();
public CoreComm CoreComm { get; private set; }
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;
bool disposed = false;
public void Dispose()
{
if (disposed) return;
2014-12-10 19:41:13 +00:00
OctoshockDll.shock_Destroy(psx);
psx = IntPtr.Zero;
2014-12-10 19:41:13 +00:00
disposed = true;
}
2014-12-10 19:41:13 +00:00
class DiscInterface : IDisposable
{
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);
}
2014-12-10 19:41:13 +00:00
OctoshockDll.ShockDisc_ReadTOC cbReadTOC;
OctoshockDll.ShockDisc_ReadLBA cbReadLBA;
2014-12-10 19:41:13 +00:00
public DiscSystem.Disc Disc;
public IntPtr OctoshockHandle;
2014-12-10 19:41:13 +00:00
public void Dispose()
{
OctoshockDll.shock_DestroyDisc(OctoshockHandle);
OctoshockHandle = IntPtr.Zero;
}
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
2014-12-10 19:41:13 +00:00
tracks101[0].lba = tracks101[0].adr = tracks101[0].control = 0;
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;
}
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;
}
2014-12-10 19:41:13 +00:00
byte[] SectorBuffer = new byte[2352];
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;
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)
{
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();
}
2014-12-10 19:41:13 +00:00
return OctoshockDll.SHOCK_OK;
}
2014-12-10 19:41:13 +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-10 19:41:13 +00:00
public Octoshock(CoreComm comm, DiscSystem.Disc disc)
{
ServiceProvider = new BasicServiceProvider(this);
var domains = new List<MemoryDomain>();
CoreComm = comm;
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");
2014-12-10 19:41:13 +00:00
//create the instance
fixed (byte* pFirmware = firmware)
OctoshockDll.shock_Create(out psx, discInfo.region, pFirmware);
//these should track values in octoshock gpu.cpp FillVideoParams
//if (discInfo.region == OctoshockDll.eRegion.EU)
//{
// VirtualWidth = 377; // " Dunno :( "
// VirtualHeight = 288;
//}
//else
//{
// VirtualWidth = 320; // Dunno :(
// VirtualHeight = 240;
//}
//BUT-for now theyre normalized (NOTE: THIS MESSES UP THE ASPECT RATIOS)
VirtualWidth = 700;
VirtualHeight = 480;
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);
}
2014-12-10 19:41:13 +00:00
public IEmulatorServiceProvider ServiceProvider { get; private set; }
void Attach()
{
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
}
2014-12-10 19:41:13 +00:00
//public void LoadCuePath(string path)
//{
// Attach();
// DiscSystem.Disc.FromCCDPath
//}
static Octoshock()
{
}
2014-12-10 19:41:13 +00:00
[FeatureNotImplemented]
public void ResetCounters()
{
// FIXME when all this stuff is implemented
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.ShockFramebufferInfo fb = new OctoshockDll.ShockFramebufferInfo();
fb.flags = OctoshockDll.eShockFramebufferFlags.Normalize;
2014-12-10 19:41:13 +00:00
OctoshockDll.shock_GetFramebuffer(psx, ref fb);
2014-12-10 19:41:13 +00:00
//Console.WriteLine(fb.height);
2014-12-10 19:41:13 +00:00
if (render == false) return;
2014-12-10 19:41:13 +00:00
int w = fb.width;
int h = fb.height;
BufferWidth = w;
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);
frameBuffer = new int[len];
2014-12-10 19:41:13 +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
}
}
[FeatureNotImplemented]
public ControllerDefinition ControllerDefinition { get { return NullController; } }
[FeatureNotImplemented]
public IController Controller { get; set; }
public int Frame
{
[FeatureNotImplemented]
get;
[FeatureNotImplemented]
set;
}
[FeatureNotImplemented]
public bool DeterministicEmulation { get { return true; } }
public int[] GetVideoBuffer() { return frameBuffer; }
public int VirtualWidth { get; private set; }
public int VirtualHeight { get; private set; }
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; }
}
}