Skip to content

Commit

Permalink
Merge pull request #1051 from AKuHAK/kr_sector_hack
Browse files Browse the repository at this point in the history
Fixing issues with cdvdman, custom sector sizes
  • Loading branch information
rickgaiser authored Aug 9, 2023
2 parents 219a75d + 13d1ca3 commit 2123e3e
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 49 deletions.
2 changes: 1 addition & 1 deletion modules/iopcore/cdvdfsv/ncmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ static void *cbrpc_cdvdNcmds(int fno, void *buf, int size)
DPRINTF("cbrpc_cdvdNcmds GetToc eeaddr=%08x\n", (int)eeaddr);
char toc[2064];
memset(toc, 0, 2064);
int result = sceCdGetToc(toc);
int result = sceCdGetToc((u8 *)toc);
*(int *)buf = result;
if (result)
sysmemSendEE(toc, (void *)eeaddr, 2064);
Expand Down
66 changes: 49 additions & 17 deletions modules/iopcore/cdvdman/cdvdman.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static void cdvdman_signal_read_end(void);
static void cdvdman_signal_read_end_intr(void);
static void cdvdman_startThreads(void);
static void cdvdman_create_semaphores(void);
static int cdvdman_read(u32 lsn, u32 sectors, void *buf);
static int cdvdman_read(u32 lsn, u32 sectors, u16 sector_size, void *buf);

// Sector cache to improve IO
static u8 MAX_SECTOR_CACHE = 0;
Expand Down Expand Up @@ -351,13 +351,18 @@ static int cdvdman_read_sectors(u32 lsn, unsigned int sectors, void *buf)
return (cdvdman_stat.err == SCECdErNO ? 0 : 1);
}

static int cdvdman_read(u32 lsn, u32 sectors, void *buf)
static int cdvdman_read(u32 lsn, u32 sectors, u16 sector_size, void *buf)
{
cdvdman_stat.status = SCECdStatRead;

// OPL only has 2048 bytes no matter what. For other sizes we have to copy to the offset and prepoluate the sector header data (the extra bytes.)
u32 offset = 0;

if (sector_size == 2340)
offset = 12; // head - sub - data(2048) -- edc-ecc

buf = (void *)PHYSADDR(buf);
#ifdef HDD_DRIVER // As of now, only the ATA interface requires this. We do this here to share cdvdman_buf.
if ((u32)(buf)&3) {
if (((u32)(buf)&3) || (sector_size != 2048)) {
// For transfers to unaligned buffers, a double-copy is required to avoid stalling the device's DMA channel.
WaitSema(cdvdman_searchfilesema);

Expand All @@ -369,24 +374,48 @@ static int cdvdman_read(u32 lsn, u32 sectors, void *buf)
if (nsectors > CDVDMAN_BUF_SECTORS)
nsectors = CDVDMAN_BUF_SECTORS;

// For other sizes we can only read one sector at a time.
// There are only very few games (CDDA games, EA Tiburon) that will be affected
if (sector_size != 2048)
nsectors = 1;

cdvdman_read_sectors(rpos, nsectors, cdvdman_buf);

rpos += nsectors;
sectors -= nsectors;
nbytes = nsectors * 2048;

memcpy(buf, cdvdman_buf, nbytes);
nbytes = nsectors * sector_size;


// Copy the data for buffer.
// For any sector other than 2048 one sector at a time is copied.
memcpy((void *)((u32)buf + offset), cdvdman_buf, nbytes);

// For these custom sizes we need to manually fix the header.
// For 2340 we have 12bytes. 4 are position.
if (sector_size == 2340) {
u8 *header = (u8 *)buf;
// position.
sceCdlLOCCD p;
sceCdIntToPos(rpos - 1, &p); // to get current pos.
header[0] = p.minute;
header[1] = p.second;
header[2] = p.sector;
header[3] = 0; // p.track for cdda only non-zero

// Subheader and copy of subheader.
header[4] = header[8] = 0;
header[5] = header[9] = 0;
header[6] = header[10] = 0x8;
header[7] = header[11] = 0;
}

buf = (void *)((u8 *)buf + nbytes);
}

SignalSema(cdvdman_searchfilesema);
} else {
#endif
cdvdman_read_sectors(lsn, sectors, buf);
#ifdef HDD_DRIVER
}
#endif

ReadPos = 0; /* Reset the buffer offset indicator. */

Expand Down Expand Up @@ -419,7 +448,7 @@ static int cdvdman_common_lock(int IntrContext)
return 1;
}

