Movies: bk2 movie format support (incomplete + sync issues vs NesHawk)

This commit is contained in:
Souryo 2017-04-22 13:19:21 -04:00
parent c477d75b66
commit 194d933685
23 changed files with 705 additions and 52 deletions

View file

@ -521,6 +521,7 @@ void BaseMapper::Initialize(RomData &romData)
_gameSystem = romData.System;
_crc32 = romData.Crc32;
_sha1Hash = romData.Sha1;
_prgCrc32 = romData.PrgCrc32;
switch(romData.BusConflicts) {
case BusConflictType::Default: _hasBusConflicts = HasBusConflicts(); break;
@ -707,9 +708,9 @@ RomFormat BaseMapper::GetRomFormat()
return _romFormat;
}
uint32_t BaseMapper::GetCrc32()
HashInfo BaseMapper::GetHashInfo()
{
return _crc32;
return { _crc32, _sha1Hash };
}
uint32_t BaseMapper::GetPrgCrc32()

View file

@ -46,6 +46,7 @@ private:
uint32_t _chrPageNumbers[64];
uint32_t _crc32 = 0;
string _sha1Hash = "";
uint32_t _prgCrc32 = 0;
vector<uint8_t> _originalPrgRom;
@ -164,7 +165,7 @@ public:
virtual void SetDefaultNametables(uint8_t* nametableA, uint8_t* nametableB);
GameSystem GetGameSystem();
uint32_t GetCrc32();
HashInfo GetHashInfo();
uint32_t GetPrgCrc32();
string GetRomName();
RomFormat GetRomFormat();

190
Core/BizhawkMovie.cpp Normal file
View file

@ -0,0 +1,190 @@
#include "stdafx.h"
#include "BizhawkMovie.h"
#include "VsControlManager.h"
#include "FDS.h"
BizhawkMovie::BizhawkMovie()
{
_originalPowerOnState = EmulationSettings::GetRamPowerOnState();
MessageManager::RegisterNotificationListener(this);
}
BizhawkMovie::~BizhawkMovie()
{
MessageManager::UnregisterNotificationListener(this);
EmulationSettings::SetRamPowerOnState(_originalPowerOnState);
}
void BizhawkMovie::ProcessNotification(ConsoleNotificationType type, void* parameter)
{
if(type == ConsoleNotificationType::PpuFrameDone) {
int32_t frameNumber = PPU::GetFrameCount() - 1;
if(frameNumber < _systemActionByFrame.size()) {
uint32_t systemAction = _systemActionByFrame[frameNumber];
if(systemAction & 0x01) {
//Power, not implemented yet
}
if(systemAction & 0x02) {
//Reset, not implemented yet
}
if(_gameSystem == GameSystem::FDS) {
//FDS timings between NesHawk & Mesen are currently significantly different
//So FDS games will always go out of sync
if(systemAction & 0x04) {
FDS::EjectDisk();
} else if(systemAction >= 8) {
systemAction >>= 3;
uint32_t diskNumber = 0;
while(!(systemAction & 0x01)) {
systemAction >>= 1;
diskNumber++;
}
FDS::InsertDisk(diskNumber);
}
} else if(_gameSystem == GameSystem::VsUniSystem) {
if(VsControlManager::GetInstance()) {
if(systemAction & 0x04) {
VsControlManager::GetInstance()->InsertCoin(0);
}
if(systemAction & 0x08) {
VsControlManager::GetInstance()->InsertCoin(1);
}
VsControlManager::GetInstance()->SetServiceButtonState(systemAction & 0x10 ? true : false);
}
}
}
}
}
uint8_t BizhawkMovie::GetState(uint8_t port)
{
int32_t frameNumber = PPU::GetFrameCount() - 1;
if(frameNumber < _dataByFrame[0].size()) {
return _dataByFrame[port][frameNumber];
} else {
EndMovie();
EmulationSettings::SetRamPowerOnState(_originalPowerOnState);
_isPlaying = false;
return 0;
}
}
bool BizhawkMovie::InitializeGameData(ZipReader & reader)
{
std::stringstream ss = reader.GetStream("Header.txt");
_gameSystem = GameSystem::NesNtsc;
bool result = false;
while(!ss.eof()) {
string line;
std::getline(ss, line);
if(line.compare(0, 4, "SHA1", 4) == 0) {
if(line.size() >= 45) {
string sha1 = line.substr(5, 40);
if(Console::LoadROM("", sha1)) {
result = true;
}
}
} else if(line.compare(0, 9, "BoardName", 9) == 0) {
if(line.compare(10, 8, "MAPPER99", 8) == 0) {
//VS System
_gameSystem = GameSystem::VsUniSystem;
} else if(line.compare(10, 3, "FDS", 3) == 0) {
//FDS
_gameSystem = GameSystem::FDS;
}
}
}
return result;
}
bool BizhawkMovie::InitializeInputData(ZipReader & reader)
{
const uint8_t orValues[8] = { 0x10, 0x20, 0x40, 0x80, 0x08, 0x04, 0x02, 0x01 };
std::stringstream ss = reader.GetStream("Input Log.txt");
int systemActionCount = 2;
if(_gameSystem == GameSystem::FDS) {
//Eject disk + Insert Disk #XX
systemActionCount += FDS::GetSideCount() + 1;
} else if(_gameSystem == GameSystem::VsUniSystem) {
//Insert coin 1, 2 + service button
systemActionCount += 3;
}
while(!ss.eof()) {
string line;
std::getline(ss, line);
if(line.size() > 0 && line[0] == '|') {
line.erase(std::remove(line.begin(), line.end(), '|'), line.end());
line = line.substr(0, line.size() - 1);
//Read power/reset/FDS/VS/etc. commands
uint32_t systemAction = 0;
for(int i = 0; i < systemActionCount; i++) {
if(line[i] != '.') {
systemAction |= (1 << i);
}
}
_systemActionByFrame.push_back(systemAction);
//Only supports regular controllers (up to 4 of them)
for(int i = 0; i < 8*4; i++) {
uint8_t port = i / 8;
if(port <= 3) {
uint8_t portValue = 0;
for(int j = 0; j < 8 && i + j + systemActionCount < line.size(); j++) {
if(line[i+j+systemActionCount] != '.') {
portValue |= orValues[j];
}
}
i += 7;
_dataByFrame[port].push_back(portValue);
}
}
}
}
return _dataByFrame[0].size() > 0;
}
bool BizhawkMovie::Play(stringstream & filestream, bool autoLoadRom)
{
Console::Pause();
ZipReader reader;
reader.LoadArchive(filestream);
if(InitializeGameData(reader)) {
if(InitializeInputData(reader)) {
//NesHawk initializes memory to 1s
EmulationSettings::SetRamPowerOnState(RamPowerOnState::AllOnes);
Console::Reset(false);
_isPlaying = true;
}
}
Console::Resume();
return _isPlaying;
}
bool BizhawkMovie::IsRecording()
{
return false;
}
bool BizhawkMovie::IsPlaying()
{
return _isPlaying;
}
void BizhawkMovie::RecordState(uint8_t port, uint8_t value)
{
//Not implemented
}
void BizhawkMovie::Record(string filename, bool reset)
{
//Not implemented
}

