mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Separate Lisa tag decoding from Lisa filesystem and added
Priam tags.
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
2016-08-21 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* LisaTag.cs:
|
||||
* DiscImageChef.Decoders.csproj: Separate Lisa tag decoding
|
||||
from Lisa filesystem and added Priam tags.
|
||||
|
||||
2016-08-18 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* ATIP.cs: Make ATIP manufacturer resolver a public method.
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
<Compile Include="SCSI\SSC\DensitySupport.cs" />
|
||||
<Compile Include="SCSI\Types.cs" />
|
||||
<Compile Include="SCSI\ModesEncoders.cs" />
|
||||
<Compile Include="LisaTag.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
||||
360
DiscImageChef.Decoders/LisaTag.cs
Normal file
360
DiscImageChef.Decoders/LisaTag.cs
Normal file
@@ -0,0 +1,360 @@
|
||||
// /***************************************************************************
|
||||
// The Disc Image Chef
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : LisaTag.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Component
|
||||
//
|
||||
// --[ Description ] ----------------------------------------------------------
|
||||
//
|
||||
// Description
|
||||
//
|
||||
// --[ 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2016 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
using System;
|
||||
namespace DiscImageChef.Decoders
|
||||
{
|
||||
public static class LisaTag
|
||||
{
|
||||
/// <summary>
|
||||
/// LisaOS tag as stored on Apple Profile and FileWare disks (20 bytes)
|
||||
/// </summary>
|
||||
public struct ProfileTag
|
||||
{
|
||||
/// <summary>0x00, Lisa OS version number</summary>
|
||||
public ushort version;
|
||||
/// <summary>0x02 bits 7 to 6, kind of info in this block</summary>
|
||||
public byte kind;
|
||||
/// <summary>0x02 bits 5 to 0, reserved</summary>
|
||||
public byte reserved;
|
||||
/// <summary>0x03, disk volume number</summary>
|
||||
public byte volume;
|
||||
/// <summary>0x04, file ID</summary>
|
||||
public short fileID;
|
||||
/// <summary>
|
||||
/// 0x06 bit 7, checksum valid?
|
||||
/// </summary>
|
||||
public bool validChk;
|
||||
/// <summary>
|
||||
/// 0x06 bits 6 to 0, used bytes in block
|
||||
/// </summary>
|
||||
public ushort usedBytes;
|
||||
/// <summary>
|
||||
/// 0x08, 3 bytes, absolute page number
|
||||
/// </summary>
|
||||
public uint absPage;
|
||||
/// <summary>
|
||||
/// 0x0B, checksum of data
|
||||
/// </summary>
|
||||
public byte checksum;
|
||||
/// <summary>
|
||||
/// 0x0C, relative page number
|
||||
/// </summary>
|
||||
public ushort relPage;
|
||||
/// <summary>
|
||||
/// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block
|
||||
/// </summary>
|
||||
public uint nextBlock;
|
||||
/// <summary>
|
||||
/// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block
|
||||
/// </summary>
|
||||
public uint prevBlock;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool isFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool isLast;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LisaOS tag as stored on Priam DataTower disks (24 bytes)
|
||||
/// </summary>
|
||||
public struct PriamTag
|
||||
{
|
||||
/// <summary>0x00, Lisa OS version number</summary>
|
||||
public ushort version;
|
||||
/// <summary>0x02 bits 7 to 6, kind of info in this block</summary>
|
||||
public byte kind;
|
||||
/// <summary>0x02 bits 5 to 0, reserved</summary>
|
||||
public byte reserved;
|
||||
/// <summary>0x03, disk volume number</summary>
|
||||
public byte volume;
|
||||
/// <summary>0x04, file ID</summary>
|
||||
public short fileID;
|
||||
/// <summary>
|
||||
/// 0x06 bit 7, checksum valid?
|
||||
/// </summary>
|
||||
public bool validChk;
|
||||
/// <summary>
|
||||
/// 0x06 bits 6 to 0, used bytes in block
|
||||
/// </summary>
|
||||
public ushort usedBytes;
|
||||
/// <summary>
|
||||
/// 0x08, 3 bytes, absolute page number
|
||||
/// </summary>
|
||||
public uint absPage;
|
||||
/// <summary>
|
||||
/// 0x0B, checksum of data
|
||||
/// </summary>
|
||||
public byte checksum;
|
||||
/// <summary>
|
||||
/// 0x0C, relative page number
|
||||
/// </summary>
|
||||
public ushort relPage;
|
||||
/// <summary>
|
||||
/// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block
|
||||
/// </summary>
|
||||
public uint nextBlock;
|
||||
/// <summary>
|
||||
/// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block
|
||||
/// </summary>
|
||||
public uint prevBlock;
|
||||
/// <summary>
|
||||
/// 0x14, disk size
|
||||
/// </summary>
|
||||
public uint diskSize;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool isFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool isLast;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LisaOS tag as stored on Apple Sony disks (12 bytes)
|
||||
/// </summary>
|
||||
public struct SonyTag
|
||||
{
|
||||
/// <summary>0x00, Lisa OS version number</summary>
|
||||
public ushort version;
|
||||
/// <summary>0x02 bits 7 to 6, kind of info in this block</summary>
|
||||
public byte kind;
|
||||
/// <summary>0x02 bits 5 to 0, reserved</summary>
|
||||
public byte reserved;
|
||||
/// <summary>0x03, disk volume number</summary>
|
||||
public byte volume;
|
||||
/// <summary>0x04, file ID</summary>
|
||||
public short fileID;
|
||||
/// <summary>
|
||||
/// 0x06, relative page number
|
||||
/// </summary>
|
||||
public ushort relPage;
|
||||
/// <summary>
|
||||
/// 0x08, 3 bytes, next block, 0x7FF if it's last block, 0x8000 set if block is valid
|
||||
/// </summary>
|
||||
public ushort nextBlock;
|
||||
/// <summary>
|
||||
/// 0x0A, 3 bytes, previous block, 0x7FF if it's first block
|
||||
/// </summary>
|
||||
public ushort prevBlock;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool isFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool isLast;
|
||||
}
|
||||
|
||||
public static SonyTag? DecodeSonyTag(byte[] tag)
|
||||
{
|
||||
if(tag == null || tag.Length != 12)
|
||||
return null;
|
||||
|
||||
SonyTag snTag = new SonyTag();
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
byte[] tmp = new byte[4];
|
||||
|
||||
snTag.version = BigEndianBitConverter.ToUInt16(tag, 0);
|
||||
snTag.kind = (byte)((tag[2] & 0xC0) >> 6);
|
||||
snTag.reserved = (byte)(tag[2] & 0x3F);
|
||||
snTag.volume = tag[3];
|
||||
snTag.fileID = BigEndianBitConverter.ToInt16(tag, 4);
|
||||
snTag.relPage = BigEndianBitConverter.ToUInt16(tag, 6);
|
||||
snTag.nextBlock = (ushort)(BigEndianBitConverter.ToUInt16(tag, 8) & 0x7FF);
|
||||
snTag.prevBlock = (ushort)(BigEndianBitConverter.ToUInt16(tag, 10) & 0x7FF);
|
||||
|
||||
snTag.isLast = snTag.nextBlock == 0x7FF;
|
||||
snTag.isFirst = snTag.prevBlock == 0x7FF;
|
||||
|
||||
return snTag;
|
||||
}
|
||||
|
||||
public static ProfileTag? DecodeProfileTag(byte[] tag)
|
||||
{
|
||||
if(tag == null || tag.Length != 20)
|
||||
return null;
|
||||
|
||||
ProfileTag phTag = new ProfileTag();
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
byte[] tmp = new byte[4];
|
||||
|
||||
phTag.version = BigEndianBitConverter.ToUInt16(tag, 0);
|
||||
phTag.kind = (byte)((tag[2] & 0xC0) >> 6);
|
||||
phTag.reserved = (byte)(tag[2] & 0x3F);
|
||||
phTag.volume = tag[3];
|
||||
phTag.fileID = BigEndianBitConverter.ToInt16(tag, 4);
|
||||
phTag.validChk |= (tag[6] & 0x80) == 0x80;
|
||||
phTag.usedBytes = (ushort)(BigEndianBitConverter.ToUInt16(tag, 6) & 0x7FFF);
|
||||
|
||||
tmp[0] = 0x00;
|
||||
tmp[1] = tag[8];
|
||||
tmp[2] = tag[9];
|
||||
tmp[3] = tag[10];
|
||||
phTag.absPage = BigEndianBitConverter.ToUInt32(tmp, 0);
|
||||
|
||||
phTag.checksum = tag[11];
|
||||
phTag.relPage = BigEndianBitConverter.ToUInt16(tag, 12);
|
||||
|
||||
tmp[0] = 0x00;
|
||||
tmp[1] = tag[14];
|
||||
tmp[2] = tag[15];
|
||||
tmp[3] = tag[16];
|
||||
phTag.nextBlock = BigEndianBitConverter.ToUInt32(tmp, 0);
|
||||
|
||||
tmp[0] = 0x00;
|
||||
tmp[1] = tag[17];
|
||||
tmp[2] = tag[18];
|
||||
tmp[3] = tag[19];
|
||||
phTag.prevBlock = BigEndianBitConverter.ToUInt32(tmp, 0);
|
||||
|
||||
phTag.isLast = phTag.nextBlock == 0xFFFFFF;
|
||||
phTag.isFirst = phTag.prevBlock == 0xFFFFFF;
|
||||
|
||||
return phTag;
|
||||
}
|
||||
|
||||
public static PriamTag? DecodePriamTag(byte[] tag)
|
||||
{
|
||||
if(tag == null || tag.Length != 24)
|
||||
return null;
|
||||
|
||||
PriamTag pmTag = new PriamTag();
|
||||
|
||||
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
||||
|
||||
byte[] tmp = new byte[4];
|
||||
|
||||
pmTag.version = BigEndianBitConverter.ToUInt16(tag, 0);
|
||||
pmTag.kind = (byte)((tag[2] & 0xC0) >> 6);
|
||||
pmTag.reserved = (byte)(tag[2] & 0x3F);
|
||||
pmTag.volume = tag[3];
|
||||
pmTag.fileID = BigEndianBitConverter.ToInt16(tag, 4);
|
||||
pmTag.validChk |= (tag[6] & 0x80) == 0x80;
|
||||
pmTag.usedBytes = (ushort)(BigEndianBitConverter.ToUInt16(tag, 6) & 0x7FFF);
|
||||
|
||||
tmp[0] = 0x00;
|
||||
tmp[1] = tag[8];
|
||||
tmp[2] = tag[9];
|
||||
tmp[3] = tag[10];
|
||||
pmTag.absPage = BigEndianBitConverter.ToUInt32(tmp, 0);
|
||||
|
||||
pmTag.checksum = tag[11];
|
||||
pmTag.relPage = BigEndianBitConverter.ToUInt16(tag, 12);
|
||||
|
||||
tmp[0] = 0x00;
|
||||
tmp[1] = tag[14];
|
||||
tmp[2] = tag[15];
|
||||
tmp[3] = tag[16];
|
||||
pmTag.nextBlock = BigEndianBitConverter.ToUInt32(tmp, 0);
|
||||
|
||||
tmp[0] = 0x00;
|
||||
tmp[1] = tag[17];
|
||||
tmp[2] = tag[18];
|
||||
tmp[3] = tag[19];
|
||||
pmTag.prevBlock = BigEndianBitConverter.ToUInt32(tmp, 0);
|
||||
|
||||
pmTag.diskSize = BigEndianBitConverter.ToUInt32(tag, 20);
|
||||
|
||||
pmTag.isLast = pmTag.nextBlock == 0xFFFFFF;
|
||||
pmTag.isFirst = pmTag.prevBlock == 0xFFFFFF;
|
||||
|
||||
return pmTag;
|
||||
}
|
||||
|
||||
public static PriamTag? DecodeTag(byte[] tag)
|
||||
{
|
||||
if(tag == null)
|
||||
return null;
|
||||
|
||||
PriamTag pmTag = new PriamTag();
|
||||
|
||||
switch(tag.Length)
|
||||
{
|
||||
case 12:
|
||||
SonyTag? snTag = DecodeSonyTag(tag);
|
||||
|
||||
if(snTag == null)
|
||||
return null;
|
||||
|
||||
pmTag = new PriamTag();
|
||||
pmTag.absPage = 0;
|
||||
pmTag.checksum = 0;
|
||||
pmTag.diskSize = 0;
|
||||
pmTag.fileID = snTag.Value.fileID;
|
||||
pmTag.kind = snTag.Value.kind;
|
||||
pmTag.nextBlock = snTag.Value.nextBlock;
|
||||
pmTag.prevBlock = snTag.Value.prevBlock;
|
||||
pmTag.relPage = snTag.Value.relPage;
|
||||
pmTag.reserved = snTag.Value.reserved;
|
||||
pmTag.usedBytes = 0;
|
||||
pmTag.validChk = false;
|
||||
pmTag.version = snTag.Value.version;
|
||||
pmTag.volume = snTag.Value.volume;
|
||||
pmTag.isFirst = snTag.Value.isFirst;
|
||||
pmTag.isLast = snTag.Value.isLast;
|
||||
|
||||
return pmTag;
|
||||
case 20:
|
||||
ProfileTag? phTag = DecodeProfileTag(tag);
|
||||
|
||||
if(phTag == null)
|
||||
return null;
|
||||
|
||||
pmTag = new PriamTag();
|
||||
pmTag.absPage = phTag.Value.absPage;
|
||||
pmTag.checksum = phTag.Value.checksum;
|
||||
pmTag.diskSize = 0;
|
||||
pmTag.fileID = phTag.Value.fileID;
|
||||
pmTag.kind = phTag.Value.kind;
|
||||
pmTag.nextBlock = phTag.Value.nextBlock;
|
||||
pmTag.prevBlock = phTag.Value.prevBlock;
|
||||
pmTag.relPage = phTag.Value.relPage;
|
||||
pmTag.reserved = phTag.Value.reserved;
|
||||
pmTag.usedBytes = phTag.Value.usedBytes;
|
||||
pmTag.validChk = phTag.Value.validChk;
|
||||
pmTag.version = phTag.Value.version;
|
||||
pmTag.volume = phTag.Value.volume;
|
||||
pmTag.isFirst = phTag.Value.isFirst;
|
||||
pmTag.isLast = phTag.Value.isLast;
|
||||
|
||||
return pmTag;
|
||||
case 24:
|
||||
return DecodePriamTag(tag);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
2016-08-21 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* Dir.cs:
|
||||
* File.cs:
|
||||
* Info.cs:
|
||||
* Super.cs:
|
||||
* Xattr.cs:
|
||||
* Extent.cs:
|
||||
* Structs.cs:
|
||||
* DiscImageChef.Filesystems.csproj: Separate Lisa tag decoding
|
||||
from Lisa filesystem and added Priam tags.
|
||||
|
||||
2016-08-18 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* exFAT.cs:
|
||||
|
||||
@@ -118,6 +118,10 @@
|
||||
<Project>{9F213318-5CB8-4066-A757-074489C9F818}</Project>
|
||||
<Name>DiscImageChef.Metadata</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\DiscImageChef.Decoders\DiscImageChef.Decoders.csproj">
|
||||
<Project>{0BEB3088-B634-4289-AE17-CDF2D25D00D5}</Project>
|
||||
<Name>DiscImageChef.Decoders</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="LisaFS\" />
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
using DiscImageChef.Decoders;
|
||||
|
||||
namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
@@ -174,10 +175,10 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// If root catalog is not pointed in MDDF (unchecked) maybe it's always following S-Records File?
|
||||
for(ulong i = 0; i < device.GetSectors(); i++)
|
||||
{
|
||||
Tag catTag;
|
||||
LisaTag.PriamTag catTag;
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out catTag);
|
||||
|
||||
if(catTag.fileID == FILEID_CATALOG && catTag.relBlock == 0)
|
||||
if(catTag.fileID == FILEID_CATALOG && catTag.relPage == 0)
|
||||
{
|
||||
firstCatalogBlock = device.ReadSectors(i, 4);
|
||||
break;
|
||||
@@ -194,7 +195,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Traverse double-linked list until first catalog block
|
||||
while(prevCatalogPointer != 0xFFFFFFFF)
|
||||
{
|
||||
Tag prevTag;
|
||||
LisaTag.PriamTag prevTag;
|
||||
DecodeTag(device.ReadSectorTag(prevCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag), out prevTag);
|
||||
|
||||
if(prevTag.fileID != FILEID_CATALOG)
|
||||
@@ -213,7 +214,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Traverse double-linked list to read full catalog
|
||||
while(nextCatalogPointer != 0xFFFFFFFF)
|
||||
{
|
||||
Tag nextTag;
|
||||
LisaTag.PriamTag nextTag;
|
||||
DecodeTag(device.ReadSectorTag(nextCatalogPointer + mddf.mddf_block + volumePrefix, SectorTagType.AppleSectorTag), out nextTag);
|
||||
|
||||
if(nextTag.fileID != FILEID_CATALOG)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
using System;
|
||||
using DiscImageChef.Console;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
using DiscImageChef.Decoders;
|
||||
|
||||
namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
@@ -76,7 +77,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// Pointers are relative to MDDF
|
||||
ptr += mddf.mddf_block + volumePrefix;
|
||||
|
||||
Tag extTag;
|
||||
LisaTag.PriamTag extTag;
|
||||
|
||||
// This happens on some disks.
|
||||
// This is a filesystem corruption that makes LisaOS crash on scavenge.
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
using System;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
using DiscImageChef.Console;
|
||||
using DiscImageChef.Decoders;
|
||||
|
||||
namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
@@ -212,7 +213,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
}
|
||||
}
|
||||
|
||||
Tag sysTag;
|
||||
LisaTag.PriamTag sysTag;
|
||||
|
||||
// Should be enough to check 100 sectors?
|
||||
for(ulong i = 0; i < 100; i++)
|
||||
@@ -247,9 +248,9 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
|
||||
// Relative block for $Loader starts at $Boot block
|
||||
if(sysTag.fileID == FILEID_LOADER_SIGNED)
|
||||
sysTag.relBlock--;
|
||||
sysTag.relPage--;
|
||||
|
||||
Array.Copy(sector, 0, buf, sector.Length * sysTag.relBlock, sector.Length);
|
||||
Array.Copy(sector, 0, buf, sector.Length * sysTag.relPage, sector.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using DiscImageChef.Console;
|
||||
using DiscImageChef.Decoders;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
|
||||
namespace DiscImageChef.Filesystems.LisaFS
|
||||
@@ -61,7 +62,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(int i = 0; i < 100; i++)
|
||||
{
|
||||
Tag searchTag;
|
||||
LisaTag.PriamTag searchTag;
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.fileID);
|
||||
@@ -150,7 +151,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(int i = 0; i < 100; i++)
|
||||
{
|
||||
Tag searchTag;
|
||||
LisaTag.PriamTag searchTag;
|
||||
DecodeTag(imagePlugin.ReadSectorTag((ulong)i, SectorTagType.AppleSectorTag), out searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.fileID);
|
||||
|
||||
@@ -207,48 +207,6 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
public byte scavenge_flag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The sector tag. Before the sector is encoded to GCR the tag is attached to the data.
|
||||
/// Its size and format varies depending on device.
|
||||
/// Lisa OS relies on tags for scavenging a floppy, but ignores most of them for normal usage,
|
||||
/// except on hard disks where the checksum byte is absolutely enforced (a sector with an invalid
|
||||
/// one gives an OS error).
|
||||
/// </summary>
|
||||
struct Tag
|
||||
{
|
||||
/// <summary>0x00 version</summary>
|
||||
public ushort version;
|
||||
/// <summary>0x02 unknown</summary>
|
||||
public ushort unknown;
|
||||
/// <summary>0x04 File ID. Negative numbers are extents for the file with same absolute value number</summary>
|
||||
public short fileID;
|
||||
/// <summary>Only in 20 bytes tag at 0x06, mask 0x8000 if valid tag</summary>
|
||||
public ushort usedBytes;
|
||||
/// <summary>Only in 20 bytes tag at 0x08, 3 bytes</summary>
|
||||
public uint absoluteBlock;
|
||||
/// <summary>Only in 20 bytes tag at 0x0B, checksum byte</summary>
|
||||
public byte checksum;
|
||||
/// <summary>0x06 in 12 bytes tag, 0x0C in 20 bytes tag, relative block</summary>
|
||||
public ushort relBlock;
|
||||
/// <summary>
|
||||
/// Next block for this file.
|
||||
/// In 12 bytes tag at 0x08, 2 bytes, 0x8000 bit seems always set, 0x07FF means this is last block.
|
||||
/// In 20 bytes tag at 0x0E, 3 bytes, 0xFFFFFF means this is last block.
|
||||
/// </summary>
|
||||
public uint nextBlock;
|
||||
/// <summary>
|
||||
/// Previous block for this file.
|
||||
/// In 12 bytes tag at 0x0A, 2 bytes, 0x07FF means this is first block.
|
||||
/// In 20 bytes tag at 0x11, 3 bytes, 0xFFFFFF means this is first block.
|
||||
/// </summary>
|
||||
public uint prevBlock;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool isFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool isLast;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An entry in the catalog from V3.
|
||||
/// The first entry is bigger than the rest, may be a header, I have not needed any of its values so I just ignored it.
|
||||
|
||||
@@ -34,6 +34,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using DiscImageChef.Console;
|
||||
using DiscImageChef.ImagePlugins;
|
||||
using DiscImageChef.Decoders;
|
||||
|
||||
namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
@@ -80,7 +81,7 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
// LisaOS searches sectors until tag tells MDDF resides there, so we'll search 100 sectors
|
||||
for(ulong i = 0; i < 100; i++)
|
||||
{
|
||||
Tag searchTag;
|
||||
LisaTag.PriamTag searchTag;
|
||||
DecodeTag(device.ReadSectorTag(i, SectorTagType.AppleSectorTag), out searchTag);
|
||||
|
||||
DicConsole.DebugWriteLine("LisaFS plugin", "Sector {0}, file ID 0x{1:X4}", i, searchTag.fileID);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using DiscImageChef.Decoders;
|
||||
|
||||
namespace DiscImageChef.Filesystems.LisaFS
|
||||
{
|
||||
@@ -214,47 +215,15 @@ namespace DiscImageChef.Filesystems.LisaFS
|
||||
/// <returns>Error number.</returns>
|
||||
/// <param name="tag">Sector tag.</param>
|
||||
/// <param name="decoded">Decoded sector tag.</param>
|
||||
Errno DecodeTag(byte[] tag, out Tag decoded)
|
||||
Errno DecodeTag(byte[] tag, out LisaTag.PriamTag decoded)
|
||||
{
|
||||
decoded = new Tag();
|
||||
decoded = new LisaTag.PriamTag();
|
||||
LisaTag.PriamTag? pmTag = LisaTag.DecodeTag(tag);
|
||||
|
||||
if(tag.Length == 12)
|
||||
{
|
||||
decoded.version = BigEndianBitConverter.ToUInt16(tag, 0x00);
|
||||
decoded.unknown = BigEndianBitConverter.ToUInt16(tag, 0x02);
|
||||
decoded.fileID = BigEndianBitConverter.ToInt16(tag, 0x04);
|
||||
decoded.relBlock = BigEndianBitConverter.ToUInt16(tag, 0x06);
|
||||
decoded.nextBlock = BigEndianBitConverter.ToUInt16(tag, 0x08);
|
||||
decoded.nextBlock &= 0x7FF;
|
||||
decoded.prevBlock = BigEndianBitConverter.ToUInt16(tag, 0x0A);
|
||||
decoded.prevBlock &= 0x7FF;
|
||||
|
||||
if(decoded.nextBlock == 0x7FF)
|
||||
decoded.isLast = true;
|
||||
if(decoded.prevBlock == 0x7FF)
|
||||
decoded.isFirst = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
decoded.version = BigEndianBitConverter.ToUInt16(tag, 0x00);
|
||||
decoded.unknown = BigEndianBitConverter.ToUInt16(tag, 0x02);
|
||||
decoded.fileID = BigEndianBitConverter.ToInt16(tag, 0x04);
|
||||
decoded.usedBytes = BigEndianBitConverter.ToUInt16(tag, 0x06);
|
||||
decoded.absoluteBlock = BigEndianBitConverter.ToUInt32(tag, 0x07);
|
||||
decoded.absoluteBlock &= 0xFFFFFF;
|
||||
decoded.checksum = tag[0x0B];
|
||||
decoded.relBlock = BigEndianBitConverter.ToUInt16(tag, 0x0C);
|
||||
decoded.nextBlock = BigEndianBitConverter.ToUInt32(tag, 0x0D);
|
||||
decoded.nextBlock &= 0xFFFFFF;
|
||||
decoded.prevBlock = BigEndianBitConverter.ToUInt32(tag, 0x10);
|
||||
decoded.prevBlock &= 0xFFFFFF;
|
||||
|
||||
if(decoded.nextBlock == 0xFFFFFF)
|
||||
decoded.isLast = true;
|
||||
if(decoded.prevBlock == 0xFFFFFF)
|
||||
decoded.isFirst = true;
|
||||
}
|
||||
if(!pmTag.HasValue)
|
||||
return Errno.InvalidArgument;
|
||||
|
||||
decoded = pmTag.Value;
|
||||
return Errno.NoError;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user