diff --git a/BizHawk.Emulation/Disc/CUE_format.cs b/BizHawk.Emulation/Disc/CUE_format.cs index 1fba4fa671..330eca9133 100644 --- a/BizHawk.Emulation/Disc/CUE_format.cs +++ b/BizHawk.Emulation/Disc/CUE_format.cs @@ -100,12 +100,14 @@ namespace BizHawk.DiscSystem { var cue_track = cue_file.Tracks[t]; - //record the disc LBA that this sector started on + //record the disc LBA that this track started on int track_disc_lba_start = Sectors.Count; //record the pregap location. it will default to the start of the track unless we supplied a pregap command int track_disc_pregap_lba = track_disc_lba_start; + int blob_track_start = blob_timestamp; + //enforce a rule of our own: every track within the file must have the same sector size //we do know that files can change between track types within a file, but we're not sure what to do if the sector size changes if (Cue.BINSectorSizeForTrackType(cue_track.TrackType) != blob_sectorsize) throw new Cue.CueBrokenException("Found different sector sizes within a cue blob. We don't know how to handle that."); @@ -118,25 +120,30 @@ namespace BizHawk.DiscSystem toc_track.TrackType = cue_track.TrackType; session.Tracks.Add(toc_track); - //check whether a pregap is requested. - //when this happens for the first track in a file, some empty sectors are generated - //when it happens for any other track, its just another way of specifying index 0 LBA - if (cue_track.PreGap.LBA > 0) + if (curr_track == 1) { - if (t == 0) - for (int i = 0; i < cue_track.PreGap.LBA; i++) - { - Sectors.Add(new SectorEntry(pregap_sector)); - } - else track_disc_pregap_lba -= cue_track.PreGap.LBA; + if (cue_track.PreGap.LBA != 0) + throw new InvalidOperationException("not supported: cue files with track 1 pregaps"); + //but now we add one anyway + cue_track.PreGap = new Cue.CueTimestamp(150); } - //look ahead to the next track's index 0 so we can see how long this track's last index is + //check whether a pregap is requested. + //this causes empty sectors to get generated without consuming data from the blob + if (cue_track.PreGap.LBA > 0) + { + for (int i = 0; i < cue_track.PreGap.LBA; i++) + { + Sectors.Add(new SectorEntry(pregap_sector)); + } + } + + //look ahead to the next track's index 1 so we can see how long this track's last index is //or, for the last track, use the length of the file int track_length_lba; if (t == cue_file.Tracks.Count - 1) track_length_lba = blob_length_lba - blob_timestamp; - else track_length_lba = cue_file.Tracks[t + 1].Indexes[0].Timestamp.LBA - blob_timestamp; + else track_length_lba = cue_file.Tracks[t + 1].Indexes[1].Timestamp.LBA - blob_timestamp; //toc_track.length_lba = track_length_lba; //xxx //find out how many indexes we have @@ -156,13 +163,11 @@ namespace BizHawk.DiscSystem if (index == 0) toc_index.lba = track_disc_pregap_lba; else toc_index.lba = Sectors.Count; - //toc_index.lba += 150; //TODO - consider whether to add 150 here - //calculate length of the index //if it is the last index then we use our calculation from before, otherwise we check the next index int index_length_lba; if (is_last_index) - index_length_lba = track_disc_lba_start + track_length_lba - blob_timestamp - blob_disc_lba_start; + index_length_lba = track_length_lba - (blob_timestamp - blob_track_start); else index_length_lba = cue_track.Indexes[index + 1].Timestamp.LBA - blob_timestamp; //emit sectors @@ -232,7 +237,6 @@ namespace BizHawk.DiscSystem } //track loop } //file loop - //finally, analyze the length of the sessions and the entire disc by summing the lengths of the tracks //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 @@ -240,6 +244,10 @@ namespace BizHawk.DiscSystem foreach (var toc_session in TOC.Sessions) { var firstTrack = toc_session.Tracks[0]; + + //track 0, index 0 is actually -150. but cue sheets will never say that + //firstTrack.Indexes[0].lba -= 150; + var lastTrack = toc_session.Tracks[toc_session.Tracks.Count - 1]; session.length_lba = lastTrack.Indexes[0].lba + lastTrack.length_lba - firstTrack.Indexes[0].lba; TOC.length_lba += toc_session.length_lba; diff --git a/BizHawk.Emulation/Disc/Disc.API.cs b/BizHawk.Emulation/Disc/Disc.API.cs index 5c640f098c..b202be5fe9 100644 --- a/BizHawk.Emulation/Disc/Disc.API.cs +++ b/BizHawk.Emulation/Disc/Disc.API.cs @@ -49,35 +49,19 @@ namespace BizHawk.DiscSystem { //main API to read a 2352-byte LBA from a disc. //this starts at the beginning of the disc (at the lead-in) - //so add 150 to get to a FAD-address in the user data area + //so add 150 to get to get an address in the user data area public void ReadLBA_2352(int lba, byte[] buffer, int offset) { - if (lba < 150) - { - //lead-in area not supported yet - //in the future it will return something to mate with the - //subchannel data which we will load or calculate from the TOC - return; - } - - Sectors[lba - 150].Sector.Read(buffer, offset); + Sectors[lba].Sector.Read(buffer, offset); } //main API to read a 2048-byte LBA from a disc. //this starts at the beginning of the disc (at the lead-in) - //so add 150 to get to a FAD-address in the user data area + //so add 150 to get to get an address in the user data area public void ReadLBA_2048(int lba, byte[] buffer, int offset) { - if (lba < 150) - { - //lead-in area not supported yet - //in the future it will return something to mate with the - //subchannel data which we will load or calculate from the TOC - return; - } - byte[] temp = new byte[2352]; - Sectors[lba - 150].Sector.Read(temp, offset); + Sectors[lba].Sector.Read(temp, offset); Array.Copy(temp, 16, buffer, offset, 2048); } diff --git a/BizHawk.Emulation/Disc/Disc.cs b/BizHawk.Emulation/Disc/Disc.cs index ca3ead08e4..4e5c69159c 100644 --- a/BizHawk.Emulation/Disc/Disc.cs +++ b/BizHawk.Emulation/Disc/Disc.cs @@ -318,15 +318,17 @@ namespace BizHawk.DiscSystem if (!prefs.OneBinPerTrack) { + //this is the preferred mode of dumping things. we will always write full sectors. string cue = TOC.GenerateCUE(prefs); var bfd = new CueBin.BinFileDescriptor(); bfd.name = baseName + ".bin"; ret.cue = string.Format("FILE \"{0}\" BINARY\n", bfd.name) + cue; ret.bins.Add(bfd); bfd.SectorSize = 2352; - for (int i = 0; i < TOC.length_lba; i++) + //skip the lead-in! + for (int i = 150; i < TOC.length_lba; i++) { - bfd.lbas.Add(i+150); + bfd.lbas.Add(i); bfd.lba_zeros.Add(false); } } @@ -351,6 +353,7 @@ namespace BizHawk.DiscSystem } sbCue.AppendFormat("FILE \"{0}\" BINARY\n", bfd.name); + //bool dropIndex0 = track.Indexes[0].num sbCue.AppendFormat(" TRACK {0:D2} {1}\n", track.num, Cue.TrackTypeStringForTrackType(track.TrackType)); foreach (var index in track.Indexes) { diff --git a/BizHawk.Emulation/Disc/DiscTOC.cs b/BizHawk.Emulation/Disc/DiscTOC.cs index b7470d4e4e..f4fdc3a7e2 100644 --- a/BizHawk.Emulation/Disc/DiscTOC.cs +++ b/BizHawk.Emulation/Disc/DiscTOC.cs @@ -42,7 +42,10 @@ namespace BizHawk.DiscSystem public string GenerateCUE(CueBinPrefs prefs) { + //this generates a single-file cue!!!!!!! dont expect it to generate bin-per-track! StringBuilder sb = new StringBuilder(); + + bool leadin = true; foreach (var session in Sessions) { if (!prefs.SingleSession) @@ -51,6 +54,7 @@ namespace BizHawk.DiscSystem if (prefs.AnnotateCue) sb.AppendFormat("SESSION {0:D2} (length={1})\n", session.num, session.length_lba); else sb.AppendFormat("SESSION {0:D2}\n", session.num); } + foreach (var track in session.Tracks) { ETrackType trackType = track.TrackType; @@ -62,10 +66,22 @@ namespace BizHawk.DiscSystem else sb.AppendFormat(" TRACK {0:D2} {1}\n", track.num, Cue.TrackTypeStringForTrackType(trackType)); foreach (var index in track.Indexes) { + //we no longer want to generate pregaps here. bloated bin FTW! maybe this can be an optimization later so i'll leave it. //if (prefs.PreferPregapCommand && index.num == 0) // sb.AppendFormat(" PREGAP {0}\n", new Cue.CueTimestamp(index.length_lba).Value); - //else - sb.AppendFormat(" INDEX {0:D2} {1}\n", index.num, new Cue.CueTimestamp(index.lba).Value); + + if (leadin) + { + //don't generate the first index, it is illogical + } + else + { + //subtract leadin + int lba = index.lba - 150; + sb.AppendFormat(" INDEX {0:D2} {1}\n", index.num, new Cue.CueTimestamp(lba).Value); + } + + leadin = false; } } }