📄 hdl_dump.cpp
字号:
#endif /* INCLUDE_ZERO_CMD defined? */
/**************************************************************/
static int
query_devices (void)
{
osal_dlist_t *hard_drives;
osal_dlist_t *optical_drives;
int result = osal_query_devices (&hard_drives, &optical_drives);
if (result == RET_OK)
{
u_int32_t i;
fprintf (stdout, "Hard drives:\n");
for (i=0; i<hard_drives->used; ++i)
{
const osal_dev_t *dev = hard_drives->device + i;
fprintf (stdout, "\t%s ", dev->name);
if (dev->status == 0)
{
fprintf (stdout, "%lu MB", (unsigned long) (dev->capacity / 1024) / 1024);
if (dev->is_ps2 == RET_OK)
fprintf (stdout, ", formatted Playstation 2 HDD\n");
else
fprintf (stdout, "\n");
}
else
{
char *error = osal_get_error_msg (dev->status);
if (error != NULL)
{
fprintf (stdout, error);
osal_dispose_error_msg (error);
}
else
fprintf (stdout, "error querying device.\n");
}
}
fprintf (stdout, "\nOptical drives:\n");
for (i=0; i<optical_drives->used; ++i)
{
const osal_dev_t *dev = optical_drives->device + i;
fprintf (stdout, "\t%s ", dev->name);
if (dev->status == 0)
fprintf (stdout, "%lu MB\n", (unsigned long) (dev->capacity / 1024) / 1024);
else
{
char *error = osal_get_error_msg (dev->status);
if (error != NULL)
{
fprintf (stdout, error);
osal_dispose_error_msg (error);
}
else
fprintf (stdout, "error querying device.\n");
}
}
osal_dlist_free (optical_drives);
osal_dlist_free (hard_drives);
}
#if defined (_WITH_ASPI)
if (aspi_load () == RET_OK)
{
scsi_devices_list_t *dlist;
result = aspi_scan_scsi_bus (&dlist);
if (result == RET_OK)
{
u_int32_t i;
fprintf (stdout, "\nDrives via ASPI:\n");
for (i=0; i<dlist->used; ++i)
{
switch (dlist->device [i].type)
{
case 0x00: /* HDD most likely */
printf ("\thdd%d:%d:%d ",
dlist->device [i].host,
dlist->device [i].scsi_id,
dlist->device [i].lun);
break;
case 0x05: /* MMC device */
printf ("\tcd%d:%d:%d ",
dlist->device [i].host,
dlist->device [i].scsi_id,
dlist->device [i].lun);
break;
}
if (dlist->device [i].size_in_sectors != -1 &&
dlist->device [i].sector_size != -1)
printf ("%lu MB\n",
(unsigned long) (((u_int64_t) dlist->device [i].size_in_sectors *
dlist->device [i].sector_size) / (1024 * 1024)));
else
printf ("Stat failed.\n");
}
aspi_dlist_free (dlist);
}
else
fprintf (stderr, "\nError scanning SCSI bus.\n");
aspi_unload ();
}
else
fprintf (stderr, "\nUnable to initialize ASPI.\n");
#endif /* _WITH_ASPI */
return (result);
}
/**************************************************************/
static int
cdvd_info (const char *path)
{
iin_t *iin;
int result = iin_probe (path, &iin);
if (result == OSAL_OK)
{
char volume_id [32 + 1];
char signature [12 + 1];
u_int32_t num_sectors, sector_size;
result = iin->stat (iin, §or_size, &num_sectors);
if (result == OSAL_OK)
result = isofs_get_ps_cdvd_details (iin, volume_id, signature);
if (result == OSAL_OK)
printf ("\"%s\" \"%s\" %luKB\n",
signature, volume_id,
(unsigned long) (((u_int64_t) num_sectors * sector_size) / 1024));
iin->close (iin);
}
return (result);
}
/**************************************************************/
#if defined (INCLUDE_READ_TEST_CMD)
static int
read_test (const char *path,
progress_t *pgs)
{
iin_t *iin;
int result = iin_probe (path, &iin);
if (result == OSAL_OK)
{
u_int32_t sector_size, num_sectors;
result = iin->stat (iin, §or_size, &num_sectors);
if (result == OSAL_OK)
{
u_int32_t sector = 0;
u_int32_t len;
pgs_prepare (pgs, (u_int64_t) num_sectors * sector_size);
do
{
const char *data; /* not used */
u_int32_t sectors = (num_sectors > IIN_NUM_SECTORS ? IIN_NUM_SECTORS : num_sectors);
/* TODO: would "buffer overflow" if read more than IIN_NUM_SECTORS? */
result = iin->read (iin, sector, sectors, &data, &len);
if (result == RET_OK)
{
u_int32_t sectors_read = len / IIN_SECTOR_SIZE;
sector += sectors_read;
num_sectors -= sectors_read;
pgs_update (pgs, sector * IIN_SECTOR_SIZE);
}
}
while (result == OSAL_OK && num_sectors > 0 && len > 0);
}
iin->close (iin);
}
return (result);
}
#endif /* INCLUDE_READ_TEST_CMD defined? */
/**************************************************************/
#if defined (INCLUDE_COMPARE_IIN_CMD)
static int
compare_iin (const char *path1,
const char *path2,
progress_t *pgs)
{
iin_t *iin1, *iin2;
int different = 0;
int longer_file = 0;
int result = iin_probe (path1, &iin1);
if (result == OSAL_OK)
{
result = iin_probe (path2, &iin2);
if (result == OSAL_OK)
{
u_int32_t len1, len2;
const char *data1, *data2;
u_int32_t sector = 0;
u_int32_t sector_size1, num_sectors1;
u_int32_t sector_size2, num_sectors2;
u_int64_t size1, size2;
result = iin1->stat (iin1, §or_size1, &num_sectors1);
if (result == OSAL_OK)
{
size1 = (u_int64_t) num_sectors1 * sector_size1;
result = iin2->stat (iin2, §or_size2, &num_sectors2);
}
if (result == OSAL_OK)
{
size2 = (u_int64_t) num_sectors2 * sector_size2;
if (sector_size1 == IIN_SECTOR_SIZE &&
sector_size2 == IIN_SECTOR_SIZE)
/* progress indicator is set up against the shorter file */
pgs_prepare (pgs, size1 < size2 ? size1 : size2);
else
/* unable to compare with different sector sizes */
result = RET_DIFFERENT;
}
len1 = len2 = IIN_SECTOR_SIZE;
while (result == OSAL_OK &&
len1 / IIN_SECTOR_SIZE > 0 &&
len2 / IIN_SECTOR_SIZE > 0)
{
u_int32_t sectors1 = (num_sectors1 > IIN_NUM_SECTORS ?
IIN_NUM_SECTORS : num_sectors1);
result = iin1->read (iin1, sector, sectors1, &data1, &len1);
if (result == OSAL_OK)
{
u_int32_t sectors2 = (num_sectors2 > IIN_NUM_SECTORS ?
IIN_NUM_SECTORS : num_sectors2);
result = iin2->read (iin2, sector, sectors2, &data2, &len2);
if (result == OSAL_OK)
{
u_int32_t len = (len1 <= len2 ? len1 : len2); /* lesser from the two */
u_int32_t len_s = len / IIN_SECTOR_SIZE;
if (memcmp (data1, data2, len) != 0)
{
different = 1;
break;
}
if (len1 != len2 &&
(len1 == 0 || len2 == 0))
{ /* track which file is longer */
if (len2 == 0)
longer_file = 1;
else if (len1 == 0)
longer_file = 2;
}
num_sectors1 -= len_s;
num_sectors2 -= len_s;
sector += len_s;
pgs_update (pgs, (u_int64_t) sector * IIN_SECTOR_SIZE);
}
}
} /* loop */
iin2->close (iin2);
}
iin1->close (iin1);
}
/* handle result code */
if (result == OSAL_OK)
{ /* no I/O errors */
if (different == 0)
{ /* contents are the same */
switch (longer_file)
{
case 0: return (RET_OK); /* neither */
case 1: return (RET_1ST_LONGER);
case 2: return (RET_2ND_LONGER);
default: return (RET_ERR); /* should not be here */
}
}
else
/* contents are different */
return (RET_DIFFERENT);
}
else
return (result);
}
#endif /* INCLUDE_COMPARE_IIN_CMD defined? */
/**************************************************************/
int
inject (const char *output,
const char *name,
const char *input,
const char *startup, /* or NULL */
unsigned char compat_flags,
int is_dvd,
progress_t *pgs)
{
hdl_game_t game;
int result = RET_OK;
iin_t *iin = NULL;
hio_t *hio = NULL;
result = iin_probe (input, &iin);
if (result == RET_OK)
result = hio_probe (output, &hio);
if (result == RET_OK)
{
memset (&game, 0, sizeof (hdl_game_t));
memcpy (game.name, name, sizeof (game.name) - 1);
game.name [sizeof (game.name) - 1] = '\0';
if (startup != NULL)
{ /* use given startup file */
memcpy (game.startup, startup, sizeof (game.startup) - 1);
game.startup [sizeof (game.startup) - 1] = '\0';
}
else
{ /* try to autodetect startup file */
char volume_id [32 + 1], signature [12 + 1];
result = isofs_get_ps_cdvd_details (iin, volume_id, signature);
if (result == RET_OK)
strcpy (game.startup, signature);
}
game.compat_flags = compat_flags;
game.is_dvd = is_dvd;
if (result == RET_OK)
result = hdl_inject (hio, iin, &game, pgs);
}
if (hio != NULL)
hio->close (hio);
if (iin != NULL)
iin->close (iin);
return (result);
}
/**************************************************************/
static int
remote_poweroff (const char *ip)
{
hio_t *hio;
int result = hio_probe (ip, &hio);
if (result == RET_OK)
{
result = hio->poweroff (hio);
hio->close (hio);
}
return (result);
}
/**************************************************************/
static int
progress_cb (progress_t *pgs)
{
static time_t last_flush = 0;
time_t now = time (NULL);
if (pgs->remaining != -1)
fprintf (stdout,
"%3d%%, %s remaining (est.), avg %.2f MBps, "
"curr %.2f MBps \r",
pgs->pc_completed, pgs->remaining_text,
pgs->avg_bps / (1024.0 * 1024.0),
pgs->curr_bps / (1024.0 * 1024.0));
else
fprintf (stdout, "%3d%%\r", pgs->pc_completed);
if (now > last_flush)
{ /* flush about once per second */
fflush (stdout);
last_flush = now;
}
return (RET_OK);
}
/* progress is allocated, but never freed, which is not a big deal for a CLI app */
progress_t*
get_progress (void)
{
#if 0
return (NULL);
#else
progress_t *pgs = pgs_alloc (&progress_cb);
return (pgs);
#endif
}
/**************************************************************/
void
show_usage_and_exit (const char *app_path,
const char *command)
{
int command_found;
static const struct help_entry_t
{
const char *command_name;
const char *command_arguments;
const char *description;
const char *example1, *example2;
int dangerous;
} help [] =
{
{ CMD_QUERY, NULL,
"Displays a list of all hard- and optical drives.",
NULL, NULL, 0 },
#if defined (INCLUDE_DUMP_CMD)
{ CMD_DUMP, "device file",
"Makes device image (AKA ISO-image).",
"cd0: c:\\tekken.iso", NULL, 0 },
#endif
#if defined (INCLUDE_COMPARE_CMD)
{ CMD_COMPARE, "file_or_device1 file_or_device2",
"Compares two files or devices.",
"cd0: c:\\tekken.iso", NULL, 0 },
#endif
#if defined (INCLUDE_COMPARE_IIN_CMD)
{ CMD_COMPARE_IIN, "iin1 iin2",
"Compares two ISO inputs.",
"c:\\tekken.cue cd0:", "c:\\gt3.gi hdd1:GT3", 0 },
#endif
{ CMD_TOC, "device",
"Displays PlayStation 2 HDD TOC.",
"hdd1:", "192.168.0.10", 0 },
{ CMD_HDL_TOC, "device",
"Displays a list of all HD Loader games on the PlayStation 2 HDD.",
"hdd1:", "192.168.0.10", 0 },
#if defined (INCLUDE_MAP_CMD)
{ CMD_MAP, "device",
"Displays PlayStation 2 HDD usage map.",
"hdd1:", NULL, 0 },
#endif
{ CMD_DELETE, "device partition",
"Deletes PlayStation 2 HDD partition. Use \"map\" to find exact partition name.",
"hdd1: \"PP.HDL.Tekken Tag Tournament\"", NULL, 1 },
#if defined (INCLUDE_ZERO_CMD)
{ CMD_ZERO, "device",
"Fills HDD with zeroes. All information on the HDD will be lost.",
"hdd1:", NULL, 1 },
#endif
#if !defined (CRIPPLED_INJECTION) && defined (INCLUDE_CUTOUT_CMD)
{ CMD_CUTOUT, "device size_in_MB",
"Displays partition table as if a new partition has been created.",
"hdd1: 2560", NULL, 0 },
#endif
#if defined (INCLUDE_INFO_CMD)
{ CMD_HDL_INFO, "device partition",
"Displays information about HD Loader partition.",
"hdd1: \"tekken tag tournament\"", NULL, 0 },
#endif
{ CMD_HDL_EXTRACT, "device partition output_file",
"Extracts application image from HD Loader partition.",
"hdd1: \"tekken tag tournament\" c:\\tekken.iso", NULL, 0 },
{ CMD_HDL_INJECT_CD, "device partition file signature",
"Creates a new HD Loader partition from a CD.\n"
"Supported inputs: plain ISO files, CDRWIN cuesheets, Nero images and tracks,\n"
"RecordNow! Global images, HD Loader partitions (hdd1:PP.HDL.Xenosaga) and\n"
"Sony CD/DVD generator IML files (if files are listed with full paths).",
"hdd1: \"Tekken Tag Tournament\" cd0: SCES_xxx.xx",
"hdd1: \"Tekken Tag Tournament\" c:\\tekken.iso SCES_xxx.xx", 1 },
{ CMD_HDL_INJECT_DVD, "device partition file signature",
"Creates a new HD Loader partition from a DVD.\n"
"DVD9 cannot be directly installed from the DVD-ROM drive -\n"
"use ISO image or IML file instead.\n"
"Supported inputs: plain ISO files, CDRWIN cuesheets, Nero images and tracks,\n"
"RecordNow! Global images, HD Loader partitions (hdd1:PP.HDL.Xenosaga) and\n"
"Sony CD/DVD generator IML files (if files are listed with full paths).",
"hdd1: \"Gran Turismo 3\" cd0: SCES_xxx.xx",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -