Skip to content

Commit

Permalink
Merge branch 'feature/DiscJuggler-CDI-format.attempt-2'
Browse files Browse the repository at this point in the history
  • Loading branch information
GerbilSoft committed Oct 18, 2024
2 parents a4bf52f + 21e2bc3 commit 4316487
Show file tree
Hide file tree
Showing 10 changed files with 984 additions and 55 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
* Nintendo Wii save files
* Windows/DOS executables
* DMG: Detect Analogue Pocket ROM images.
* Dreamcast: CDI format disc images are now supported.
* Fixes #107: Dreamcast: CDI support.

* Bug fixes:
* On Linux, rp-config now correctly detects KDE Plasma 6 and uses the
Expand Down Expand Up @@ -86,6 +88,8 @@
* GameCubeSave: Adjust icon delays.
* Reported by @Louis322.
* WiiTicket: Recognize CA04-XS09 from early Wii U titles.
* Windows: Reverted an rpcli manifest change from v2.1 that broke
compatibility with Windows XP.

## v2.3 (released 2024/03/03)

Expand Down
3 changes: 3 additions & 0 deletions src/libromdata/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ SET(${PROJECT_NAME}_SRCS
data/Xbox360_STFS_ContentType.cpp

disc/Cdrom2352Reader.cpp
disc/CdiReader.cpp
disc/CIAReader.cpp
disc/CisoGcnReader.cpp
disc/CisoPspReader.cpp
Expand Down Expand Up @@ -329,6 +330,7 @@ SET(${PROJECT_NAME}_H
data/XboxPublishers_data.h
data/Xbox360_STFS_ContentType.hpp

disc/CdiReader.hpp
disc/Cdrom2352Reader.hpp
disc/CIAReader.hpp
disc/CisoGcnReader.hpp
Expand All @@ -341,6 +343,7 @@ SET(${PROJECT_NAME}_H
disc/GdiReader.hpp
disc/IResourceReader.hpp
disc/IsoPartition.hpp
disc/MultiTrackSparseDiscReader.hpp
disc/NASOSReader.hpp
disc/NCCHReader.hpp
disc/NCCHReader_p.hpp
Expand Down
119 changes: 82 additions & 37 deletions src/libromdata/Console/Dreamcast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ using namespace LibRpTexture;
#include "disc/Cdrom2352Reader.hpp"
#include "disc/IsoPartition.hpp"
#include "disc/GdiReader.hpp"
#include "disc/CdiReader.hpp"

// Other RomData subclasses
#include "Media/ISO.hpp"
Expand Down Expand Up @@ -58,6 +59,7 @@ class DreamcastPrivate final : public RomDataPrivate
Iso2048 = 0, // ISO-9660, 2048-byte sectors.
Iso2352 = 1, // ISO-9660, 2352-byte sectors.
GDI = 2, // GD-ROM cuesheet
CDI = 3, // DiscJuggler image

Max
};
Expand Down Expand Up @@ -119,9 +121,9 @@ const char *const DreamcastPrivate::exts[] = {
".iso", // ISO-9660 (2048-byte)
".bin", // Raw (2352-byte)
".gdi", // GD-ROM cuesheet
".cdi", // DiscJuggler

// TODO: Add these formats?
//".cdi", // DiscJuggler
//".nrg", // Nero

nullptr
Expand All @@ -130,11 +132,13 @@ const char *const DreamcastPrivate::mimeTypes[] = {
// Unofficial MIME types.
"application/x-dreamcast-iso-image",
"application/x-dc-rom",
"application/x-cdi",

// Unofficial MIME types from FreeDesktop.org.
// TODO: Get the above types upstreamed and get rid of this.
"application/x-dreamcast-rom",
"application/x-gd-rom-cue",
"application/x-discjuggler-cd-image",

nullptr
};
Expand Down Expand Up @@ -194,19 +198,32 @@ rp_image_const_ptr DreamcastPrivate::load0GDTEX(void)

// Create the ISO-9660 file system reader if it isn't already opened.
if (!isoPartition) {
if (discType == DiscType::GDI) {
// Open track 3 as ISO-9660.
GdiReader *const gdiReader = dynamic_cast<GdiReader*>(discReader.get());
assert(gdiReader != nullptr);
if (!gdiReader) {
return {};
switch (discType) {
case DiscType::GDI:
case DiscType::CDI: {
// Open track 3 as ISO-9660.
MultiTrackSparseDiscReader *const mtsDiscReader = dynamic_cast<MultiTrackSparseDiscReader*>(discReader.get());
assert(mtsDiscReader != nullptr);
if (!mtsDiscReader) {
return {};
}

isoPartition = mtsDiscReader->openIsoPartition(3);
if (!isoPartition) {
// NOTE: Some CDIs only have two tracks.
// Try reading track 2 instead.
isoPartition = mtsDiscReader->openIsoPartition(2);
}
break;
}
isoPartition = gdiReader->openIsoPartition(3);
} else {
// Standalone track.
// Using the ISO start offset calculated earlier.
isoPartition = std::make_shared<IsoPartition>(discReader, 0, iso_start_offset);

default:
// Standalone track.
// Using the ISO start offset calculated earlier.
isoPartition = std::make_shared<IsoPartition>(discReader, 0, iso_start_offset);
break;
}

if (!isoPartition->isOpen()) {
// Unable to open the ISO-9660 partition.
isoPartition.reset();
Expand Down Expand Up @@ -354,7 +371,7 @@ Dreamcast::Dreamcast(const IRpFilePtr &file)

switch (d->discType) {
case DreamcastPrivate::DiscType::Iso2048:
// 2048-byte sectors.
// 2048-byte sectors
// TODO: Determine session start address.
d->mimeType = "application/x-dreamcast-rom"; // unofficial
memcpy(&d->discHeader, &sector, sizeof(d->discHeader));
Expand All @@ -368,7 +385,7 @@ Dreamcast::Dreamcast(const IRpFilePtr &file)
break;

case DreamcastPrivate::DiscType::Iso2352: {
// 2352-byte sectors.
// 2352-byte sectors
d->mimeType = "application/x-dreamcast-rom"; // unofficial
const uint8_t *const data = cdromSectorDataPtr(&sector);
memcpy(&d->discHeader, data, sizeof(d->discHeader));
Expand All @@ -377,22 +394,38 @@ Dreamcast::Dreamcast(const IRpFilePtr &file)
break;
}

case DreamcastPrivate::DiscType::GDI: {
// GD-ROM cuesheet.
// iso_start_offset isn't used for GDI.
d->discReader = std::make_shared<GdiReader>(d->file);
GdiReader *const gdiReader = static_cast<GdiReader*>(d->discReader.get());
case DreamcastPrivate::DiscType::GDI:
case DreamcastPrivate::DiscType::CDI: {
// GD-ROM cuesheet or DiscJuggler image
// GDI does't use iso_start_offset.
// CDI manages its own iso_start_offset.
const char *mimeType;
if (d->discType == DreamcastPrivate::DiscType::GDI) {
d->discReader = std::make_shared<CdiReader>(d->file);
mimeType = "application/x-gd-rom-cue";
} else /*if (d->discType == DreamcastPrivate::DiscType::CDI)*/ {
d->discReader = std::make_shared<CdiReader>(d->file);
mimeType = "application/x-discjuggler-cd-image";
}

MultiTrackSparseDiscReader *const mtsDiscReader = static_cast<MultiTrackSparseDiscReader*>(d->discReader.get());
// Read the actual track 3 disc header.
const int lba_track03 = gdiReader->startingLBA(3);
int lba_track03 = mtsDiscReader->startingLBA(3);
if (lba_track03 < 0) {
// Error getting the track 03 LBA.
d->discReader.reset();
d->file.reset();
return;
// NOTE: Some CDIs only hvae two tracks.
// Try reading track 2 instead.
lba_track03 = mtsDiscReader->startingLBA(2);
if (lba_track03 < 0) {
// Error getting the track 03 LBA.
d->discReader.reset();
d->file.reset();
return;
}
}

// TODO: Don't hard-code 2048?
gdiReader->seekAndRead(lba_track03*2048, &d->discHeader, sizeof(d->discHeader));
d->mimeType = "application/x-gd-rom-cue"; // unofficial
mtsDiscReader->seekAndRead(lba_track03*2048, &d->discHeader, sizeof(d->discHeader));
d->mimeType = mimeType;
break;
}

Expand Down Expand Up @@ -440,14 +473,16 @@ int Dreamcast::isRomSupported_static(const DetectInfo *info)
}

if (info->ext && info->ext[0] != 0) {
// Check for ".gdi".
if (!strcasecmp(info->ext, ".gdi")) {
// This is a GD-ROM cuesheet.
// Check the first line.
if (GdiReader::isDiscSupported_static(info->header.pData, info->header.size) >= 0) {
// This is a supported GD-ROM cuesheet.
return static_cast<int>(DreamcastPrivate::DiscType::GDI);
}
} else if (!strcasecmp(info->ext, ".cdi")) {
// This is a DiscJuggler disc image.
return static_cast<int>(DreamcastPrivate::DiscType::CDI);
}
}

Expand Down Expand Up @@ -769,18 +804,28 @@ int Dreamcast::loadFieldData(void)
// Try to open the ISO-9660 object.
// NOTE: Only done here because the ISO-9660 fields
// are used for field info only.
// TODO: Get from GdiReader for GDI.
ISOPtr isoData;
if (d->discType == DreamcastPrivate::DiscType::GDI) {
// Open track 3 as ISO-9660.
GdiReader *const gdiReader = dynamic_cast<GdiReader*>(d->discReader.get());
assert(gdiReader != nullptr);
if (gdiReader) {
isoData = gdiReader->openIsoRomData(3);
switch (d->discType) {
case DreamcastPrivate::DiscType::GDI:
case DreamcastPrivate::DiscType::CDI: {
// Open track 3 as ISO-9660.
MultiTrackSparseDiscReader *const mtsDiscReader = dynamic_cast<MultiTrackSparseDiscReader*>(d->discReader.get());
assert(mtsDiscReader != nullptr);
if (mtsDiscReader) {
isoData = mtsDiscReader->openIsoRomData(3);
if (!isoData) {
// NOTE: Some CDIs only have two tracks.
// Try reading track 2 instead.
isoData = mtsDiscReader->openIsoRomData(2);
}
}
break;
}
} else {
// ISO object for ISO-9660 PVD
isoData = std::make_shared<ISO>(d->discReader);

default:
// ISO object for ISO-9660 PVD
isoData = std::make_shared<ISO>(d->discReader);
break;
}

if (isoData && isoData->isOpen()) {
Expand Down
Loading

0 comments on commit 4316487

Please sign in to comment.