static void Create_Channel_List()
{
	for(u32 i = 0; i < ChannelHandle.Count(); i++)
	{
		chan = ChannelHandle.GetChannel(i);
		if(chan->id == NULL) 
			continue; // Skip invalid channels
		memset((void*)&ListElement, 0, sizeof(dir_discHdr));
		ListElement.index = m_gameList.size();
		ListElement.settings[0] = TITLE_UPPER(chan->title);
		ListElement.settings[1] = TITLE_LOWER(chan->title);
		strncpy(ListElement.id, chan->id, 4);
		ListElement.casecolor = CustomTitles.getColor("COVERS", ListElement.id, 0xFFFFFF).intVal();
		const char *CustomTitle = CustomTitles.getString("TITLES", ListElement.id).c_str();
		if(gameTDB.IsLoaded())
		{
			if(ListElement.casecolor == 0xFFFFFF)
				ListElement.casecolor = gameTDB.GetCaseColor(ListElement.id);
			ListElement.wifi = gameTDB.GetWifiPlayers(ListElement.id);
			ListElement.players = gameTDB.GetPlayers(ListElement.id);
			if(CustomTitle == NULL || CustomTitle[0] == '\0')
				gameTDB.GetTitle(ListElement.id, CustomTitle);
		}
		if(CustomTitle != NULL && CustomTitle[0] != '\0')
			mbstowcs(ListElement.title, CustomTitle, 63);
		else
			wcsncpy(ListElement.title, chan->name, 64);
		ListElement.type = TYPE_CHANNEL;
		m_gameList.push_back(ListElement);
	}
}
bool NandTitle::Exists(u64 tid)
{
	char app[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
	tmd* titleTmd = GetTMD(tid);
	if (!titleTmd) return false;

	u16 i;
	bool ok = false;
	for (i = 0; i < titleTmd->num_contents; i++)
	{
		if (!titleTmd->contents[i].index)
		{
			ok = true;
			break;
		}
	}
	if (!ok) return false;

	snprintf(app, sizeof(app), "/title/%08x/%08x/content/%08x.app", TITLE_UPPER( tid ), TITLE_LOWER( tid ),
			titleTmd->contents[i].cid);
	s32 fd = ISFS_Open(app, ISFS_OPEN_READ);
	if (fd >= 0) ISFS_Close(fd);

	//gprintf(" fd: %d\n", fd );
	return fd >= 0 || fd == -102; //102 means it exists, but we dont have permission to open it

}
Exemplo n.º 3
0
void tell_cIOS_to_return_to_channel(void)
	{
    if (TITLE_UPPER(old_title_id) > 1 && TITLE_LOWER(old_title_id) > 2) // Don't change anything for system menu or no title id
        {
		static u64 sm_title_id ATTRIBUTE_ALIGN(32);
		sm_title_id = old_title_id; // title id to be launched in place of the system menu
		
		int ret;
		
		static ioctlv vector[0x08] ATTRIBUTE_ALIGN(32);

		vector[0].data = &sm_title_id;
		vector[0].len = 8;

		int es_fd = IOS_Open("/dev/es", 0);
		if (es_fd < 0)
			{
			debug("Couldn't open ES module\n");
			return;
			}
		
		ret = IOS_Ioctlv(es_fd, 0xA1, 1, 0, vector);
		
		debug ("tell_cIOS_to_return_to_channel = %d\n", ret);

		IOS_Close(es_fd);
        }
	}
u64 NandTitle::FindU32(const char *s)
{
	u32 tid = (u32) strtoull(s, NULL, 16);
	if(!tid)
		return 0;

	for (u32 i = 0; i < titleIds.size(); i++)
	{
		if (TITLE_LOWER(titleIds[i]) == tid)
			return titleIds[i];
	}
	return 0;
}
Exemplo n.º 5
0
bool PriiloaderCheck(u64 id)
{
	if (TITLE_UPPER(id) == 1 && TITLE_LOWER(id) == 2)
	{
		char pl_tmd[ISFS_MAXPATH];
		snprintf(pl_tmd, MAX_CHARACTERS(pl_tmd), "/title/00000001/00000002/content/title_or.tmd");
		s32 cfd = ISFS_Open(pl_tmd, ISFS_OPEN_READ);
		if (cfd >= 0)
		{
			ISFS_Close(cfd);
			printf("Priiloader detected in System Menu!\n");
			logfile("Priiloader detected in System Menu!\r\n");
			return true;
		}
	}
	
	return false;
}
GuiSaveIcon * IconSaveBrowser::GetSaveIcon(int i)
{	
	u64 tid = browser->GetItemSaveTid(browser->GetPageIndex() + i);
	
	char savepath[MAXPATHLEN];
	snprintf(savepath, sizeof(savepath),"/title/%08x/%08x/data/banner.bin", TITLE_UPPER(tid),TITLE_LOWER(tid));
	
	u8* buffer = NULL;
	u32 size = 0;
	Nand::LoadFile(savepath, &buffer, &size);
	
	GuiSaveIcon * Icon = new GuiSaveIcon(buffer, size);
	
	free(buffer);
	buffer = NULL;
	
	return Icon;
}
Exemplo n.º 7
0
s32 identify(u64 titleid, u32 *ios){
	char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
	u8 *tmdBuffer = NULL;
	u32 tmdSize;
	signed_blob *tikBuffer = NULL;
	u32 tikSize;
	u8 *certBuffer = NULL;
	u32 certSize;
	
	int ret;

	printf("Reading TMD...");
	fflush(stdout);
	
	sprintf(filepath, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(titleid), TITLE_LOWER(titleid));
	ret = read_file(filepath, &tmdBuffer, &tmdSize);
	if (ret < 0)
	{
		printf("Reading TMD failed\n");
		return ret;
	}
	printf("done\n");

	*ios = (u32)(tmdBuffer[0x18b]);

	printf("Generating fake ticket...");
	fflush(stdout);
	/*
	sprintf(filepath, "/ticket/%08x/%08x.tik", TITLE_UPPER(titleid), TITLE_LOWER(titleid));
	ret = read_file(filepath, &tikBuffer, &tikSize);
	if (ret < 0)
	{
		printf("Reading ticket failed\n");
		free(tmdBuffer);
		return ret;
	}*/
	Identify_GenerateTik(&tikBuffer,&tikSize);
	printf("done\n");

	printf("Reading certs...");
	fflush(stdout);

	sprintf(filepath, "/sys/cert.sys");
	ret = read_file(filepath, &certBuffer, &certSize);
	if (ret < 0)
	{
		printf("Reading certs failed\n");
		free(tmdBuffer);
		free(tikBuffer);
		return ret;
	}
	printf("done\n");
	
	printf("ES_Identify...");
	fflush(stdout);

	ret = ES_Identify((signed_blob*)certBuffer, certSize, (signed_blob*)tmdBuffer, tmdSize, tikBuffer, tikSize, NULL);
	if (ret < 0)
	{
		switch(ret)
		{
			case ES_EINVAL:
				printf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret);
				break;
			case ES_EALIGN:
				printf("Error! ES_Identify (ret = %d;) Data not aligned!\n", ret);
				break;
			case ES_ENOTINIT:
				printf("Error! ES_Identify (ret = %d;) ES not initialized!\n", ret);
				break;
			case ES_ENOMEM:
				printf("Error! ES_Identify (ret = %d;) No memory!\n", ret);
				break;
			default:
				printf("Error! ES_Identify (ret = %d)\n", ret);
				break;
		}
		free(tmdBuffer);
		free(tikBuffer);
		free(certBuffer);
		return ret;
	}
	printf("done\n");
	
	free(tmdBuffer);
	free(tikBuffer);
	free(certBuffer);
	return 0;
}
Exemplo n.º 8
0
s32 *get_ioslist(u32 *cnt)
{
	u64 *buf = 0;
	s32 res;
	u32 i, k = 0, tcnt = 0, icnt = 0;
	s32 *ioses = NULL;
	
	bool skip_title;
	
	/* Get stored IOS versions */
	res = ES_GetNumTitles(&tcnt);
	if (res < 0)
	{
		printf("\t- ES_GetNumTitles: Error! (result = %ld).\n", res);
		return 0;
	}
	
	buf = memalign(32, sizeof(u64) * tcnt);
	if (!buf) 
	{
		printf("\t- Error allocating titlelist memory buffer!\n");
		return 0;
	}
	
	res = ES_GetTitles(buf, tcnt);
	if (res < 0)
	{
		printf("\t- ES_GetTitles: Error! (result = %ld).\n", res);
		free(buf);
		return 0;
	}
	
	for (i = 0; i < tcnt; i++)
	{
		/* Skip BC, MIOS, System Menu, BootMii IOS, BC-NAND, BC-WFS and stub IOSses */
		if ((TITLE_UPPER(buf[i - k]) == 1) && (TITLE_LOWER(buf[i - k]) > 2) && (TITLE_LOWER(buf[i - k]) < 0xFE))
		{
			u32 tmdSize = 0;
			tmd *iosTMD = NULL;
			signed_blob *iosTMDBuffer = NULL;
			
			/* Get stored TMD size */
			res = ES_GetStoredTMDSize(buf[i - k], &tmdSize);
			if (res < 0)
			{
				printf("\t- ES_GetStoredTMDSize: Error! (result = %ld / IOS%lu).\n", res, ((u32)buf[i - k]));
				break;
			}
			
			iosTMDBuffer = (signed_blob*)memalign(32, (tmdSize+31)&(~31));
			if (!iosTMDBuffer)
			{
				res = -1;
				printf("\t- Error allocating IOS%lu TMD buffer (size = %lu bytes).\n", ((u32)buf[i - k]), tmdSize);
				break;
			}
			
			memset(iosTMDBuffer, 0, tmdSize);
			
			/* Get stored TMD */
			res = ES_GetStoredTMD(buf[i - k], iosTMDBuffer, tmdSize);
			if (res < 0)
			{
				printf("\t- ES_GetStoredTMD: Error! (result = %ld / IOS%lu).\n", res, ((u32)buf[i - k]));
				free(iosTMDBuffer);
				break;
			}
			
			iosTMD = (tmd*)SIGNATURE_PAYLOAD(iosTMDBuffer);
			
			/* Calculate title size */
			u16 j;
			u32 titleSize = 0;
			for (j = 0; j < iosTMD->num_contents; j++)
			{
				tmd_content *content = &iosTMD->contents[j];
				
				/* Add content size */
				titleSize += content->size;
			}
			
			/* Check if this IOS is a stub */
			skip_title = (titleSize < 0x100000);
			
			free(iosTMDBuffer);
		} else {
			skip_title = true;
		}
		
		if (!skip_title)
		{
			icnt++;
		} else {
			/* Move around memory blocks */
			if ((tcnt - 1) > i)
			{
				memmove(&(buf[i - k]), &(buf[i - k + 1]), (sizeof(u64) * (tcnt - i - 1)));
				k++;
			}
		}
	}
	
	if (res < 0)
	{
		free(buf);
		return 0;
	}
	
	if (realloc(buf, sizeof(u64) * icnt) == NULL)
	{
		printf("\t- Error reallocating titlelist memory block!\n");
		free(buf);
		return 0;
	}
	
	ioses = (s32 *)malloc(sizeof(s32) * icnt);
	if (!ioses)
	{
		printf("\t- Error allocating IOS memory buffer!\n");
		free(buf);
		return 0;
	}
	
	for (i = 0; i < icnt; i++) ioses[i] = (s32)buf[i];
	
	free(buf);
	qsort(ioses, icnt, sizeof(s32), __s32Cmp);
	*cnt = icnt;
	
	return ioses;
}
Exemplo n.º 9
0
s32 extractChannelContents(u64 titleID, char* location)
{
	u32 TitleIDH=TITLE_UPPER(titleID);
	u32 TitleIDL=TITLE_LOWER(titleID);
	if(ES_SetUID(titleID)<0)
		return ERR_UID;

	u32 tmd_size ATTRIBUTE_ALIGN(32);


	if(ES_GetStoredTMDSize(titleID, &tmd_size)<0)
		return ERR_TMDSIZE;

	signed_blob *TMD = (signed_blob *)memalign( 32, tmd_size );
	memset(TMD, 0, tmd_size);

	if(ES_GetStoredTMD(titleID, TMD, tmd_size)<0)
	{
		free(TMD);
		return ERR_TMD;
	}

	u32 cnt ATTRIBUTE_ALIGN(32);

	if(ES_GetNumTicketViews(titleID, &cnt)<0)
	{
		free(TMD);
		return ERR_TIKCOUNT;
	}

	if( cnt <= 0 )
	{
		free(TMD);
		return ERR_TIKCOUNT;
	}

	tikview *views = (tikview *)memalign( 32, sizeof(tikview)*cnt );
	if(ES_GetTicketViews(titleID, views, cnt)<0)
	{
		free(views);
		free(TMD);
		return ERR_TIK;
	}
	printf("Allocated and filled views.\n");
	sleep(3);

	Identify_SU();

	int z;
	tmd_content *TMDc = TMD_CONTENTS(((tmd*)(SIGNATURE_PAYLOAD(TMD))));		// OH GOD CREDIAR, WTF WAS THAT MESS!
	// List format is "XXXXXXXX = YYYYYYYY" where X is index, and Y is cid.
	char *lookup_list=calloc(21,((tmd*)(SIGNATURE_PAYLOAD(TMD)))->num_contents);
	ClearScreen();
	printf("\nNumber of contents: %d\n",((tmd*)(SIGNATURE_PAYLOAD(TMD)))->num_contents);
	sleep(1);
	for(z=0; z < ((tmd*)(SIGNATURE_PAYLOAD(TMD)))->num_contents; z++)
	{
		/* Get Content */
		char nameDirectory[80];
		sprintf(nameDirectory,"/title/%08x/%08x/content/%08x.app",TitleIDH,TitleIDL,TMDc[z].cid);
		s32 contentFd=ISFS_Open(nameDirectory,ISFS_OPEN_READ);
		u8 *data=calloc(TMDc[z].size,1);
		if(contentFd<0)
		{
			switch(contentFd)
			{
				case ISFS_EINVAL:
					printf("FAILED! (Invalid Argument %s)\n\tQuitting...\n",nameDirectory);
					sleep(5);
					Finish(1);
					break;
			
				case ISFS_ENOMEM:
					printf("FAILED! (Out of memory %s)\n\tQuitting...\n",nameDirectory);
					sleep(5);
					Finish(1);
					break;
			
				default:
					goto skip;
//					Finish(1);
					break;
			}
		}
		int isUnaligned = ((int)data)%32 | TMDc[z].size%32;
		int alignedLen = (TMDc[z].size+31)&0xffffffe0;
		unsigned char* alignedBuf;
		if(isUnaligned) alignedBuf = memalign(32, alignedLen);
		else alignedBuf = data;
		ISFS_Seek(contentFd,0,0);
		ISFS_Read(contentFd, alignedBuf, alignedLen);
		// If it was unaligned, you have to copy it and clean up
		if(isUnaligned){
			memcpy(data, alignedBuf, TMDc[z].size);
			free(alignedBuf);
		}
		ISFS_Close(contentFd);

		// Do copying here.
		// data is the actual content data (use fwrite with it :P).
		// Copy the file with it's index as it's filename
		char* destination=calloc(sizeof(location)+14, 1);
		char lookup_entry[21];
		sprintf(destination, "%s/%08x.app",location,TMDc[z].index);
		sprintf(lookup_entry, "%08x = %08x\n",TMDc[z].index,TMDc[z].cid);
		strcat(lookup_list, lookup_entry);
		printf("Got destination as: %s\n", destination);
		sleep(3);
		FILE *dfd=fopen(destination,"wb+");
		printf("Opened %s\n", destination);
		sleep(3);
//		free(destination);
		fwrite(data, TMDc[z].size, 1, dfd);
		printf("Wrote data to %s\n", destination);
		sleep(3);
		fclose(dfd);
		printf("Closed %s\n", destination);
		sleep(2);
skip:
		_nop();
	}
	// Make a file containing the lookups called files.txt
	char* lookup_file=calloc(sizeof(location)+14, 1);
	sprintf(lookup_file, "%s/files.txt",location);
	printf("Got destination as: %s\n", lookup_file);
	sleep(3);
	FILE* lfd=fopen(lookup_file,"wb+");
	printf("Opened %s\n", lookup_file);
	sleep(3);
//	free(lookup_file);
	fwrite(lookup_list, 21, ((tmd*)SIGNATURE_PAYLOAD(TMD))->num_contents, lfd);
	printf("Wrote lookups to %s\n", lookup_file);
	sleep(3);
	fclose(lfd);
	printf("Closed %s\n", lookup_file);
	sleep(2);
	printf("Freed TMD and views");
	sleep(1);
Exemplo n.º 10
0
	return ERR_NONE;
}

