mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
197 lines
4.3 KiB
C++
197 lines
4.3 KiB
C++
////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Nestopia - NES/Famicom emulator written in C++
|
|
//
|
|
// Copyright (C) 2003-2008 Martin Freij
|
|
//
|
|
// This file is part of Nestopia.
|
|
//
|
|
// Nestopia 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.
|
|
//
|
|
// Nestopia 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 Nestopia; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <new>
|
|
#include "NstVector.hpp"
|
|
#include "NstPatcher.hpp"
|
|
#include "NstPatcherIps.hpp"
|
|
#include "NstPatcherUps.hpp"
|
|
|
|
namespace Nes
|
|
{
|
|
namespace Core
|
|
{
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("s", on)
|
|
#endif
|
|
|
|
Patcher::Patcher(bool b)
|
|
:
|
|
ips (NULL),
|
|
ups (NULL),
|
|
bypassChecksum (b)
|
|
{
|
|
}
|
|
|
|
Patcher::~Patcher()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
void Patcher::Destroy()
|
|
{
|
|
delete ips;
|
|
ips = NULL;
|
|
|
|
delete ups;
|
|
ups = NULL;
|
|
}
|
|
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("", on)
|
|
#endif
|
|
|
|
Result Patcher::Load(std::istream& stream)
|
|
{
|
|
Destroy();
|
|
|
|
if (Ips::IsIps( stream ))
|
|
{
|
|
ips = new (std::nothrow) Ips;
|
|
return ips ? ips->Load( stream ) : RESULT_ERR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if (Ups::IsUps( stream ))
|
|
{
|
|
ups = new (std::nothrow) Ups;
|
|
return ups ? ups->Load( stream, bypassChecksum ) : RESULT_ERR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return RESULT_ERR_INVALID_FILE;
|
|
}
|
|
|
|
Result Patcher::Load(std::istream& patchStream,std::istream& srcStream)
|
|
{
|
|
Result result = Load( patchStream );
|
|
|
|
if (NES_SUCCEEDED(result))
|
|
{
|
|
result = Test( srcStream );
|
|
|
|
if (NES_FAILED(result))
|
|
Destroy();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
Result Patcher::Save(std::ostream& stream) const
|
|
{
|
|
return
|
|
(
|
|
ips ? ips->Save( stream ) :
|
|
ups ? ups->Save( stream ) : RESULT_ERR_NOT_READY
|
|
);
|
|
}
|
|
|
|
Result Patcher::Test(std::istream& stream) const
|
|
{
|
|
return
|
|
(
|
|
ips ? ips->Test( stream ) :
|
|
ups ? ups->Test( stream, bypassChecksum ) : RESULT_ERR_NOT_READY
|
|
);
|
|
}
|
|
|
|
Result Patcher::Test(const Block* const blocks,const uint numBlocks) const
|
|
{
|
|
NST_ASSERT( blocks || !numBlocks );
|
|
|
|
if (numBlocks > 1)
|
|
{
|
|
Vector<byte> buffer;
|
|
|
|
try
|
|
{
|
|
dword size = 0;
|
|
|
|
for (uint i=0; i < numBlocks; ++i)
|
|
size += blocks[i].size;
|
|
|
|
buffer.Reserve( size );
|
|
}
|
|
catch (...)
|
|
{
|
|
return RESULT_ERR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
for (uint i=0; i < numBlocks; ++i)
|
|
buffer.Append( blocks[i].data, blocks[i].size );
|
|
|
|
return Test( buffer.Begin(), buffer.Size() );
|
|
}
|
|
else
|
|
{
|
|
return Test( blocks ? blocks->data : NULL, blocks ? blocks->size : 0 );
|
|
}
|
|
}
|
|
|
|
Result Patcher::Test(const byte* const data,const dword size) const
|
|
{
|
|
return
|
|
(
|
|
ips ? ips->Test( data, size ) :
|
|
ups ? ups->Test( data, size, bypassChecksum ) : RESULT_ERR_NOT_READY
|
|
);
|
|
}
|
|
|
|
bool Patcher::Patch(const byte* const src,byte* const dst,const dword size,const dword offset) const
|
|
{
|
|
return
|
|
(
|
|
ips ? ips->Patch( src, dst, size, offset ) :
|
|
ups ? ups->Patch( src, dst, size, offset ) : false
|
|
);
|
|
}
|
|
|
|
Result Patcher::Create(const Type type,const byte* const src,const byte* const dst,const dword length)
|
|
{
|
|
Destroy();
|
|
|
|
switch (type)
|
|
{
|
|
case IPS:
|
|
|
|
ips = new (std::nothrow) Ips;
|
|
return ips ? ips->Create( src, dst, length ) : RESULT_ERR_OUT_OF_MEMORY;
|
|
|
|
case UPS:
|
|
|
|
ups = new (std::nothrow) Ups;
|
|
return ups ? ups->Create( src, dst, length ) : RESULT_ERR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return RESULT_ERR_UNSUPPORTED;
|
|
}
|
|
|
|
bool Patcher::Empty() const
|
|
{
|
|
return
|
|
(
|
|
ips ? ips->Empty() :
|
|
ups ? ups->Empty() : true
|
|
);
|
|
}
|
|
}
|
|
}
|