34
Core/BizhawkMovie.h Normal file
View file

@ -0,0 +1,34 @@
#include "../Utilities/ZipReader.h"
#include "../Utilities/StringUtilities.h"
#include "Console.h"
#include "MovieManager.h"
#include "PPU.h"
class BizhawkMovie : public IMovie, public INotificationListener
{
private:
vector<uint32_t> _systemActionByFrame;
vector<uint8_t> _dataByFrame[4];
bool _isPlaying = false;
RamPowerOnState _originalPowerOnState;
GameSystem _gameSystem;
bool InitializeGameData(ZipReader &reader);
bool InitializeInputData(ZipReader &reader);
public:
BizhawkMovie();
virtual ~BizhawkMovie();
void RecordState(uint8_t port, uint8_t value) override;
void Record(string filename, bool reset);
uint8_t GetState(uint8_t port) override;
bool Play(stringstream &filestream, bool autoLoadRom) override;
bool IsRecording() override;
bool IsPlaying() override;
void ProcessNotification(ConsoleNotificationType type, void* parameter);
};

View file

@ -117,12 +117,25 @@ void Console::LoadROM(string filepath, stringstream *filestream, int32_t archive
Console::Resume();
}
bool Console::LoadROM(string filename, uint32_t crc32Hash)
bool Console::LoadROM(string romName, uint32_t crc32Hash)
{
HashInfo hashInfo{ crc32Hash, "" };
return Console::LoadROM(romName, hashInfo);
}
bool Console::LoadROM(string romName, string sha1Hash)
{
HashInfo hashInfo{ 0, sha1Hash };
return Console::LoadROM(romName, hashInfo);
}
bool Console::LoadROM(string romName, HashInfo hashInfo)
{
string currentRomFilepath = Console::GetROMPath();
string currentFolder = FolderUtilities::GetFolderName(currentRomFilepath);
if(!currentRomFilepath.empty()) {
if(Console::GetCrc32() == crc32Hash) {
HashInfo gameHashInfo = Instance->_mapper->GetHashInfo();
if(gameHashInfo.Crc32Hash == hashInfo.Crc32Hash || gameHashInfo.Sha1Hash.compare(hashInfo.Sha1Hash) == 0) {
//Current game matches, no need to do anything
return true;
}
@ -130,7 +143,7 @@ bool Console::LoadROM(string filename, uint32_t crc32Hash)
int32_t archiveFileIndex = -1;
for(string folder : FolderUtilities::GetKnownGameFolders()) {
string match = RomLoader::FindMatchingRomInFolder(folder, filename, crc32Hash, true, archiveFileIndex);
string match = RomLoader::FindMatchingRomInFolder(folder, romName, hashInfo, true, archiveFileIndex);
if(!match.empty()) {
Console::LoadROM(match, nullptr, archiveFileIndex);
return true;
@ -139,7 +152,7 @@ bool Console::LoadROM(string filename, uint32_t crc32Hash)
//Perform slow CRC32 search for ROM
for(string folder : FolderUtilities::GetKnownGameFolders()) {
string match = RomLoader::FindMatchingRomInFolder(folder, filename, crc32Hash, false, archiveFileIndex);
string match = RomLoader::FindMatchingRomInFolder(folder, romName, hashInfo, false, archiveFileIndex);
if(!match.empty()) {
Console::LoadROM(match, nullptr, archiveFileIndex);
return true;
@ -175,7 +188,7 @@ RomFormat Console::GetRomFormat()
uint32_t Console::GetCrc32()
{
if(Instance->_mapper) {
return Instance->_mapper->GetCrc32();
return Instance->_mapper->GetHashInfo().Crc32Hash;
} else {
return 0;
}

View file

@ -74,7 +74,9 @@ class Console
static void LoadState(uint8_t *buffer, uint32_t bufferSize);
static void LoadROM(string filepath, stringstream *filestream = nullptr, int32_t archiveFileIndex = -1, string patchFilepath = "");
static bool LoadROM(string romName, HashInfo hashInfo);
static bool LoadROM(string romName, uint32_t crc32Hash);
static bool LoadROM(string romName, string sha1Hash);
static string GetROMPath();
static string GetRomName();
static RomFormat GetRomFormat();

View file

@ -424,6 +424,7 @@
<ClInclude Include="BF9096.h" />
<ClInclude Include="BF909x.h" />
<ClInclude Include="BisqwitNtscFilter.h" />
<ClInclude Include="BizhawkMovie.h" />
<ClInclude Include="Bmc11160.h" />
<ClInclude Include="Bmc12in1.h" />
<ClInclude Include="Bmc190in1.h" />
@ -769,6 +770,7 @@
<ClCompile Include="BaseControlDevice.cpp" />
<ClCompile Include="BaseMapper.cpp" />
<ClCompile Include="BisqwitNtscFilter.cpp" />
<ClCompile Include="BizhawkMovie.cpp" />
<ClCompile Include="Breakpoint.cpp" />
<ClCompile Include="CheatManager.cpp" />
<ClCompile Include="CodeDataLogger.cpp" />

View file

@ -1153,6 +1153,9 @@
<ClInclude Include="SealieComputing.h">
<Filter>Nes\Mappers</Filter>
</ClInclude>
<ClInclude Include="BizhawkMovie.h">
<Filter>Movies</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -1359,5 +1362,8 @@
<ClCompile Include="Profiler.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="BizhawkMovie.cpp">
<Filter>Movies</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -61,11 +61,7 @@ uint8_t MesenMovie::GetState(uint8_t port)
if(_readPosition[port] >= _data.DataSize[port]) {
//End of movie file
MessageManager::DisplayMessage("Movies", "MovieEnded");
MessageManager::SendNotification(ConsoleNotificationType::MovieEnded);
if(EmulationSettings::CheckFlag(EmulationFlags::PauseOnMovieEnd)) {
EmulationSettings::SetFlags(EmulationFlags::Paused);
}
EndMovie();
_playing = false;
}
@ -124,13 +120,9 @@ void MesenMovie::Stop()
}
Save();
}
if(_playing) {
MessageManager::DisplayMessage("Movies", "MovieEnded");
_playing = false;
}
}
void MesenMovie::Play(stringstream &filestream, bool autoLoadRom, string filename)
bool MesenMovie::Play(stringstream &filestream, bool autoLoadRom)
{
Stop();
@ -145,12 +137,9 @@ void MesenMovie::Play(stringstream &filestream, bool autoLoadRom, string filenam
CheatManager::SetCheats(_cheatList);
_playing = true;
if(!filename.empty()) {
MessageManager::DisplayMessage("Movies", "MoviePlaying", FolderUtilities::GetFilename(filename, true));
}
}
Console::Resume();
return _playing;
}
struct MovieHeader

View file

@ -35,7 +35,7 @@ private:
protected:
void PushState(uint8_t port);
void Record(string filename, bool reset);
void Play(stringstream &filestream, bool autoLoadRom, string filename = "");
bool Play(stringstream &filestream, bool autoLoadRom);
bool IsPlaying();
bool IsRecording();

View file

@ -1,6 +1,8 @@
#include "stdafx.h"
#include "../Utilities/FolderUtilities.h"
#include "MovieManager.h"
#include "MesenMovie.h"
#include "BizhawkMovie.h"
shared_ptr<IMovie> MovieManager::_instance;
@ -18,11 +20,13 @@ void MovieManager::Play(string filename)
std::stringstream ss;
ss << file.rdbuf();
file.close();
MovieManager::Play(ss, true);
if(MovieManager::Play(ss, true)) {
MessageManager::DisplayMessage("Movies", "MoviePlaying", FolderUtilities::GetFilename(filename, true));
}
}
}
void MovieManager::Play(std::stringstream &filestream, bool autoLoadRom)
bool MovieManager::Play(std::stringstream &filestream, bool autoLoadRom)
{
char header[3] = { };
filestream.read(header, 3);
@ -30,13 +34,26 @@ void MovieManager::Play(std::stringstream &filestream, bool autoLoadRom)
if(memcmp(header, "MMO", 3) == 0) {
shared_ptr<IMovie> movie(new MesenMovie());
movie->Play(filestream, autoLoadRom);
_instance = movie;
if(movie->Play(filestream, autoLoadRom)) {
_instance = movie;
return true;
}
} else if(memcmp(header, "PK", 2) == 0) {
shared_ptr<IMovie> movie(new BizhawkMovie());
if(movie->Play(filestream, autoLoadRom)) {
_instance = movie;
return true;
}
}
return false;
}
void MovieManager::Stop()
{
if(_instance && _instance->IsPlaying()) {
MessageManager::DisplayMessage("Movies", "MovieEnded");
}
_instance.reset();
}

View file

@ -1,14 +1,26 @@
#pragma once
#include "stdafx.h"
#include "MessageManager.h"
#include "EmulationSettings.h"
class IMovie
{
protected:
void EndMovie()
{
MessageManager::DisplayMessage("Movies", "MovieEnded");
MessageManager::SendNotification(ConsoleNotificationType::MovieEnded);
if(EmulationSettings::CheckFlag(EmulationFlags::PauseOnMovieEnd)) {
EmulationSettings::SetFlags(EmulationFlags::Paused);
}
}
public:
virtual void RecordState(uint8_t port, uint8_t value) = 0;
virtual uint8_t GetState(uint8_t port) = 0;
virtual void Record(string filename, bool reset) = 0;
virtual void Play(stringstream &filestream, bool autoLoadRom, string filename = "") = 0;
virtual bool Play(stringstream &filestream, bool autoLoadRom) = 0;
virtual bool IsRecording() = 0;
virtual bool IsPlaying() = 0;
@ -22,7 +34,7 @@ private:
public:
static void Record(string filename, bool reset);
static void Play(string filename);
static void Play(std::stringstream &filestream, bool autoLoadRom);
static bool Play(std::stringstream &filestream, bool autoLoadRom);
static void Stop();
static bool Playing();
static bool Recording();

View file

@ -982,6 +982,7 @@ void PPU::SendFrame()
void PPU::BeginVBlank()
{
_frameCount++;
SendFrame();
TriggerNmi();
}
@ -1000,7 +1001,6 @@ void PPU::Exec()
_cycle = 0;
if(++_scanline > _vblankEnd) {
_lastUpdatedPixel = -1;
_frameCount++;
_scanline = -1;
UpdateMinimumDrawCycles();
}

View file

@ -37,6 +37,12 @@ enum class BusConflictType
No
};
struct HashInfo
{
uint32_t Crc32Hash;
string Sha1Hash;
};
struct NESHeader
{
/*
@ -311,6 +317,7 @@ struct RomData
vector<vector<uint8_t>> FdsDiskData;
vector<uint8_t> RawData;
string Sha1;
uint32_t Crc32 = 0;
uint32_t PrgCrc32 = 0;
uint32_t PrgChrCrc32 = 0;

View file

@ -2,6 +2,7 @@
#include "../Utilities/FolderUtilities.h"
#include "../Utilities/ArchiveReader.h"
#include "../Utilities/CRC32.h"
#include "../Utilities/sha1.h"
#include "../Utilities/BpsPatcher.h"
#include "../Utilities/IpsPatcher.h"
#include "../Utilities/UpsPatcher.h"
@ -158,6 +159,7 @@ bool RomLoader::LoadFromMemory(uint8_t* buffer, size_t length, string romName)
}
_romData.Crc32 = crc;
_romData.Sha1 = SHA1::GetHash(fileData);
_romData.RawData = fileData;
_romData.RomName = romName;
_romData.Filename = _filename;
@ -217,12 +219,12 @@ RomData RomLoader::GetRomData()
return _romData;
}
int32_t RomLoader::FindMatchingRomInFile(string filename, uint32_t crc32Hash)
int32_t RomLoader::FindMatchingRomInFile(string filename, HashInfo hashInfo)
{
RomLoader loader;
int32_t fileIndex = 0;
while(loader.LoadFile(filename, nullptr, "", fileIndex)) {
if(crc32Hash == loader._romData.Crc32) {
if(hashInfo.Crc32Hash == loader._romData.Crc32 || hashInfo.Sha1Hash.compare(loader._romData.Sha1) == 0) {
return fileIndex;
}
fileIndex++;
@ -230,7 +232,7 @@ int32_t RomLoader::FindMatchingRomInFile(string filename, uint32_t crc32Hash)
return -1;
}
string RomLoader::FindMatchingRomInFolder(string folder, string romFilename, uint32_t crc32Hash, bool useFastSearch, int32_t &archiveFileIndex)
string RomLoader::FindMatchingRomInFolder(string folder, string romFilename, HashInfo hashInfo, bool useFastSearch, int32_t &archiveFileIndex)
{
std::transform(romFilename.begin(), romFilename.end(), romFilename.begin(), ::tolower);
vector<string> validExtensions = { { ".nes", ".zip", ".7z", ".fds" } };
@ -248,7 +250,7 @@ string RomLoader::FindMatchingRomInFolder(string folder, string romFilename, uin
string originalFilename = romFile;
std::transform(romFile.begin(), romFile.end(), romFile.begin(), ::tolower);
if(FolderUtilities::GetFilename(romFile, true).compare(romFilename) == 0) {
archiveFileIndex = RomLoader::FindMatchingRomInFile(romFile, crc32Hash);
archiveFileIndex = RomLoader::FindMatchingRomInFile(romFile, hashInfo);
if(archiveFileIndex >= 0) {
return originalFilename;
}
@ -257,7 +259,7 @@ string RomLoader::FindMatchingRomInFolder(string folder, string romFilename, uin
} else {
for(string romFile : romFiles) {
//Slower search by CRC value
archiveFileIndex = RomLoader::FindMatchingRomInFile(romFile, crc32Hash);
archiveFileIndex = RomLoader::FindMatchingRomInFile(romFile, hashInfo);
if(archiveFileIndex >= 0) {
return romFile;
}

View file

@ -16,12 +16,12 @@ class RomLoader
uint8_t* ReadFile(istream &file, uint32_t &fileSize);
bool LoadFromMemory(uint8_t* buffer, size_t length, string romName);
static int32_t FindMatchingRomInFile(string filename, uint32_t crc32Hash);
static int32_t FindMatchingRomInFile(string filename, HashInfo hashInfo);
void ApplyPatch(string patchPath, vector<uint8_t> &data);
public:
bool LoadFile(string filename, istream *filestream = nullptr, string patchFilename = "", int32_t archiveFileIndex = -1);
RomData GetRomData();
static string FindMatchingRomInFolder(string folder, string romFilename, uint32_t crc32Hash, bool useFastSearch, int32_t &archiveFileIndex);
static string FindMatchingRomInFolder(string folder, string romFilename, HashInfo hashInfo, bool useFastSearch, int32_t &archiveFileIndex);
static vector<string> GetArchiveRomList(string filename);
};

View file

@ -6,6 +6,7 @@
#include "VsZapper.h"
#include <assert.h>
#include "StandardController.h"
#include "MovieManager.h"
enum class VsInputType
{
@ -179,7 +180,7 @@ public:
void RefreshAllPorts() override
{
ControlManager::RefreshAllPorts();
if(_inputType != VsInputType::Default) {
if(!MovieManager::Playing() && _inputType != VsInputType::Default) {
RemapControllerButtons();
}
}

View file

@ -47,6 +47,23 @@ vector<string> ArchiveReader::GetFileList(std::initializer_list<string> extensio
return filenames;
}
bool ArchiveReader::LoadArchive(std::istream &in)
{
in.seekg(0, std::ios::end);
std::streampos filesize = in.tellg();
in.seekg(0, std::ios::beg);
if(_buffer) {
delete[] _buffer;
_buffer = nullptr;
}
_buffer = new uint8_t[(uint32_t)filesize];
in.read((char*)_buffer, filesize);
bool result = LoadArchive(_buffer, (size_t)filesize);
return result;
}
bool ArchiveReader::LoadArchive(void* buffer, size_t size)
{
if(InternalLoadArchive(buffer, size)) {
@ -59,20 +76,9 @@ bool ArchiveReader::LoadArchive(void* buffer, size_t size)
bool ArchiveReader::LoadArchive(string filename)
{
ifstream in(filename, std::ios::binary | std::ios::in);
if(in) {
in.seekg(0, std::ios::end);
std::streampos filesize = in.tellg();
in.seekg(0, std::ios::beg);
if(_buffer) {
delete[] _buffer;
_buffer = nullptr;
}
_buffer = new uint8_t[(uint32_t)filesize];
in.read((char*)_buffer, filesize);
bool result = LoadArchive(_buffer, (size_t)filesize);
return result;
if(in.good()) {
LoadArchive(in);
in.close();
}
return false;
}

View file

@ -13,6 +13,8 @@ public:
bool LoadArchive(void* buffer, size_t size);
bool LoadArchive(string filename);
bool LoadArchive(std::istream &in);
std::stringstream GetStream(string filename);
vector<string> GetFileList(std::initializer_list<string> extensions);

View file

@ -348,6 +348,7 @@
<ClInclude Include="Scale2x\scale2x.h" />
<ClInclude Include="Scale2x\scale3x.h" />
<ClInclude Include="Scale2x\scalebit.h" />
<ClInclude Include="sha1.h" />
<ClInclude Include="StringUtilities.h" />
<ClInclude Include="SZReader.h" />
<ClInclude Include="UPnPPortMapper.h" />
@ -480,6 +481,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='PGO Optimize|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="sha1.cpp" />
<ClCompile Include="SimpleLock.cpp" />
<ClCompile Include="Socket.cpp" />
<ClCompile Include="stdafx.cpp">

View file

@ -155,6 +155,9 @@
<ClInclude Include="orfanidis_eq.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="sha1.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -268,5 +271,8 @@
<ClCompile Include="BpsPatcher.cpp">
<Filter>Patches</Filter>
</ClCompile>
<ClCompile Include="sha1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

319
Utilities/sha1.cpp Normal file
View file

@ -0,0 +1,319 @@
/*
sha1.cpp - source code of
============
SHA-1 in C++
============
100% Public Domain.
Original C Code
-- Steve Reid <steve@edmweb.com>
Small changes to fit into bglibs
-- Bruce Guenter <bruce@untroubled.org>
Translation to simpler C++ Code
-- Volker Grabsch <vog@notjusthosting.com>
Safety fixes
-- Eugene Hopkinson <slowriot at voxelstorm dot com>
*/
#include "stdafx.h"
#include "sha1.h"
#include <sstream>
#include <iomanip>
#include <fstream>
static const size_t BLOCK_INTS = 16; /* number of 32bit integers per SHA1 block */
static const size_t BLOCK_BYTES = BLOCK_INTS * 4;
static void reset(uint32_t digest[], std::string &buffer, uint64_t &transforms)
{
/* SHA1 initialization constants */
digest[0] = 0x67452301;
digest[1] = 0xefcdab89;
digest[2] = 0x98badcfe;
digest[3] = 0x10325476;
digest[4] = 0xc3d2e1f0;
/* Reset counters */
buffer = "";
transforms = 0;
}
static uint32_t rol(const uint32_t value, const size_t bits)
{
return (value << bits) | (value >> (32 - bits));
}
static uint32_t blk(const uint32_t block[BLOCK_INTS], const size_t i)
{
return rol(block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i], 1);
}
/*
* (R0+R1), R2, R3, R4 are the different operations used in SHA1
*/
static void R0(const uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
z += ((w&(x^y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5);
w = rol(w, 30);
}
static void R1(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
block[i] = blk(block, i);
z += ((w&(x^y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5);
w = rol(w, 30);
}
static void R2(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
block[i] = blk(block, i);
z += (w^x^y) + block[i] + 0x6ed9eba1 + rol(v, 5);
w = rol(w, 30);
}
static void R3(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
block[i] = blk(block, i);
z += (((w | x)&y) | (w&x)) + block[i] + 0x8f1bbcdc + rol(v, 5);
w = rol(w, 30);
}
static void R4(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
block[i] = blk(block, i);
z += (w^x^y) + block[i] + 0xca62c1d6 + rol(v, 5);
w = rol(w, 30);
}
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
static void transform(uint32_t digest[], uint32_t block[BLOCK_INTS], uint64_t &transforms)
{
/* Copy digest[] to working vars */
uint32_t a = digest[0];
uint32_t b = digest[1];
uint32_t c = digest[2];
uint32_t d = digest[3];
uint32_t e = digest[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(block, a, b, c, d, e, 0);
R0(block, e, a, b, c, d, 1);
R0(block, d, e, a, b, c, 2);
R0(block, c, d, e, a, b, 3);
R0(block, b, c, d, e, a, 4);
R0(block, a, b, c, d, e, 5);
R0(block, e, a, b, c, d, 6);
R0(block, d, e, a, b, c, 7);
R0(block, c, d, e, a, b, 8);
R0(block, b, c, d, e, a, 9);
R0(block, a, b, c, d, e, 10);
R0(block, e, a, b, c, d, 11);
R0(block, d, e, a, b, c, 12);
R0(block, c, d, e, a, b, 13);
R0(block, b, c, d, e, a, 14);
R0(block, a, b, c, d, e, 15);
R1(block, e, a, b, c, d, 0);
R1(block, d, e, a, b, c, 1);
R1(block, c, d, e, a, b, 2);
R1(block, b, c, d, e, a, 3);
R2(block, a, b, c, d, e, 4);
R2(block, e, a, b, c, d, 5);
R2(block, d, e, a, b, c, 6);
R2(block, c, d, e, a, b, 7);
R2(block, b, c, d, e, a, 8);
R2(block, a, b, c, d, e, 9);
R2(block, e, a, b, c, d, 10);
R2(block, d, e, a, b, c, 11);
R2(block, c, d, e, a, b, 12);
R2(block, b, c, d, e, a, 13);
R2(block, a, b, c, d, e, 14);
R2(block, e, a, b, c, d, 15);
R2(block, d, e, a, b, c, 0);
R2(block, c, d, e, a, b, 1);
R2(block, b, c, d, e, a, 2);
R2(block, a, b, c, d, e, 3);
R2(block, e, a, b, c, d, 4);
R2(block, d, e, a, b, c, 5);
R2(block, c, d, e, a, b, 6);
R2(block, b, c, d, e, a, 7);
R3(block, a, b, c, d, e, 8);
R3(block, e, a, b, c, d, 9);
R3(block, d, e, a, b, c, 10);
R3(block, c, d, e, a, b, 11);
R3(block, b, c, d, e, a, 12);
R3(block, a, b, c, d, e, 13);
R3(block, e, a, b, c, d, 14);
R3(block, d, e, a, b, c, 15);
R3(block, c, d, e, a, b, 0);
R3(block, b, c, d, e, a, 1);
R3(block, a, b, c, d, e, 2);
R3(block, e, a, b, c, d, 3);
R3(block, d, e, a, b, c, 4);
R3(block, c, d, e, a, b, 5);
R3(block, b, c, d, e, a, 6);
R3(block, a, b, c, d, e, 7);
R3(block, e, a, b, c, d, 8);
R3(block, d, e, a, b, c, 9);
R3(block, c, d, e, a, b, 10);
R3(block, b, c, d, e, a, 11);
R4(block, a, b, c, d, e, 12);
R4(block, e, a, b, c, d, 13);
R4(block, d, e, a, b, c, 14);
R4(block, c, d, e, a, b, 15);
R4(block, b, c, d, e, a, 0);
R4(block, a, b, c, d, e, 1);
R4(block, e, a, b, c, d, 2);
R4(block, d, e, a, b, c, 3);
R4(block, c, d, e, a, b, 4);
R4(block, b, c, d, e, a, 5);
R4(block, a, b, c, d, e, 6);
R4(block, e, a, b, c, d, 7);
R4(block, d, e, a, b, c, 8);
R4(block, c, d, e, a, b, 9);
R4(block, b, c, d, e, a, 10);
R4(block, a, b, c, d, e, 11);
R4(block, e, a, b, c, d, 12);
R4(block, d, e, a, b, c, 13);
R4(block, c, d, e, a, b, 14);
R4(block, b, c, d, e, a, 15);
/* Add the working vars back into digest[] */
digest[0] += a;
digest[1] += b;
digest[2] += c;
digest[3] += d;
digest[4] += e;
/* Count the number of transformations */
transforms++;
}
static void buffer_to_block(const std::string &buffer, uint32_t block[BLOCK_INTS])
{
/* Convert the std::string (byte buffer) to a uint32_t array (MSB) */
for(size_t i = 0; i < BLOCK_INTS; i++) {
block[i] = (buffer[4 * i + 3] & 0xff)
| (buffer[4 * i + 2] & 0xff) << 8
| (buffer[4 * i + 1] & 0xff) << 16
| (buffer[4 * i + 0] & 0xff) << 24;
}
}
SHA1::SHA1()
{
reset(digest, buffer, transforms);
}
void SHA1::update(const std::string &s)
{
std::istringstream is(s);
update(is);
}
void SHA1::update(std::istream &is)
{
char sbuf[BLOCK_BYTES];
uint32_t block[BLOCK_INTS];
while(true) {
is.read(sbuf, BLOCK_BYTES - buffer.size());
buffer.append(sbuf, is.gcount());
if(buffer.size() != BLOCK_BYTES) {
return;
}
buffer_to_block(buffer, block);
transform(digest, block, transforms);
buffer.clear();
}
}
/*
* Add padding and return the message digest.
*/
std::string SHA1::final()
{
/* Total number of hashed bits */
uint64_t total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8;
/* Padding */
buffer += (char)0x80;
size_t orig_size = buffer.size();
while(buffer.size() < BLOCK_BYTES) {
buffer += (char)0x00;
}
uint32_t block[BLOCK_INTS];
buffer_to_block(buffer, block);
if(orig_size > BLOCK_BYTES - 8) {
transform(digest, block, transforms);
for(size_t i = 0; i < BLOCK_INTS - 2; i++) {
block[i] = 0;
}
}
/* Append total_bits, split this uint64_t into two uint32_t */
block[BLOCK_INTS - 1] = (uint32_t)total_bits;
block[BLOCK_INTS - 2] = (uint32_t)(total_bits >> 32);
transform(digest, block, transforms);
/* Hex std::string */
std::ostringstream result;
for(size_t i = 0; i < sizeof(digest) / sizeof(digest[0]); i++) {
result << std::uppercase << std::hex << std::setfill('0') << std::setw(8);
result << digest[i];
}
/* Reset for next run */
reset(digest, buffer, transforms);
return result.str();
}
std::string SHA1::GetHash(vector<uint8_t> &data)
{
std::stringstream ss;
ss.write((char*)data.data(), data.size());
SHA1 checksum;
checksum.update(ss);
return checksum.final();
}
std::string SHA1::GetHash(std::istream &stream)
{
SHA1 checksum;
checksum.update(stream);
return checksum.final();
}
std::string SHA1::GetHash(const std::string &filename)
{
std::ifstream stream(filename.c_str(), std::ios::binary);
SHA1 checksum;
checksum.update(stream);
return checksum.final();
}

41
Utilities/sha1.h Normal file
View file

@ -0,0 +1,41 @@
/*
sha1.h - header of
============
SHA-1 in C++
============
100% Public Domain.
Original C Code
-- Steve Reid <steve@edmweb.com>
Small changes to fit into bglibs
-- Bruce Guenter <bruce@untroubled.org>
Translation to simpler C++ Code
-- Volker Grabsch <vog@notjusthosting.com>
Safety fixes
-- Eugene Hopkinson <slowriot at voxelstorm dot com>
*/
#pragma once
#include <cstdint>
#include <iostream>
#include <string>
class SHA1
{
public:
SHA1();
void update(const std::string &s);
void update(std::istream &is);
std::string final();
static std::string GetHash(const std::string &filename);
static std::string GetHash(std::istream &stream);
static std::string GetHash(vector<uint8_t> &data);
private:
uint32_t digest[5];
std::string buffer;
uint64_t transforms;
};