void changeChannelName(u64 titleID)
{
	printf("Identifying as 00000001-00000000 (SU)!... ");
	CheckESRetval(ES_Identify(SU_IDENTIFY));
//	if(ES_SetUID(titleID)<0)
//		return;

	u32 tmd_size ATTRIBUTE_ALIGN(32);


	if(CheckESRetval(ES_GetStoredTMDSize(titleID, &tmd_size))!=0)
		return;

	signed_blob *TMD = (signed_blob *)memalign( 32, tmd_size );
	memset(TMD, 0, tmd_size);

	if(CheckESRetval(ES_GetStoredTMD(titleID, TMD, tmd_size))!=0)
	{
		free(TMD);
		return;
	}

	u32 cnt ATTRIBUTE_ALIGN(32);

	if(CheckESRetval(ES_GetNumTicketViews(titleID, &cnt))!=0)
	{
		free(TMD);
		return;
	}

	if( cnt <= 0 )
	{
		free(TMD);
		return;
	}

	tikview *views = (tikview *)memalign( 32, sizeof(tikview)*cnt );

	if(CheckESRetval(ES_GetTicketViews(titleID, views, cnt))!=0)
	{
		free(views);
		free(TMD);
		return;
	}
	char *name=calloc((0x54/2),1);
	int z;
	for(z=0; z < 1; ++z)
	{
		tmd_content *TMDc = TMD_CONTENTS(((tmd*)(SIGNATURE_PAYLOAD(TMD))));		// OH GOD CREDIAR, WTF WAS THAT MESS!!!
		//printf("%d,",TMDc->index);
		s32 cfd = ES_OpenTitleContent( titleID, TMDc->index);
		free(views);
		if(CheckESRetval(cfd)!=0)
		{	
			;
			//printf("ES_OpenContent(%d) failed\n", cfd);
			//sleep(10);
			//exit(0);
		} else {
			u64 sz ATTRIBUTE_ALIGN(32) = 0x140;
			u8 *data = (u8*)memalign(32, sz);

			if( TMDc->size < sz )
				sz = TMDc->size;

			if( data != NULL )
			{
				if(ES_ReadContent(cfd, data, sz)<0)
				{
					free(data);
					return;
				}

				int y;
				int chan_name_offset=(language_setting*0x54);				// Set to WiiMU's language
				for(y=0;y<(0x54/2);y++)
					name[y]=data[(0x9C+chan_name_offset)+(y*2)+1];

			}
			if(CheckESRetval(ES_CloseContent(cfd))!=0)
			{
				;
				//printf("ES_CloseContent failed\n");
				//sleep(10);
				//exit(0);
			}
			free(data);
		}
	}
	int wiistring_size;
reenter:
	wiistring_size=type_string_wiimote(name, 0x54/2);
	if(wiistring_size<=0)
	{
		printf("\n\nPlease enter a name!\n");
		sleep(3);
		goto reenter;
	}
	name[wiistring_size+1]=0;

	/* Get Content */
	char nameDirectory[80];
	tmd_content *TMDc = TMD_CONTENTS(((tmd*)(SIGNATURE_PAYLOAD(TMD))));
	sprintf(nameDirectory,"/title/%08x/%08x/content/%08x.app",TITLE_UPPER(titleID),TITLE_LOWER(titleID),TMDc->cid);
	s32 contentFd=ISFS_Open(nameDirectory,ISFS_OPEN_RW);
	CheckISFSRetval(contentFd);
	ClearScreen();
	printf("\n\nOpened content!\n");
	u8 *data=calloc(TMDc->size,1);
	int isUnaligned = ((int)data)%32 | TMDc->size%32;
	int alignedLen = (TMDc->size+31)&0xffffffe0;
	u8* alignedBuf;
	if(isUnaligned) alignedBuf = memalign(32, alignedLen);
	else alignedBuf = data;
	CheckISFSRetval(ISFS_Seek(contentFd,0,0));
	CheckISFSRetval(ISFS_Read(contentFd, alignedBuf, alignedLen));
	printf("Read content!\n");
	int y;
	int chan_name_offset=(SYSCONF_GetArea()*0x54);		// Edits the one for the Wii's system Menu
	char* nameOut=calloc(96,1);
	for(y=0;y<(0x54/2);y++)
		nameOut[(y*2)+1]=name[y];
	printf("Wrote new name! %s\n", name);
	CheckISFSRetval(ISFS_Seek(contentFd,(0x9C+chan_name_offset),0));
	printf("Seeked to location!\n");
	if(nameOut==NULL)
	{
		printf("FAILED! (Name Out is NULL!)\n");
		sleep(5);
		Finish(1);
	}
	if(((u32)nameOut%32)!=0)
	{
		isUnaligned = ((int)nameOut)%32 | 0x54%32;
		alignedLen = (0x54+31)&0xffffffe0;
		if(isUnaligned){ alignedBuf = memalign(32, alignedLen); memcpy(alignedBuf, nameOut, 0x54); }
		else alignedBuf = (u8*)nameOut;
	}
	CheckISFSRetval(ISFS_Write(contentFd, alignedBuf, 0x54));
	printf("Wrote content name!\nReading new Header Chunk!\n");
	CheckISFSRetval(ISFS_Seek(contentFd,0,0));
	CheckISFSRetval(ISFS_Read(contentFd, alignedBuf, alignedLen));
	printf("Read content!\n");
	u8* header_chunk=calloc(0x640, 1);
	int i;
	for(i=0;i<0x630;i++)
		header_chunk[i]=alignedBuf[i];
	for(i=0x630;i<0x640;i++)
		header_chunk[i]=0;
	u8* hash=calloc(0x10,1);
	md5(header_chunk, 0x640, hash);
	CheckISFSRetval(ISFS_Seek(contentFd,0x630,0));
	printf("Seeked to location!\n");
	if(hash==NULL)
	{
		printf("FAILED! (Hash is NULL!)\n");
		sleep(5);
		Finish(1);
	}
	if(((u32)hash%32)!=0)
	{
		isUnaligned = ((int)hash)%32 | 0x10%32;
		alignedLen = (0x10+31)&0xffffffe0;
		if(isUnaligned){ alignedBuf = memalign(32, alignedLen); memcpy(alignedBuf, hash, 0x10); }
		else alignedBuf = hash;
Exemplo n.º 11
0
/********************************************************************************
 * TitleBrowser- opens a browser with a list of installed Titles
 *********************************************************************************/
bool TitleSelector(char output[])
{
	gprintf("TitleSelector()\n");

	s32 num_titles;
	s32 r = -1;
	bool ret = false;
	u64 *titleList = NULL;

	// Get count of titles of the good titles
	num_titles = NandTitles.SetType(0x10001);
	u32 n = num_titles;

	for (u32 i = 0; i < n; i++)
	{
		u64 tid = NandTitles.Next();
		if (!tid)
		{
			break;
		}

		//remove ones not actually installed on the nand
		if (!NandTitles.Exists(tid))
		{
			num_titles--;
		}
	}

	//make a list of just the tids we are adding to the titlebrowser
	titleList = (u64*) memalign(32, num_titles * sizeof(u64));
	if (!titleList)
	{
		gprintf("TitleLister(): out of memory!\n");
		return false;
	}
	OptionList options4;
	//write the titles on the option browser

	std::string Filepath = Settings.titlestxt_path;
	Filepath += "wiitdb.xml";

	GameTDB *XML_DB = new GameTDB(Filepath.c_str());
	XML_DB->SetLanguageCode(Settings.db_language);

	s32 i = 0;
	NandTitles.SetType(0x10001);
	while (i < num_titles)
	{
		u64 tid = NandTitles.Next();
		if (!tid)
		{
			gprintf("shit happened\n");
			break;
		}

		if (!NandTitles.Exists(tid))
			continue;

		char id[5];
		NandTitles.AsciiTID(tid, (char*) &id);

		const char* name = NULL;
		std::string TitleName;

		if(XML_DB->GetTitle(id, TitleName))
			name = TitleName.c_str();
		else
			name = NandTitles.NameOf(tid);
		//gprintf("%016llx: %s: %s\n%p\t%p\n", tid, id, name, &id, name );

		options4.SetName(i, "%s", id);
		options4.SetValue(i, "%s", name ? name : tr( "Unknown" ));
		titleList[i] = tid;
		i++;
	}

	delete XML_DB;
	XML_DB = NULL;

	options4.SetName(i, " ");
	options4.SetValue(i, "%s", tr( "Clear" ));

	bool exit = false;

	GuiImageData btnOutline(Resources::GetFile("button_dialogue_box.png"), Resources::GetFileSize("button_dialogue_box.png"));
	GuiImageData settingsbg(Resources::GetFile("settings_background.png"), Resources::GetFileSize("settings_background.png"));

	GuiImage settingsbackground(&settingsbg);
	GuiButton settingsbackgroundbtn(settingsbackground.GetWidth(), settingsbackground.GetHeight());
	settingsbackgroundbtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
	settingsbackgroundbtn.SetPosition(0, 0);
	settingsbackgroundbtn.SetImage(&settingsbackground);

	GuiTrigger trigA;
	trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
	GuiTrigger trigB;
	trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B);

	GuiText cancelBtnTxt(tr( "Back" ), 22, thColor("r=0 g=0 b=0 a=255 - prompt windows button text color"));
	cancelBtnTxt.SetMaxWidth(btnOutline.GetWidth() - 30);
	GuiImage cancelBtnImg(&btnOutline);
	if (Settings.wsprompt)
	{
		cancelBtnTxt.SetWidescreen(Settings.widescreen);
		cancelBtnImg.SetWidescreen(Settings.widescreen);
	}
	GuiButton cancelBtn(&cancelBtnImg, &cancelBtnImg, 2, 3, 180, 400, &trigA, btnSoundOver, btnSoundClick2, 1);
	cancelBtn.SetLabel(&cancelBtnTxt);
	cancelBtn.SetTrigger(&trigB);

	GuiOptionBrowser optionBrowser4(396, 280, &options4, "bg_options_settings.png");
	optionBrowser4.SetPosition(0, 90);
	optionBrowser4.SetAlignment(ALIGN_CENTER, ALIGN_TOP);

	HaltGui();
	GuiWindow w(screenwidth, screenheight);
	w.Append(&settingsbackgroundbtn);
	w.Append(&cancelBtn);
	w.Append(&optionBrowser4);
	mainWindow->SetState(STATE_DISABLED);
	mainWindow->Append(&w);

	ResumeGui();

	while (!exit)
	{
		VIDEO_WaitVSync();

		if (shutdown == 1) Sys_Shutdown();
		if (reset == 1) Sys_Reboot();

		r = optionBrowser4.GetClickedOption();

		if (r > -1)
		{ //if a click happened
			if (r < num_titles)
			{
				u64 tid = titleList[r];
				sprintf(output, "%08x", TITLE_LOWER( tid ));
			}
			else output[0] = 0;
			ret = true;
			exit = true;
		}

		else if (cancelBtn.GetState() == STATE_CLICKED)
		{
			//break the loop and end the function
			exit = true;
		}
	}

	HaltGui();
	mainWindow->SetState(STATE_DEFAULT);
	mainWindow->Remove(&w);
	free(titleList);
	ResumeGui();

	return ret;
}
Exemplo n.º 12
0
int TitleBrowser()
{
	u32 num_titles;
	u32 num_sys_titles;
	s32 ret = -1;
	u64 *titleList = NULL;

	// Get count of titles of the good titles
	num_titles = NandTitles.SetType(0x10001);
	u32 n = num_titles;
	for (u32 i = 0; i < n; i++)
	{
		u64 tid = NandTitles.Next();
		if (!tid)
		{
			break;
		}

		//remove ones not actually installed on the nand
		if (!NandTitles.Exists(tid))
		{
			num_titles--;
		}
	}

	// Get count of system titles
	num_sys_titles = NandTitles.SetType(0x10002);
	n = num_sys_titles;
	for (u32 i = 0; i < n; i++)
	{
		u64 tid = NandTitles.Next();
		if (!tid)
		{
			break;
		}
		//these can't be booted anyways
		if (TITLE_LOWER( tid ) == 0x48414741 || TITLE_LOWER( tid ) == 0x48414141 || TITLE_LOWER( tid ) == 0x48414641)
		{
			num_sys_titles--;
			continue;
		}

		//these aren't installed on the nand
		if (!NandTitles.Exists(tid))
		{
			num_sys_titles--;
		}
	}

	//make a list of just the tids we are adding to the titlebrowser
	titleList = (u64*) memalign(32, (num_titles + num_sys_titles) * sizeof(u64));
	if (!titleList)
	{
		gprintf("TitleBrowser(): out of memory!\n");
		return -1;
	}
	OptionList options3;
	//write the titles on the option browser

	std::string Filepath = Settings.titlestxt_path;
	Filepath += "wiitdb.xml";

	GameTDB *XML_DB = new GameTDB(Filepath.c_str());
	XML_DB->SetLanguageCode(Settings.db_language);

	u32 i = 0;
	NandTitles.SetType(0x10001);
	//first add the good stuff
	while (i < num_titles)
	{
		u64 tid = NandTitles.Next();
		if (!tid)
		{
			gprintf("shit happened3\n");
			break;
		}
		gprintf("[ %u ] tid: %016llx\t%s\n", i, tid, NandTitles.NameOf(tid));

		if (!NandTitles.Exists(tid))
		{
			continue;
		}

		char id[5];
		NandTitles.AsciiTID(tid, (char*) &id);

		const char* name = NULL;
		std::string TitleName;

		if(XML_DB->GetTitle(id, TitleName))
			name = TitleName.c_str();
		else
			name = NandTitles.NameOf(tid);

		options3.SetName(i, "%s", id);
		options3.SetValue(i, "%s", name ? name : tr( "Unknown" ));
		titleList[i] = tid;
		i++;
	}

	NandTitles.SetType(0x10002);
	while (i < num_sys_titles + num_titles)
	{
		u64 tid = NandTitles.Next();
		if (!tid)
		{
			break;
		}
		if (TITLE_LOWER( tid ) == 0x48414741 || TITLE_LOWER( tid ) == 0x48414141 || TITLE_LOWER( tid ) == 0x48414641) continue;

		if (!NandTitles.Exists(tid))
		{
			continue;
		}

		char id[5];
		NandTitles.AsciiTID(tid, (char*) &id);

		const char* name = NULL;
		std::string TitleName;

		if(XML_DB->GetTitle(id, TitleName))
			name = TitleName.c_str();
		else
			name = NandTitles.NameOf(tid);

		options3.SetName(i, "%s", id);
		options3.SetValue(i, "%s", name ? name : tr( "Unknown" ));
		titleList[i] = tid;
		i++;
	}

	delete XML_DB;
	XML_DB = NULL;

	if (i == num_titles + num_sys_titles)
	{
		options3.SetName(i, " ");
		options3.SetValue(i, "%s", tr( "Wii Settings" ));
	}

	bool exit = false;
	int total = num_titles + num_sys_titles;

	if (IsNetworkInit()) ResumeNetworkWait();

	GuiImageData btnOutline(Resources::GetFile("button_dialogue_box.png"), Resources::GetFileSize("button_dialogue_box.png"));
	GuiImageData settingsbg(Resources::GetFile("settings_background.png"), Resources::GetFileSize("settings_background.png"));

	GuiTrigger trigA;
	trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
	GuiTrigger trigHome;
	trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0);
	GuiTrigger trigB;
	trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B);

	GuiText titleTxt(tr( "Title Launcher" ), 28, ( GXColor )
	{   0, 0, 0, 255});
	titleTxt.SetAlignment(ALIGN_CENTER, ALIGN_TOP);
	titleTxt.SetPosition(12, 40);
	titleTxt.SetMaxWidth(356, SCROLL_HORIZONTAL);

	GuiImage settingsbackground(&settingsbg);
	GuiButton settingsbackgroundbtn(settingsbackground.GetWidth(), settingsbackground.GetHeight());
	settingsbackgroundbtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
	settingsbackgroundbtn.SetPosition(0, 0);
	settingsbackgroundbtn.SetImage(&settingsbackground);

	GuiText cancelBtnTxt(tr( "Back" ), 22, thColor("r=0 g=0 b=0 a=255 - prompt windows button text color"));
	cancelBtnTxt.SetMaxWidth(btnOutline.GetWidth() - 30);
	GuiImage cancelBtnImg(&btnOutline);
	if (Settings.wsprompt)
	{
		cancelBtnTxt.SetWidescreen(Settings.widescreen);
		cancelBtnImg.SetWidescreen(Settings.widescreen);
	}
	GuiButton cancelBtn(&cancelBtnImg, &cancelBtnImg, 2, 3, 180, 400, &trigA, btnSoundOver, btnSoundClick2, 1);
	cancelBtn.SetScale(0.9);
	cancelBtn.SetLabel(&cancelBtnTxt);
	cancelBtn.SetTrigger(&trigB);

	GuiOptionBrowser optionBrowser3(396, 280, &options3, "bg_options_settings.png");
	optionBrowser3.SetPosition(0, 90);
	optionBrowser3.SetAlignment(ALIGN_CENTER, ALIGN_TOP);

	GuiImageData wifiImgData(Resources::GetFile("wifi_btn.png"), Resources::GetFileSize("wifi_btn.png"));
	GuiImage wifiImg(&wifiImgData);
	if (Settings.wsprompt)
	{
		wifiImg.SetWidescreen(Settings.widescreen);
	}
	GuiButton wifiBtn(wifiImg.GetWidth(), wifiImg.GetHeight());
	wifiBtn.SetImage(&wifiImg);
	wifiBtn.SetPosition(100, 400);
	wifiBtn.SetEffectGrow();
	wifiBtn.SetAlpha(80);
	wifiBtn.SetTrigger(&trigA);

	HaltGui();
	GuiWindow w(screenwidth, screenheight);
	w.Append(&settingsbackgroundbtn);
	w.Append(&titleTxt);
	w.Append(&cancelBtn);
	w.Append(&wifiBtn);
	w.Append(&optionBrowser3);
	mainWindow->Append(&w);

	ResumeGui();

	while (!exit)
	{
		VIDEO_WaitVSync();

		if (shutdown == 1) Sys_Shutdown();
		if (reset == 1)
			Sys_Reboot();

		else if (wifiBtn.GetState() == STATE_CLICKED)
		{
			ResumeNetworkWait();
			wifiBtn.ResetState();
		}

		if (IsNetworkInit())
		{
			wifiBtn.SetAlpha(255);
		}

		ret = optionBrowser3.GetClickedOption();

		if (ret > -1)
		{ //if a click happened

			if (ret < total)
			{
				//set the title's name, number, ID to text
				char text[0x100];
				char id[5];
				NandTitles.AsciiTID(titleList[ret], (char*) &id);

				snprintf(text, sizeof(text), "%s : %s", id, NandTitles.NameOf(titleList[ret]));

				//prompt to boot selected title
				if (WindowPrompt(tr( "Boot?" ), text, tr( "OK" ), tr( "Cancel" )))
				{ //if they say yes
					ExitApp();
					WII_Initialize();
					WII_LaunchTitle(titleList[ret]);
					//this really shouldn't be needed because the title will be booted
					exit = true;
					break;
				}
				else
				{
					//if they said no to booting the title
					ret = -1;
					optionBrowser3.ResetState();
				}

			}
			else if (ret == total)
			{ //if they clicked to go to the wii settings
				ExitApp();
				WII_Initialize();
				WII_ReturnToSettings();
			}
		}
		if (cancelBtn.GetState() == STATE_CLICKED)
		{
			//break the loop and end the function
			exit = true;
			ret = -10;
		}
	}

	CloseConnection();
	if (IsNetworkInit()) HaltNetworkThread();

	HaltGui();
	mainWindow->Remove(&w);
	free(titleList);
	ResumeGui();

	return ret;
}
Exemplo n.º 13
0
s32 identify(u64 titleid, u32 *ios)
{
	char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
	u8 *tmdBuffer = NULL;
	u32 tmdSize;
	signed_blob *tikBuffer = NULL;
	u32 tikSize;
	u8 *certBuffer = NULL;
	u32 certSize;
	
	int ret;

	debug("Reading TMD...");
	fflush(stdout);
	
	sprintf(filepath, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(titleid), TITLE_LOWER(titleid));
	ret = read_full_file_from_nand(filepath, &tmdBuffer, &tmdSize);
	if (ret < 0)
	{
		debug("ERR: (identify) Reading TMD failed\n");
		return ret;
	}
	debug("done\n");

	*ios = (u32)(tmdBuffer[0x18b]);

	debug("Generating fake ticket...");
	fflush(stdout);

	Identify_GenerateTik(&tikBuffer,&tikSize);
	debug("done\n");

	debug("Reading certs...");
	fflush(stdout);

	sprintf(filepath, "/sys/cert.sys");
	ret = read_full_file_from_nand(filepath, &certBuffer, &certSize);
	if (ret < 0)
		{
		debug("Reading certs failed, trying to use embedded one\n");

		certBuffer = allocate_memory(cert_sys_size);
		certSize = cert_sys_size;
		
		if (certBuffer != NULL)
			memcpy (certBuffer, cert_sys, cert_sys_size);
		else
			{
			free(tmdBuffer);
			free(tikBuffer);
			return ret;
			}
		}
	debug("done\n");
	
	debug("ES_Identify...");
	fflush(stdout);

	ret = ES_Identify((signed_blob*)certBuffer, certSize, (signed_blob*)tmdBuffer, tmdSize, tikBuffer, tikSize, NULL);
	if (ret < 0)
	{
		switch(ret)
		{
			case ES_EINVAL:
				debug("ERR: (identify) ES_Identify (ret = %d;) Data invalid!\n", ret);
				break;
			case ES_EALIGN:
				debug("ERR: (identify) ES_Identify (ret = %d;) Data not aligned!\n", ret);
				break;
			case ES_ENOTINIT:
				debug("ERR: (identify) ES_Identify (ret = %d;) ES not initialized!\n", ret);
				break;
			case ES_ENOMEM:
				debug("ERR: (identify) ES_Identify (ret = %d;) No memory!\n", ret);
				break;
			default:
				debug("ERR: (identify) ES_Identify (ret = %d)\n", ret);
				break;
		}
		free(tmdBuffer);
		free(tikBuffer);
		free(certBuffer);
		sleep (5);
		return ret;
	}
	debug("done\n");
	
	free(tmdBuffer);
	free(tikBuffer);
	free(certBuffer);
	return 0;
}
Exemplo n.º 14
0
s8 CopyTicket ( )
{
    s32 fd = 0;
    char TIK_Path_dest[64];
    char TIK_Path_org[64];
    memset(TIK_Path_dest,0,64);
    memset(TIK_Path_org,0,64);
    sprintf(TIK_Path_dest, "/title/%08x/%08x/content/ticket",TITLE_UPPER(title_id),TITLE_LOWER(title_id));
    sprintf(TIK_Path_org, "/ticket/%08x/%08x.tik",TITLE_UPPER(title_id),TITLE_LOWER(title_id));
    gprintf("Checking for copy ticket...\n");
    fd = ISFS_Open(TIK_Path_dest,ISFS_OPEN_READ);
    if (fd >= 0)
    {
        ISFS_Close(fd);
        printf("Skipping copy of system menu ticket...\n");
        return 1;
    }
    switch(fd)
    {
    case ISFS_EINVAL:
        abort("Unable to read ticket.path is wrong/too long or ISFS isn't init yet?");
        break;
    case ISFS_ENOMEM:
        abort("Unable to read ticket.(Out of memory)");
        break;
    case -102:
        abort("Unauthorised to get ticket. is ios%d trucha signed?",IOS_GetVersion());
        break;
    default:
        if(fd < 0)
            abort("Unable to read ticket. error %d. ",fd);
    case -106:
        printf("Priiloader system menu ticket not found.\n\tTrying to read original ticket...\n");
        break;
    }
    fd = ISFS_Open(TIK_Path_org,ISFS_OPEN_READ);
    //"/ticket/00000001/00000002.tik" -> original path which should be there on every wii.
    if (fd < 0)
    {
        switch(fd)
        {
        case ISFS_EINVAL:
            abort("Unable to read ticket.path is wrong/too long or ISFS isn't init yet?");
            break;
        case ISFS_ENOMEM:
            abort("Unable to read ticket.(Out of memory)");
            break;
        case -106:
            abort("Ticket not found");
            break;
        case -102:
            abort("Unauthorised to get ticket. is ios%d trucha signed?",IOS_GetVersion());
            break;
        default:
            abort("Unable to read ticket. error %d. ",fd);
            break;
        }

    }
    ISFS_Close(fd);
    printf("Copying system menu ticket...");
    Nand_Permissions TikPerm;
    memset(&TikPerm,0,sizeof(Nand_Permissions));
    TikPerm.otherperm = 3;
    TikPerm.groupperm = 3;
    TikPerm.ownerperm = 3;
    if (nand_copy(TIK_Path_org,TIK_Path_dest,TikPerm) < 0)
    {
        abort("Unable to copy the system menu ticket");
    }
    printf("Done!\n");
    return 1;
}
Exemplo n.º 15
0
void BuildSaveListNand()
{
	for( u32 j = 0; j < 3; j++ )
	{
		u32 type;
		switch( j )
		{
		case 0: type = 0x10000; break;
		case 1: type = 0x10001; break;
		case 2: type = 0x10004; break;
		}

		u32 cnt = NandTitles.SetType( type );
		for( u32 i = 0; i < cnt; i++ )
		{
			u64 tid = NandTitles.Next();
			char pathBuf[ 65 ]__attribute__((aligned( 32 )));

			snprintf( pathBuf, sizeof( pathBuf ), "/title/%08x/%08x/data/banner.bin", TITLE_UPPER( tid ), TITLE_LOWER( tid ) );

			u8* buf;
			u32 len;
			int ret = -1234;
			if( ( ret = NandTitle::LoadFileFromNand( pathBuf, &buf, &len ) ) < 0 || !buf )
			{
				//gprintf( "error loading: \"%s\" %i %p\n", pathBuf, ret, buf );
				continue;
			}


			//gprintf( "load %016llx\n", tid );
			BannerBin *save = new BannerBin( NULL, 0, tid );
			if( !save->SetData( buf, len ) )
			{
				gprintf( "error creating save: \"%s\"\n", pathBuf );
				delete save;
				continue;
			}

			// get size
			u32 s1 = 0, s2 = 0;
			snprintf( pathBuf, sizeof( pathBuf ), "/title/%08x/%08x/data", TITLE_UPPER( tid ), TITLE_LOWER( tid ) );
			if( !(ret = ISFS_GetUsage( pathBuf, &s1, &s2 )) )
			{
				save->blocks = RU( s1, 8 ) / 8;
			}
			else
			{
				gprintf( "ISFS_GetUsage( \"%s\" ): %i\n", pathBuf, ret );
				save->blocks = 0;
			}
			save->tid = tid;
			saveList << save;

			//return;
		}
	}
}
Exemplo n.º 16
0
s32 Download_IOS(IOS **ios, u32 iosnr, u32 revision)
{
	s32 ret;

	ret = Init_IOS(ios);
	if (ret < 0)
	{
		printf("Out of memory\n");
		goto err;
	}

	tmd *tmd_data  = NULL;
	u32 cnt;
	//static bool network_initialized = false;
	char buf[32];
	
	if (!network_initialized)
	{
		printf("Initializing network...");
		while (1) 
		{
			ret = net_init ();
			if (ret < 0) 
			{
				//if (ret != -EAGAIN) 
				if (ret != -11) 
				{
					printf ("net_init failed: %d\n", ret);
					goto err;
				}
			}
			if (!ret) break;
			usleep(100000);
			printf(".");
		}
		printf("done\n");
		network_initialized = true;
	}

	printf("Loading certs...\n");
	ret = GetCerts(&((*ios)->certs), &((*ios)->certs_size));
	if (ret < 0)
	{
		printf ("Loading certs from nand failed, ret = %d\n", ret);
		goto err;	
	}

	if ((*ios)->certs == NULL || (*ios)->certs_size == 0)
	{
		printf("certs error\n");
		ret = -1;
		goto err;		
	}

	if (!IS_VALID_SIGNATURE((*ios)->certs))
	{
		printf("Error: Bad certs signature!\n");
		ret = -1;
		goto err;
	}
	
	printf("Loading TMD...\n");
	sprintf(buf, "tmd.%u", revision);
	u8 *tmd_buffer = NULL;
	ret = get_nus_object(1, iosnr, buf, &tmd_buffer, &((*ios)->tmd_size));
	if (ret < 0)
	{
		printf("Loading tmd failed, ret = %u\n", ret);
		goto err;	
	}

	if (tmd_buffer == NULL || (*ios)->tmd_size == 0)
	{
		printf("TMD error\n");
		ret = -1;
		goto err;		
	}
	
	(*ios)->tmd_size = SIGNED_TMD_SIZE((signed_blob *)tmd_buffer);
 	(*ios)->tmd = MEM2_memalign(32, (*ios)->tmd_size);
	if ((*ios)->tmd == NULL)
	{
		printf("Out of memory\n");
		ret = -1;
		goto err;		
	}
	memcpy((*ios)->tmd, tmd_buffer, (*ios)->tmd_size);
	free(tmd_buffer);
	
	if (!IS_VALID_SIGNATURE((*ios)->tmd))
	{
		printf("Error: Bad TMD signature!\n");
		ret = -1;
		goto err;
	}

	printf("Loading ticket...\n");
	u8 *ticket_buffer = NULL;
	ret = get_nus_object(1, iosnr, "cetk", &ticket_buffer, &((*ios)->ticket_size));
	if (ret < 0)
	{
		printf("Loading ticket failed, ret = %u\n", ret);
		goto err;	
	}

	if (ticket_buffer == NULL || (*ios)->ticket_size == 0)
	{
		printf("ticket error\n");
		ret = -1;
		goto err;		
	}

	(*ios)->ticket_size = SIGNED_TIK_SIZE((signed_blob *)ticket_buffer);
 	(*ios)->ticket = MEM2_memalign(32, (*ios)->ticket_size);
	if ((*ios)->ticket == NULL)
	{
		printf("Out of memory\n");
		ret = -1;
		goto err;		
	}
	memcpy((*ios)->ticket, ticket_buffer, (*ios)->ticket_size);
	free(ticket_buffer);
	
	if(!IS_VALID_SIGNATURE((*ios)->ticket))
	{
		printf("Error: Bad ticket signature!\n");
		ret = -1;
		goto err;
	}

	/* Get TMD info */
	tmd_data = (tmd *)SIGNATURE_PAYLOAD((*ios)->tmd);

	printf("Checking titleid and revision...\n");
	if (TITLE_UPPER(tmd_data->title_id) != 1 || TITLE_LOWER(tmd_data->title_id) != iosnr)
	{
		printf("IOS has titleid: %08x%08x but expected was: %08x%08x\n", TITLE_UPPER(tmd_data->title_id), TITLE_LOWER(tmd_data->title_id), 1, iosnr);
		ret = -1;
		goto err;
	}

	if (tmd_data->title_version != revision)
	{
		printf("IOS has revision: %u but expected was: %u\n", tmd_data->title_version, revision);
		ret = -1;
		goto err;
	}

	ret = set_content_count(*ios, tmd_data->num_contents);
	if (ret < 0)
	{
		printf("Out of memory\n");
		goto err;
	}

	printf("Loading contents");
	for (cnt = 0; cnt < tmd_data->num_contents; cnt++) 
	{
		printf(".");
		tmd_content *content = &tmd_data->contents[cnt];

		/* Encrypted content size */
		(*ios)->buffer_size[cnt] = round_up((u32)content->size, 64);

		sprintf(buf, "%08x", content->cid);
   
		ret = get_nus_object(1, iosnr, buf, &((*ios)->encrypted_buffer[cnt]), &((*ios)->buffer_size[cnt]));

		if ((*ios)->buffer_size[cnt] % 16) 
		{
			printf("Content %u size is not a multiple of 16\n", cnt);
			ret = -1;
			goto err;
		}

   		if ((*ios)->buffer_size[cnt] < (u32)content->size) 
		{
			printf("Content %u size is too small\n", cnt);
			ret = -1;
			goto err;
   		} 

		(*ios)->decrypted_buffer[cnt] = MEM2_memalign(32, (*ios)->buffer_size[cnt]);
		if (!(*ios)->decrypted_buffer[cnt])
		{
			printf("Out of memory\n");
			ret = -1;
			goto err;
		}

	}
	printf("done\n");
	
	printf("Reading file into memory complete.\n");

	printf("Decrypting IOS...\n");
	decrypt_IOS(*ios);

	tmd_content *p_cr = TMD_CONTENTS(tmd_data);
	sha1 hash;
	int i;

	printf("Checking hashes...\n");
	for (i=0;i < (*ios)->content_count;i++)
	{
		SHA1((*ios)->decrypted_buffer[i], (u32)p_cr[i].size, hash);
		if (memcmp(p_cr[i].hash, hash, sizeof hash) != 0)
		{
			printf("Wrong hash for content #%u\n", i);
			ret = -1;
			goto err;
		}
	}	

	goto out;

err:
	free_IOS(ios);

out:
	return ret;
}