// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : Read.cs // Author(s) : Natalia Portillo // // Component : Disc image plugins. // // --[ Description ] ---------------------------------------------------------- // // Reads Alcohol 120% disc images. // // --[ License ] -------------------------------------------------------------- // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2020 Natalia Portillo // ****************************************************************************/ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Aaru.CommonTypes; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Exceptions; using Aaru.CommonTypes.Interfaces; using Aaru.Console; using Aaru.Decoders.CD; using Aaru.Decoders.DVD; using Aaru.Helpers; using DMI = Aaru.Decoders.Xbox.DMI; namespace Aaru.DiscImages { public sealed partial class Alcohol120 { public bool Open(IFilter imageFilter) { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); if(stream.Length < 88) return false; _isDvd = false; byte[] hdr = new byte[88]; stream.Read(hdr, 0, 88); _header = Marshal.ByteArrayToStructureLittleEndian
(hdr); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.signature = {0}", Encoding.ASCII.GetString(_header.signature)); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.version = {0}.{1}", _header.version[0], _header.version[1]); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.type = {0}", _header.type); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.sessions = {0}", _header.sessions); for(int i = 0; i < _header.unknown1.Length; i++) AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.unknown1[{1}] = 0x{0:X4}", _header.unknown1[i], i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.bcaLength = {0}", _header.bcaLength); for(int i = 0; i < _header.unknown2.Length; i++) AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.unknown2[{1}] = 0x{0:X8}", _header.unknown2[i], i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.bcaOffset = {0}", _header.bcaOffset); for(int i = 0; i < _header.unknown3.Length; i++) AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.unknown3[{1}] = 0x{0:X8}", _header.unknown3[i], i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.structuresOffset = {0}", _header.structuresOffset); for(int i = 0; i < _header.unknown4.Length; i++) AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.unknown4[{1}] = 0x{0:X8}", _header.unknown4[i], i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.sessionOffset = {0}", _header.sessionOffset); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "header.dpmOffset = {0}", _header.dpmOffset); if(_header.version[0] > _maximumSupportedVersion) return false; stream.Seek(_header.sessionOffset, SeekOrigin.Begin); _alcSessions = new Dictionary(); for(int i = 0; i < _header.sessions; i++) { byte[] sesHdr = new byte[24]; stream.Read(sesHdr, 0, 24); Session session = Marshal.SpanToStructureLittleEndian(sesHdr); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].sessionStart = {0}", session.sessionStart, i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].sessionEnd = {0}", session.sessionEnd, i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].sessionSequence = {0}", session.sessionSequence, i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].allBlocks = {0}", session.allBlocks, i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].nonTrackBlocks = {0}", session.nonTrackBlocks, i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].firstTrack = {0}", session.firstTrack, i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].lastTrack = {0}", session.lastTrack, i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].unknown = 0x{0:X8}", session.unknown, i); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].trackOffset = {0}", session.trackOffset, i); _alcSessions.Add(session.sessionSequence, session); } long footerOff = 0; bool oldIncorrectImage = false; _alcTracks = new Dictionary(); _alcToc = new Dictionary>(); foreach(Session session in _alcSessions.Values) { stream.Seek(session.trackOffset, SeekOrigin.Begin); Dictionary sesToc = new Dictionary(); for(int i = 0; i < session.allBlocks; i++) { byte[] trkHdr = new byte[80]; stream.Read(trkHdr, 0, 80); Track track = Marshal.ByteArrayToStructureLittleEndian(trkHdr); if(track.mode == TrackMode.Mode2F1Alt || track.mode == TrackMode.Mode2F1Alt) oldIncorrectImage = true; // Solve our own mistake here, sorry, but anyway seems Alcohol doesn't support DDCD if(track.zero > 0 && track.point >= 1 && track.point <= 99) { track.pmin += (byte)(track.zero * 60); track.zero = 0; oldIncorrectImage = true; } AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].mode = {0}", track.mode, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].subMode = {0}", track.subMode, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].adrCtl = {0}", track.adrCtl, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].tno = {0}", track.tno, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].point = {0:X2}", track.point, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].min = {0}", track.min, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].sec = {0}", track.sec, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].frame = {0}", track.frame, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].zero = {0}", track.zero, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].pmin = {0}", track.pmin, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].psec = {0}", track.psec, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].pframe = {0}", track.pframe, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].extraOffset = {0}", track.extraOffset, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].sectorSize = {0}", track.sectorSize, track.point, session.sessionSequence); //for(int j = 0; j < track.unknown.Length; j++) // AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].unknown[{2}] = {0}", track.unknown[j], i, j, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].startLba = {0}", track.startLba, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].startOffset = {0}", track.startOffset, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].files = {0}", track.files, track.point, session.sessionSequence); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].footerOffset = {0}", track.footerOffset, track.point, session.sessionSequence); //for(int j = 0; j < track.unknown2.Length; j++) // AaruConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].unknown2[{2}] = {0}", track.unknown2[j], i, j, session.sessionSequence); if(track.subMode == SubchannelMode.Interleaved) track.sectorSize -= 96; if(!sesToc.ContainsKey(track.point)) sesToc.Add(track.point, track); if(track.point < 0xA0) _alcTracks.Add(track.point, track); if(footerOff == 0) footerOff = track.footerOffset; _isDvd |= track.mode == TrackMode.DVD; } _alcToc.Add(session.sessionSequence, sesToc); } _alcTrackExtras = new Dictionary(); foreach(Track track in _alcTracks.Values) if(track.extraOffset > 0 && !_isDvd) { byte[] extHdr = new byte[8]; stream.Seek(track.extraOffset, SeekOrigin.Begin); stream.Read(extHdr, 0, 8); TrackExtra extra = Marshal.SpanToStructureLittleEndian(extHdr); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "track[{1}].extra.pregap = {0}", extra.pregap, track.point); AaruConsole.DebugWriteLine("Alcohol 120% plugin", "track[{1}].extra.sectors = {0}", extra.sectors, track.point); _alcTrackExtras.Add(track.point, extra); } else if(_isDvd) { var extra = new TrackExtra { sectors = track.extraOffset }; _alcTrackExtras.Add(track.point, extra); } if(footerOff > 0) { byte[] footer = new byte[16]; stream.Seek(footerOff, SeekOrigin.Begin); stream.Read(footer, 0, 16); _alcFooter = Marshal.SpanToStructureLittleEndian