Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/supportbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ void sbCreateFolders(const char *path, int createDiscImgFolders);

// ISO9660 filesystem management functions.
u32 sbGetISO9660MaxLBA(const char *path);
u32 sbGetMediaLsnCount(const char *path, u64 totalBytes);
int sbProbeISO9660(const char *path, base_game_info_t *game, u32 layer1_offset);
int sbProbeISO9660_64(const char *path, base_game_info_t *game, u32 layer1_offset);

Expand Down
9 changes: 9 additions & 0 deletions modules/iopcore/cdvdman/searchfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,13 @@ void cdvdman_searchfile_init(void)
DPRINTF("cdvdman_searchfile_init DVD9 mediaLsnCount=%d\n", mediaLsnCount);
}
}

// The PVD Volume Space Size only describes the ISO9660 volume, not the whole disc.
// Badly mastered discs (e.g. SLES_533.98) keep data past the end of the volume and
// read it by raw LBA, which works on real hardware. Prefer the real media sector
// count measured by the loader whenever it was provided.
if (cdvdman_settings.common.mediaLsnCount) {
mediaLsnCount = cdvdman_settings.common.mediaLsnCount;
DPRINTF("cdvdman_searchfile_init loader-provided mediaLsnCount=%d\n", mediaLsnCount);
}
}
7 changes: 4 additions & 3 deletions modules/iopcore/common/cdvd_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct cdvdman_settings_common
u8 zso_cache;
u8 fakemodule_flags;
u8 padding;
u32 mediaLsnCount; // Real sector count of the media. 0 = fall back to the ISO9660 PVD Volume Space Size.
} __attribute__((packed));

struct cdvdman_settings_hdd
Expand Down Expand Up @@ -88,9 +89,9 @@ struct cdvdman_settings_bdm
bd_fragment_t frags[BDM_MAX_FRAGS];
} __attribute__((packed));

