daedalus/Source/RomFile/RomFile.cpp
2023-04-25 11:01:34 +10:00

158 lines
3.7 KiB
C++

/*
Copyright (C) 2006 StrmnNrmn
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "BuildOptions.h"
#include "Base/Types.h"
#include "Debug/DBGConsole.h"
#include "RomFile/RomFile.h"
#include "RomFile/RomFileCompressed.h"
#include "RomFile/RomFileUncompressed.h"
#include "Utility/Stream.h"
#include "System/IO.h"
#include <algorithm>
#include <string.h>
#include <filesystem>
bool IsRomfilename( const char * rom_filename )
{
const char * last_period( strrchr( rom_filename, '.' ) );
if(last_period == NULL)
return false;
return (strcasecmp(last_period, ".v64") == 0 ||
strcasecmp(last_period, ".z64") == 0 ||
strcasecmp(last_period, ".n64") == 0 ||
strcasecmp(last_period, ".rom") == 0 ||
strcasecmp(last_period, ".bin") == 0 ||
strcasecmp(last_period, ".jap") == 0 ||
strcasecmp(last_period, ".pal") == 0 ||
strcasecmp(last_period, ".usa") == 0 ||
strcasecmp(last_period, ".zip") == 0);
}
std::shared_ptr<ROMFile> ROMFile::Create( const std::filesystem::path filename )
{
const char * ext = IO::Path::FindExtension( filename.c_str() );
if (ext && strcasecmp(ext, ".zip") == 0)
{
#ifdef DAEDALUS_COMPRESSED_ROM_SUPPORT
return new ROMFileCompressed( filename.c_str() );
#else
return NULL;
#endif
}
else
{
return std::make_shared<ROMFileUncompressed>( filename.c_str() );
}
}
ROMFile::ROMFile( const std::filesystem::path filename )
: mHeaderMagic( 0 )
, mFilename ( filename )
{
}
ROMFile::~ROMFile()
{
}
bool ROMFile::LoadData( u32 bytes_to_read, u8 *p_bytes, COutputStream & messages )
{
if( !LoadRawData( bytes_to_read, p_bytes, messages ) )
{
messages << "Unable to get rom info from '" << mFilename.c_str() << "'";
return false;
}
return true;
}
bool ROMFile::RequiresSwapping() const
{
DAEDALUS_ASSERT( mHeaderMagic != 0, "The header magic hasn't been set" );
return mHeaderMagic != 0x80371240;
}
bool ROMFile::SetHeaderMagic( u32 magic )
{
mHeaderMagic = magic;
switch (mHeaderMagic)
{
case 0x80371240:
case 0x40123780:
case 0x12408037:
break;
default:
DAEDALUS_ERROR( "Unhandled swapping mode: %08x - ROM format is not supported for %s", mHeaderMagic, mFilename.c_str() );
return false;
}
return true;
}
void ROMFile::CorrectSwap( u8 * p_bytes, u32 length )
{
switch (mHeaderMagic)
{
case 0x80371240:
// Pre byteswapped - no need to do anything
break;
case 0x40123780:
ByteSwap_3210( p_bytes, length );
break;
case 0x12408037:
ByteSwap_2301( p_bytes, length );
break;
default:
DAEDALUS_ERROR( "Unhandled swapping mode: %08x", mHeaderMagic );
break;
}
}
// Swap bytes from 37 80 40 12
// to 40 12 37 80
void ROMFile::ByteSwap_2301( void * p_bytes, u32 length )
{
u32* p = (u32*)p_bytes;
u32* maxp = (u32*)((u8*)p_bytes + length);
for(; p < maxp; p++)
{
std::swap(((u16*)p)[0], ((u16*)p)[1]);
}
}
// Swap bytes from 80 37 12 40
// to 40 12 37 80
void ROMFile::ByteSwap_3210( void * p_bytes, u32 length )
{
u8* p = (u8*)p_bytes;
u8* maxp = (u8*)(p + length);
for(; p < maxp; p+=4)
{
std::swap(p[0], p[3]);
std::swap(p[1], p[2]);
}
}