⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hdl_dump.cpp

📁 PS2游戏硬盘直灌(HDL)的Windows下VC的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#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, &sector_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, &sector_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, &sector_size1, &num_sectors1);
	  if (result == OSAL_OK)
	    {
	      size1 = (u_int64_t) num_sectors1 * sector_size1;
	      result = iin2->stat (iin2, &sector_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 + -