cleanup unused Blob_ZeroTypeStuff and general reorg
This commit is contained in:
parent
67468e93ec
commit
33f23e137d
|
@ -55,6 +55,8 @@
|
|||
<Compile Include="API\DiscIdentifier.cs" />
|
||||
<Compile Include="API\DiscSectorReader.cs" />
|
||||
<Compile Include="API\DiscStream.cs" />
|
||||
<Compile Include="API\DiscStructure.cs" />
|
||||
<Compile Include="API\TOCRaw.cs" />
|
||||
<Compile Include="Blobs\Blob_ECM.cs" />
|
||||
<Compile Include="Blobs\Blob_RawFile.cs" />
|
||||
<Compile Include="Blobs\Blob_WaveFile.cs" />
|
||||
|
@ -92,8 +94,6 @@
|
|||
<Compile Include="SBI_format.cs" />
|
||||
<Compile Include="SectorInterfaces.cs" />
|
||||
<Compile Include="Subcode.cs" />
|
||||
<Compile Include="TOC\DiscStructure.cs" />
|
||||
<Compile Include="TOC\TOCRaw.cs" />
|
||||
<Compile Include="TOC_format.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -7,22 +7,6 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
{
|
||||
public partial class Disc : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// A blob that always reads 0
|
||||
/// </summary>
|
||||
internal sealed class Blob_Zeros : IBlob
|
||||
{
|
||||
public int Read(long byte_pos, byte[] buffer, int offset, int count)
|
||||
{
|
||||
Array.Clear(buffer, offset, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class Blob_ZeroPadAdapter : IBlob
|
||||
{
|
||||
IBlob srcBlob;
|
||||
|
@ -58,44 +42,6 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For use with blobs which are prematurely ended: buffers what there is, and zero-pads the rest
|
||||
/// </summary>
|
||||
public sealed class Blob_ZeroPadBuffer : IBlob
|
||||
{
|
||||
public static Blob_ZeroPadBuffer MakeBufferFrom(IBlob baseBlob, long start, int bufferLength)
|
||||
{
|
||||
var ret = new Blob_ZeroPadBuffer();
|
||||
|
||||
//allocate the entire buffer we'll need, and it will already be zero-padded
|
||||
ret.buffer = new byte[bufferLength];
|
||||
|
||||
//read as much as is left
|
||||
baseBlob.Read(start, ret.buffer, 0, bufferLength);
|
||||
|
||||
//if any less got read, well, there were already zeroes there
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int Read(long byte_pos, byte[] buffer, int offset, int count)
|
||||
{
|
||||
int have = buffer.Length;
|
||||
int todo = count;
|
||||
if (have < todo)
|
||||
todo = have;
|
||||
Buffer.BlockCopy(this.buffer, 0, buffer, offset, todo);
|
||||
return todo;
|
||||
}
|
||||
|
||||
byte[] buffer;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
buffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
using System;
|
||||
|
||||
//disc type identification logic
|
||||
|
||||
namespace BizHawk.Emulation.DiscSystem
|
||||
{
|
||||
public enum DiscType
|
||||
{
|
||||
/// <summary>
|
||||
/// Nothing is known about this disc type
|
||||
/// </summary>
|
||||
UnknownFormat,
|
||||
|
||||
/// <summary>
|
||||
/// This is definitely a CDFS disc, but we can't identify anything more about it
|
||||
/// </summary>
|
||||
UnknownCDFS,
|
||||
|
||||
/// <summary>
|
||||
/// Sony PSX
|
||||
/// </summary>
|
||||
SonyPSX,
|
||||
|
||||
/// <summary>
|
||||
/// Sony PSP
|
||||
/// </summary>
|
||||
SonyPSP,
|
||||
|
||||
/// <summary>
|
||||
/// Sega Saturn
|
||||
/// </summary>
|
||||
SegaSaturn,
|
||||
|
||||
/// <summary>
|
||||
/// Its not clear whether we can ever have enough info to ID a turboCD disc (we're using hashes)
|
||||
/// </summary>
|
||||
TurboCD,
|
||||
|
||||
/// <summary>
|
||||
/// MegaDrive addon
|
||||
/// </summary>
|
||||
MegaCD
|
||||
}
|
||||
|
||||
sealed public partial class Disc
|
||||
{
|
||||
/// <summary>
|
||||
/// Attempts to determine the type of the disc.
|
||||
/// In the future, we might return a struct or a class with more detailed information
|
||||
/// </summary>
|
||||
public DiscType DetectDiscType()
|
||||
{
|
||||
//sega doesnt put anything identifying in the cdfs volume info. but its consistent about putting its own header here in sector 0
|
||||
if (DetectSegaSaturn()) return DiscType.SegaSaturn;
|
||||
|
||||
// not fully tested yet
|
||||
if (DetectMegaCD()) return DiscType.MegaCD;
|
||||
|
||||
// not fully tested yet
|
||||
if (DetectPSX()) return DiscType.SonyPSX;
|
||||
|
||||
//we dont know how to detect TurboCD.
|
||||
//an emulator frontend will likely just guess TurboCD if the disc is UnknownFormat
|
||||
|
||||
var iso = new ISOFile();
|
||||
bool isIso = iso.Parse(DiscStream.Open_LBA_2048(this));
|
||||
|
||||
if (isIso)
|
||||
{
|
||||
var appId = System.Text.Encoding.ASCII.GetString(iso.VolumeDescriptors[0].ApplicationIdentifier).TrimEnd('\0', ' ');
|
||||
//NOTE: PSX magical drop F (JP SLPS_02337) doesn't have the correct iso PVD fields
|
||||
//if (appId == "PLAYSTATION")
|
||||
// return DiscType.SonyPSX;
|
||||
if(appId == "PSP GAME")
|
||||
return DiscType.SonyPSP;
|
||||
|
||||
return DiscType.UnknownCDFS;
|
||||
}
|
||||
|
||||
return DiscType.UnknownFormat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is reasonable approach to ID saturn.
|
||||
/// </summary>
|
||||
bool DetectSegaSaturn()
|
||||
{
|
||||
return StringAt("SEGA SEGASATURN", 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// probably wrong
|
||||
/// </summary>
|
||||
bool DetectMegaCD()
|
||||
{
|
||||
return StringAt("SEGADISCSYSTEM", 0) || StringAt("SEGADISCSYSTEM", 16);
|
||||
}
|
||||
|
||||
bool DetectPSX()
|
||||
{
|
||||
if (!StringAt(" Licensed by ",0, 4)) return false;
|
||||
return (StringAt("Sony Computer Entertainment Euro", 32, 4)
|
||||
|| StringAt("Sony Computer Entertainment Inc.", 32, 4)
|
||||
|| StringAt("Sony Computer Entertainment Amer", 32, 4)
|
||||
|| StringAt("Sony Computer Entertainment of A", 32, 4)
|
||||
);
|
||||
}
|
||||
|
||||
private bool StringAt(string s, int n, int lba = 0)
|
||||
{
|
||||
byte[] data = new byte[2048];
|
||||
ReadLBA_2048(lba, data, 0);
|
||||
byte[] cmp = System.Text.Encoding.ASCII.GetBytes(s);
|
||||
byte[] cmp2 = new byte[cmp.Length];
|
||||
Buffer.BlockCopy(data, n, cmp2, 0, cmp.Length);
|
||||
return System.Linq.Enumerable.SequenceEqual(cmp, cmp2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,226 +0,0 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Emulation.DiscSystem
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The TOC contains information directly describing the structure of the disc, as well as some more logically structured information derived from that.
|
||||
/// Additionally, this class contains methods to synchronize between them.
|
||||
/// This is a bit weird.. Perhaps the different views of the data should be seaprated.
|
||||
///
|
||||
/// One final caveat - I think the TOC should be independent for independent sessions.. the concept of multi-sessioning is so thoroughly ill-supported here, it will require radical renovation ever to support.
|
||||
///
|
||||
/// Sessions -> Tracks : These are the highest-level data structures of the disc. We should probably rename this to something like DiscStructure, and save DiscTOC for the actual TOC.
|
||||
/// TOCPoint : These are the basic logical unit of data stored in the TOC. They're basically bookmarks for tracks.
|
||||
/// TOCEntry : These are the basic unit of data in the rawest view of the TOC. They're stored in the lead-in Q subchannel, and there are multiple redundant copies, and they store several different types of information.
|
||||
/// </summary>
|
||||
public class DiscTOC
|
||||
{
|
||||
/// <summary>
|
||||
/// Right now support for anything other than 1 session is totally not working
|
||||
/// </summary>
|
||||
public List<Session> Sessions = new List<Session>();
|
||||
|
||||
/// <summary>
|
||||
/// List of Points described by the TOC
|
||||
/// </summary>
|
||||
public List<TOCPoint> Points = new List<TOCPoint>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Todo - comment about what this actually means
|
||||
/// TODO - this is redundant with Sectors.Count
|
||||
/// </summary>
|
||||
public int length_aba;
|
||||
|
||||
/// <summary>
|
||||
/// todo - comment about what this actually means
|
||||
/// </summary>
|
||||
public Timestamp FriendlyLength { get { return new Timestamp(length_aba); } }
|
||||
|
||||
/// <summary>
|
||||
/// todo - comment about what this actually means
|
||||
/// </summary>
|
||||
public long BinarySize
|
||||
{
|
||||
get { return length_aba * 2352; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// seeks the point immediately before (or equal to) this LBA
|
||||
/// </summary>
|
||||
public TOCPoint SeekPoint(int lba)
|
||||
{
|
||||
int aba = lba + 150;
|
||||
for(int i=0;i<Points.Count;i++)
|
||||
{
|
||||
TOCPoint tp = Points[i];
|
||||
if (tp.ABA > aba)
|
||||
return Points[i - 1];
|
||||
}
|
||||
return Points[Points.Count - 1];
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class TOCPoint
|
||||
{
|
||||
public int Num;
|
||||
public int ABA, TrackNum, IndexNum;
|
||||
public Track Track;
|
||||
|
||||
public int LBA
|
||||
{
|
||||
get { return ABA - 150; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the Points list from the current logical TOC
|
||||
/// </summary>
|
||||
public void SynthesizeTOCPointsFromSessions()
|
||||
{
|
||||
int num = 0;
|
||||
Points.Clear();
|
||||
foreach (var ses in Sessions)
|
||||
{
|
||||
foreach (var track in ses.Tracks)
|
||||
foreach (var index in track.Indexes)
|
||||
{
|
||||
var tp = new TOCPoint
|
||||
{
|
||||
Num = num++,
|
||||
ABA = index.aba,
|
||||
TrackNum = track.num,
|
||||
IndexNum = index.num,
|
||||
Track = track
|
||||
};
|
||||
Points.Add(tp);
|
||||
}
|
||||
|
||||
var tpLeadout = new TOCPoint();
|
||||
var lastTrack = ses.Tracks[ses.Tracks.Count - 1];
|
||||
tpLeadout.Num = num++;
|
||||
tpLeadout.ABA = lastTrack.Indexes[1].aba + lastTrack.length_aba;
|
||||
tpLeadout.IndexNum = 0;
|
||||
tpLeadout.TrackNum = 100;
|
||||
tpLeadout.Track = null; //no leadout track.. now... or ever?
|
||||
Points.Add(tpLeadout);
|
||||
}
|
||||
}
|
||||
|
||||
public class Session
|
||||
{
|
||||
public int num;
|
||||
public List<Track> Tracks = new List<Track>();
|
||||
|
||||
//the length of the session (should be the sum of all track lengths)
|
||||
public int length_aba;
|
||||
public Timestamp FriendlyLength { get { return new Timestamp(length_aba); } }
|
||||
}
|
||||
|
||||
public class Track
|
||||
{
|
||||
public ETrackType TrackType;
|
||||
public int num;
|
||||
public List<Index> Indexes = new List<Index>();
|
||||
|
||||
/// <summary>
|
||||
/// a track logically starts at index 1.
|
||||
/// so this is the length from this index 1 to the next index 1 (or the end of the disc)
|
||||
/// the time before track 1 index 1 is the lead-in and isn't accounted for in any track...
|
||||
/// </summary>
|
||||
public int length_aba;
|
||||
public Timestamp FriendlyLength { get { return new Timestamp(length_aba); } }
|
||||
}
|
||||
|
||||
public class Index
|
||||
{
|
||||
public int num;
|
||||
public int aba;
|
||||
|
||||
public int LBA
|
||||
{
|
||||
get { return aba - 150; }
|
||||
}
|
||||
|
||||
//the length of the section
|
||||
//HEY! This is commented out because it is a bad idea.
|
||||
//The length of a section is almost useless, and if you want it, you are probably making an error.
|
||||
//public int length_lba;
|
||||
//public Cue.Timestamp FriendlyLength { get { return new Cue.Timestamp(length_lba); } }
|
||||
}
|
||||
|
||||
public string GenerateCUE_OneBin(CueBinPrefs prefs)
|
||||
{
|
||||
if (prefs.OneBlobPerTrack) throw new InvalidOperationException("OneBinPerTrack passed to GenerateCUE_OneBin");
|
||||
|
||||
//this generates a single-file cue!!!!!!! dont expect it to generate bin-per-track!
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
foreach (var session in Sessions)
|
||||
{
|
||||
if (!prefs.SingleSession)
|
||||
{
|
||||
//dont want to screw around with sessions for now
|
||||
if (prefs.AnnotateCue) sb.AppendFormat("SESSION {0:D2} (length={1})\n", session.num, session.length_aba);
|
||||
else sb.AppendFormat("SESSION {0:D2}\n", session.num);
|
||||
}
|
||||
|
||||
foreach (var track in session.Tracks)
|
||||
{
|
||||
ETrackType trackType = track.TrackType;
|
||||
|
||||
//mutate track type according to our principle of canonicalization
|
||||
if (trackType == ETrackType.Mode1_2048 && prefs.DumpECM)
|
||||
trackType = ETrackType.Mode1_2352;
|
||||
|
||||
if (prefs.AnnotateCue) sb.AppendFormat(" TRACK {0:D2} {1} (length={2})\n", track.num, Cue.TrackTypeStringForTrackType(trackType), track.length_aba);
|
||||
else sb.AppendFormat(" TRACK {0:D2} {1}\n", track.num, Cue.TrackTypeStringForTrackType(trackType));
|
||||
foreach (var index in track.Indexes)
|
||||
{
|
||||
//cue+bin has an implicit 150 sector pregap which neither the cue nor the bin has any awareness of
|
||||
//except for the baked-in sector addressing.
|
||||
//but, if there is an extra-long pregap, we want to reflect it this way
|
||||
int lba = index.aba - 150;
|
||||
if (lba <= 0 && index.num == 0 && track.num == 1)
|
||||
{
|
||||
}
|
||||
//dont emit index 0 when it is the same as index 1, it is illegal for some reason
|
||||
else if (index.num == 0 && index.aba == track.Indexes[1].aba)
|
||||
{
|
||||
//dont emit index 0 when it is the same as index 1, it confuses some cue parsers
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendFormat(" INDEX {0:D2} {1}\n", index.num, new Timestamp(lba).Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
public void AnalyzeLengthsFromIndexLengths()
|
||||
{
|
||||
//this is a little more complex than it looks, because the length of a thing is not determined by summing it
|
||||
//but rather by the difference in lbas between start and end
|
||||
length_aba = 0;
|
||||
foreach (var session in Sessions)
|
||||
{
|
||||
var firstTrack = session.Tracks[0];
|
||||
var lastTrack = session.Tracks[session.Tracks.Count - 1];
|
||||
session.length_aba = lastTrack.Indexes[0].aba + lastTrack.length_aba - firstTrack.Indexes[0].aba;
|
||||
length_aba += session.length_aba;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue