duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

iso_reader.h (5041B)


      1 // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
      3 
      4 #pragma once
      5 
      6 #include "common/types.h"
      7 
      8 #include <memory>
      9 #include <optional>
     10 #include <string>
     11 #include <vector>
     12 
     13 class CDImage;
     14 
     15 class Error;
     16 
     17 class IsoReader
     18 {
     19 public:
     20   enum : u32
     21   {
     22     SECTOR_SIZE = 2048
     23   };
     24 
     25 #pragma pack(push, 1)
     26 
     27   struct ISOVolumeDescriptorHeader
     28   {
     29     u8 type_code;
     30     char standard_identifier[5];
     31     u8 version;
     32   };
     33   static_assert(sizeof(ISOVolumeDescriptorHeader) == 7);
     34 
     35   struct ISOBootRecord
     36   {
     37     ISOVolumeDescriptorHeader header;
     38     char boot_system_identifier[32];
     39     char boot_identifier[32];
     40     u8 data[1977];
     41   };
     42   static_assert(sizeof(ISOBootRecord) == 2048);
     43 
     44   struct ISOPVDDateTime
     45   {
     46     char year[4];
     47     char month[2];
     48     char day[2];
     49     char hour[2];
     50     char minute[2];
     51     char second[2];
     52     char milliseconds[2];
     53     s8 gmt_offset;
     54   };
     55   static_assert(sizeof(ISOPVDDateTime) == 17);
     56 
     57   struct ISOPrimaryVolumeDescriptor
     58   {
     59     ISOVolumeDescriptorHeader header;
     60     u8 unused;
     61     char system_identifier[32];
     62     char volume_identifier[32];
     63     char unused2[8];
     64     u32 total_sectors_le;
     65     u32 total_sectors_be;
     66     char unused3[32];
     67     u16 volume_set_size_le;
     68     u16 volume_set_size_be;
     69     u16 volume_sequence_number_le;
     70     u16 volume_sequence_number_be;
     71     u16 block_size_le;
     72     u16 block_size_be;
     73     u32 path_table_size_le;
     74     u32 path_table_size_be;
     75     u32 path_table_location_le;
     76     u32 optional_path_table_location_le;
     77     u32 path_table_location_be;
     78     u32 optional_path_table_location_be;
     79     u8 root_directory_entry[34];
     80     char volume_set_identifier[128];
     81     char publisher_identifier[128];
     82     char data_preparer_identifier[128];
     83     char application_identifier[128];
     84     char copyright_file_identifier[38];
     85     char abstract_file_identifier[36];
     86     char bibliographic_file_identifier[37];
     87     ISOPVDDateTime volume_creation_time;
     88     ISOPVDDateTime volume_modification_time;
     89     ISOPVDDateTime volume_expiration_time;
     90     ISOPVDDateTime volume_effective_time;
     91     u8 structure_version;
     92     u8 unused4;
     93     u8 application_used[512];
     94     u8 reserved[653];
     95   };
     96   static_assert(sizeof(ISOPrimaryVolumeDescriptor) == 2048);
     97 
     98   struct ISODirectoryEntryDateTime
     99   {
    100     u8 years_since_1900;
    101     u8 month;
    102     u8 day;
    103     u8 hour;
    104     u8 minute;
    105     u8 second;
    106     s8 gmt_offset;
    107   };
    108 
    109   enum ISODirectoryEntryFlags : u8
    110   {
    111     ISODirectoryEntryFlag_Hidden = (1 << 0),
    112     ISODirectoryEntryFlag_Directory = (1 << 1),
    113     ISODirectoryEntryFlag_AssociatedFile = (1 << 2),
    114     ISODirectoryEntryFlag_ExtendedAttributePresent = (1 << 3),
    115     ISODirectoryEntryFlag_OwnerGroupPermissions = (1 << 4),
    116     ISODirectoryEntryFlag_MoreExtents = (1 << 7),
    117   };
    118 
    119   struct ISODirectoryEntry
    120   {
    121     u8 entry_length;
    122     u8 extended_attribute_length;
    123     u32 location_le;
    124     u32 location_be;
    125     u32 length_le;
    126     u32 length_be;
    127     ISODirectoryEntryDateTime recoding_time;
    128     ISODirectoryEntryFlags flags;
    129     u8 interleaved_unit_size;
    130     u8 interleaved_gap_size;
    131     u16 sequence_le;
    132     u16 sequence_be;
    133     u8 filename_length;
    134 
    135     ALWAYS_INLINE bool IsDirectory() const { return (flags & ISODirectoryEntryFlag_Directory); }
    136     ALWAYS_INLINE u32 GetSizeInSectors() const { return (length_le + (SECTOR_SIZE - 1)) / SECTOR_SIZE; }
    137   };
    138 
    139 #pragma pack(pop)
    140 
    141   IsoReader();
    142   ~IsoReader();
    143 
    144   static std::string_view RemoveVersionIdentifierFromPath(std::string_view path);
    145 
    146   ALWAYS_INLINE const CDImage* GetImage() const { return m_image; }
    147   ALWAYS_INLINE u32 GetTrackNumber() const { return m_track_number; }
    148   ALWAYS_INLINE u32 GetPVDLBA() const { return m_pvd_lba; }
    149   ALWAYS_INLINE const ISOPrimaryVolumeDescriptor& GetPVD() const { return m_pvd; }
    150 
    151   bool Open(CDImage* image, u32 track_number, Error* error = nullptr);
    152 
    153   std::vector<std::string> GetFilesInDirectory(std::string_view path, Error* error = nullptr);
    154   std::vector<std::pair<std::string, ISODirectoryEntry>> GetEntriesInDirectory(std::string_view path,
    155                                                                                Error* error = nullptr);
    156 
    157   std::optional<ISODirectoryEntry> LocateFile(std::string_view path, Error* error);
    158 
    159   bool FileExists(std::string_view path, Error* error = nullptr);
    160   bool DirectoryExists(std::string_view path, Error* error = nullptr);
    161   bool ReadFile(std::string_view path, std::vector<u8>* data, Error* error = nullptr);
    162   bool ReadFile(const ISODirectoryEntry& de, std::vector<u8>* data, Error* error = nullptr);
    163 
    164 private:
    165   static std::string_view GetDirectoryEntryFileName(const u8* sector, u32 de_sector_offset);
    166 
    167   bool ReadSector(u8* buf, u32 lsn, Error* error);
    168   bool ReadPVD(Error* error);
    169 
    170   std::optional<ISODirectoryEntry> LocateFile(std::string_view path, u8* sector_buffer, u32 directory_record_lba,
    171                                               u32 directory_record_size, Error* error);
    172 
    173   CDImage* m_image;
    174   u32 m_track_number;
    175 
    176   ISOPrimaryVolumeDescriptor m_pvd = {};
    177   u32 m_pvd_lba = 0;
    178 };