#define CDVDMAN_SETTINGS_DEFAULT_COMMON \
{ \
0x68, 0x68, 0x1234, 0x39393939, "DSKID", 16, 8, 16 \
#define CDVDMAN_SETTINGS_DEFAULT_COMMON \
{ \
0x68, 0x68, 0x1234, 0x39393939, "DSKID", 16, 8, 16, 0x87654321 \
}
#define CDVDMAN_SETTINGS_DEFAULT_HDD 0x12345678
#define CDVDMAN_SETTINGS_DEFAULT_SMB \
Expand Down
8 changes: 8 additions & 0 deletions src/bdmsupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ void bdmLaunchGame(item_list_t *itemList, int id, config_set_t *configSet)
int i, fd, iop_fd, index, compatmask = 0;
int EnablePS2Logo = 0;
int result;
u64 isoTotalBytes = 0;
u64 startingLBA;
unsigned int startCluster;
char partname[256], filename[32];
Expand Down Expand Up @@ -459,6 +460,8 @@ void bdmLaunchGame(item_list_t *itemList, int id, config_set_t *configSet)
iso_frag->frag_count += iFragCount;
iTotalFragCount += iFragCount;

isoTotalBytes += lseek64(fd, 0, SEEK_END);

if ((gPS2Logo) && (i == 0))
EnablePS2Logo = CheckPS2Logo(fd, 0);

Expand All @@ -469,6 +472,11 @@ void bdmLaunchGame(item_list_t *itemList, int id, config_set_t *configSet)
sbCreatePath(game, partname, pDeviceData->bdmPrefix, "/", 0);
layer1_start = sbGetISO9660MaxLBA(partname);

// Real media size, for CDVDMAN's out-of-bounds read emulation. The ISO9660 PVD
// cannot be trusted for this: badly mastered discs understate it and read data
// past the end of the volume by raw LBA.
settings->common.mediaLsnCount = sbGetMediaLsnCount(partname, isoTotalBytes);

switch (game->format) {
case GAME_FORMAT_USBLD:
layer1_part = layer1_start / 0x80000;
Expand Down
17 changes: 17 additions & 0 deletions src/ethsupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#define NEWLIB_PORT_AWARE
#include <fileXio_rpc.h> // fileXioDevctl(ethBase, SMB_***)
#include <ps2sdkapi.h> // lseek64

#include "include/nbns.h"
#include "httpclient.h"
Expand Down Expand Up @@ -668,6 +669,18 @@ static void ethLaunchGame(item_list_t *itemList, int id, config_set_t *configSet
strcpy(settings->smb_user, gPCUserName);
strcpy(settings->smb_password, gPCPassword);

// Sum the size of all parts, for CDVDMAN's out-of-bounds read emulation.
u64 isoTotalBytes = 0;
int part;
for (part = 0; part < game->parts; part++) {
sbCreatePath(game, partname, ethPrefix, "\\", part);
int fd = open(partname, O_RDONLY, 0666);
if (fd >= 0) {
isoTotalBytes += lseek64(fd, 0, SEEK_END);
close(fd);
}
}

// Initialize layer 1 information.
sbCreatePath(game, partname, ethPrefix, "\\", 0);

Expand All @@ -681,6 +694,10 @@ static void ethLaunchGame(item_list_t *itemList, int id, config_set_t *configSet

layer1_start = sbGetISO9660MaxLBA(partname);

// Real media size; the ISO9660 PVD cannot be trusted for this (badly mastered
// discs understate it and read data past the end of the volume by raw LBA).
settings->common.mediaLsnCount = sbGetMediaLsnCount(partname, isoTotalBytes);

switch (game->format) {
case GAME_FORMAT_USBLD:
layer1_part = layer1_start / 0x80000;
Expand Down
7 changes: 7 additions & 0 deletions src/hddsupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,11 @@ void hddLaunchGame(item_list_t *itemList, int id, config_set_t *configSet)
// patch start_sector
settings->lba_start = game->start_sector;

// Real media size, for CDVDMAN's out-of-bounds read emulation. The ISO9660 PVD
// cannot be trusted for this: badly mastered discs understate it and read data
// past the end of the volume by raw LBA.
settings->common.mediaLsnCount = game->total_size_in_kb / 2;

if (configGetStrCopy(configSet, CONFIG_ITEM_ALTSTARTUP, filename, sizeof(filename)) == 0)
strcpy(filename, game->startup);

Expand All @@ -596,6 +601,8 @@ void hddLaunchGame(item_list_t *itemList, int id, config_set_t *configSet)
if (maxLBA > 0 && maxLBA < ziso_total_block) { // dual layer check
settings->common.layer1_start = maxLBA - 16; // adjust second layer start
}
// For compressed images the partition size does not match the media size.
settings->common.mediaLsnCount = ziso_total_block;
}

if (gAutoLaunchGame == NULL)
Expand Down
21 changes: 21 additions & 0 deletions src/supportbase.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,26 @@ u32 sbGetISO9660MaxLBA(const char *path)
return maxLBA;
}

u32 sbGetMediaLsnCount(const char *path, u64 totalBytes)
{
u32 lsnCount;
int fd;

// For compressed images the file size does not match the media size, so use
// the uncompressed sector count from the ZISO header instead.
lsnCount = 0;
if ((fd = open(path, O_RDONLY, 0666)) >= 0) {
if (ProbeZISO(fd))
lsnCount = ziso_total_block;
close(fd);
}

if (lsnCount == 0)
lsnCount = (u32)(totalBytes / 2048);

return lsnCount;
}

int sbProbeISO9660(const char *path, base_game_info_t *game, u32 layer1_offset)
{
int result = -1, fd;
Expand Down Expand Up @@ -576,6 +596,7 @@ int sbPrepare(base_game_info_t *game, config_set_t *configSet, int size_cdvdman,
settings->media = game->media;
}
settings->flags = 0;
settings->mediaLsnCount = 0;

if (compatmask & COMPAT_MODE_1) {
settings->flags |= IOPCORE_COMPAT_ACCU_READS;
Expand Down