mirror of
https://github.com/GerbilSoft/rom-properties.git
synced 2025-06-18 11:35:38 -04:00
[libromdata] ISO: Get the sector size from the underlying disc reader classes if not reading directly from a file.
The SparseDiscReader changes in v2.3 broke this, so anything that uses an ISO-9660 format showed 2048-byte sectors, even if this wasn't the case. SparseDiscReader subclasses now have a set of CD-ROM specific fields to set, e.g. CD-ROM sector size, mode, and subchannels. For multi-track images, this should be set for the "main" data track. Updated the following classes to set these fields: - CdiReader (uses Track 02 for Dreamcast games) - GdiReader (uses Track 03 for Dreamcast games) - Cdrom2352Reader (always uses 2352-byte sectors, but gets mode from the first sector) - CisoPspReader (always uses MODE1/2048) GameCube and Wii disc reading classes don't set these, since they aren't CD-ROM formats with multiple sector sizes.
This commit is contained in:
parent
8e78811e8a
commit
5a738f8277
5
NEWS.md
5
NEWS.md
@ -10,6 +10,11 @@
|
||||
* Affects: v2.5
|
||||
* rpcli: SCSI inquiry was accidentally broken during a code cleanup.
|
||||
* Affects: v2.3 - v2.5
|
||||
* ISO: Get the sector size from the underlying disc reader classes if
|
||||
not reading directly from a file.
|
||||
* The SparseDiscReader changes in v2.3 broke this, so anything that
|
||||
uses an ISO-9660 format showed 2048-byte sectors, even if this
|
||||
wasn't the case.
|
||||
|
||||
* Other changes:
|
||||
* Added support for localsearch-3.8, the new name of Tracker.
|
||||
|
@ -16,12 +16,15 @@
|
||||
|
||||
// Other rom-properties libraries
|
||||
#include "librpbase/Achievements.hpp"
|
||||
#include "librpbase/disc/PartitionFile.hpp"
|
||||
#include "librpbase/disc/SparseDiscReader.hpp"
|
||||
#include "libi18n/i18n.h"
|
||||
using namespace LibRpBase;
|
||||
using namespace LibRpFile;
|
||||
using namespace LibRpText;
|
||||
|
||||
// C++ STL classes
|
||||
#include <typeinfo>
|
||||
using std::array;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
@ -69,6 +72,9 @@ public:
|
||||
|
||||
// Sector offset
|
||||
// Usually 0 (for 2048) or 16 (for 2352 or 2448).
|
||||
// NOTE: If SparseDiscReader is used, this will almost
|
||||
// always be 2048. Query SparseDiscReader to get the
|
||||
// actual sector size.
|
||||
unsigned int sector_offset;
|
||||
|
||||
// UDF version
|
||||
@ -783,7 +789,33 @@ int ISO::loadFieldData(void)
|
||||
// TODO: ascii_to_utf8()?
|
||||
|
||||
// Sector size
|
||||
d->fields.addField_string_numeric(C_("ISO", "Sector Size"), d->sector_size);
|
||||
// NOTE: Need to check for a SparseDiscReader first, since if one's
|
||||
// in use, ISO will always think the disc has 2048-byte sectors.
|
||||
unsigned int sector_size = 0;
|
||||
const SparseDiscReader *sdr = dynamic_cast<const SparseDiscReader*>(d->file.get());
|
||||
if (!sdr) {
|
||||
// Not a SparseDiscReader.
|
||||
// If this is a PartitionFile, check the underlying IDiscReader.
|
||||
PartitionFile *const pf = dynamic_cast<PartitionFile*>(d->file.get());
|
||||
if (pf) {
|
||||
IDiscReaderPtr dr = pf->getIDiscReader();
|
||||
sdr = dynamic_cast<const SparseDiscReader*>(dr.get());
|
||||
}
|
||||
}
|
||||
if (sdr) {
|
||||
// Get the sector size from the SparseDiscReader.
|
||||
// TODO: Also mode and subchannels?
|
||||
if (sdr->hasCdromInfo()) {
|
||||
sector_size = sdr->cdromSectorSize();
|
||||
}
|
||||
} else {
|
||||
// Use the ISO-9660 sector size.
|
||||
sector_size = d->sector_size;
|
||||
}
|
||||
|
||||
if (sector_size > 0) {
|
||||
d->fields.addField_string_numeric(C_("ISO", "Sector Size"), sector_size);
|
||||
}
|
||||
|
||||
switch (d->discType) {
|
||||
case ISOPrivate::DiscType::ISO9660:
|
||||
|
@ -59,6 +59,8 @@ public:
|
||||
|
||||
// SectorReadMode to sector size map
|
||||
static const array<uint32_t, static_cast<uint32_t>(SectorReadMode::Max)> sectorReadModeToSizeMap;
|
||||
// SectorReadMode to CD-ROM mode map
|
||||
static const array<uint8_t, static_cast<size_t>(SectorReadMode::Max)> sectorReadModeToCdromModeMap;
|
||||
|
||||
// Block range mapping
|
||||
// NOTE: This currently *only* contains data tracks.
|
||||
@ -117,9 +119,15 @@ public:
|
||||
/** CdiReaderPrivate **/
|
||||
|
||||
// SectorReadMode to sector size map
|
||||
const array<uint32_t, static_cast<uint32_t>(CdiReaderPrivate::SectorReadMode::Max)> CdiReaderPrivate::sectorReadModeToSizeMap = {{
|
||||
const array<uint32_t, static_cast<size_t>(CdiReaderPrivate::SectorReadMode::Max)> CdiReaderPrivate::sectorReadModeToSizeMap = {{
|
||||
2048, 2336, 2352, 2352+16, 2352+96
|
||||
}};
|
||||
// SectorReadMode to CD-ROM mode map
|
||||
const array<uint8_t, static_cast<size_t>(CdiReaderPrivate::SectorReadMode::Max)> CdiReaderPrivate::sectorReadModeToCdromModeMap = {{
|
||||
1, 2, 0,
|
||||
// subchannel modes (TODO)
|
||||
1, 1,
|
||||
}};
|
||||
|
||||
CdiReaderPrivate::CdiReaderPrivate(CdiReader *q)
|
||||
: super(q)
|
||||
@ -387,6 +395,33 @@ int CdiReaderPrivate::parseCdiFile(void)
|
||||
|
||||
// Done parsing the CDI.
|
||||
// TODO: Sort by LBA?
|
||||
|
||||
// Set the SparseDiscReader CD-ROM sector size values.
|
||||
// NOTE: Could be multiple sector size values, but we'll use the
|
||||
// one from Track 02 if available; otherwise, Track 01.
|
||||
BlockRange *sdrBlockRange = nullptr;
|
||||
for (unsigned int i = 3; i > 0; i--) {
|
||||
if (trackMappings.size() >= i && trackMappings[i-1] >= 0) {
|
||||
sdrBlockRange = &blockRanges[trackMappings[i-1]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sdrBlockRange) {
|
||||
unsigned int sectorSize = sdrBlockRange->sectorSize;
|
||||
// TODO: Subchannel modes. Assuming Mode 1 for these for now.
|
||||
this->hasCdromInfo = true;
|
||||
this->cdromSectorMode = sectorReadModeToCdromModeMap[static_cast<size_t>(sdrBlockRange->sectorReadMode)];
|
||||
|
||||
if (sectorSize > 2352) {
|
||||
// Subchannels are present.
|
||||
this->cdromSectorSize = 2352;
|
||||
this->cdromSubchannelSize = sectorSize - 2352;
|
||||
} else {
|
||||
// No subchannels.
|
||||
this->cdromSectorSize = sectorSize;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,10 @@ private:
|
||||
typedef SparseDiscReaderPrivate super;
|
||||
RP_DISABLE_COPY(Cdrom2352ReaderPrivate)
|
||||
|
||||
public:
|
||||
// CD-ROM sync magic magic
|
||||
static const array<uint8_t, 12> CDROM_2352_MAGIC;
|
||||
|
||||
public:
|
||||
// Physical block size
|
||||
// Supported block sizes: 2352 (raw), 2448 (raw+subchan)
|
||||
@ -46,6 +50,10 @@ public:
|
||||
|
||||
/** Cdrom2352ReaderPrivate **/
|
||||
|
||||
// CD-ROM sync magic magic
|
||||
const array<uint8_t, 12> Cdrom2352ReaderPrivate::CDROM_2352_MAGIC =
|
||||
{{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00}};
|
||||
|
||||
Cdrom2352ReaderPrivate::Cdrom2352ReaderPrivate(Cdrom2352Reader *q, unsigned int physBlockSize)
|
||||
: super(q)
|
||||
, physBlockSize(physBlockSize)
|
||||
@ -77,11 +85,35 @@ Cdrom2352Reader::Cdrom2352Reader(const IRpFilePtr &file, unsigned int physBlockS
|
||||
const off64_t fileSize = m_file->size();
|
||||
if (fileSize <= 0 || fileSize % d->physBlockSize != 0) {
|
||||
// Invalid disc size.
|
||||
m_file.reset();
|
||||
m_lastError = EIO;
|
||||
m_file.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the first sector to determine the CD-ROM mode.
|
||||
CDROM_2352_Sector_t sector;
|
||||
size_t sz_read = m_file->seekAndRead(0, §or, sizeof(sector));
|
||||
if (sz_read != sizeof(sector)) {
|
||||
// Read error.
|
||||
m_lastError = m_file->lastError();
|
||||
m_file.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the CD-ROM sync magic.
|
||||
if (memcmp(sector.sync, Cdrom2352ReaderPrivate::CDROM_2352_MAGIC.data(), Cdrom2352ReaderPrivate::CDROM_2352_MAGIC.size()) != 0) {
|
||||
// Sync magic is incorrect.
|
||||
m_lastError = EIO;
|
||||
m_file.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the CD-ROM information.
|
||||
d->hasCdromInfo = true;
|
||||
d->cdromSectorMode = sector.mode;
|
||||
d->cdromSectorSize = 2352;
|
||||
d->cdromSubchannelSize = 0;
|
||||
|
||||
// Disc parameters.
|
||||
// NOTE: A 32-bit block count allows for ~8 TiB with 2048-byte sectors.
|
||||
d->blockCount = static_cast<unsigned int>(fileSize / 2352LL);
|
||||
@ -105,13 +137,8 @@ int Cdrom2352Reader::isDiscSupported_static(const uint8_t *pHeader, size_t szHea
|
||||
return -1;
|
||||
}
|
||||
|
||||
// CD-ROM sync magic magic
|
||||
static constexpr array<uint8_t, 12> CDROM_2352_MAGIC =
|
||||
{{0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00}};
|
||||
|
||||
// Check the CD-ROM sync magic.
|
||||
if (!memcmp(pHeader, CDROM_2352_MAGIC.data(), CDROM_2352_MAGIC.size()))
|
||||
{
|
||||
if (!memcmp(pHeader, Cdrom2352ReaderPrivate::CDROM_2352_MAGIC.data(), Cdrom2352ReaderPrivate::CDROM_2352_MAGIC.size())) {
|
||||
// Valid CD-ROM sync magic.
|
||||
return 0;
|
||||
}
|
||||
|
@ -482,6 +482,12 @@ CisoPspReader::CisoPspReader(const IRpFilePtr &file)
|
||||
d->z_buffer.resize(cache_size);
|
||||
d->blockCacheIdx = ~0U;
|
||||
|
||||
// PSP disc images are always ISO-9660 Mode 1.
|
||||
d->hasCdromInfo = true;
|
||||
d->cdromSectorMode = 1;
|
||||
d->cdromSectorSize = 2048;
|
||||
d->cdromSubchannelSize = 0;
|
||||
|
||||
// Reset the disc position.
|
||||
d->pos = 0;
|
||||
}
|
||||
|
@ -242,6 +242,25 @@ int GdiReaderPrivate::parseGdiFile(char *gdibuf)
|
||||
|
||||
// Done parsing the GDI.
|
||||
// TODO: Sort by LBA?
|
||||
|
||||
// Set the SparseDiscReader CD-ROM sector size values.
|
||||
// NOTE: Could be multiple sector size values, but we'll use the
|
||||
// one from Track 03 if available; otherwise, Track 02 or Track 01.
|
||||
BlockRange *sdrBlockRange = nullptr;
|
||||
for (unsigned int i = 3; i > 0; i--) {
|
||||
if (trackMappings.size() >= i && trackMappings[i-1] >= 0) {
|
||||
sdrBlockRange = &blockRanges[trackMappings[i-1]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sdrBlockRange) {
|
||||
// TODO: Do any DC games use Mode 2 or subchannels?
|
||||
this->hasCdromInfo = true;
|
||||
this->cdromSectorMode = 1;
|
||||
this->cdromSectorSize = sdrBlockRange->sectorSize;
|
||||
this->cdromSubchannelSize = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ off64_t PartitionFile::tell(void)
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
/** File properties. **/
|
||||
/** File properties **/
|
||||
|
||||
/**
|
||||
* Get the file size.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ROM Properties Page shell extension. (librpbase) *
|
||||
* PartitionFile.hpp: IRpFile implementation for IPartition. *
|
||||
* *
|
||||
* Copyright (c) 2016-2024 by David Korth. *
|
||||
* Copyright (c) 2016-2025 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
@ -15,80 +15,92 @@ namespace LibRpBase {
|
||||
|
||||
class PartitionFile final : public LibRpFile::IRpFile
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Open a file from an IPartition.
|
||||
* NOTE: These files are read-only.
|
||||
*
|
||||
* @param partition [in] IPartition (or IDiscReader) object
|
||||
* @param offset [in] File starting offset
|
||||
* @param size [in] File size
|
||||
*/
|
||||
PartitionFile(const IDiscReaderPtr& partition, off64_t offset, off64_t size);
|
||||
public:
|
||||
/**
|
||||
* Open a file from an IPartition.
|
||||
* NOTE: These files are read-only.
|
||||
*
|
||||
* @param partition [in] IPartition (or IDiscReader) object
|
||||
* @param offset [in] File starting offset
|
||||
* @param size [in] File size
|
||||
*/
|
||||
PartitionFile(const IDiscReaderPtr& partition, off64_t offset, off64_t size);
|
||||
|
||||
private:
|
||||
typedef IRpFile super;
|
||||
RP_DISABLE_COPY(PartitionFile)
|
||||
private:
|
||||
typedef IRpFile super;
|
||||
RP_DISABLE_COPY(PartitionFile)
|
||||
|
||||
public:
|
||||
/**
|
||||
* Is the file open?
|
||||
* This usually only returns false if an error occurred.
|
||||
* @return True if the file is open; false if it isn't.
|
||||
*/
|
||||
bool isOpen(void) const final;
|
||||
public:
|
||||
/**
|
||||
* Is the file open?
|
||||
* This usually only returns false if an error occurred.
|
||||
* @return True if the file is open; false if it isn't.
|
||||
*/
|
||||
bool isOpen(void) const final;
|
||||
|
||||
/**
|
||||
* Close the file.
|
||||
*/
|
||||
void close(void) final;
|
||||
/**
|
||||
* Close the file.
|
||||
*/
|
||||
void close(void) final;
|
||||
|
||||
/**
|
||||
* Read data from the file.
|
||||
* @param ptr Output data buffer.
|
||||
* @param size Amount of data to read, in bytes.
|
||||
* @return Number of bytes read.
|
||||
*/
|
||||
ATTR_ACCESS_SIZE(write_only, 2, 3)
|
||||
size_t read(void *ptr, size_t size) final;
|
||||
/**
|
||||
* Read data from the file.
|
||||
* @param ptr Output data buffer.
|
||||
* @param size Amount of data to read, in bytes.
|
||||
* @return Number of bytes read.
|
||||
*/
|
||||
ATTR_ACCESS_SIZE(write_only, 2, 3)
|
||||
size_t read(void *ptr, size_t size) final;
|
||||
|
||||
/**
|
||||
* Write data to the file.
|
||||
* (NOTE: Not valid for PartitionFile; this will always return 0.)
|
||||
* @param ptr Input data buffer.
|
||||
* @param size Amount of data to read, in bytes.
|
||||
* @return Number of bytes written.
|
||||
*/
|
||||
ATTR_ACCESS_SIZE(read_only, 2, 3)
|
||||
size_t write(const void *ptr, size_t size) final;
|
||||
/**
|
||||
* Write data to the file.
|
||||
* (NOTE: Not valid for PartitionFile; this will always return 0.)
|
||||
* @param ptr Input data buffer.
|
||||
* @param size Amount of data to read, in bytes.
|
||||
* @return Number of bytes written.
|
||||
*/
|
||||
ATTR_ACCESS_SIZE(read_only, 2, 3)
|
||||
size_t write(const void *ptr, size_t size) final;
|
||||
|
||||
/**
|
||||
* Set the file position.
|
||||
* @param pos File position.
|
||||
* @return 0 on success; -1 on error.
|
||||
*/
|
||||
int seek(off64_t pos) final;
|
||||
/**
|
||||
* Set the file position.
|
||||
* @param pos File position.
|
||||
* @return 0 on success; -1 on error.
|
||||
*/
|
||||
int seek(off64_t pos) final;
|
||||
|
||||
/**
|
||||
* Get the file position.
|
||||
* @return File position, or -1 on error.
|
||||
*/
|
||||
off64_t tell(void) final;
|
||||
/**
|
||||
* Get the file position.
|
||||
* @return File position, or -1 on error.
|
||||
*/
|
||||
off64_t tell(void) final;
|
||||
|
||||
public:
|
||||
/** File properties. **/
|
||||
public:
|
||||
/** File properties **/
|
||||
|
||||
/**
|
||||
* Get the file size.
|
||||
* @return File size, or negative on error.
|
||||
*/
|
||||
off64_t size(void) final;
|
||||
/**
|
||||
* Get the file size.
|
||||
* @return File size, or negative on error.
|
||||
*/
|
||||
off64_t size(void) final;
|
||||
|
||||
protected:
|
||||
IDiscReaderPtr m_partition;
|
||||
off64_t m_offset; // File starting offset.
|
||||
off64_t m_size; // File size.
|
||||
off64_t m_pos; // Current position.
|
||||
public:
|
||||
/** PartitionFile functions **/
|
||||
|
||||
/**
|
||||
* Get the underlying IDiscReader.
|
||||
* @return IDiscReaderPtr
|
||||
*/
|
||||
inline IDiscReaderPtr getIDiscReader(void)
|
||||
{
|
||||
return m_partition;
|
||||
}
|
||||
|
||||
protected:
|
||||
IDiscReaderPtr m_partition;
|
||||
off64_t m_offset; // File starting offset.
|
||||
off64_t m_size; // File size.
|
||||
off64_t m_pos; // Current position.
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<PartitionFile> PartitionFilePtr;
|
||||
|
@ -23,6 +23,10 @@ SparseDiscReaderPrivate::SparseDiscReaderPrivate(SparseDiscReader *q)
|
||||
, disc_size(0)
|
||||
, pos(-1)
|
||||
, block_size(0)
|
||||
, hasCdromInfo(false)
|
||||
, cdromSectorMode(0)
|
||||
, cdromSectorSize(0)
|
||||
, cdromSubchannelSize(0)
|
||||
{
|
||||
// NOTE: Can't check q->m_file here.
|
||||
|
||||
@ -209,6 +213,50 @@ off64_t SparseDiscReader::size(void)
|
||||
return d->disc_size;
|
||||
}
|
||||
|
||||
/** SparseDiscReader-specific properties **/
|
||||
|
||||
// CD-ROM specific information
|
||||
|
||||
/**
|
||||
* Is CD-ROM specific information set?
|
||||
* @return True if set; false if not.
|
||||
*/
|
||||
bool SparseDiscReader::hasCdromInfo(void) const
|
||||
{
|
||||
RP_D(const SparseDiscReader);
|
||||
return d->hasCdromInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CD-ROM sector mode.
|
||||
* @return 0 for audio, 1 for MODE1, or 2 for MODE2.
|
||||
*/
|
||||
uint8_t SparseDiscReader::cdromSectorMode(void) const
|
||||
{
|
||||
RP_D(const SparseDiscReader);
|
||||
return d->cdromSectorMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CD-ROM sector size.
|
||||
* @return CD-ROM sector size, or 0 if not applicable.
|
||||
*/
|
||||
unsigned int SparseDiscReader::cdromSectorSize(void) const
|
||||
{
|
||||
RP_D(const SparseDiscReader);
|
||||
return d->cdromSectorSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CD-ROM subchannel size.
|
||||
* @return CD-ROM subchannel size, or 0 if not applicable.
|
||||
*/
|
||||
unsigned int SparseDiscReader::cdromSubchannelSize(void) const
|
||||
{
|
||||
RP_D(const SparseDiscReader);
|
||||
return d->cdromSubchannelSize;
|
||||
}
|
||||
|
||||
/** SparseDiscReader **/
|
||||
|
||||
/**
|
||||
|
@ -29,7 +29,7 @@ protected:
|
||||
SparseDiscReaderPrivate *const d_ptr;
|
||||
|
||||
public:
|
||||
/** IDiscReader functions. **/
|
||||
/** IDiscReader functions **/
|
||||
|
||||
/**
|
||||
* Read data from the disc image.
|
||||
@ -59,8 +59,37 @@ public:
|
||||
*/
|
||||
off64_t size(void) final;
|
||||
|
||||
public:
|
||||
/** SparseDiscReader-specific properties **/
|
||||
|
||||
// CD-ROM specific information
|
||||
|
||||
/**
|
||||
* Is CD-ROM specific information set?
|
||||
* @return True if set; false if not.
|
||||
*/
|
||||
bool hasCdromInfo(void) const;
|
||||
|
||||
/**
|
||||
* Get the CD-ROM sector mode.
|
||||
* @return 1 or 2 for MODE1 or MODE2, or 0 if not applicable. (Audio CDs are not supported.)
|
||||
*/
|
||||
uint8_t cdromSectorMode(void) const;
|
||||
|
||||
/**
|
||||
* Get the CD-ROM sector size.
|
||||
* @return CD-ROM sector size, or 0 if not applicable.
|
||||
*/
|
||||
unsigned int cdromSectorSize(void) const;
|
||||
|
||||
/**
|
||||
* Get the CD-ROM subchannel size.
|
||||
* @return CD-ROM subchannel size, or 0 if not applicable.
|
||||
*/
|
||||
unsigned int cdromSubchannelSize(void) const;
|
||||
|
||||
protected:
|
||||
/** Virtual functions for SparseDiscReader subclasses. **/
|
||||
/** Virtual functions for SparseDiscReader subclasses **/
|
||||
|
||||
/**
|
||||
* Get the physical address of the specified logical block index.
|
||||
|
@ -33,6 +33,12 @@ public:
|
||||
off64_t disc_size; // Virtual disc image size.
|
||||
off64_t pos; // Read position.
|
||||
unsigned int block_size; // Block size.
|
||||
|
||||
// CD-ROM specific information
|
||||
bool hasCdromInfo;
|
||||
uint8_t cdromSectorMode;
|
||||
unsigned int cdromSectorSize;
|
||||
unsigned int cdromSubchannelSize;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user