readme.txt

(11 KB) Pobierz
Files:
libcobra.a, cobra.h -> cobra library
Iso9660Gen.cpp, Iso9660Gen.h, Ps3IsoGen.cpp, Ps3IsoGen.h, iso9660.h, scandir.c -> to generate ps3 isos from directory
scandir is necessary because there is no scandir implementation in the sony sdk.



The proper way to mount an iso:

// This function mounts an iso. If there is an iso previously mounted, it umounts it.
int do_mount_iso(char *files[], ...)
{
	unsigned int effective_disctype, iso_disctype;
	
	cobra_get_disctype(NULL, &effective_disctype, &iso_disctype);
	
	// If there is an effective disc in the system, it must be ejected
	if (effective_disctype != DISC_TYPE_NONE)
	{
		cobra_send_fake_disc_eject_event();
	}
	
	// If there is an iso mounted, unmount it
	if (iso_disctype != DISC_TYPE_NONE)
	{
		cobra_umount_disc_image();
	}
	
	result = cobra_mount_XXX_disc_image(...);
	if (result != 0)
	{
		// Error processing
		...
	}
	
	// Issue the insert event now
	cobra_send_fake_disc_insert_event();
	return 0;
}

After the fake insert, the xmb automounter will typically mount the file system in a small period of time... except when it fails (for example, it fails with some psx games,
this is not a cobra bug, it happens with some original cd's too)

If you are gonna exit after mounting the iso, there is no reason  to wait for the automounter to mount the filesystem, except for ps3 isos:
You should check if the iso is a valid one (not encrypted one). Afer mounting a ps3 iso you could have a code like this:

// Verifyng if iso is valid. Waiting a max of 1 second for XMB automonter to mount the disc
for ( i = 0; i < 50; i++)
{
	CellFsStat stat;
				
	if (cellFsStat("/dev_bdvd", &stat) == 0)
	{
		int fd;
					
		if (cellFsOpen("/dev_bdvd/PS3_GAME/USRDIR/EBOOT.BIN", CELL_FS_O_RDONLY, &fd, NULL, 0) == 0)
		{
			uint32_t sig;
			uint64_t nread;
						
			cellFsRead(fd, &sig, 4, &nread);
			cellFsClose(fd);
						
			if (sig != 0x53434500 && sig != 0x7F454c46)
			{
				// show error dialog here
				do_umount_iso();
				return;
			}						
		}
					
		break;
	}
	
	sys_timer_usleep(20000);
}

if (i == 50)
{
	// Not valid either
	do_umount_so();
	return;
}



Specific cases of PSX iso:

All supported psx isos or cue/bin in cobra must be 2352.
To get the track definition, proceed like this:

TrackDef tracks[100];
char bin_filename[256];
int num_tracks;

if (file extension is iso)
{
	tracks[0].lba = 0;
	tracks[0].is_audio = 0;
	num_tracks = 1;
}
else if (file extension is cue)
{
	result = cobra_parse_cue(cue_buf, cue_buf_size, &tracks, 100, &num_tracks, bin_filename, 255);
	if (result != 0)
	{
		...;
		error processing;
	}
}

Cobra USB Manager doesn't list bin files. Instead it list isos and cue.
When a cue is detected, it is parsed and if succesfull it tries the following things to detect the bin path

- Firstly it merges the bin filename from what cobra_parse_cue detected, and the directory where the cue is.
- If it fails, and this is the internal disk, which is case sensitive, it tries to find a file that has same name but with different case.
- If that fails too, it tries to check if a file with same base name as cue but with bin extension exists.


Specific case of PS2 isos:

PS2 isos can be 2048 or 2352. Easiest way to detect this is to seek to offset 0x8000 and check the CD001 signature. IF present, it is a 2048 iso, otherwise, assume a 2352 one.
If it is a 2048 iso, there is no need to pass any track definition to the mount function, pass NULL.
If it is a 2352, proceed like in the PSX case.


The proper way to umount an iso:

int do_umount_iso(void)
{
	unsigned int real_disctype, effective_disctype, iso_disctype;
	
	cobra_get_disctype(&real_disctype, &effective_disctype, &iso_disctype);
	
	if (iso_disctype == DISC_TYPE_NONE)
		return 0; // Exit now, no iso mounted
		
	// If there is an effective disc in the system, it must be ejected
	if (effective_disctype != DISC_TYPE_NONE)
	{
		cobra_send_fake_disc_eject_event();
	}
	
	cobra_umount_disc_image();
	
	// If there is a real disc in the system, issue an insert event
	if (real_disctype != DISC_TYPE_NONE)
	{
		cobra_send_fake_disc_insert_event();
	}
	
	return 0;
}


Application start: on application start, cobra_lib_init should be called, iso should be umounted, psp iso game unset, jb game unmapped, and any other mapped path also unmapped
The fastest way to do all of this at once:

cobra_lib_init();
do_umount_iso();
cobra_map_game(NULL, NULL, NULL);
cobra_map_paths(NULL, NULL, 0);
cobra_unset_psp_game();

Disc dumping:

Common method for BD (not ps3), DVD and PS2 DVD:

proceed like you are probably currently doing in multiman, this is, use sys_storage_get_device_info to get the disc size, and sys_storage_open, read and close for the dumping.
For DVD, and PS2 DVD you could do additional processing to create a MDS when dual layer is detected.
Before closing the sys_storage handle, do some code like this:


DiscPhysInfo layer0;
DiscPhysInfo layer1;

if (cobra_get_disc_phys_info(handle, 0, &layer0) == 0)
{
	if (layer0.num_layers == 1) // 1 means 2
	{
		if (cobra_get_disc_phys_info(handle, 1, &layer1) == 0)
		{
			cobra_create_mds(mds_path, size_in_sectors, &layer0, &layer1);
		}
	}
}

For BD, there is no point in creating the mds file.

Disc dumping method for PS3 BD:

Use sys_storage_get_device_info to get the size of the disc in sectors.
Forget about any other sys_storage* function and use the cobra_read_ps3_disc function. Don't forget to do a cobra_disc_auth before the dump


Disc dumping for PSX CD and PS2 CD:

DON'T use sys_storage_get_device_info to get the size;
Instead use cobra_get_cd_td and make lba_end-tracks[0].lba 
This function is also needed to get the tracks definition, that you need for cobra_cd_read and to generate the cue.
Multiply by 2352, not 2048, to get the size in bytes

Use sys_storage_open to open the disc, cobra_cd_read to read the disc, and sys_storage_close to close the disc.
Don't assume that the disc starts at lba 0. Assume that it starts at tracks[0].lba

As specified in cobra_cd_read, you shouldn't cross the boundary of a track in a single call. Because of it, it is probably a better idea to have
a function that dumps a track, and then a global function that does something like this:

int do_dump_ps_cd(...)
{
	TrackDef tracks[100];
	uint32_t lba_end;
	unsigned int num_tracks;
	
	result = sys_storage_open(..., &handle, ...);
	if (result != 0)
	{
		// Error processing
		...
	}
	
	result = cobra_get_cd_td(handle, &tracks, 100, &num_tracks, &lba_end);
	if (result != 0)
	{
		// Error processing
		...
	}
	
	// Check that first track is not audio, since cobra can't handle isos with first track as audio
	if (tracks[0].is_audio)
	{
		// Error processing
		...
	}
	
	// Check that all other tracks are audio, since cobra can't handle isos with more than one data track
	for (i = 1; i < num_tracks; i++)
	{
		if (!tracks[i].is_audio)
		{
			// Error processing
			...
		}
	}
	
	// dump tracks
	for (i = 0; i < num_tracks; i++)
	{
		uint32_t track_size;
		
		if (i == (num_tracks-1))
		{
			track_size = lba_end - tracks[i].lba;
		}
		else
		{
			track_size = tracks[i+1].lba - tracks[i].lba;
		}
		
		result = do_dump_track(handle, tracks[i].lba, track_size, tracks[i].is_audio);
		if (result != 0)
		{
			// Error processing
			...
		}
	}
	
	sys_storage_close(handle);
	
	if (num_tracks > 1)
	{
		// Create the cue here, see below
	}
	
	return 0;
}

As stated in cobra.h, it seems that some errors are common in CD's.
cobra_cd_read already does 10 retries on one by one sectors. If EIO is returned, you should probably continue with dumping and add the returned value in num_errors
to some global counter, and if it bypasses certain number, abort the dump. If an error different than EIO is returned, abort inmediatelly. 

Creating the cue:

First of all, if you detect that there is only one track, use .iso extension for the output file, otherwise use .bin extension.
If there is more than one track, create the cue with cobra_create_cue, and pass the tracks definition that cobra_get_cd_td returned.


Disc authentification:
When a disc change is detected, you should issue a cobra_disc_auth command. 

The disc authentification problem in PSX CD-R, PS2 CD-R and PS2 DVD+-R

Cobra core usually gets the disc type from the data returned directly by the bd drive. But when detecting a CD or DVD, it tries to check if it is a PSX or PS2 disc 
by reading some data from it.
However, if the system is in PS3 disc authentification mode, it fails in reading the CD or DVD, and effective_disctype will be DISC_TYPE_CD or DISC_TYPE_DVD

The work around is to do something like this when detecting a new CD or DVD in the system:

(the following code assumes that there is no iso mounted)

void on_new_disc_insert()
{
	unsigned int effective_disctype;
	
	cobra_get_disctype(NULL, &effective_disctype, NULL);
	
	if (effective_disctype == DISC_TYPE_CD || effective_disctype == DISC_TYPE_DVD)
	{
		cobra_disc_auth();
		cobra_send_fake_disc_eject_event();
		sys_timer_usleep(300);
		cobra_send_fake_disc_insert_event();
		
		// Now if the disc was indeed a PS CD/DVD backup, effective_disctype will have proper value
		cobra_get_disctype(NULL, &effective_disctype, NULL);
	}
	
	// process efective_disctype here
}

You could also move the disc_auth before the "if", since anyways you will need to have the disc authenticated


To allow or not to allow PS2:

int allow_ps2 = 0;

if (cobra_get_ps2_emu_type() != PS2_EMU_SW)
{
	allow_ps2 = 1;
}
else
{
	CobraConfig *config;
	
	cobra_read_config(&config);
	allow_ps2 = config.ps2softemu;
}

Generate an ISO from a directory using Iso9660Gen and Ps3IsoGen c++ classes:
Make sure to add -DNOT_SCANDIR to PPU_CPPFLAGS, and include scandir.c file in PPU_SRCS

Normal non ps...
Zgłoś jeśli naruszono regulamin