Skip to content

Commit

Permalink
Merge pull request ps2homebrew#673 from rickgaiser/bd_defrag2
Browse files Browse the repository at this point in the history
Add fat32/exfat fragmentation tolerance
  • Loading branch information
uyjulian authored Jun 16, 2022
2 parents c765d3e + ecb9d7c commit 4a1e95e
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 78 deletions.
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,6 @@ clean:
echo "Cleaning..."
echo "-Interface"
rm -fr $(MAPFILE) $(EE_BIN) $(EE_BIN_PACKED) $(EE_BIN_STRIPPED) $(EE_VPKD).* $(EE_OBJS_DIR) $(EE_ASM_DIR)
echo "-Language"
rm -fr $(LNG_SRC_DIR) $(LNG_DIR)lang_*.lng $(INTERNAL_LANGUAGE_C) $(INTERNAL_LANGUAGE_H)
echo "-EE core"
$(MAKE) -C ee_core clean
echo "-IOP core"
Expand Down Expand Up @@ -314,6 +312,10 @@ clean:
echo "-pc tools"
$(MAKE) -C pc clean

realclean: clean
echo "-Language"
rm -fr $(LNG_SRC_DIR) $(LNG_DIR)lang_*.lng $(INTERNAL_LANGUAGE_C) $(INTERNAL_LANGUAGE_H)

rebuild: clean all

run: $(EE_BIN_PACKED)
Expand Down
1 change: 1 addition & 0 deletions modules/iopcore/cdvdman/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ IOP_BIN = bdm_cdvdman.irx
IOP_OBJS_DIR = obj.bdm/
IOP_OBJS += device-bdm.o
IOP_CFLAGS += -DBDM_DRIVER
IOP_LIBS += -L$(PS2SDK)/iop/lib -lbdm
ifeq ($(IOPCORE_DEBUG),1)
USE_DEV9 = 1
endif
Expand Down
45 changes: 3 additions & 42 deletions modules/iopcore/cdvdman/device-bdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "internal.h"

#include <bdm.h>
#include <bd_defrag.h>

#include "device.h"

Expand Down Expand Up @@ -85,11 +86,6 @@ void DeviceStop(void)