int cdvdman_AsyncRead(u32 lsn, u32 sectors, void *buf)
int cdvdman_AsyncRead(u32 lsn, u32 sectors, u16 sector_size, void *buf)
{
int IsIntrContext, OldState;

Expand All @@ -435,6 +464,7 @@ int cdvdman_AsyncRead(u32 lsn, u32 sectors, void *buf)

cdvdman_stat.cdread_lba = lsn;
cdvdman_stat.cdread_sectors = sectors;
cdvdman_stat.sector_size = sector_size;
cdvdman_stat.cdread_buf = buf;

CpuResumeIntr(OldState);
Expand All @@ -447,7 +477,7 @@ int cdvdman_AsyncRead(u32 lsn, u32 sectors, void *buf)
return 1;
}

int cdvdman_SyncRead(u32 lsn, u32 sectors, void *buf)
int cdvdman_SyncRead(u32 lsn, u32 sectors, u16 sector_size, void *buf)
{
int IsIntrContext, OldState;

Expand All @@ -463,7 +493,7 @@ int cdvdman_SyncRead(u32 lsn, u32 sectors, void *buf)

CpuResumeIntr(OldState);

cdvdman_read(lsn, sectors, buf);
cdvdman_read(lsn, sectors, sector_size, buf);

cdvdman_cb_event(SCECdFuncRead);
sync_flag = 0;
Expand All @@ -486,13 +516,15 @@ u32 sceCdPosToInt(sceCdlLOCCD *p)
{
register u32 result;

result = ((u32)p->minute >> 16) * 10 + ((u32)p->minute & 0xF);
result = ((u32)p->minute >> 4) * 10 + ((u32)p->minute & 0xF);
result *= 60;
result += ((u32)p->second >> 16) * 10 + ((u32)p->second & 0xF);
result += ((u32)p->second >> 4) * 10 + ((u32)p->second & 0xF);
result *= 75;
result += ((u32)p->sector >> 16) * 10 + ((u32)p->sector & 0xF);
result += ((u32)p->sector >> 4) * 10 + ((u32)p->sector & 0xF);
result -= 150;

DPRINTF("%s({0x%X, 0x%X, 0x%X, 0x%X}) = %d\n", __FUNCTION__, p->minute, p->second, p->sector, p->track, result);

return result;
}

Expand Down Expand Up @@ -700,7 +732,7 @@ static void cdvdman_cdread_Thread(void *args)
while (1) {
WaitSema(cdrom_rthread_sema);

cdvdman_read(cdvdman_stat.cdread_lba, cdvdman_stat.cdread_sectors, cdvdman_stat.cdread_buf);
cdvdman_read(cdvdman_stat.cdread_lba, cdvdman_stat.cdread_sectors, cdvdman_stat.sector_size, cdvdman_stat.cdread_buf);

/* This streaming callback is not compatible with the original SONY stream channel 0 (IOP) callback's design.
The original is run from the interrupt handler, but we want it to run
Expand Down
5 changes: 3 additions & 2 deletions modules/iopcore/cdvdman/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ typedef struct
int disc_type_reg;
u32 cdread_lba;
u32 cdread_sectors;
u16 sector_size;
void *cdread_buf;
} cdvdman_status_t;

Expand All @@ -99,8 +100,8 @@ typedef void (*StmCallback_t)(void);

// Internal (common) function prototypes
extern void SetStm0Callback(StmCallback_t callback);
extern int cdvdman_AsyncRead(u32 lsn, u32 sectors, void *buf);
extern int cdvdman_SyncRead(u32 lsn, u32 sectors, void *buf);
extern int cdvdman_AsyncRead(u32 lsn, u32 sectors, u16 sector_size, void *buf);
extern int cdvdman_SyncRead(u32 lsn, u32 sectors, u16 sector_size, void *buf);
extern int cdvdman_sendSCmd(u8 cmd, const void *in, u16 in_size, void *out, u16 out_size);
extern void cdvdman_cb_event(int reason);

Expand Down
16 changes: 9 additions & 7 deletions modules/iopcore/cdvdman/ioops.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,11 @@ static int cdvdman_open(iop_file_t *f, const char *filename, int mode)
sceCdlFILE cdfile;

WaitSema(cdrom_io_sema);
WaitEventFlag(cdvdman_stat.intr_ef, 1, WEF_AND, NULL);

cdvdman_init();

if (f->unit < 2) {
sceCdDiskReady(0);

fh = cdvdman_getfilefreeslot();
if (fh) {
r = sceCdLayerSearchFile(&cdfile, filename, f->unit);
Expand Down Expand Up @@ -230,6 +229,8 @@ static int cdrom_open(iop_file_t *f, const char *filename, int mode)
int result;
char path_buffer[128]; // Original buffer size in the SCE CDVDMAN module.

WaitEventFlag(cdvdman_stat.intr_ef, 1, WEF_AND, NULL);

DPRINTF("cdrom_open %s mode=%d layer %d\n", filename, mode, f->unit);

strncpy(path_buffer, filename, sizeof(path_buffer));
Expand All @@ -247,6 +248,7 @@ static int cdrom_close(iop_file_t *f)
FHANDLE *fh = (FHANDLE *)f->privdata;

WaitSema(cdrom_io_sema);
WaitEventFlag(cdvdman_stat.intr_ef, 1, WEF_AND, NULL);

DPRINTF("cdrom_close\n");

Expand All @@ -266,14 +268,13 @@ static int cdrom_read(iop_file_t *f, void *buf, int size)
int rpos;

WaitSema(cdrom_io_sema);
WaitEventFlag(cdvdman_stat.intr_ef, 1, WEF_AND, NULL);

DPRINTF("cdrom_read size=%db (%ds) file_position=%d\n", size, size / 2048, fh->position);

if ((fh->position + size) > fh->filesize)
size = fh->filesize - fh->position;

sceCdDiskReady(0);

rpos = 0;
if (size > 0) {
// Phase 1: read data until the offset of the file is nicely aligned to a 2048-byte boundary.
Expand Down Expand Up @@ -334,6 +335,7 @@ static int cdrom_lseek(iop_file_t *f, int offset, int where)
FHANDLE *fh = (FHANDLE *)f->privdata;

WaitSema(cdrom_io_sema);
WaitEventFlag(cdvdman_stat.intr_ef, 1, WEF_AND, NULL);

DPRINTF("cdrom_lseek offset=%d where=%d\n", offset, where);

Expand Down Expand Up @@ -366,11 +368,11 @@ static int cdrom_getstat(iop_file_t *f, const char *filename, iox_stat_t *stat)
char path_buffer[128]; // Original buffer size in the SCE CDVDMAN module.

DPRINTF("cdrom_getstat %s layer %d\n", filename, f->unit);
WaitEventFlag(cdvdman_stat.intr_ef, 1, WEF_AND, NULL);

strncpy(path_buffer, filename, sizeof(path_buffer));
cdrom_purifyPath(path_buffer); // Unlike the SCE original, purify the path right away.

sceCdDiskReady(0);
return sceCdLayerSearchFile((sceCdlFILE *)&stat->attr, path_buffer, f->unit) - 1;
}

Expand All @@ -391,12 +393,12 @@ static int cdrom_dread(iop_file_t *f, iox_dirent_t *dirent)
struct dirTocEntry *tocEntryPointer;

WaitSema(cdrom_io_sema);
WaitEventFlag(cdvdman_stat.intr_ef, 1, WEF_AND, NULL);

DPRINTF("cdrom_dread fh->lsn=%lu\n", fh->lsn);

sceCdDiskReady(0);
if ((r = sceCdRead(fh->lsn, 1, cdvdman_fs_buf, NULL)) == 1) {
sceCdSync(0);
// sceCdSync(0); // TODO: need to verify

do {
r = 0;
Expand Down
18 changes: 15 additions & 3 deletions modules/iopcore/cdvdman/ncmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,24 @@ int sceCdRead(u32 lsn, u32 sectors, void *buf, sceCdRMode *mode)
{
int result;

DPRINTF("sceCdRead lsn=%d sectors=%d buf=%08x\n", (int)lsn, (int)sectors, (int)buf);
u16 sector_size = 2048;

// Is is NULL in our emulated cdvdman routines so check if valid.
if (mode) {
// 0 is 2048
if (mode->datapattern == SCECdSecS2328)
sector_size = 2328;

if (mode->datapattern == SCECdSecS2340)
sector_size = 2340;
}

DPRINTF("sceCdRead lsn=%d sectors=%d sector_size=%d buf=%08x\n", (int)lsn, (int)sectors, (int)sector_size, (int)buf);

if ((!(cdvdman_settings.common.flags & IOPCORE_COMPAT_ALT_READ)) || QueryIntrContext()) {
result = cdvdman_AsyncRead(lsn, sectors, buf);
result = cdvdman_AsyncRead(lsn, sectors, sector_size, buf);
} else {
result = cdvdman_SyncRead(lsn, sectors, buf);
result = cdvdman_SyncRead(lsn, sectors, sector_size, buf);
}

return result;
Expand Down
Loading

0 comments on commit 2123e3e

Please sign in to comment.