Пример #1
0
BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] )
{
	*fe_out = NULL;
	
	fex_type_t type;
	RETURN_ERR( fex_identify_file( &type, path ) );
	
	return fex_open_type( fe_out, path, type );
}
Пример #2
0
int ArchiveFile::ExtractItem(int index, const char* outFilename) const
{
	assert(!s_formatInfos.empty());
	//assert(index >= 0 && index < m_numItems);
	if(!(index >= 0 && index < m_numItems)) return 0;

	ArchiveItem& item = m_items[index];
	int rv = item.size;

	DWORD outAttributes = GetFileAttributes(outFilename);
	if(outAttributes & FILE_ATTRIBUTE_READONLY)
		SetFileAttributes(outFilename, outAttributes & ~FILE_ATTRIBUTE_READONLY); // temporarily remove read-only attribute so we can decompress to there

	if(m_typeIndex < 0)
	{
		// uncompressed
		if(!CopyFile(m_filename, outFilename, false))
			rv = 0;
	}
	else
	{
		fex_t * object;
		fex_err_t err = fex_open_type( &object, m_filename, s_formatInfos[m_typeIndex].type );
		if ( !err )
		{
			if ( index != 0 ) err = fex_seek_arc( object, item.offset );
			if ( !err )
			{
				unsigned char * buffer = new unsigned char[item.size];
				err = fex_read( object, buffer, item.size );
				if ( !err )
				{
					FILE * f = fopen(outFilename, "wb");
					if (f)
					{
						fwrite( buffer, 1, item.size, f );
						fclose( f );
					}
					else rv = 0;
				}
				else rv = 0;
			}
			else rv = 0;
			fex_close( object );
		}
		else rv = 0;
	}

	if(outAttributes & FILE_ATTRIBUTE_READONLY)
		SetFileAttributes(outFilename, outAttributes); // restore read-only attribute

	return rv;
}
Пример #3
0
int ArchiveFile::ExtractItem(int index, unsigned char* outBuffer, int bufSize) const
{
	assert(!s_formatInfos.empty());
	//assert(index >= 0 && index < m_numItems);
	if(!(index >= 0 && index < m_numItems)) return 0;

	ArchiveItem& item = m_items[index];

	if(bufSize < item.size)
		return 0;

	if(m_typeIndex < 0)
	{
		// uncompressed
		FILE* file = fopen(m_filename, "rb");
		fread(outBuffer, 1, item.size, file);
		fclose(file);
	}
	else
	{
		fex_t * object;
		fex_err_t err = fex_open_type( &object, m_filename, s_formatInfos[m_typeIndex].type );
		if ( !err )
		{
			if ( index != 0 ) err = fex_seek_arc( object, item.offset );
			if ( !err )
			{
				err = fex_read( object, outBuffer, item.size );
				if ( !err )
				{
					fex_close( object );
					return item.size;
				}
			}
			fex_close( object );
		}

		return 0;
	}

	return item.size;
}
Пример #4
0
ArchiveFile::ArchiveFile(const char* filename)
{
	assert(!s_formatInfos.empty());

	m_typeIndex = -1;
	m_numItems = 0;
	m_items = NULL;
	m_filename = NULL;

	FILE* file = fopen(filename, "rb");
	if(!file)
		return;

	//TODO - maybe windows only check here if we ever drop fex into portable code. unfortunately this is probably too unwieldy to ever happen

	//convert the filename to unicode
	wchar_t temp_wchar[MAX_PATH*2];
	char filename_utf8[MAX_PATH*4];
	MultiByteToWideChar(CP_THREAD_ACP,0,filename,-1,temp_wchar,ARRAY_SIZE(temp_wchar));
	//now convert it back to utf-8. is there a way to do this in one step?
	WideCharToMultiByte(CP_UTF8,0,temp_wchar,-1,filename_utf8,ARRAY_SIZE(filename_utf8), NULL, NULL);


	m_filename = new char[strlen(filename_utf8)+1];
	strcpy(m_filename, filename_utf8);

	// detect archive type using format signature in file
	for(size_t i = 0; i < s_formatInfos.size() && m_typeIndex < 0; i++)
	{
		for (size_t j = 0; j < s_formatInfos[i].signatures.size(); j++)
		{
			fseek(file, 0, SEEK_SET);

			std::string& formatSig = s_formatInfos[i].signatures[j];
			int len = formatSig.size();

			if(len == 0)
				continue; // because some formats have no signature

			char* fileSig = (char*)_alloca(len);
			fread(fileSig, 1, len, file);

			if(!memcmp(formatSig.c_str(), fileSig, len))
				m_typeIndex = i;
		}
	}

	// if no signature match has been found, detect archive type using filename.
	// this is only for signature-less formats
	const char* fileExt = strrchr(filename, '.');
	if(fileExt++)
	{
		for(size_t i = 0; i < s_formatInfos.size() && m_typeIndex < 0; i++)
		{
			if(s_formatInfos[i].signatures.empty())
			{
				std::vector<std::string>& formatExts = s_formatInfos[i].extensions;
				for(size_t j = 0; j < formatExts.size(); j++)
				{
					if(!_stricmp(formatExts[j].c_str(), fileExt))
					{
						m_typeIndex = i;
						break;
					}
				}
			}
		}
	}

	if(m_typeIndex < 0)
	{
		// uncompressed

		m_numItems = 1;
		m_items = new ArchiveItem[m_numItems];

		fseek(file, 0, SEEK_END);
		m_items[0].size = ftell(file);

		m_items[0].name = new char[strlen(filename)+1];
		strcpy(m_items[0].name, filename);

		m_items[0].wname = _wcsdup(temp_wchar);
	}
	else
	{
		fex_t * object;
		fex_err_t err = fex_open_type( &object, m_filename, s_formatInfos[m_typeIndex].type );
		if ( !err )
		{
			int numItems = 0;
			while ( !fex_done(object) )
			{
				numItems++;
				err = fex_next(object);
				if ( err ) break;
			}
			err = fex_rewind(object);
			if ( err )
			{
				fex_close(object);
				return;
			}

			m_numItems = numItems;
			m_items = new ArchiveItem[m_numItems];

			for (int i = 0; i < m_numItems; i++)
			{
				ArchiveItem& item = m_items[i];

				const char * name = fex_name(object);
				item.name = new char[strlen(name)+1];
				strcpy(item.name, name);

				const wchar_t* wname = fex_wname(object);
				if(wname)
				{
					item.wname = _wcsdup(fex_wname(object));
				}
				else
				{
					const char* name = fex_name(object);
					wchar_t temp_wchar[MAX_PATH];
					//what code page to use??? who knows. 
					MultiByteToWideChar(CP_ACP,0,name,-1,temp_wchar,ARRAY_SIZE(temp_wchar));
					item.wname = _wcsdup(temp_wchar);
				}


				err = fex_stat(object);
				if (err) break;

				item.size = fex_size(object);
				item.offset = fex_tell_arc(object);

				fex_next(object);
			}
			
			fex_close(object);
		}
	}

	fclose(file);
}