void DeviceFSInit(void)
{
int i;
DPRINTF("USB: NumParts = %d\n", cdvdman_settings.common.NumParts);
for (i = 0; i < cdvdman_settings.common.NumParts; i++)
DPRINTF("USB: LBAs[%d] = %lu\n", i, cdvdman_settings.LBAs[i]);

DPRINTF("Waiting for device...\n");
WaitSema(bdm_io_sema);
DPRINTF("Waiting for device...done!\n");
Expand All @@ -110,51 +106,16 @@ void DeviceUnmount(void)

int DeviceReadSectors(u32 lsn, void *buffer, unsigned int sectors)
{
u32 sector;
u16 count;
register u32 r, sectors_to_read, lbound, ubound, nlsn, offslsn;
register int i, esc_flag = 0;
u8 *p = (u8 *)buffer;
int rv = SCECdErNO;

// DPRINTF("%s(%u, 0x%p, %u)\n", __func__, (unsigned int)lsn, buffer, sectors);

if (g_bd == NULL)
return SCECdErTRMOPN;

lbound = 0;
ubound = (cdvdman_settings.common.NumParts > 1) ? 0x80000 : 0xFFFFFFFF;
offslsn = lsn;
r = nlsn = 0;
sectors_to_read = sectors;

WaitSema(bdm_io_sema);
for (i = 0; i < cdvdman_settings.common.NumParts; i++, lbound = ubound, ubound += 0x80000, offslsn -= 0x80000) {

if (lsn >= lbound && lsn < ubound) {
if ((lsn + sectors) > (ubound - 1)) {
sectors_to_read = ubound - lsn;
sectors -= sectors_to_read;
nlsn = ubound;
} else
esc_flag = 1;

sector = cdvdman_settings.LBAs[i] + (offslsn * g_bd_sectors_per_sector);
count = sectors_to_read * g_bd_sectors_per_sector;
if (g_bd->read(g_bd, sector, &p[r], count) != count) {
rv = SCECdErREAD;
break;
}

r += sectors_to_read * 2048;
offslsn += sectors_to_read;
sectors_to_read = sectors;
lsn = nlsn;
}

if (esc_flag)
break;
}
if (bd_defrag(g_bd, cdvdman_settings.fragfile[0].frag_count, &cdvdman_settings.frags[cdvdman_settings.fragfile[0].frag_start], lsn * 4, buffer, sectors * 4) != (sectors * 4))
rv = SCECdErREAD;
SignalSema(bdm_io_sema);

return rv;
Expand Down
6 changes: 6 additions & 0 deletions modules/iopcore/cdvdman/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,13 @@ extern void cdvdman_initdev(void);

extern struct CDVDMAN_SETTINGS_TYPE cdvdman_settings;

#ifdef HDD_DRIVER
// HDD driver also uses this buffer, for aligning unaligned reads.
#define CDVDMAN_BUF_SECTORS 2
#else
// Normally this buffer is only used by 'searchfile', only 1 sector used
#define CDVDMAN_BUF_SECTORS 1
#endif
extern u8 cdvdman_buf[CDVDMAN_BUF_SECTORS * 2048];

extern int cdrom_io_sema;
Expand Down
8 changes: 0 additions & 8 deletions modules/iopcore/cdvdman/ioplib_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@
#include "ioplib_util.h"
#include "smsutils.h"

#ifdef __IOPCORE_DEBUG
#define DPRINTF(args...) printf(args)
#else
#define DPRINTF(args...) \
do { \
} while (0)
#endif

typedef struct ModuleStatus
{
char name[56];
Expand Down
22 changes: 20 additions & 2 deletions modules/iopcore/common/cdvd_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#ifndef __CDVD_CONFIG__
#define __CDVD_CONFIG__

#include <tamtypes.h>
#include <usbhdfsd-common.h>

// flags
#define IOPCORE_COMPAT_ALT_READ 0x0001
#define IOPCORE_COMPAT_0_SKIP_VIDEOS 0x0002
Expand All @@ -13,7 +16,7 @@
// fakemodule_flags
#define FAKE_MODULE_FLAG_DEV9 (1 << 0) // not used, compiled in
#define FAKE_MODULE_FLAG_USBD (1 << 1) // Used with BDM-USB or PADEMU
#define FAKE_MODULE_FLAG_SMAP (1 << 2) // not used, compiled in
#define FAKE_MODULE_FLAG_SMAP (1 << 2) // Used with SMB or BDM-UDPBD
#define FAKE_MODULE_FLAG_ATAD (1 << 3) // not used, compiled in
#define FAKE_MODULE_FLAG_CDVDSTM (1 << 4) // not used, compiled in
#define FAKE_MODULE_FLAG_CDVDFSV (1 << 5) // not used, compiled in
Expand Down Expand Up @@ -58,10 +61,25 @@ struct cdvdman_settings_smb
};
} __attribute__((packed));

#define BDM_MAX_FILES 1 // ISO
#define BDM_MAX_FRAGS 64 // 64 * 8bytes = 512bytes

struct cdvdman_fragfile
{
u8 frag_start; /// First fragment in the fragment table
u8 frag_count; /// Munber of fragments in the fragment table
} __attribute__((packed));

struct cdvdman_settings_bdm
{
struct cdvdman_settings_common common;
u32 LBAs[ISO_MAX_PARTS];

// Fragmented files:
// 0 = ISO
struct cdvdman_fragfile fragfile[BDM_MAX_FILES];

// Fragment table, containing the fragments of all files
bd_fragment_t frags[BDM_MAX_FRAGS];
} __attribute__((packed));

#endif
61 changes: 37 additions & 24 deletions src/bdmsupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "include/cheatman.h"
#include "modules/iopcore/common/cdvd_config.h"

#include <usbhdfsd-common.h>

#define NEWLIB_PORT_AWARE
#include <fileXio_rpc.h> // fileXioIoctl, fileXioDevctl

Expand Down Expand Up @@ -314,38 +316,49 @@ static void bdmLaunchGame(int id, config_set_t *configSet)
int irx_size = size_bdm_cdvdman_irx;
compatmask = sbPrepare(game, configSet, irx_size, irx, &index);
settings = (struct cdvdman_settings_bdm *)((u8 *)irx + index);
if (settings == NULL)
return;
memset(&settings->frags[0], 0, sizeof(bd_fragment_t) * BDM_MAX_FRAGS);
u8 iTotalFragCount = 0;

//
// Add ISO as fragfile[0] to fragment list
//
struct cdvdman_fragfile *iso_frag = &settings->fragfile[0];
iso_frag->frag_start = 0;
iso_frag->frag_count = 0;
for (i = 0; i < game->parts; i++) {
int fidx;

// Open file
sbCreatePath(game, partname, bdmPrefix, "/", i);
fd = open(partname, O_RDONLY);
if (fd >= 0) {
int *pBDMDriver = (int *)bdmDriver;
*pBDMDriver = fileXioIoctl(fd, USBMASS_IOCTL_GET_DRIVERNAME, "");
LOG("bdmDriver=%s\n", bdmDriver);

if (settings != NULL)
settings->LBAs[i] = fileXioIoctl(fd, USBMASS_IOCTL_GET_LBA, "");

if (fileXioIoctl(fd, USBMASS_IOCTL_CHECK_CHAIN, "") != 1) {
close(fd);
// Game is fragmented. Do not continue.
if (settings != NULL)
sbUnprepare(&settings->common);

guiMsgBox(_l(_STR_ERR_FRAGMENTED), 0, NULL);
return;
}
if (fd < 0) {
sbUnprepare(&settings->common);
guiMsgBox(_l(_STR_ERR_FILE_INVALID), 0, NULL);
return;
}

if ((gPS2Logo) && (i == 0))
EnablePS2Logo = CheckPS2Logo(fd, 0);
// Get driver - we should only need to do this once
int *pBDMDriver = (int *)bdmDriver;
*pBDMDriver = fileXioIoctl(fd, USBMASS_IOCTL_GET_DRIVERNAME, "");

// Get fragment list
int iFragCount = fileXioIoctl2(fd, USBMASS_IOCTL_GET_FRAGLIST, NULL, 0, (void *)&settings->frags[iTotalFragCount], sizeof(bd_fragment_t) * (BDM_MAX_FRAGS - iTotalFragCount));
if (iFragCount > BDM_MAX_FRAGS) {
// Too many fragments
close(fd);
} else {
// Unable to open part of the game. Do not continue.
if (settings != NULL)
sbUnprepare(&settings->common);
guiMsgBox(_l(_STR_ERR_FILE_INVALID), 0, NULL);
sbUnprepare(&settings->common);
guiMsgBox(_l(_STR_ERR_FRAGMENTED), 0, NULL);
return;
}
iso_frag->frag_count += iFragCount;
iTotalFragCount += iFragCount;

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

close(fd);
}

// Initialize layer 1 information.
Expand Down

0 comments on commit 4a1e95e

Please sign in to comment.