mirror of
https://github.com/SourMesen/Mesen2.git
synced 2024-05-23 06:28:10 -04:00
Save state support
This commit is contained in:
parent
fe958a8285
commit
73913e1f0c
|
@ -8,6 +8,8 @@
|
|||
#include "../Utilities/HexUtilities.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
#include "../Utilities/sha1.h"
|
||||
|
||||
BaseCartridge::~BaseCartridge()
|
||||
{
|
||||
|
@ -158,6 +160,11 @@ RomInfo BaseCartridge::GetRomInfo()
|
|||
return info;
|
||||
}
|
||||
|
||||
string BaseCartridge::GetSha1Hash()
|
||||
{
|
||||
return SHA1::GetHash(_prgRom, _prgRomSize);
|
||||
}
|
||||
|
||||
void BaseCartridge::LoadBattery()
|
||||
{
|
||||
if(_saveRamSize > 0) {
|
||||
|
@ -240,6 +247,11 @@ void BaseCartridge::RegisterHandlers(MemoryManager &mm)
|
|||
}
|
||||
}
|
||||
|
||||
void BaseCartridge::Serialize(Serializer &s)
|
||||
{
|
||||
s.StreamArray(_saveRam, _saveRamSize);
|
||||
}
|
||||
|
||||
void BaseCartridge::DisplayCartInfo()
|
||||
{
|
||||
int nameLength = 21;
|
||||
|
|
|
@ -1,39 +1,12 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "IMemoryHandler.h"
|
||||
#include "CartTypes.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class MemoryManager;
|
||||
class VirtualFile;
|
||||
|
||||
struct SnesCartInformation
|
||||
{
|
||||
uint8_t MakerCode[2];
|
||||
uint8_t GameCode[4];
|
||||
uint8_t Reserved[7];
|
||||
uint8_t ExpansionRamSize;
|
||||
uint8_t SpecialVersion;
|
||||
uint8_t CartridgeType;
|
||||
|
||||
char CartName[21];
|
||||
uint8_t MapMode;
|
||||
uint8_t RomType;
|
||||
uint8_t RomSize;
|
||||
uint8_t SramSize;
|
||||
|
||||
uint8_t DestinationCode;
|
||||
uint8_t Reserved2;
|
||||
uint8_t Version;
|
||||
|
||||
uint8_t ChecksumComplement[2];
|
||||
uint8_t Checksum[2];
|
||||
};
|
||||
|
||||
struct RomInfo
|
||||
{
|
||||
SnesCartInformation Header;
|
||||
string RomPath;
|
||||
};
|
||||
|
||||
namespace CartFlags
|
||||
{
|
||||
enum CartFlags
|
||||
|
@ -47,7 +20,7 @@ namespace CartFlags
|
|||
};
|
||||
}
|
||||
|
||||
class BaseCartridge
|
||||
class BaseCartridge : public ISerializable
|
||||
{
|
||||
private:
|
||||
vector<unique_ptr<IMemoryHandler>> _prgRomHandlers;
|
||||
|
@ -79,6 +52,7 @@ public:
|
|||
void Init();
|
||||
|
||||
RomInfo GetRomInfo();
|
||||
string GetSha1Hash();
|
||||
|
||||
void RegisterHandlers(MemoryManager &mm);
|
||||
|
||||
|
@ -86,4 +60,6 @@ public:
|
|||
uint8_t* DebugGetSaveRam() { return _saveRam; }
|
||||
uint32_t DebugGetPrgRomSize() { return _prgRomSize; }
|
||||
uint32_t DebugGetSaveRamSize() { return _saveRamSize; }
|
||||
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "stdafx.h"
|
||||
#include "BaseControlDevice.h"
|
||||
#include "Console.h"
|
||||
#include "KeyManager.h"
|
||||
#include "../Utilities/StringUtilities.h"
|
||||
#include "Console.h"
|
||||
//#include "EmulationSettings.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
BaseControlDevice::BaseControlDevice(shared_ptr<Console> console, uint8_t port, KeyMappingSet keyMappingSet)
|
||||
{
|
||||
|
@ -32,16 +32,6 @@ void BaseControlDevice::InternalSetStateFromInput()
|
|||
{
|
||||
}
|
||||
|
||||
//TODO
|
||||
/*
|
||||
void BaseControlDevice::StreamState(bool saving)
|
||||
{
|
||||
auto lock = _stateLock.AcquireSafe();
|
||||
VectorInfo<uint8_t> state{ &_state.State };
|
||||
Stream(_strobe, state);
|
||||
}
|
||||
*/
|
||||
|
||||
bool BaseControlDevice::IsCurrentPort(uint16_t addr)
|
||||
{
|
||||
return _port == (addr - 0x4016);
|
||||
|
@ -277,3 +267,10 @@ void BaseControlDevice::SwapButtons(shared_ptr<BaseControlDevice> state1, uint8_
|
|||
state1->SetBit(button1);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseControlDevice::Serialize(Serializer &s)
|
||||
{
|
||||
auto lock = _stateLock.AcquireSafe();
|
||||
s.Stream(_strobe);
|
||||
s.StreamVector(_state.State);
|
||||
}
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
#include "SettingTypes.h"
|
||||
#include "IKeyManager.h"
|
||||
#include "../Utilities/SimpleLock.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class Console;
|
||||
|
||||
class BaseControlDevice
|
||||
class BaseControlDevice : public ISerializable
|
||||
{
|
||||
private:
|
||||
ControlDeviceState _state;
|
||||
|
@ -80,4 +81,6 @@ public:
|
|||
virtual void WriteRam(uint16_t addr, uint8_t value) = 0;
|
||||
|
||||
void static SwapButtons(shared_ptr<BaseControlDevice> state1, uint8_t button1, shared_ptr<BaseControlDevice> state2, uint8_t button2);
|
||||
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
||||
|
|
31
Core/CartTypes.h
Normal file
31
Core/CartTypes.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
struct SnesCartInformation
|
||||
{
|
||||
uint8_t MakerCode[2];
|
||||
uint8_t GameCode[4];
|
||||
uint8_t Reserved[7];
|
||||
uint8_t ExpansionRamSize;
|
||||
uint8_t SpecialVersion;
|
||||
uint8_t CartridgeType;
|
||||
|
||||
char CartName[21];
|
||||
uint8_t MapMode;
|
||||
uint8_t RomType;
|
||||
uint8_t RomSize;
|
||||
uint8_t SramSize;
|
||||
|
||||
uint8_t DestinationCode;
|
||||
uint8_t Reserved2;
|
||||
uint8_t Version;
|
||||
|
||||
uint8_t ChecksumComplement[2];
|
||||
uint8_t Checksum[2];
|
||||
};
|
||||
|
||||
struct RomInfo
|
||||
{
|
||||
SnesCartInformation Header;
|
||||
string RomPath;
|
||||
};
|
|
@ -21,7 +21,11 @@
|
|||
#include "KeyManager.h"
|
||||
#include "EventType.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "SaveStateManager.h"
|
||||
#include "DebugStats.h"
|
||||
#include "CartTypes.h"
|
||||
#include "ConsoleLock.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
#include "../Utilities/Timer.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "../Utilities/PlatformUtilities.h"
|
||||
|
@ -33,10 +37,13 @@ Console::~Console()
|
|||
|
||||
void Console::Initialize()
|
||||
{
|
||||
_lockCounter = 0;
|
||||
|
||||
_settings.reset(new EmuSettings());
|
||||
_notificationManager.reset(new NotificationManager());
|
||||
_videoDecoder.reset(new VideoDecoder(shared_from_this()));
|
||||
_videoRenderer.reset(new VideoRenderer(shared_from_this()));
|
||||
_saveStateManager.reset(new SaveStateManager(shared_from_this()));
|
||||
_soundMixer.reset(new SoundMixer(this));
|
||||
_debugHud.reset(new DebugHud());
|
||||
|
||||
|
@ -55,6 +62,9 @@ void Console::Release()
|
|||
_videoRenderer.reset();
|
||||
_debugHud.reset();
|
||||
_notificationManager.reset();
|
||||
_saveStateManager.reset();
|
||||
_soundMixer.reset();
|
||||
_settings.reset();
|
||||
}
|
||||
|
||||
void Console::Run()
|
||||
|
@ -81,6 +91,8 @@ void Console::Run()
|
|||
_cpu->Exec();
|
||||
|
||||
if(previousFrameCount != _ppu->GetFrameCount()) {
|
||||
WaitForLock();
|
||||
|
||||
frameLimiter.ProcessFrame();
|
||||
frameLimiter.WaitForNextFrame();
|
||||
|
||||
|
@ -169,6 +181,18 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
|
|||
//_debugger.reset();
|
||||
//GetDebugger();
|
||||
//}
|
||||
|
||||
_notificationManager->SendNotification(ConsoleNotificationType::GameLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
RomInfo Console::GetRomInfo()
|
||||
{
|
||||
shared_ptr<BaseCartridge> cart = _cart;
|
||||
if(cart) {
|
||||
return cart->GetRomInfo();
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,6 +208,63 @@ double Console::GetFrameDelay()
|
|||
return frameDelay;
|
||||
}
|
||||
|
||||
ConsoleLock Console::AcquireLock()
|
||||
{
|
||||
return ConsoleLock(this);
|
||||
}
|
||||
|
||||
void Console::Lock()
|
||||
{
|
||||
_lockCounter++;
|
||||
_runLock.Acquire();
|
||||
}
|
||||
|
||||
void Console::Unlock()
|
||||
{
|
||||
_runLock.Release();
|
||||
_lockCounter--;
|
||||
}
|
||||
|
||||
void Console::WaitForLock()
|
||||
{
|
||||
if(_lockCounter > 0) {
|
||||
//Need to temporarely pause the emu (to save/load a state, etc.)
|
||||
_runLock.Release();
|
||||
|
||||
//Spin wait until we are allowed to start again
|
||||
while(_lockCounter > 0) {}
|
||||
|
||||
_runLock.Acquire();
|
||||
}
|
||||
}
|
||||
|
||||
void Console::Serialize(ostream &out)
|
||||
{
|
||||
Serializer serializer(SaveStateManager::FileFormatVersion);
|
||||
serializer.Stream(_cpu.get());
|
||||
serializer.Stream(_memoryManager.get());
|
||||
serializer.Stream(_ppu.get());
|
||||
serializer.Stream(_dmaController.get());
|
||||
serializer.Stream(_internalRegisters.get());
|
||||
serializer.Stream(_cart.get());
|
||||
serializer.Stream(_controlManager.get());
|
||||
serializer.Stream(_spc.get());
|
||||
serializer.Save(out);
|
||||
}
|
||||
|
||||
void Console::Deserialize(istream &in, uint32_t fileFormatVersion)
|
||||
{
|
||||
Serializer serializer(in, fileFormatVersion);
|
||||
serializer.Stream(_cpu.get());
|
||||
serializer.Stream(_memoryManager.get());
|
||||
serializer.Stream(_ppu.get());
|
||||
serializer.Stream(_dmaController.get());
|
||||
serializer.Stream(_internalRegisters.get());
|
||||
serializer.Stream(_cart.get());
|
||||
serializer.Stream(_controlManager.get());
|
||||
serializer.Stream(_spc.get());
|
||||
}
|
||||
|
||||
shared_ptr<SoundMixer> Console::GetSoundMixer()
|
||||
{
|
||||
return _soundMixer;
|
||||
|
@ -209,6 +290,11 @@ shared_ptr<EmuSettings> Console::GetSettings()
|
|||
return _settings;
|
||||
}
|
||||
|
||||
shared_ptr<SaveStateManager> Console::GetSaveStateManager()
|
||||
{
|
||||
return _saveStateManager;
|
||||
}
|
||||
|
||||
shared_ptr<DebugHud> Console::GetDebugHud()
|
||||
{
|
||||
return _debugHud;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "CartTypes.h"
|
||||
#include "ConsoleLock.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "../Utilities/SimpleLock.h"
|
||||
|
||||
|
@ -18,6 +20,7 @@ class VideoRenderer;
|
|||
class VideoDecoder;
|
||||
class NotificationManager;
|
||||
class EmuSettings;
|
||||
class SaveStateManager;
|
||||
enum class MemoryOperationType;
|
||||
enum class SnesMemoryType;
|
||||
enum class EventType;
|
||||
|
@ -42,14 +45,18 @@ private:
|
|||
shared_ptr<VideoDecoder> _videoDecoder;
|
||||
shared_ptr<DebugHud> _debugHud;
|
||||
shared_ptr<EmuSettings> _settings;
|
||||
shared_ptr<SaveStateManager> _saveStateManager;
|
||||
|
||||
thread::id _emulationThreadId;
|
||||
|
||||
|
||||
atomic<uint32_t> _lockCounter;
|
||||
SimpleLock _runLock;
|
||||
|
||||
SimpleLock _debuggerLock;
|
||||
atomic<bool> _stopFlag;
|
||||
|
||||
double GetFrameDelay();
|
||||
void WaitForLock();
|
||||
|
||||
public:
|
||||
~Console();
|
||||
|
@ -61,12 +68,21 @@ public:
|
|||
void Stop();
|
||||
|
||||
void LoadRom(VirtualFile romFile, VirtualFile patchFile);
|
||||
RomInfo GetRomInfo();
|
||||
|
||||
ConsoleLock AcquireLock();
|
||||
void Lock();
|
||||
void Unlock();
|
||||
|
||||
void Serialize(ostream &out);
|
||||
void Deserialize(istream &in, uint32_t fileFormatVersion);
|
||||
|
||||
shared_ptr<SoundMixer> GetSoundMixer();
|
||||
shared_ptr<VideoRenderer> GetVideoRenderer();
|
||||
shared_ptr<VideoDecoder> GetVideoDecoder();
|
||||
shared_ptr<NotificationManager> GetNotificationManager();
|
||||
shared_ptr<EmuSettings> GetSettings();
|
||||
shared_ptr<SaveStateManager> GetSaveStateManager();
|
||||
|
||||
shared_ptr<DebugHud> GetDebugHud();
|
||||
|
||||
|
|
14
Core/ConsoleLock.cpp
Normal file
14
Core/ConsoleLock.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "stdafx.h"
|
||||
#include "ConsoleLock.h"
|
||||
#include "Console.h"
|
||||
|
||||
ConsoleLock::ConsoleLock(Console *console)
|
||||
{
|
||||
_console = console;
|
||||
_console->Lock();
|
||||
}
|
||||
|
||||
ConsoleLock::~ConsoleLock()
|
||||
{
|
||||
_console->Unlock();
|
||||
}
|
14
Core/ConsoleLock.h
Normal file
14
Core/ConsoleLock.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
class Console;
|
||||
|
||||
class ConsoleLock
|
||||
{
|
||||
private:
|
||||
Console *_console = nullptr;
|
||||
|
||||
public:
|
||||
ConsoleLock(Console *console);
|
||||
~ConsoleLock();
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
#include "IInputProvider.h"
|
||||
#include "IInputRecorder.h"
|
||||
#include "SnesController.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
ControlManager::ControlManager(shared_ptr<Console> console)
|
||||
{
|
||||
|
@ -216,4 +217,11 @@ void ControlManager::Write(uint16_t addr, uint8_t value)
|
|||
for(shared_ptr<BaseControlDevice> &device : _controlDevices) {
|
||||
device->WriteRam(addr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ControlManager::Serialize(Serializer &s)
|
||||
{
|
||||
for(shared_ptr<BaseControlDevice> &device : _controlDevices) {
|
||||
s.Stream(device.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "stdafx.h"
|
||||
#include "../Utilities/SimpleLock.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
#include "IMemoryHandler.h"
|
||||
|
||||
class BaseControlDevice;
|
||||
|
@ -12,13 +13,13 @@ struct ControlDeviceState;
|
|||
enum class ControllerType;
|
||||
enum class ExpansionPortDevice;
|
||||
|
||||
class ControlManager
|
||||
class ControlManager : public ISerializable
|
||||
{
|
||||
private:
|
||||
vector<IInputRecorder*> _inputRecorders;
|
||||
vector<IInputProvider*> _inputProviders;
|
||||
|
||||
//Static so that power cycle does not reset its value
|
||||
//TODO: Static so that power cycle does not reset its value
|
||||
uint32_t _pollCounter;
|
||||
|
||||
protected:
|
||||
|
@ -57,4 +58,6 @@ public:
|
|||
|
||||
uint8_t Read(uint16_t addr);
|
||||
void Write(uint16_t addr, uint8_t value);
|
||||
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
||||
|
|
|
@ -54,8 +54,10 @@
|
|||
<ClInclude Include="blargg_source.h" />
|
||||
<ClInclude Include="Breakpoint.h" />
|
||||
<ClInclude Include="BreakpointManager.h" />
|
||||
<ClInclude Include="CartTypes.h" />
|
||||
<ClInclude Include="CodeDataLogger.h" />
|
||||
<ClInclude Include="Console.h" />
|
||||
<ClInclude Include="ConsoleLock.h" />
|
||||
<ClInclude Include="ControlDeviceState.h" />
|
||||
<ClInclude Include="ControlManager.h" />
|
||||
<ClInclude Include="Cpu.h" />
|
||||
|
@ -104,6 +106,7 @@
|
|||
<ClInclude Include="RamHandler.h" />
|
||||
<ClInclude Include="RegisterHandlerA.h" />
|
||||
<ClInclude Include="RomHandler.h" />
|
||||
<ClInclude Include="SaveStateManager.h" />
|
||||
<ClInclude Include="ScaleFilter.h" />
|
||||
<ClInclude Include="SettingTypes.h" />
|
||||
<ClInclude Include="ShortcutKeyHandler.h" />
|
||||
|
@ -130,6 +133,7 @@
|
|||
<ClCompile Include="BreakpointManager.cpp" />
|
||||
<ClCompile Include="CodeDataLogger.cpp" />
|
||||
<ClCompile Include="Console.cpp" />
|
||||
<ClCompile Include="ConsoleLock.cpp" />
|
||||
<ClCompile Include="ControlManager.cpp" />
|
||||
<ClCompile Include="Cpu.cpp" />
|
||||
<ClCompile Include="Cpu.Instructions.cpp" />
|
||||
|
@ -152,6 +156,8 @@
|
|||
<ClCompile Include="NtscFilter.cpp" />
|
||||
<ClCompile Include="Ppu.cpp" />
|
||||
<ClCompile Include="PpuTools.cpp" />
|
||||
<ClCompile Include="RegisterHandlerB.cpp" />
|
||||
<ClCompile Include="SaveStateManager.cpp" />
|
||||
<ClCompile Include="ScaleFilter.cpp" />
|
||||
<ClCompile Include="ShortcutKeyHandler.cpp" />
|
||||
<ClCompile Include="SNES_SPC.cpp" />
|
||||
|
|
|
@ -227,6 +227,15 @@
|
|||
<ClInclude Include="ShortcutKeyHandler.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SaveStateManager.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CartTypes.h">
|
||||
<Filter>SNES</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ConsoleLock.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
|
@ -362,6 +371,13 @@
|
|||
<ClCompile Include="DebugStats.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RegisterHandlerB.cpp">
|
||||
<Filter>SNES</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SaveStateManager.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ConsoleLock.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="SNES">
|
||||
|
|
10
Core/Cpu.cpp
10
Core/Cpu.cpp
|
@ -4,6 +4,7 @@
|
|||
#include "Console.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "EventType.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
Cpu::Cpu(Console *console)
|
||||
{
|
||||
|
@ -612,3 +613,12 @@ bool Cpu::CheckFlag(uint8_t flag)
|
|||
{
|
||||
return (_state.PS & flag) == flag;
|
||||
}
|
||||
|
||||
void Cpu::Serialize(Serializer &s)
|
||||
{
|
||||
s.Stream(
|
||||
_state.A, _state.CycleCount, _state.D, _state.DBR, _state.EmulationMode, _state.IrqSource, _state.K,
|
||||
_state.NmiFlag, _state.PC, _state.PrevIrqSource, _state.PrevNmiFlag, _state.PS, _state.SP, _state.StopState,
|
||||
_state.X, _state.Y
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,11 +7,12 @@
|
|||
|
||||
#include "stdafx.h"
|
||||
#include "CpuTypes.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class MemoryManager;
|
||||
class Console;
|
||||
|
||||
class Cpu
|
||||
class Cpu : public ISerializable
|
||||
{
|
||||
private:
|
||||
static constexpr uint32_t NmiVector = 0x00FFEA;
|
||||
|
@ -300,6 +301,9 @@ public:
|
|||
bool CheckIrqSource(IrqSource source);
|
||||
void ClearIrqSource(IrqSource source);
|
||||
|
||||
// Inherited via ISerializable
|
||||
void Serialize(Serializer &s) override;
|
||||
|
||||
#ifdef DUMMYCPU
|
||||
private:
|
||||
uint32_t _writeCounter = 0;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "DmaController.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "MessageManager.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
DmaController::DmaController(MemoryManager *memoryManager)
|
||||
{
|
||||
|
@ -428,5 +429,19 @@ uint8_t DmaController::Read(uint16_t addr)
|
|||
return channel.HdmaLineCounterAndRepeat;
|
||||
}
|
||||
}
|
||||
return 0; //TODO : open bus
|
||||
}
|
||||
return _memoryManager->GetOpenBus();
|
||||
}
|
||||
|
||||
void DmaController::Serialize(Serializer &s)
|
||||
{
|
||||
s.Stream(_hdmaPending, _hdmaChannels);
|
||||
for(int i = 0; i < 8; i++) {
|
||||
s.Stream(
|
||||
_channel[i].Decrement, _channel[i].DestAddress, _channel[i].DoTransfer, _channel[i].FixedTransfer,
|
||||
_channel[i].HdmaBank, _channel[i].HdmaFinished, _channel[i].HdmaIndirectAddressing,
|
||||
_channel[i].HdmaLineCounterAndRepeat, _channel[i].HdmaTableAddress, _channel[i].InterruptedByHdma,
|
||||
_channel[i].InvertDirection, _channel[i].SrcAddress, _channel[i].SrcBank, _channel[i].TransferMode,
|
||||
_channel[i].TransferSize, _channel[i].UnusedFlag
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "CpuTypes.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class MemoryManager;
|
||||
|
||||
|
@ -28,7 +29,7 @@ struct DmaChannelConfig
|
|||
bool UnusedFlag;
|
||||
};
|
||||
|
||||
class DmaController
|
||||
class DmaController : public ISerializable
|
||||
{
|
||||
private:
|
||||
static constexpr uint8_t _transferByteCount[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
|
@ -57,4 +58,6 @@ public:
|
|||
|
||||
void Write(uint16_t addr, uint8_t value);
|
||||
uint8_t Read(uint16_t addr);
|
||||
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
|
@ -4,6 +4,12 @@
|
|||
#include "MessageManager.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
|
||||
uint32_t EmuSettings::GetVersion()
|
||||
{
|
||||
//0.1.0
|
||||
return 0x00000100;
|
||||
}
|
||||
|
||||
void EmuSettings::ProcessString(string & str, const char ** strPointer)
|
||||
{
|
||||
//Make a copy of the string and keep it (the original pointer will not be valid after the call is over)
|
||||
|
|
|
@ -24,6 +24,8 @@ private:
|
|||
void SetShortcutKey(EmulatorShortcut shortcut, KeyCombination keyCombination, int keySetIndex);
|
||||
|
||||
public:
|
||||
uint32_t GetVersion();
|
||||
|
||||
void SetVideoConfig(VideoConfig config);
|
||||
VideoConfig GetVideoConfig();
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Ppu.h"
|
||||
#include "ControlManager.h"
|
||||
#include "MessageManager.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
|
||||
InternalRegisters::InternalRegisters(shared_ptr<Console> console)
|
||||
|
@ -101,7 +102,7 @@ uint8_t InternalRegisters::Read(uint16_t addr)
|
|||
return (uint8_t)(_controllerData[((addr & 0x0E) - 8) >> 1] >> 8);
|
||||
|
||||
default:
|
||||
MessageManager::DisplayMessage("Debug", "Unimplemented register read: " + HexUtilities::ToHex(addr));
|
||||
MessageManager::Log("[Debug] Unimplemented register read: " + HexUtilities::ToHex(addr));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +160,16 @@ void InternalRegisters::Write(uint16_t addr, uint8_t value)
|
|||
case 0x420D: _enableFastRom = (value & 0x01) != 0; break;
|
||||
|
||||
default:
|
||||
MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
MessageManager::Log("[Debug] Unimplemented register write: " + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InternalRegisters::Serialize(Serializer &s)
|
||||
{
|
||||
s.Stream(
|
||||
_multOperand1, _multOperand2, _multOrRemainderResult, _dividend, _divisor, _divResult, _enableAutoJoypadRead,
|
||||
_enableFastRom, _nmiFlag, _enableNmi, _enableHorizontalIrq, _enableVerticalIrq, _horizontalTimer,
|
||||
_verticalTimer, _ioPortOutput, _controllerData[0], _controllerData[1], _controllerData[2], _controllerData[3]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class Console;
|
||||
|
||||
class InternalRegisters
|
||||
class InternalRegisters : public ISerializable
|
||||
{
|
||||
private:
|
||||
shared_ptr<Console> _console;
|
||||
|
@ -46,4 +47,6 @@ public:
|
|||
|
||||
uint8_t Read(uint16_t addr);
|
||||
void Write(uint16_t addr, uint8_t value);
|
||||
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
|
@ -10,6 +10,7 @@
|
|||
#include "RamHandler.h"
|
||||
#include "MessageManager.h"
|
||||
#include "DebugTypes.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
|
||||
void MemoryManager::Initialize(shared_ptr<Console> console)
|
||||
|
@ -165,7 +166,7 @@ uint8_t MemoryManager::Read(uint32_t addr, MemoryOperationType type)
|
|||
} else {
|
||||
//open bus
|
||||
value = _openBus;
|
||||
MessageManager::DisplayMessage("Debug", "Read - missing handler: $" + HexUtilities::ToHex(addr));
|
||||
MessageManager::Log("[Debug] Read - missing handler: $" + HexUtilities::ToHex(addr));
|
||||
}
|
||||
_console->ProcessCpuRead(addr, value, type);
|
||||
return value;
|
||||
|
@ -181,7 +182,7 @@ uint8_t MemoryManager::ReadDma(uint32_t addr)
|
|||
} else {
|
||||
//open bus
|
||||
value = _openBus;
|
||||
MessageManager::DisplayMessage("Debug", "Read - missing handler: $" + HexUtilities::ToHex(addr));
|
||||
MessageManager::Log("[Debug] Read - missing handler: $" + HexUtilities::ToHex(addr));
|
||||
}
|
||||
_console->ProcessCpuRead(addr, value, MemoryOperationType::DmaRead);
|
||||
return value;
|
||||
|
@ -212,7 +213,7 @@ void MemoryManager::Write(uint32_t addr, uint8_t value, MemoryOperationType type
|
|||
if(_handlers[addr >> 12]) {
|
||||
return _handlers[addr >> 12]->Write(addr, value);
|
||||
} else {
|
||||
MessageManager::DisplayMessage("Debug", "Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
MessageManager::Log("[Debug] Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,7 +225,7 @@ void MemoryManager::WriteDma(uint32_t addr, uint8_t value)
|
|||
if(_handlers[addr >> 12]) {
|
||||
return _handlers[addr >> 12]->Write(addr, value);
|
||||
} else {
|
||||
MessageManager::DisplayMessage("Debug", "Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
MessageManager::Log("[Debug] Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,3 +292,9 @@ int MemoryManager::GetRelativeAddress(AddressInfo &address, int32_t cpuAddress)
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MemoryManager::Serialize(Serializer &s)
|
||||
{
|
||||
s.Stream(_masterClock, _openBus);
|
||||
s.StreamArray(_workRam, MemoryManager::WorkRamSize);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "DebugTypes.h"
|
||||
#include "Ppu.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class IMemoryHandler;
|
||||
class RegisterHandlerA;
|
||||
|
@ -12,7 +12,7 @@ class Console;
|
|||
class Ppu;
|
||||
enum class MemoryOperationType;
|
||||
|
||||
class MemoryManager
|
||||
class MemoryManager : public ISerializable
|
||||
{
|
||||
public:
|
||||
constexpr static uint32_t WorkRamSize = 0x20000;
|
||||
|
@ -65,6 +65,8 @@ public:
|
|||
bool IsWorkRam(uint32_t cpuAddress);
|
||||
AddressInfo GetAbsoluteAddress(uint32_t addr);
|
||||
int GetRelativeAddress(AddressInfo &address, int32_t cpuAddress = -1);
|
||||
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
||||
|
||||
template<uint16_t value>
|
||||
|
|
44
Core/Ppu.cpp
44
Core/Ppu.cpp
|
@ -12,6 +12,7 @@
|
|||
#include "MessageManager.h"
|
||||
#include "EventType.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
Ppu::Ppu(shared_ptr<Console> console)
|
||||
{
|
||||
|
@ -1270,7 +1271,7 @@ uint8_t Ppu::Read(uint16_t addr)
|
|||
}
|
||||
|
||||
default:
|
||||
MessageManager::DisplayMessage("Debug", "Unimplemented register read: " + HexUtilities::ToHex(addr));
|
||||
MessageManager::Log("[Debug] Unimplemented register read: " + HexUtilities::ToHex(addr));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1600,11 +1601,50 @@ void Ppu::Write(uint32_t addr, uint8_t value)
|
|||
break;
|
||||
|
||||
default:
|
||||
MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
MessageManager::Log("[Debug] Unimplemented register write: " + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Ppu::Serialize(Serializer &s)
|
||||
{
|
||||
s.Stream(
|
||||
_forcedVblank, _screenBrightness, _cycle, _scanline, _frameCount, _drawStartX, _drawEndX, _irqDelay, _bgMode,
|
||||
_mode1Bg3Priority, _mainScreenLayers, _subScreenLayers, _vramAddress, _vramIncrementValue, _vramAddressRemapping,
|
||||
_vramAddrIncrementOnSecondReg, _vramReadBuffer, _ppu1OpenBus, _ppu2OpenBus, _cgramAddress, _mosaicSize, _mosaicEnabled,
|
||||
_mosaicStartScanline, _oamMode, _oamBaseAddress, _oamAddressOffset, _oamRamAddress, _enableOamPriority,
|
||||
_internalOamAddress, _oamWriteBuffer, _timeOver, _rangeOver, _hiResMode, _screenInterlace, _objInterlace,
|
||||
_overscanMode, _directColorMode, _colorMathClipMode, _colorMathPreventMode, _colorMathAddSubscreen, _colorMathEnabled,
|
||||
_colorMathSubstractMode, _colorMathHalveResult, _fixedColor, _hvScrollLatchValue, _hScrollLatchValue,
|
||||
_horizontalLocation, _horizontalLocToggle, _verticalLocation, _verticalLocationToggle, _locationLatched,
|
||||
_maskLogic[0], _maskLogic[1], _maskLogic[2], _maskLogic[3], _maskLogic[4], _maskLogic[5],
|
||||
_windowMaskMain[0], _windowMaskMain[1], _windowMaskMain[2], _windowMaskMain[3], _windowMaskMain[4],
|
||||
_windowMaskSub[0], _windowMaskSub[1], _windowMaskSub[2], _windowMaskSub[3], _windowMaskSub[4],
|
||||
_mode7.CenterX, _mode7.CenterY, _mode7.ExtBgEnabled, _mode7.FillWithTile0, _mode7.HorizontalMirroring,
|
||||
_mode7.HScroll, _mode7.LargeMap, _mode7.Matrix[0], _mode7.Matrix[1], _mode7.Matrix[2], _mode7.Matrix[3],
|
||||
_mode7.ValueLatch, _mode7.VerticalMirroring, _mode7.VScroll
|
||||
);
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
s.Stream(
|
||||
_layerConfig[i].ChrAddress, _layerConfig[i].DoubleHeight, _layerConfig[i].DoubleWidth, _layerConfig[i].HScroll,
|
||||
_layerConfig[i].LargeTiles, _layerConfig[i].TilemapAddress, _layerConfig[i].VScroll
|
||||
);
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2; i++) {
|
||||
s.Stream(
|
||||
_window[i].ActiveLayers[0], _window[i].ActiveLayers[1], _window[i].ActiveLayers[2], _window[i].ActiveLayers[3], _window[i].ActiveLayers[4], _window[i].ActiveLayers[5],
|
||||
_window[i].InvertedLayers[0], _window[i].InvertedLayers[1], _window[i].InvertedLayers[2], _window[i].InvertedLayers[3], _window[i].InvertedLayers[4], _window[i].InvertedLayers[5],
|
||||
_window[i].Left, _window[i].Right
|
||||
);
|
||||
}
|
||||
|
||||
s.StreamArray(_vram, Ppu::VideoRamSize);
|
||||
s.StreamArray(_oamRam, Ppu::SpriteRamSize);
|
||||
s.StreamArray(_cgram, Ppu::CgRamSize);
|
||||
}
|
||||
|
||||
/* Everything below this point is used to select the proper arguments for templates */
|
||||
template<uint8_t layerIndex, uint8_t bpp, bool processHighPriority, bool forMainScreen, uint16_t basePaletteOffset, bool hiResMode, bool largeTileWidth, bool largeTileHeight, uint8_t activeWindowCount, bool applyMosaic>
|
||||
void Ppu::RenderTilemap()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "PpuTypes.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class Console;
|
||||
class InternalRegisters;
|
||||
|
@ -20,7 +21,7 @@ struct SpriteInfo
|
|||
uint8_t LargeSprite;
|
||||
};
|
||||
|
||||
class Ppu
|
||||
class Ppu : public ISerializable
|
||||
{
|
||||
public:
|
||||
constexpr static uint32_t SpriteRamSize = 544;
|
||||
|
@ -242,4 +243,6 @@ public:
|
|||
|
||||
uint8_t Read(uint16_t addr);
|
||||
void Write(uint32_t addr, uint8_t value);
|
||||
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
69
Core/RegisterHandlerB.cpp
Normal file
69
Core/RegisterHandlerB.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include "stdafx.h"
|
||||
#include "RegisterHandlerB.h"
|
||||
#include "Console.h"
|
||||
#include "Ppu.h"
|
||||
#include "Spc.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
RegisterHandlerB::RegisterHandlerB(Console * console, Ppu * ppu, Spc * spc, uint8_t * workRam)
|
||||
{
|
||||
_console = console;
|
||||
_ppu = ppu;
|
||||
_spc = spc;
|
||||
_workRam = workRam;
|
||||
_wramPosition = 0;
|
||||
_memoryType = SnesMemoryType::Register;
|
||||
}
|
||||
|
||||
uint8_t RegisterHandlerB::Read(uint32_t addr)
|
||||
{
|
||||
addr &= 0xFFFF;
|
||||
if(addr >= 0x2140 && addr <= 0x217F) {
|
||||
return _spc->Read(addr & 0x03);
|
||||
} else if(addr == 0x2180) {
|
||||
uint8_t value = _workRam[_wramPosition];
|
||||
_console->ProcessWorkRamRead(_wramPosition, value);
|
||||
_wramPosition = (_wramPosition + 1) & 0x1FFFF;
|
||||
return value;
|
||||
} else {
|
||||
return _ppu->Read(addr);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t RegisterHandlerB::Peek(uint32_t addr)
|
||||
{
|
||||
//Avoid side effects for now
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RegisterHandlerB::Write(uint32_t addr, uint8_t value)
|
||||
{
|
||||
addr &= 0xFFFF;
|
||||
if(addr >= 0x2140 && addr <= 0x217F) {
|
||||
return _spc->Write(addr & 0x03, value);
|
||||
} if(addr >= 0x2180 && addr <= 0x2183) {
|
||||
switch(addr & 0xFFFF) {
|
||||
case 0x2180:
|
||||
_console->ProcessWorkRamWrite(_wramPosition, value);
|
||||
_workRam[_wramPosition] = value;
|
||||
_wramPosition = (_wramPosition + 1) & 0x1FFFF;
|
||||
break;
|
||||
|
||||
case 0x2181: _wramPosition = (_wramPosition & 0x1FF00) | value; break;
|
||||
case 0x2182: _wramPosition = (_wramPosition & 0x100FF) | (value << 8); break;
|
||||
case 0x2183: _wramPosition = (_wramPosition & 0xFFFF) | ((value & 0x01) << 16); break;
|
||||
}
|
||||
} else {
|
||||
_ppu->Write(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
AddressInfo RegisterHandlerB::GetAbsoluteAddress(uint32_t address)
|
||||
{
|
||||
return { -1, SnesMemoryType::CpuMemory };
|
||||
}
|
||||
|
||||
void RegisterHandlerB::Serialize(Serializer &s)
|
||||
{
|
||||
s.Stream(_wramPosition);
|
||||
}
|
|
@ -1,75 +1,30 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "IMemoryHandler.h"
|
||||
#include "Console.h"
|
||||
#include "Ppu.h"
|
||||
#include "Spc.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class RegisterHandlerB : public IMemoryHandler
|
||||
class Console;
|
||||
class Ppu;
|
||||
class Spc;
|
||||
|
||||
class RegisterHandlerB : public IMemoryHandler, public ISerializable
|
||||
{
|
||||
private:
|
||||
Console *_console;
|
||||
Ppu *_ppu;
|
||||
Spc *_spc;
|
||||
|
||||
uint8_t *_workRam;
|
||||
uint32_t _wramPosition;
|
||||
|
||||
public:
|
||||
RegisterHandlerB(Console *console, Ppu *ppu, Spc *spc, uint8_t *workRam)
|
||||
{
|
||||
_console = console;
|
||||
_ppu = ppu;
|
||||
_spc = spc;
|
||||
_workRam = workRam;
|
||||
_wramPosition = 0;
|
||||
_memoryType = SnesMemoryType::Register;
|
||||
}
|
||||
RegisterHandlerB(Console *console, Ppu *ppu, Spc *spc, uint8_t *workRam);
|
||||
|
||||
uint8_t Read(uint32_t addr) override
|
||||
{
|
||||
addr &= 0xFFFF;
|
||||
if(addr >= 0x2140 && addr <= 0x217F) {
|
||||
return _spc->Read(addr & 0x03);
|
||||
} else if(addr == 0x2180) {
|
||||
uint8_t value = _workRam[_wramPosition];
|
||||
_console->ProcessWorkRamRead(_wramPosition, value);
|
||||
_wramPosition = (_wramPosition + 1) & 0x1FFFF;
|
||||
return value;
|
||||
} else {
|
||||
return _ppu->Read(addr);
|
||||
}
|
||||
}
|
||||
uint8_t Read(uint32_t addr) override;
|
||||
uint8_t Peek(uint32_t addr) override;
|
||||
void Write(uint32_t addr, uint8_t value) override;
|
||||
|
||||
uint8_t Peek(uint32_t addr) override
|
||||
{
|
||||
//Avoid side effects for now
|
||||
return 0;
|
||||
}
|
||||
AddressInfo GetAbsoluteAddress(uint32_t address) override;
|
||||
|
||||
void Write(uint32_t addr, uint8_t value) override
|
||||
{
|
||||
addr &= 0xFFFF;
|
||||
if(addr >= 0x2140 && addr <= 0x217F) {
|
||||
return _spc->Write(addr & 0x03, value);
|
||||
} if(addr >= 0x2180 && addr <= 0x2183) {
|
||||
switch(addr & 0xFFFF) {
|
||||
case 0x2180:
|
||||
_console->ProcessWorkRamWrite(_wramPosition, value);
|
||||
_workRam[_wramPosition] = value;
|
||||
_wramPosition = (_wramPosition + 1) & 0x1FFFF;
|
||||
break;
|
||||
|
||||
case 0x2181: _wramPosition = (_wramPosition & 0x1FF00) | value; break;
|
||||
case 0x2182: _wramPosition = (_wramPosition & 0x100FF) | (value << 8); break;
|
||||
case 0x2183: _wramPosition = (_wramPosition & 0xFFFF) | ((value & 0x01) << 16); break;
|
||||
}
|
||||
} else {
|
||||
_ppu->Write(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
AddressInfo GetAbsoluteAddress(uint32_t address) override
|
||||
{
|
||||
return { -1, SnesMemoryType::CpuMemory };
|
||||
}
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
1358
Core/SPC_DSP.cpp
1358
Core/SPC_DSP.cpp
File diff suppressed because it is too large
Load diff
186
Core/SPC_DSP.h
186
Core/SPC_DSP.h
|
@ -1,4 +1,4 @@
|
|||
// Fast SNES SPC-700 DSP emulator (about 3x speed of accurate one)
|
||||
// Highly accurate SNES SPC-700 DSP emulator
|
||||
|
||||
// snes_spc 0.9.0
|
||||
#ifndef SPC_DSP_H
|
||||
|
@ -6,12 +6,14 @@
|
|||
|
||||
#include "blargg_common.h"
|
||||
|
||||
extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); }
|
||||
|
||||
class SPC_DSP {
|
||||
public:
|
||||
typedef BOOST::uint8_t uint8_t;
|
||||
|
||||
// Setup
|
||||
|
||||
|
||||
// Initializes DSP and has it use the 64K RAM provided
|
||||
void init( void* ram_64k );
|
||||
|
||||
|
@ -26,14 +28,14 @@ public:
|
|||
int sample_count() const;
|
||||
|
||||
// Emulation
|
||||
|
||||
|
||||
// Resets DSP to power-on state
|
||||
void reset();
|
||||
|
||||
// Emulates pressing reset switch on SNES
|
||||
void soft_reset();
|
||||
|
||||
// Reads/writes DSP registers. For accuracy, you must first call spc_run_dsp()
|
||||
// Reads/writes DSP registers. For accuracy, you must first call run()
|
||||
// to catch the DSP up to present.
|
||||
int read ( int addr ) const;
|
||||
void write( int addr, int data );
|
||||
|
@ -41,23 +43,28 @@ public:
|
|||
// Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks
|
||||
// a pair of samples is be generated.
|
||||
void run( int clock_count );
|
||||
|
||||
|
||||
// Sound control
|
||||
|
||||
// Mutes voices corresponding to non-zero bits in mask (overrides VxVOL with 0).
|
||||
// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
|
||||
// Reduces emulation accuracy.
|
||||
enum { voice_count = 8 };
|
||||
void mute_voices( int mask );
|
||||
|
||||
// If true, prevents channels and global volumes from being phase-negated
|
||||
void disable_surround( bool disable = true );
|
||||
|
||||
// State
|
||||
|
||||
// Resets DSP and uses supplied values to initialize registers
|
||||
enum { register_count = 128 };
|
||||
void load( uint8_t const regs [register_count] );
|
||||
|
||||
// Saves/loads exact emulator state
|
||||
enum { state_size = 640 }; // maximum space needed when saving
|
||||
typedef dsp_copy_func_t copy_func_t;
|
||||
void copy_state( unsigned char** io, copy_func_t );
|
||||
|
||||
// Returns non-zero if new key-on events occurred since last call
|
||||
bool check_kon();
|
||||
|
||||
// DSP register addresses
|
||||
|
||||
// Global registers
|
||||
|
@ -86,6 +93,7 @@ public:
|
|||
enum { extra_size = 16 };
|
||||
sample_t* extra() { return m.extra; }
|
||||
sample_t const* out_pos() const { return m.out; }
|
||||
void disable_surround( bool ) { } // not supported
|
||||
public:
|
||||
BLARGG_DISABLE_NOTHROW
|
||||
|
||||
|
@ -99,18 +107,21 @@ public:
|
|||
struct voice_t
|
||||
{
|
||||
int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling)
|
||||
int* buf_pos; // place in buffer where next samples will be decoded
|
||||
int buf_pos; // place in buffer where next samples will be decoded
|
||||
int interp_pos; // relative fractional position in sample (0x1000 = 1.0)
|
||||
int brr_addr; // address of current BRR block
|
||||
int brr_offset; // current decoding offset in BRR block
|
||||
uint8_t* regs; // pointer to voice's DSP registers
|
||||
int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc.
|
||||
int kon_delay; // KON delay/current setup phase
|
||||
env_mode_t env_mode;
|
||||
int env; // current envelope level
|
||||
int hidden_env; // used by GAIN mode 7, very obscure quirk
|
||||
int volume [2]; // copy of volume from DSP registers, with surround disabled
|
||||
int enabled; // -1 if enabled, 0 if muted
|
||||
uint8_t t_envx_out;
|
||||
};
|
||||
private:
|
||||
enum { brr_block_size = 9 };
|
||||
|
||||
struct state_t
|
||||
{
|
||||
uint8_t regs [register_count];
|
||||
|
@ -122,22 +133,53 @@ private:
|
|||
int every_other_sample; // toggles every sample
|
||||
int kon; // KON value when last checked
|
||||
int noise;
|
||||
int counter;
|
||||
int echo_offset; // offset from ESA in echo buffer
|
||||
int echo_length; // number of bytes that echo_offset will stop at
|
||||
int phase; // next clock cycle to run (0-31)
|
||||
unsigned counters [4];
|
||||
bool kon_check; // set when a new KON occurs
|
||||
|
||||
// Hidden registers also written to when main register is written to
|
||||
int new_kon;
|
||||
uint8_t endx_buf;
|
||||
uint8_t envx_buf;
|
||||
uint8_t outx_buf;
|
||||
|
||||
// Temporary state between clocks
|
||||
|
||||
// read once per sample
|
||||
int t_pmon;
|
||||
int t_non;
|
||||
int t_eon;
|
||||
int t_dir;
|
||||
int t_koff;
|
||||
|
||||
voice_t voices [voice_count];
|
||||
// read a few clocks ahead then used
|
||||
int t_brr_next_addr;
|
||||
int t_adsr0;
|
||||
int t_brr_header;
|
||||
int t_brr_byte;
|
||||
int t_srcn;
|
||||
int t_esa;
|
||||
int t_echo_enabled;
|
||||
|
||||
unsigned* counter_select [32];
|
||||
// internal state that is recalculated every sample
|
||||
int t_dir_addr;
|
||||
int t_pitch;
|
||||
int t_output;
|
||||
int t_looped;
|
||||
int t_echo_ptr;
|
||||
|
||||
// left/right sums
|
||||
int t_main_out [2];
|
||||
int t_echo_out [2];
|
||||
int t_echo_in [2];
|
||||
|
||||
voice_t voices [voice_count];
|
||||
|
||||
// non-emulation state
|
||||
uint8_t* ram; // 64K shared RAM between DSP and SMP
|
||||
int mute_mask;
|
||||
int surround_threshold;
|
||||
sample_t* out;
|
||||
sample_t* out_end;
|
||||
sample_t* out_begin;
|
||||
|
@ -146,10 +188,49 @@ private:
|
|||
state_t m;
|
||||
|
||||
void init_counter();
|
||||
void run_counter( int );
|
||||
void run_counters();
|
||||
unsigned read_counter( int rate );
|
||||
|
||||
int interpolate( voice_t const* v );
|
||||
void run_envelope( voice_t* const v );
|
||||
void decode_brr( voice_t* v );
|
||||
|
||||
void misc_27();
|
||||
void misc_28();
|
||||
void misc_29();
|
||||
void misc_30();
|
||||
|
||||
void voice_output( voice_t const* v, int ch );
|
||||
void voice_V1( voice_t* const );
|
||||
void voice_V2( voice_t* const );
|
||||
void voice_V3( voice_t* const );
|
||||
void voice_V3a( voice_t* const );
|
||||
void voice_V3b( voice_t* const );
|
||||
void voice_V3c( voice_t* const );
|
||||
void voice_V4( voice_t* const );
|
||||
void voice_V5( voice_t* const );
|
||||
void voice_V6( voice_t* const );
|
||||
void voice_V7( voice_t* const );
|
||||
void voice_V8( voice_t* const );
|
||||
void voice_V9( voice_t* const );
|
||||
void voice_V7_V4_V1( voice_t* const );
|
||||
void voice_V8_V5_V2( voice_t* const );
|
||||
void voice_V9_V6_V3( voice_t* const );
|
||||
|
||||
void echo_read( int ch );
|
||||
int echo_output( int ch );
|
||||
void echo_write( int ch );
|
||||
void echo_22();
|
||||
void echo_23();
|
||||
void echo_24();
|
||||
void echo_25();
|
||||
void echo_26();
|
||||
void echo_27();
|
||||
void echo_28();
|
||||
void echo_29();
|
||||
void echo_30();
|
||||
|
||||
void soft_reset_common();
|
||||
void write_outline( int addr, int data );
|
||||
void update_voice_vol( int addr );
|
||||
};
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -162,51 +243,62 @@ inline int SPC_DSP::read( int addr ) const
|
|||
return m.regs [addr];
|
||||
}
|
||||
|
||||
inline void SPC_DSP::update_voice_vol( int addr )
|
||||
{
|
||||
int l = (int8_t) m.regs [addr + v_voll];
|
||||
int r = (int8_t) m.regs [addr + v_volr];
|
||||
|
||||
if ( l * r < m.surround_threshold )
|
||||
{
|
||||
// signs differ, so negate those that are negative
|
||||
l ^= l >> 7;
|
||||
r ^= r >> 7;
|
||||
}
|
||||
|
||||
voice_t& v = m.voices [addr >> 4];
|
||||
int enabled = v.enabled;
|
||||
v.volume [0] = l & enabled;
|
||||
v.volume [1] = r & enabled;
|
||||
}
|
||||
|
||||
inline void SPC_DSP::write( int addr, int data )
|
||||
{
|
||||
assert( (unsigned) addr < register_count );
|
||||
|
||||
m.regs [addr] = (uint8_t) data;
|
||||
int low = addr & 0x0F;
|
||||
if ( low < 0x2 ) // voice volumes
|
||||
{
|
||||
update_voice_vol( low ^ addr );
|
||||
}
|
||||
else if ( low == 0xC )
|
||||
switch ( addr & 0x0F )
|
||||
{
|
||||
case v_envx:
|
||||
m.envx_buf = (uint8_t) data;
|
||||
break;
|
||||
|
||||
case v_outx:
|
||||
m.outx_buf = (uint8_t) data;
|
||||
break;
|
||||
|
||||
case 0x0C:
|
||||
if ( addr == r_kon )
|
||||
m.new_kon = (uint8_t) data;
|
||||
|
||||
if ( addr == r_endx ) // always cleared, regardless of data written
|
||||
{
|
||||
m.endx_buf = 0;
|
||||
m.regs [r_endx] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SPC_DSP::disable_surround( bool disable )
|
||||
inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; }
|
||||
|
||||
inline bool SPC_DSP::check_kon()
|
||||
{
|
||||
m.surround_threshold = disable ? 0 : -0x4000;
|
||||
bool old = m.kon_check;
|
||||
m.kon_check = 0;
|
||||
return old;
|
||||
}
|
||||
|
||||
#define SPC_NO_COPY_STATE_FUNCS 1
|
||||
#if !SPC_NO_COPY_STATE_FUNCS
|
||||
|
||||
#define SPC_LESS_ACCURATE 1
|
||||
class SPC_State_Copier {
|
||||
SPC_DSP::copy_func_t func;
|
||||
unsigned char** buf;
|
||||
public:
|
||||
SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; }
|
||||
void copy( void* state, size_t size );
|
||||
int copy_int( int state, int size );
|
||||
void skip( int count );
|
||||
void extra();
|
||||
};
|
||||
|
||||
#define SPC_COPY( type, state )\
|
||||
{\
|
||||
state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\
|
||||
assert( (BOOST::type) state == state );\
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
250
Core/SaveStateManager.cpp
Normal file
250
Core/SaveStateManager.cpp
Normal file
|
@ -0,0 +1,250 @@
|
|||
#include "stdafx.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/ZipWriter.h"
|
||||
#include "../Utilities/ZipReader.h"
|
||||
#include "SaveStateManager.h"
|
||||
#include "MessageManager.h"
|
||||
#include "Console.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "VideoDecoder.h"
|
||||
#include "BaseCartridge.h"
|
||||
|
||||
SaveStateManager::SaveStateManager(shared_ptr<Console> console)
|
||||
{
|
||||
_console = console;
|
||||
_lastIndex = 1;
|
||||
}
|
||||
|
||||
string SaveStateManager::GetStateFilepath(int stateIndex)
|
||||
{
|
||||
string romPath = _console->GetRomInfo().RomPath;
|
||||
string folder = FolderUtilities::GetSaveStateFolder();
|
||||
string filename = FolderUtilities::GetFilename(romPath, false) + "_" + std::to_string(stateIndex) + ".mst";
|
||||
return FolderUtilities::CombinePath(folder, filename);
|
||||
}
|
||||
|
||||
uint64_t SaveStateManager::GetStateInfo(int stateIndex)
|
||||
{
|
||||
string filepath = SaveStateManager::GetStateFilepath(stateIndex);
|
||||
ifstream file(filepath, ios::in | ios::binary);
|
||||
|
||||
if(file) {
|
||||
file.close();
|
||||
return FolderUtilities::GetFileModificationTime(filepath);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SaveStateManager::MoveToNextSlot()
|
||||
{
|
||||
_lastIndex = (_lastIndex % MaxIndex) + 1;
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateSlotSelected", std::to_string(_lastIndex));
|
||||
}
|
||||
|
||||
void SaveStateManager::MoveToPreviousSlot()
|
||||
{
|
||||
_lastIndex = (_lastIndex == 1 ? SaveStateManager::MaxIndex : (_lastIndex - 1));
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateSlotSelected", std::to_string(_lastIndex));
|
||||
}
|
||||
|
||||
void SaveStateManager::SaveState()
|
||||
{
|
||||
SaveState(_lastIndex);
|
||||
}
|
||||
|
||||
bool SaveStateManager::LoadState()
|
||||
{
|
||||
return LoadState(_lastIndex);
|
||||
}
|
||||
|
||||
void SaveStateManager::GetSaveStateHeader(ostream &stream)
|
||||
{
|
||||
uint32_t emuVersion = _console->GetSettings()->GetVersion();
|
||||
uint32_t formatVersion = SaveStateManager::FileFormatVersion;
|
||||
stream.write("MST", 3);
|
||||
stream.write((char*)&emuVersion, sizeof(emuVersion));
|
||||
stream.write((char*)&formatVersion, sizeof(uint32_t));
|
||||
|
||||
string sha1Hash = _console->GetCartridge()->GetSha1Hash();
|
||||
stream.write(sha1Hash.c_str(), sha1Hash.size());
|
||||
|
||||
RomInfo romInfo = _console->GetCartridge()->GetRomInfo();
|
||||
string romName = FolderUtilities::GetFilename(romInfo.RomPath, true);
|
||||
uint32_t nameLength = (uint32_t)romName.size();
|
||||
stream.write((char*)&nameLength, sizeof(uint32_t));
|
||||
stream.write(romName.c_str(), romName.size());
|
||||
}
|
||||
|
||||
void SaveStateManager::SaveState(ostream &stream)
|
||||
{
|
||||
GetSaveStateHeader(stream);
|
||||
_console->Serialize(stream);
|
||||
}
|
||||
|
||||
bool SaveStateManager::SaveState(string filepath)
|
||||
{
|
||||
ofstream file(filepath, ios::out | ios::binary);
|
||||
|
||||
if(file) {
|
||||
auto lock = _console->AcquireLock();
|
||||
SaveState(file);
|
||||
file.close();
|
||||
|
||||
//TODO LUA
|
||||
/*shared_ptr<Debugger> debugger = _console->GetDebugger(false);
|
||||
if(debugger) {
|
||||
debugger->ProcessEvent(EventType::StateSaved);
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SaveStateManager::SaveState(int stateIndex, bool displayMessage)
|
||||
{
|
||||
string filepath = SaveStateManager::GetStateFilepath(stateIndex);
|
||||
if(SaveState(filepath)) {
|
||||
if(displayMessage) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateSaved", std::to_string(stateIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SaveStateManager::LoadState(istream &stream, bool hashCheckRequired)
|
||||
{
|
||||
char header[3];
|
||||
stream.read(header, 3);
|
||||
if(memcmp(header, "MST", 3) == 0) {
|
||||
uint32_t emuVersion, fileFormatVersion;
|
||||
|
||||
stream.read((char*)&emuVersion, sizeof(emuVersion));
|
||||
if(emuVersion > _console->GetSettings()->GetVersion()) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateNewerVersion");
|
||||
return false;
|
||||
}
|
||||
|
||||
stream.read((char*)&fileFormatVersion, sizeof(fileFormatVersion));
|
||||
if(fileFormatVersion < 1) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateIncompatibleVersion");
|
||||
return false;
|
||||
} else {
|
||||
char hash[41] = {};
|
||||
stream.read(hash, 40);
|
||||
|
||||
uint32_t nameLength = 0;
|
||||
stream.read((char*)&nameLength, sizeof(uint32_t));
|
||||
|
||||
vector<char> nameBuffer(nameLength);
|
||||
stream.read(nameBuffer.data(), nameBuffer.size());
|
||||
string romName(nameBuffer.data(), nameLength);
|
||||
|
||||
//TODO
|
||||
/*shared_ptr<BaseCartridge> cartridge = _console->GetCartridge();
|
||||
if(cartridge) {
|
||||
string sha1Hash = cartridge->GetSha1Hash();
|
||||
bool gameLoaded = !sha1Hash.empty();
|
||||
if(sha1Hash != string(hash)) {
|
||||
//CRC doesn't match
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
//Stop any movie that might have been playing/recording if a state is loaded
|
||||
//(Note: Loading a state is disabled in the UI while a movie is playing/recording)
|
||||
//TODO MovieManager::Stop();
|
||||
|
||||
_console->Deserialize(stream, fileFormatVersion);
|
||||
|
||||
return true;
|
||||
}
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateInvalidFile");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SaveStateManager::LoadState(string filepath, bool hashCheckRequired)
|
||||
{
|
||||
ifstream file(filepath, ios::in | ios::binary);
|
||||
bool result = false;
|
||||
|
||||
if(file.good()) {
|
||||
auto lock = _console->AcquireLock();
|
||||
if(LoadState(file, hashCheckRequired)) {
|
||||
result = true;
|
||||
}
|
||||
file.close();
|
||||
|
||||
//TODO LUA
|
||||
/*shared_ptr<Debugger> debugger = _console->GetDebugger(false);
|
||||
if(debugger) {
|
||||
debugger->ProcessEvent(EventType::StateLoaded);
|
||||
}*/
|
||||
} else {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateEmpty");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SaveStateManager::LoadState(int stateIndex)
|
||||
{
|
||||
string filepath = SaveStateManager::GetStateFilepath(stateIndex);
|
||||
if(LoadState(filepath, false)) {
|
||||
MessageManager::DisplayMessage("SaveStates", "SaveStateLoaded", std::to_string(stateIndex));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO
|
||||
/*
|
||||
void SaveStateManager::SaveRecentGame(string romName, string romPath, string patchPath)
|
||||
{
|
||||
if(!_console->GetSettings()->CheckFlag(EmulationFlags::ConsoleMode) && !_console->GetSettings()->CheckFlag(EmulationFlags::DisableGameSelectionScreen) && _console->GetRomInfo().Format != RomFormat::Nsf) {
|
||||
string filename = FolderUtilities::GetFilename(_console->GetRomInfo().RomName, false) + ".rgd";
|
||||
ZipWriter writer;
|
||||
writer.Initialize(FolderUtilities::CombinePath(FolderUtilities::GetRecentGamesFolder(), filename));
|
||||
|
||||
std::stringstream pngStream;
|
||||
_console->GetVideoDecoder()->TakeScreenshot(pngStream);
|
||||
writer.AddFile(pngStream, "Screenshot.png");
|
||||
|
||||
std::stringstream stateStream;
|
||||
SaveStateManager::SaveState(stateStream);
|
||||
writer.AddFile(stateStream, "Savestate.mst");
|
||||
|
||||
std::stringstream romInfoStream;
|
||||
romInfoStream << romName << std::endl;
|
||||
romInfoStream << romPath << std::endl;
|
||||
romInfoStream << patchPath << std::endl;
|
||||
writer.AddFile(romInfoStream, "RomInfo.txt");
|
||||
writer.Save();
|
||||
}
|
||||
}
|
||||
|
||||
void SaveStateManager::LoadRecentGame(string filename, bool resetGame)
|
||||
{
|
||||
ZipReader reader;
|
||||
reader.LoadArchive(filename);
|
||||
|
||||
stringstream romInfoStream, stateStream;
|
||||
reader.GetStream("RomInfo.txt", romInfoStream);
|
||||
reader.GetStream("Savestate.mst", stateStream);
|
||||
|
||||
string romName, romPath, patchPath;
|
||||
std::getline(romInfoStream, romName);
|
||||
std::getline(romInfoStream, romPath);
|
||||
std::getline(romInfoStream, patchPath);
|
||||
|
||||
_console->Pause();
|
||||
try {
|
||||
if(_console->Initialize(romPath, patchPath)) {
|
||||
if(!resetGame) {
|
||||
SaveStateManager::LoadState(stateStream, false);
|
||||
}
|
||||
}
|
||||
} catch(std::exception ex) {
|
||||
_console->Stop();
|
||||
}
|
||||
_console->Resume();
|
||||
}
|
||||
*/
|
40
Core/SaveStateManager.h
Normal file
40
Core/SaveStateManager.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
class Console;
|
||||
|
||||
class SaveStateManager
|
||||
{
|
||||
private:
|
||||
static constexpr uint32_t MaxIndex = 10;
|
||||
|
||||
atomic<uint32_t> _lastIndex;
|
||||
shared_ptr<Console> _console;
|
||||
|
||||
string GetStateFilepath(int stateIndex);
|
||||
|
||||
public:
|
||||
static constexpr uint32_t FileFormatVersion = 1;
|
||||
|
||||
SaveStateManager(shared_ptr<Console> console);
|
||||
|
||||
uint64_t GetStateInfo(int stateIndex);
|
||||
|
||||
void SaveState();
|
||||
bool LoadState();
|
||||
|
||||
void GetSaveStateHeader(ostream & stream);
|
||||
|
||||
void SaveState(ostream &stream);
|
||||
bool SaveState(string filepath);
|
||||
void SaveState(int stateIndex, bool displayMessage = true);
|
||||
bool LoadState(istream &stream, bool hashCheckRequired = true);
|
||||
bool LoadState(string filepath, bool hashCheckRequired = true);
|
||||
bool LoadState(int stateIndex);
|
||||
|
||||
//void SaveRecentGame(string romName, string romPath, string patchPath);
|
||||
//void LoadRecentGame(string filename, bool resetGame);
|
||||
|
||||
void MoveToNextSlot();
|
||||
void MoveToPreviousSlot();
|
||||
};
|
|
@ -316,6 +316,7 @@ enum class EmulatorShortcut
|
|||
LoadStateSlot8,
|
||||
LoadStateSlot9,
|
||||
LoadStateSlot10,
|
||||
LoadStateSlotAuto,
|
||||
LoadStateFromFile,
|
||||
|
||||
OpenFile,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "BaseControlDevice.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
class SnesController : public BaseControlDevice
|
||||
{
|
||||
|
@ -52,13 +53,11 @@ protected:
|
|||
((uint8_t)IsPressed(Buttons::R) << 11);
|
||||
}
|
||||
|
||||
//TODO
|
||||
/*
|
||||
void StreamState(bool saving) override
|
||||
void Serialize(Serializer &s) override
|
||||
{
|
||||
BaseControlDevice::StreamState(saving);
|
||||
Stream(_stateBuffer);
|
||||
}*/
|
||||
BaseControlDevice::Serialize(s);
|
||||
s.Stream(_stateBuffer);
|
||||
}
|
||||
|
||||
void RefreshStateBuffer() override
|
||||
{
|
||||
|
|
28
Core/Spc.cpp
28
Core/Spc.cpp
|
@ -4,6 +4,7 @@
|
|||
#include "Console.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "SoundMixer.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
Spc::Spc(shared_ptr<Console> console, vector<uint8_t> &spcRomData)
|
||||
{
|
||||
|
@ -55,3 +56,30 @@ void Spc::ProcessEndFrame()
|
|||
uint64_t remainder = (_console->GetMemoryManager()->GetMasterClock() - _startFrameMasterClock) * 1024000 % 21477000 / 1024000;
|
||||
_startFrameMasterClock = _console->GetMemoryManager()->GetMasterClock() - remainder;
|
||||
}
|
||||
|
||||
void Spc::Serialize(Serializer &s)
|
||||
{
|
||||
s.Stream(_startFrameMasterClock);
|
||||
|
||||
uint8_t state[SNES_SPC::state_size];
|
||||
memset(state, 0, SNES_SPC::state_size);
|
||||
if(s.IsSaving()) {
|
||||
uint8_t *out = state;
|
||||
_spc->copy_state(&out, [](uint8_t** output, void* in, size_t size) {
|
||||
memcpy(*output, in, size);
|
||||
*output += size;
|
||||
});
|
||||
|
||||
s.StreamArray(state, SNES_SPC::state_size);
|
||||
} else {
|
||||
s.StreamArray(state, SNES_SPC::state_size);
|
||||
|
||||
uint8_t *in = state;
|
||||
_spc->copy_state(&in, [](uint8_t** input, void* output, size_t size) {
|
||||
memcpy(output, *input, size);
|
||||
*input += size;
|
||||
});
|
||||
|
||||
_spc->set_output(_soundBuffer, Spc::SampleBufferSize >> 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
|
||||
class Console;
|
||||
struct SNES_SPC;
|
||||
|
||||
class Spc
|
||||
class Spc : public ISerializable
|
||||
{
|
||||
private:
|
||||
static constexpr int SampleBufferSize = 0x100000;
|
||||
|
@ -25,4 +26,6 @@ public:
|
|||
void Write(uint32_t addr, uint8_t value);
|
||||
|
||||
void ProcessEndFrame();
|
||||
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
|
@ -1,7 +1,9 @@
|
|||
#include "stdafx.h"
|
||||
#include "../Core/Console.h"
|
||||
#include "../Core/EmuSettings.h"
|
||||
#include "../Core/VideoDecoder.h"
|
||||
#include "../Core/MessageManager.h"
|
||||
#include "../Core/SaveStateManager.h"
|
||||
#include "../Core/INotificationListener.h"
|
||||
#include "../Core/KeyManager.h"
|
||||
#include "../Core/ShortcutKeyHandler.h"
|
||||
|
@ -36,7 +38,7 @@ extern "C" {
|
|||
return true;
|
||||
}
|
||||
|
||||
DllExport uint32_t __stdcall GetMesenVersion() { return 0x00000100; }
|
||||
DllExport uint32_t __stdcall GetMesenVersion() { return _console->GetSettings()->GetVersion(); }
|
||||
|
||||
DllExport void __stdcall InitDll()
|
||||
{
|
||||
|
@ -157,6 +159,12 @@ extern "C" {
|
|||
|
||||
DllExport void __stdcall WriteLogEntry(char* message) { MessageManager::Log(message); }
|
||||
|
||||
DllExport void __stdcall SaveState(uint32_t stateIndex) { _console->GetSaveStateManager()->SaveState(stateIndex); }
|
||||
DllExport void __stdcall LoadState(uint32_t stateIndex) { _console->GetSaveStateManager()->LoadState(stateIndex); }
|
||||
DllExport void __stdcall SaveStateFile(char* filepath) { _console->GetSaveStateManager()->SaveState(filepath); }
|
||||
DllExport void __stdcall LoadStateFile(char* filepath) { _console->GetSaveStateManager()->LoadState(filepath); }
|
||||
DllExport int64_t __stdcall GetStateInfo(uint32_t stateIndex) { return _console->GetSaveStateManager()->GetStateInfo(stateIndex); }
|
||||
|
||||
DllExport void __stdcall PgoRunTest(vector<string> testRoms, bool enableDebugger)
|
||||
{
|
||||
FolderUtilities::SetHomeFolder("../PGOMesenHome");
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace Mesen.GUI.Config
|
|||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.LoadStateSlot5, new KeyCombination() { Key1 = InputApi.GetKeyCode("F5") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.LoadStateSlot6, new KeyCombination() { Key1 = InputApi.GetKeyCode("F6") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.LoadStateSlot7, new KeyCombination() { Key1 = InputApi.GetKeyCode("F7") }));
|
||||
//TODO ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.LoadStateSlotAuto, new KeyCombination() { Key1 = InputApi.GetKeyCode("F8") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.LoadStateSlotAuto, new KeyCombination() { Key1 = InputApi.GetKeyCode("F8") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.LoadStateFromFile, new KeyCombination() { Key1 = InputApi.GetKeyCode("Ctrl"), Key2 = InputApi.GetKeyCode("L") }));
|
||||
|
||||
ShortcutKeys2 = new List<ShortcutKeyInfo>();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Mesen.GUI.Forms;
|
||||
using Mesen.GUI.Emulation;
|
||||
using Mesen.GUI.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
|
@ -73,6 +73,7 @@ namespace Mesen.GUI.Config.Shortcuts
|
|||
LoadStateSlot8,
|
||||
LoadStateSlot9,
|
||||
LoadStateSlot10,
|
||||
LoadStateSlotAuto,
|
||||
LoadStateFromFile,
|
||||
|
||||
OpenFile
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Mesen.GUI
|
||||
{
|
||||
public static class EmuRunner
|
||||
{
|
||||
private static Thread _emuThread = null;
|
||||
|
||||
public static void LoadRom(ResourcePath romPath, ResourcePath? patchPath = null)
|
||||
{
|
||||
if(!frmSelectRom.SelectRom(ref romPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EmuApi.LoadRom(romPath, patchPath);
|
||||
|
||||
ConfigManager.Config.RecentFiles.AddRecentFile(romPath, patchPath);
|
||||
|
||||
_emuThread = new Thread(() => {
|
||||
EmuApi.Run();
|
||||
});
|
||||
_emuThread.Start();
|
||||
}
|
||||
|
||||
public static bool IsRunning()
|
||||
{
|
||||
return _emuThread != null;
|
||||
}
|
||||
|
||||
public static void SaveState(uint slot)
|
||||
{
|
||||
if(_emuThread != null) {
|
||||
//EmuApi.SaveState(slot);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadState(uint slot)
|
||||
{
|
||||
if(_emuThread != null) {
|
||||
//EmuApi.LoadState(slot);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadStateFromFile()
|
||||
{
|
||||
if(_emuThread != null) {
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.InitialDirectory = ConfigManager.SaveStateFolder;
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterSavestate"));
|
||||
if(ofd.ShowDialog(Application.OpenForms[0]) == DialogResult.OK) {
|
||||
//EmuApi.LoadStateFile(ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveStateToFile()
|
||||
{
|
||||
if(_emuThread != null) {
|
||||
using(SaveFileDialog sfd = new SaveFileDialog()) {
|
||||
sfd.InitialDirectory = ConfigManager.SaveStateFolder;
|
||||
//TODO
|
||||
//sfd.FileName = EmuApi.GetRomInfo().GetRomName() + ".mst";
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterSavestate"));
|
||||
if(sfd.ShowDialog(Application.OpenForms[0]) == DialogResult.OK) {
|
||||
//EmuApi.SaveStateFile(sfd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
UI/Emulation/EmuRunner.cs
Normal file
38
UI/Emulation/EmuRunner.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Mesen.GUI.Emulation
|
||||
{
|
||||
public static class EmuRunner
|
||||
{
|
||||
private static Thread _emuThread = null;
|
||||
|
||||
public static void LoadRom(ResourcePath romPath, ResourcePath? patchPath = null)
|
||||
{
|
||||
if(!frmSelectRom.SelectRom(ref romPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EmuApi.LoadRom(romPath, patchPath);
|
||||
|
||||
ConfigManager.Config.RecentFiles.AddRecentFile(romPath, patchPath);
|
||||
|
||||
_emuThread = new Thread(() => {
|
||||
EmuApi.Run();
|
||||
});
|
||||
_emuThread.Start();
|
||||
}
|
||||
|
||||
public static bool IsRunning()
|
||||
{
|
||||
return _emuThread != null;
|
||||
}
|
||||
}
|
||||
}
|
116
UI/Emulation/SaveStateManager.cs
Normal file
116
UI/Emulation/SaveStateManager.cs
Normal file
|
@ -0,0 +1,116 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Config.Shortcuts;
|
||||
using Mesen.GUI.Forms;
|
||||
using Mesen.GUI.Properties;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Mesen.GUI.Emulation
|
||||
{
|
||||
public static class SaveStateManager
|
||||
{
|
||||
private const int NumberOfSaveSlots = 10;
|
||||
|
||||
public static void UpdateStateMenu(ToolStripMenuItem menu, bool forSave)
|
||||
{
|
||||
for(uint i = 1; i <= NumberOfSaveSlots + (forSave ? 0 : 1); i++) {
|
||||
Int64 fileTime = EmuApi.GetStateInfo(i);
|
||||
string label;
|
||||
bool isAutoSaveSlot = i == NumberOfSaveSlots + 1;
|
||||
string slotName = isAutoSaveSlot ? "Auto" : i.ToString();
|
||||
|
||||
if(fileTime == 0) {
|
||||
label = slotName + ". " + ResourceHelper.GetMessage("EmptyState");
|
||||
} else {
|
||||
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(fileTime).ToLocalTime();
|
||||
label = slotName + ". " + dateTime.ToShortDateString() + " " + dateTime.ToShortTimeString();
|
||||
}
|
||||
|
||||
if(i == NumberOfSaveSlots + 1) {
|
||||
//Autosave slot (load only)
|
||||
menu.DropDownItems[NumberOfSaveSlots + 1].Text = label;
|
||||
} else {
|
||||
menu.DropDownItems[(int)i - 1].Text = label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void InitializeStateMenu(ToolStripMenuItem menu, bool forSave, ShortcutHandler shortcutHandler)
|
||||
{
|
||||
Action<uint> addSaveStateInfo = (i) => {
|
||||
ToolStripMenuItem item = new ToolStripMenuItem();
|
||||
menu.DropDownItems.Add(item);
|
||||
|
||||
if(forSave) {
|
||||
shortcutHandler.BindShortcut(item, (EmulatorShortcut)((int)EmulatorShortcut.SaveStateSlot1 + i - 1));
|
||||
} else {
|
||||
shortcutHandler.BindShortcut(item, (EmulatorShortcut)((int)EmulatorShortcut.LoadStateSlot1 + i - 1));
|
||||
}
|
||||
};
|
||||
|
||||
for(uint i = 1; i <= NumberOfSaveSlots; i++) {
|
||||
addSaveStateInfo(i);
|
||||
}
|
||||
|
||||
if(!forSave) {
|
||||
menu.DropDownItems.Add("-");
|
||||
addSaveStateInfo(NumberOfSaveSlots + 1);
|
||||
menu.DropDownItems.Add("-");
|
||||
ToolStripMenuItem loadFromFile = new ToolStripMenuItem(ResourceHelper.GetMessage("LoadFromFile"), Resources.Folder);
|
||||
menu.DropDownItems.Add(loadFromFile);
|
||||
shortcutHandler.BindShortcut(loadFromFile, EmulatorShortcut.LoadStateFromFile);
|
||||
} else {
|
||||
menu.DropDownItems.Add("-");
|
||||
ToolStripMenuItem saveToFile = new ToolStripMenuItem(ResourceHelper.GetMessage("SaveToFile"), Resources.SaveFloppy);
|
||||
menu.DropDownItems.Add(saveToFile);
|
||||
shortcutHandler.BindShortcut(saveToFile, EmulatorShortcut.SaveStateToFile);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveState(uint slot)
|
||||
{
|
||||
if(EmuRunner.IsRunning()) {
|
||||
EmuApi.SaveState(slot);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadState(uint slot)
|
||||
{
|
||||
if(EmuRunner.IsRunning()) {
|
||||
EmuApi.LoadState(slot);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadStateFromFile()
|
||||
{
|
||||
if(EmuRunner.IsRunning()) {
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.InitialDirectory = ConfigManager.SaveStateFolder;
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterSavestate"));
|
||||
if(ofd.ShowDialog(Application.OpenForms[0]) == DialogResult.OK) {
|
||||
EmuApi.LoadStateFile(ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveStateToFile()
|
||||
{
|
||||
if(EmuRunner.IsRunning()) {
|
||||
using(SaveFileDialog sfd = new SaveFileDialog()) {
|
||||
sfd.InitialDirectory = ConfigManager.SaveStateFolder;
|
||||
//TODO
|
||||
//sfd.FileName = EmuApi.GetRomInfo().GetRomName() + ".mst";
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterSavestate"));
|
||||
if(sfd.ShowDialog(Application.OpenForms[0]) == DialogResult.OK) {
|
||||
EmuApi.SaveStateFile(sfd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Config.Shortcuts;
|
||||
using Mesen.GUI.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
@ -8,7 +9,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Mesen.GUI.Forms
|
||||
namespace Mesen.GUI.Emulation
|
||||
{
|
||||
public class ShortcutHandler
|
||||
{
|
||||
|
@ -92,29 +93,30 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
case EmulatorShortcut.TakeScreenshot: EmuApi.TakeScreenshot(); break;
|
||||
|
||||
case EmulatorShortcut.LoadStateFromFile: EmuRunner.LoadStateFromFile(); break;
|
||||
case EmulatorShortcut.SaveStateToFile: EmuRunner.SaveStateToFile(); break;
|
||||
case EmulatorShortcut.LoadStateFromFile: SaveStateManager.LoadStateFromFile(); break;
|
||||
case EmulatorShortcut.SaveStateToFile: SaveStateManager.SaveStateToFile(); break;
|
||||
|
||||
case EmulatorShortcut.SaveStateSlot1: EmuRunner.SaveState(1); break;
|
||||
case EmulatorShortcut.SaveStateSlot2: EmuRunner.SaveState(2); break;
|
||||
case EmulatorShortcut.SaveStateSlot3: EmuRunner.SaveState(3); break;
|
||||
case EmulatorShortcut.SaveStateSlot4: EmuRunner.SaveState(4); break;
|
||||
case EmulatorShortcut.SaveStateSlot5: EmuRunner.SaveState(5); break;
|
||||
case EmulatorShortcut.SaveStateSlot6: EmuRunner.SaveState(6); break;
|
||||
case EmulatorShortcut.SaveStateSlot7: EmuRunner.SaveState(7); break;
|
||||
case EmulatorShortcut.SaveStateSlot8: EmuRunner.SaveState(8); break;
|
||||
case EmulatorShortcut.SaveStateSlot9: EmuRunner.SaveState(9); break;
|
||||
case EmulatorShortcut.SaveStateSlot10: EmuRunner.SaveState(10); break;
|
||||
case EmulatorShortcut.LoadStateSlot1: EmuRunner.LoadState(1); break;
|
||||
case EmulatorShortcut.LoadStateSlot2: EmuRunner.LoadState(2); break;
|
||||
case EmulatorShortcut.LoadStateSlot3: EmuRunner.LoadState(3); break;
|
||||
case EmulatorShortcut.LoadStateSlot4: EmuRunner.LoadState(4); break;
|
||||
case EmulatorShortcut.LoadStateSlot5: EmuRunner.LoadState(5); break;
|
||||
case EmulatorShortcut.LoadStateSlot6: EmuRunner.LoadState(6); break;
|
||||
case EmulatorShortcut.LoadStateSlot7: EmuRunner.LoadState(7); break;
|
||||
case EmulatorShortcut.LoadStateSlot8: EmuRunner.LoadState(8); break;
|
||||
case EmulatorShortcut.LoadStateSlot9: EmuRunner.LoadState(9); break;
|
||||
case EmulatorShortcut.LoadStateSlot10: EmuRunner.LoadState(10); break;
|
||||
case EmulatorShortcut.SaveStateSlot1: SaveStateManager.SaveState(1); break;
|
||||
case EmulatorShortcut.SaveStateSlot2: SaveStateManager.SaveState(2); break;
|
||||
case EmulatorShortcut.SaveStateSlot3: SaveStateManager.SaveState(3); break;
|
||||
case EmulatorShortcut.SaveStateSlot4: SaveStateManager.SaveState(4); break;
|
||||
case EmulatorShortcut.SaveStateSlot5: SaveStateManager.SaveState(5); break;
|
||||
case EmulatorShortcut.SaveStateSlot6: SaveStateManager.SaveState(6); break;
|
||||
case EmulatorShortcut.SaveStateSlot7: SaveStateManager.SaveState(7); break;
|
||||
case EmulatorShortcut.SaveStateSlot8: SaveStateManager.SaveState(8); break;
|
||||
case EmulatorShortcut.SaveStateSlot9: SaveStateManager.SaveState(9); break;
|
||||
case EmulatorShortcut.SaveStateSlot10: SaveStateManager.SaveState(10); break;
|
||||
case EmulatorShortcut.LoadStateSlot1: SaveStateManager.LoadState(1); break;
|
||||
case EmulatorShortcut.LoadStateSlot2: SaveStateManager.LoadState(2); break;
|
||||
case EmulatorShortcut.LoadStateSlot3: SaveStateManager.LoadState(3); break;
|
||||
case EmulatorShortcut.LoadStateSlot4: SaveStateManager.LoadState(4); break;
|
||||
case EmulatorShortcut.LoadStateSlot5: SaveStateManager.LoadState(5); break;
|
||||
case EmulatorShortcut.LoadStateSlot6: SaveStateManager.LoadState(6); break;
|
||||
case EmulatorShortcut.LoadStateSlot7: SaveStateManager.LoadState(7); break;
|
||||
case EmulatorShortcut.LoadStateSlot8: SaveStateManager.LoadState(8); break;
|
||||
case EmulatorShortcut.LoadStateSlot9: SaveStateManager.LoadState(9); break;
|
||||
case EmulatorShortcut.LoadStateSlot10: SaveStateManager.LoadState(10); break;
|
||||
case EmulatorShortcut.LoadStateSlotAuto: SaveStateManager.LoadState(11); break;
|
||||
}
|
||||
|
||||
//TODO
|
64
UI/Forms/frmMain.Designer.cs
generated
64
UI/Forms/frmMain.Designer.cs
generated
|
@ -32,6 +32,9 @@
|
|||
this.mnuFile = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuOpen = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuSaveState = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuLoadState = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuRecentFiles = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuExit = new System.Windows.Forms.ToolStripMenuItem();
|
||||
|
@ -152,6 +155,9 @@
|
|||
this.mnuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuOpen,
|
||||
this.toolStripMenuItem2,
|
||||
this.mnuSaveState,
|
||||
this.mnuLoadState,
|
||||
this.toolStripMenuItem10,
|
||||
this.mnuRecentFiles,
|
||||
this.toolStripMenuItem6,
|
||||
this.mnuExit});
|
||||
|
@ -165,30 +171,49 @@
|
|||
this.mnuOpen.Image = global::Mesen.GUI.Properties.Resources.Folder;
|
||||
this.mnuOpen.Name = "mnuOpen";
|
||||
this.mnuOpen.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
|
||||
this.mnuOpen.Size = new System.Drawing.Size(146, 22);
|
||||
this.mnuOpen.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuOpen.Text = "Open";
|
||||
//
|
||||
// toolStripMenuItem2
|
||||
//
|
||||
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
|
||||
this.toolStripMenuItem2.Size = new System.Drawing.Size(143, 6);
|
||||
this.toolStripMenuItem2.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// mnuSaveState
|
||||
//
|
||||
this.mnuSaveState.Name = "mnuSaveState";
|
||||
this.mnuSaveState.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuSaveState.Text = "Save State";
|
||||
this.mnuSaveState.DropDownOpening += new System.EventHandler(this.mnuSaveState_DropDownOpening);
|
||||
//
|
||||
// mnuLoadState
|
||||
//
|
||||
this.mnuLoadState.Name = "mnuLoadState";
|
||||
this.mnuLoadState.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuLoadState.Text = "Load State";
|
||||
this.mnuLoadState.DropDownOpening += new System.EventHandler(this.mnuLoadState_DropDownOpening);
|
||||
//
|
||||
// toolStripMenuItem10
|
||||
//
|
||||
this.toolStripMenuItem10.Name = "toolStripMenuItem10";
|
||||
this.toolStripMenuItem10.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// mnuRecentFiles
|
||||
//
|
||||
this.mnuRecentFiles.Name = "mnuRecentFiles";
|
||||
this.mnuRecentFiles.Size = new System.Drawing.Size(146, 22);
|
||||
this.mnuRecentFiles.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRecentFiles.Text = "Recent Files";
|
||||
//
|
||||
// toolStripMenuItem6
|
||||
//
|
||||
this.toolStripMenuItem6.Name = "toolStripMenuItem6";
|
||||
this.toolStripMenuItem6.Size = new System.Drawing.Size(143, 6);
|
||||
this.toolStripMenuItem6.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// mnuExit
|
||||
//
|
||||
this.mnuExit.Image = global::Mesen.GUI.Properties.Resources.Exit;
|
||||
this.mnuExit.Name = "mnuExit";
|
||||
this.mnuExit.Size = new System.Drawing.Size(146, 22);
|
||||
this.mnuExit.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuExit.Text = "Exit";
|
||||
this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click);
|
||||
//
|
||||
|
@ -209,7 +234,7 @@
|
|||
this.mnuPause.Enabled = false;
|
||||
this.mnuPause.Image = global::Mesen.GUI.Properties.Resources.MediaPause;
|
||||
this.mnuPause.Name = "mnuPause";
|
||||
this.mnuPause.Size = new System.Drawing.Size(139, 22);
|
||||
this.mnuPause.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuPause.Text = "Pause";
|
||||
//
|
||||
// mnuReset
|
||||
|
@ -217,7 +242,7 @@
|
|||
this.mnuReset.Enabled = false;
|
||||
this.mnuReset.Image = global::Mesen.GUI.Properties.Resources.Refresh;
|
||||
this.mnuReset.Name = "mnuReset";
|
||||
this.mnuReset.Size = new System.Drawing.Size(139, 22);
|
||||
this.mnuReset.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuReset.Text = "Reset";
|
||||
//
|
||||
// mnuPowerCycle
|
||||
|
@ -225,19 +250,19 @@
|
|||
this.mnuPowerCycle.Enabled = false;
|
||||
this.mnuPowerCycle.Image = global::Mesen.GUI.Properties.Resources.PowerCycle;
|
||||
this.mnuPowerCycle.Name = "mnuPowerCycle";
|
||||
this.mnuPowerCycle.Size = new System.Drawing.Size(139, 22);
|
||||
this.mnuPowerCycle.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuPowerCycle.Text = "Power Cycle";
|
||||
//
|
||||
// toolStripMenuItem24
|
||||
//
|
||||
this.toolStripMenuItem24.Name = "toolStripMenuItem24";
|
||||
this.toolStripMenuItem24.Size = new System.Drawing.Size(136, 6);
|
||||
this.toolStripMenuItem24.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// mnuPowerOff
|
||||
//
|
||||
this.mnuPowerOff.Image = global::Mesen.GUI.Properties.Resources.MediaStop;
|
||||
this.mnuPowerOff.Name = "mnuPowerOff";
|
||||
this.mnuPowerOff.Size = new System.Drawing.Size(139, 22);
|
||||
this.mnuPowerOff.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuPowerOff.Text = "Power Off";
|
||||
//
|
||||
// optionsToolStripMenuItem
|
||||
|
@ -272,7 +297,7 @@
|
|||
this.mnuShowFPS});
|
||||
this.mnuEmulationSpeed.Image = global::Mesen.GUI.Properties.Resources.Speed;
|
||||
this.mnuEmulationSpeed.Name = "mnuEmulationSpeed";
|
||||
this.mnuEmulationSpeed.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuEmulationSpeed.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuEmulationSpeed.Text = "Speed";
|
||||
this.mnuEmulationSpeed.DropDownOpening += new System.EventHandler(this.mnuEmulationSpeed_DropDownOpening);
|
||||
//
|
||||
|
@ -360,7 +385,7 @@
|
|||
this.mnuFullscreen});
|
||||
this.mnuVideoScale.Image = global::Mesen.GUI.Properties.Resources.Fullscreen;
|
||||
this.mnuVideoScale.Name = "mnuVideoScale";
|
||||
this.mnuVideoScale.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuVideoScale.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuVideoScale.Text = "Video Size";
|
||||
this.mnuVideoScale.DropDownOpening += new System.EventHandler(this.mnuVideoScale_DropDownOpening);
|
||||
//
|
||||
|
@ -446,7 +471,7 @@
|
|||
this.mnuBilinearInterpolation});
|
||||
this.mnuVideoFilter.Image = global::Mesen.GUI.Properties.Resources.VideoFilter;
|
||||
this.mnuVideoFilter.Name = "mnuVideoFilter";
|
||||
this.mnuVideoFilter.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuVideoFilter.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuVideoFilter.Text = "Video Filter";
|
||||
this.mnuVideoFilter.DropDownOpening += new System.EventHandler(this.mnuVideoFilter_DropDownOpening);
|
||||
//
|
||||
|
@ -627,13 +652,13 @@
|
|||
// toolStripMenuItem4
|
||||
//
|
||||
this.toolStripMenuItem4.Name = "toolStripMenuItem4";
|
||||
this.toolStripMenuItem4.Size = new System.Drawing.Size(149, 6);
|
||||
this.toolStripMenuItem4.Size = new System.Drawing.Size(132, 6);
|
||||
//
|
||||
// mnuAudioConfig
|
||||
//
|
||||
this.mnuAudioConfig.Image = global::Mesen.GUI.Properties.Resources.Audio;
|
||||
this.mnuAudioConfig.Name = "mnuAudioConfig";
|
||||
this.mnuAudioConfig.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuAudioConfig.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuAudioConfig.Text = "Audio";
|
||||
this.mnuAudioConfig.Click += new System.EventHandler(this.mnuAudioConfig_Click);
|
||||
//
|
||||
|
@ -641,20 +666,20 @@
|
|||
//
|
||||
this.mnuVideoConfig.Image = global::Mesen.GUI.Properties.Resources.VideoOptions;
|
||||
this.mnuVideoConfig.Name = "mnuVideoConfig";
|
||||
this.mnuVideoConfig.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuVideoConfig.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuVideoConfig.Text = "Video";
|
||||
this.mnuVideoConfig.Click += new System.EventHandler(this.mnuVideoConfig_Click);
|
||||
//
|
||||
// toolStripMenuItem3
|
||||
//
|
||||
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
|
||||
this.toolStripMenuItem3.Size = new System.Drawing.Size(149, 6);
|
||||
this.toolStripMenuItem3.Size = new System.Drawing.Size(132, 6);
|
||||
//
|
||||
// mnuPreferences
|
||||
//
|
||||
this.mnuPreferences.Image = global::Mesen.GUI.Properties.Resources.Settings;
|
||||
this.mnuPreferences.Name = "mnuPreferences";
|
||||
this.mnuPreferences.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuPreferences.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuPreferences.Text = "Preferences";
|
||||
this.mnuPreferences.Click += new System.EventHandler(this.mnuPreferences_Click);
|
||||
//
|
||||
|
@ -940,5 +965,8 @@
|
|||
private System.Windows.Forms.ToolStripMenuItem mnuLogWindow;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem7;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTakeScreenshot;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuSaveState;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuLoadState;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem10;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Config.Shortcuts;
|
||||
using Mesen.GUI.Debugger;
|
||||
using Mesen.GUI.Emulation;
|
||||
using Mesen.GUI.Forms.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -42,6 +43,9 @@ namespace Mesen.GUI.Forms
|
|||
_notifListener = new NotificationListener();
|
||||
_notifListener.OnNotification += OnNotificationReceived;
|
||||
|
||||
SaveStateManager.InitializeStateMenu(mnuSaveState, true, _shortcuts);
|
||||
SaveStateManager.InitializeStateMenu(mnuLoadState, false, _shortcuts);
|
||||
|
||||
BindShortcuts();
|
||||
}
|
||||
|
||||
|
@ -64,6 +68,13 @@ namespace Mesen.GUI.Forms
|
|||
private void OnNotificationReceived(NotificationEventArgs e)
|
||||
{
|
||||
switch(e.NotificationType) {
|
||||
case ConsoleNotificationType.GameLoaded:
|
||||
this.BeginInvoke((Action)(() => {
|
||||
SaveStateManager.UpdateStateMenu(mnuLoadState, false);
|
||||
SaveStateManager.UpdateStateMenu(mnuSaveState, true);
|
||||
}));
|
||||
break;
|
||||
|
||||
case ConsoleNotificationType.ResolutionChanged:
|
||||
ScreenSize size = EmuApi.GetScreenSize(false);
|
||||
this.BeginInvoke((Action)(() => {
|
||||
|
@ -327,5 +338,15 @@ namespace Mesen.GUI.Forms
|
|||
mnuEmuSpeedTriple.Checked = emulationSpeed == 300;
|
||||
mnuEmuSpeedMaximumSpeed.Checked = emulationSpeed == 0;
|
||||
}
|
||||
|
||||
private void mnuLoadState_DropDownOpening(object sender, EventArgs e)
|
||||
{
|
||||
SaveStateManager.UpdateStateMenu(mnuLoadState, false);
|
||||
}
|
||||
|
||||
private void mnuSaveState_DropDownOpening(object sender, EventArgs e)
|
||||
{
|
||||
SaveStateManager.UpdateStateMenu(mnuSaveState, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,12 @@ namespace Mesen.GUI
|
|||
[DllImport(DllPath)] public static extern void DisplayMessage([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string title, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string message, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string param1 = null);
|
||||
|
||||
[DllImport(DllPath)] public static extern IntPtr GetArchiveRomList([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filename);
|
||||
|
||||
[DllImport(DllPath)] public static extern void SaveState(UInt32 stateIndex);
|
||||
[DllImport(DllPath)] public static extern void LoadState(UInt32 stateIndex);
|
||||
[DllImport(DllPath)] public static extern void SaveStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filepath);
|
||||
[DllImport(DllPath)] public static extern void LoadStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filepath);
|
||||
[DllImport(DllPath)] public static extern Int64 GetStateInfo(UInt32 stateIndex);
|
||||
}
|
||||
|
||||
public struct ScreenSize
|
||||
|
|
|
@ -460,6 +460,7 @@
|
|||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Debugger\WatchManager.cs" />
|
||||
<Compile Include="Emulation\SaveStateManager.cs" />
|
||||
<Compile Include="Forms\BaseConfigForm.Designer.cs">
|
||||
<DependentUpon>BaseConfigForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -525,7 +526,7 @@
|
|||
<Compile Include="Forms\OpenSaveFileDialogExtensions.cs" />
|
||||
<Compile Include="Forms\ResourceHelper.cs" />
|
||||
<Compile Include="Forms\ResourcePath.cs" />
|
||||
<Compile Include="Forms\ShortcutHandler.cs" />
|
||||
<Compile Include="Emulation\ShortcutHandler.cs" />
|
||||
<Compile Include="Interop\DebugApi.cs" />
|
||||
<Compile Include="Interop\ConfigApi.cs" />
|
||||
<Compile Include="Interop\InputApi.cs" />
|
||||
|
@ -535,7 +536,7 @@
|
|||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ResourceExtractor.cs" />
|
||||
<Compile Include="EmuRunner.cs" />
|
||||
<Compile Include="Emulation\EmuRunner.cs" />
|
||||
<Compile Include="RuntimeChecker.cs" />
|
||||
<Compile Include="SingleInstance.cs" />
|
||||
<Compile Include="Utilities\ArchiveHelper.cs" />
|
||||
|
|
10
Utilities/ISerializable.h
Normal file
10
Utilities/ISerializable.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
class Serializer;
|
||||
|
||||
class ISerializable
|
||||
{
|
||||
public:
|
||||
virtual void Serialize(Serializer &s) = 0;
|
||||
};
|
||||
|
140
Utilities/Serializer.cpp
Normal file
140
Utilities/Serializer.cpp
Normal file
|
@ -0,0 +1,140 @@
|
|||
#include "stdafx.h"
|
||||
#include <algorithm>
|
||||
#include "Serializer.h"
|
||||
#include "ISerializable.h"
|
||||
|
||||
Serializer::Serializer(uint32_t version)
|
||||
{
|
||||
_version = version;
|
||||
|
||||
_streamSize = 0x50000;
|
||||
_stream = new uint8_t[_streamSize];
|
||||
_position = 0;
|
||||
_saving = true;
|
||||
}
|
||||
|
||||
Serializer::Serializer(istream &file, uint32_t version)
|
||||
{
|
||||
_version = version;
|
||||
|
||||
_position = 0;
|
||||
_saving = false;
|
||||
|
||||
file.read((char*)&_streamSize, sizeof(_streamSize));
|
||||
_stream = new uint8_t[_streamSize];
|
||||
file.read((char*)_stream, _streamSize);
|
||||
}
|
||||
|
||||
Serializer::~Serializer()
|
||||
{
|
||||
delete[] _stream;
|
||||
}
|
||||
|
||||
void Serializer::EnsureCapacity(uint32_t typeSize)
|
||||
{
|
||||
//Make sure the current block/stream is large enough to fit the next write
|
||||
uint32_t oldSize;
|
||||
uint32_t sizeRequired;
|
||||
uint8_t *oldBuffer;
|
||||
if(_inBlock) {
|
||||
oldBuffer = _blockBuffer;
|
||||
oldSize = _blockSize;
|
||||
sizeRequired = _blockPosition + typeSize;
|
||||
} else {
|
||||
oldBuffer = _stream;
|
||||
oldSize = _streamSize;
|
||||
sizeRequired = _position + typeSize;
|
||||
}
|
||||
|
||||
uint8_t *newBuffer = nullptr;
|
||||
uint32_t newSize = oldSize * 2;
|
||||
if(oldSize < sizeRequired) {
|
||||
while(newSize < sizeRequired) {
|
||||
newSize *= 2;
|
||||
}
|
||||
|
||||
newBuffer = new uint8_t[newSize];
|
||||
memcpy(newBuffer, oldBuffer, oldSize);
|
||||
delete[] oldBuffer;
|
||||
}
|
||||
|
||||
if(newBuffer) {
|
||||
if(_inBlock) {
|
||||
_blockBuffer = newBuffer;
|
||||
_blockSize = newSize;
|
||||
} else {
|
||||
_stream = newBuffer;
|
||||
_streamSize = newSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Serializer::RecursiveStream()
|
||||
{
|
||||
}
|
||||
|
||||
void Serializer::StreamStartBlock()
|
||||
{
|
||||
if(_inBlock) {
|
||||
throw new std::runtime_error("Cannot start a new block before ending the last block");
|
||||
}
|
||||
|
||||
if(!_saving) {
|
||||
InternalStream(_blockSize);
|
||||
_blockSize = std::min(_blockSize, (uint32_t)0xFFFFF);
|
||||
_blockBuffer = new uint8_t[_blockSize];
|
||||
ArrayInfo<uint8_t> arrayInfo = { _blockBuffer, _blockSize };
|
||||
InternalStream(arrayInfo);
|
||||
} else {
|
||||
_blockSize = 0x100;
|
||||
_blockBuffer = new uint8_t[_blockSize];
|
||||
}
|
||||
_blockPosition = 0;
|
||||
_inBlock = true;
|
||||
}
|
||||
|
||||
void Serializer::StreamEndBlock()
|
||||
{
|
||||
_inBlock = false;
|
||||
if(_saving) {
|
||||
InternalStream(_blockPosition);
|
||||
ArrayInfo<uint8_t> arrayInfo = { _blockBuffer, _blockPosition };
|
||||
InternalStream(arrayInfo);
|
||||
}
|
||||
|
||||
delete[] _blockBuffer;
|
||||
_blockBuffer = nullptr;
|
||||
}
|
||||
|
||||
void Serializer::Save(ostream& file)
|
||||
{
|
||||
file.write((char*)&_position, sizeof(_position));
|
||||
file.write((char*)_stream, _position);
|
||||
}
|
||||
|
||||
void Serializer::WriteEmptyBlock(ostream* file)
|
||||
{
|
||||
int blockSize = 0;
|
||||
file->write((char*)&blockSize, sizeof(blockSize));
|
||||
}
|
||||
|
||||
void Serializer::SkipBlock(istream* file)
|
||||
{
|
||||
int blockSize = 0;
|
||||
file->read((char*)&blockSize, sizeof(blockSize));
|
||||
file->seekg(blockSize, std::ios::cur);
|
||||
}
|
||||
|
||||
void Serializer::Stream(ISerializable &obj)
|
||||
{
|
||||
//StreamStartBlock();
|
||||
obj.Serialize(*this);
|
||||
//StreamEndBlock();
|
||||
}
|
||||
|
||||
void Serializer::Stream(ISerializable *obj)
|
||||
{
|
||||
//StreamStartBlock();
|
||||
obj->Serialize(*this);
|
||||
//StreamEndBlock();
|
||||
}
|
219
Utilities/Serializer.h
Normal file
219
Utilities/Serializer.h
Normal file
|
@ -0,0 +1,219 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
class Serializer;
|
||||
class ISerializable;
|
||||
|
||||
template<typename T>
|
||||
struct ArrayInfo
|
||||
{
|
||||
T* Array;
|
||||
uint32_t ElementCount;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct VectorInfo
|
||||
{
|
||||
vector<T>* Vector;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ValueInfo
|
||||
{
|
||||
T* Value;
|
||||
T DefaultValue;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct EmptyInfo
|
||||
{
|
||||
T Empty;
|
||||
};
|
||||
|
||||
class Serializer
|
||||
{
|
||||
private:
|
||||
uint8_t* _stream = nullptr;
|
||||
uint32_t _position = 0;
|
||||
uint32_t _streamSize = 0;
|
||||
uint32_t _version = 0;
|
||||
|
||||
bool _inBlock = false;
|
||||
uint8_t* _blockBuffer = nullptr;
|
||||
uint32_t _blockSize = 0;
|
||||
uint32_t _blockPosition = 0;
|
||||
|
||||
bool _saving = false;
|
||||
|
||||
private:
|
||||
void EnsureCapacity(uint32_t typeSize);
|
||||
|
||||
template<typename T> void StreamElement(T &value, T defaultValue = T());
|
||||
template<typename T> void InternalStream(EmptyInfo<T> &info);
|
||||
template<typename T> void InternalStream(ArrayInfo<T> &info);
|
||||
template<typename T> void InternalStream(VectorInfo<T> &info);
|
||||
template<typename T> void InternalStream(ValueInfo<T> &info);
|
||||
template<typename T> void InternalStream(T &value);
|
||||
void RecursiveStream();
|
||||
|
||||
template<typename T, typename... T2> void RecursiveStream(T &value, T2&... args);
|
||||
|
||||
void StreamStartBlock();
|
||||
void StreamEndBlock();
|
||||
|
||||
public:
|
||||
Serializer(uint32_t version);
|
||||
Serializer(istream &file, uint32_t version);
|
||||
~Serializer();
|
||||
|
||||
uint32_t GetVersion() { return _version; }
|
||||
bool IsSaving() { return _saving; }
|
||||
|
||||
template<typename... T> void Stream(T&... args);
|
||||
template<typename T> void StreamArray(T *array, uint32_t size);
|
||||
template<typename T> void StreamVector(vector<T> &list);
|
||||
|
||||
void Save(ostream &file);
|
||||
|
||||
void Stream(ISerializable &obj);
|
||||
void Stream(ISerializable *obj);
|
||||
|
||||
void WriteEmptyBlock(ostream* file);
|
||||
void SkipBlock(istream* file);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void Serializer::StreamElement(T &value, T defaultValue)
|
||||
{
|
||||
if(_saving) {
|
||||
uint8_t* bytes = (uint8_t*)&value;
|
||||
int typeSize = sizeof(T);
|
||||
|
||||
EnsureCapacity(typeSize);
|
||||
|
||||
for(int i = 0; i < typeSize; i++) {
|
||||
if(_inBlock) {
|
||||
_blockBuffer[_blockPosition++] = bytes[i];
|
||||
} else {
|
||||
_stream[_position++] = bytes[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(_inBlock) {
|
||||
if(_blockPosition + sizeof(T) <= _blockSize) {
|
||||
memcpy(&value, _blockBuffer + _blockPosition, sizeof(T));
|
||||
_blockPosition += sizeof(T);
|
||||
} else {
|
||||
value = defaultValue;
|
||||
_blockPosition = _blockSize;
|
||||
}
|
||||
} else {
|
||||
if(_position + sizeof(T) <= _streamSize) {
|
||||
memcpy(&value, _stream + _position, sizeof(T));
|
||||
_position += sizeof(T);
|
||||
} else {
|
||||
value = defaultValue;
|
||||
_position = _streamSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Serializer::InternalStream(EmptyInfo<T> &info)
|
||||
{
|
||||
if(_inBlock) {
|
||||
_blockPosition += sizeof(T);
|
||||
} else {
|
||||
_position += sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Serializer::InternalStream(ArrayInfo<T> &info)
|
||||
{
|
||||
T* pointer = info.Array;
|
||||
|
||||
uint32_t count = info.ElementCount;
|
||||
StreamElement<uint32_t>(count);
|
||||
|
||||
if(!_saving) {
|
||||
//Reset array to 0 before loading from file
|
||||
memset(info.Array, 0, sizeof(T) * info.ElementCount);
|
||||
}
|
||||
|
||||
//Load the number of elements requested, or the maximum possible (based on what is present in the save state)
|
||||
for(uint32_t i = 0; i < info.ElementCount && i < count; i++) {
|
||||
StreamElement<T>(*pointer);
|
||||
pointer++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Serializer::InternalStream(VectorInfo<T> &info)
|
||||
{
|
||||
vector<T> *vector = info.Vector;
|
||||
|
||||
uint32_t count = (uint32_t)vector->size();
|
||||
StreamElement<uint32_t>(count);
|
||||
|
||||
if(!_saving) {
|
||||
if(count > 0xFFFFFF) {
|
||||
throw std::runtime_error("Invalid save state");
|
||||
}
|
||||
vector->resize(count);
|
||||
memset(vector->data(), 0, sizeof(T)*count);
|
||||
}
|
||||
|
||||
//Load the number of elements requested
|
||||
T* pointer = vector->data();
|
||||
for(uint32_t i = 0; i < count; i++) {
|
||||
StreamElement<T>(*pointer);
|
||||
pointer++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Serializer::InternalStream(ValueInfo<T> &info)
|
||||
{
|
||||
StreamElement<T>(*info.Value, info.DefaultValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Serializer::InternalStream(T &value)
|
||||
{
|
||||
StreamElement<T>(value);
|
||||
}
|
||||
|
||||
template<typename T, typename... T2>
|
||||
void Serializer::RecursiveStream(T &value, T2&... args)
|
||||
{
|
||||
InternalStream(value);
|
||||
RecursiveStream(args...);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
void Serializer::Stream(T&... args)
|
||||
{
|
||||
//StreamStartBlock();
|
||||
RecursiveStream(args...);
|
||||
//StreamEndBlock();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Serializer::StreamArray(T *array, uint32_t size)
|
||||
{
|
||||
ArrayInfo<T> info;
|
||||
info.Array = array;
|
||||
info.ElementCount = size;
|
||||
InternalStream(info);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Serializer::StreamVector(vector<T> &list)
|
||||
{
|
||||
VectorInfo<T> info;
|
||||
info.Vector = &list;
|
||||
InternalStream(info);
|
||||
}
|
|
@ -413,6 +413,7 @@
|
|||
<ClInclude Include="HQX\common.h" />
|
||||
<ClInclude Include="HQX\hqx.h" />
|
||||
<ClInclude Include="IpsPatcher.h" />
|
||||
<ClInclude Include="ISerializable.h" />
|
||||
<ClInclude Include="KreedSaiEagle\SaiEagle.h" />
|
||||
<ClInclude Include="LowPassFilter.h" />
|
||||
<ClInclude Include="md5.h" />
|
||||
|
@ -426,6 +427,7 @@
|
|||
<ClInclude Include="Scale2x\scale2x.h" />
|
||||
<ClInclude Include="Scale2x\scale3x.h" />
|
||||
<ClInclude Include="Scale2x\scalebit.h" />
|
||||
<ClInclude Include="Serializer.h" />
|
||||
<ClInclude Include="sha1.h" />
|
||||
<ClInclude Include="snes_ntsc.h" />
|
||||
<ClInclude Include="snes_ntsc_config.h" />
|
||||
|
@ -584,6 +586,7 @@
|
|||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Libretro|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='PGO Optimize|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Serializer.cpp" />
|
||||
<ClCompile Include="sha1.cpp" />
|
||||
<ClCompile Include="SimpleLock.cpp" />
|
||||
<ClCompile Include="snes_ntsc.cpp" />
|
||||
|
|
|
@ -1,117 +1,98 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="xBRZ">
|
||||
<UniqueIdentifier>{34df7dd9-5f1b-4aec-9212-1b70f1fada59}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="HQX">
|
||||
<UniqueIdentifier>{c29925fd-7698-4db8-a328-73ef7f8993a9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Scale2x">
|
||||
<UniqueIdentifier>{87329bd1-28ac-4ced-a4c2-b51777018d16}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="KreedSaiEagle">
|
||||
<UniqueIdentifier>{8e159744-fb91-4e16-aa82-8d8703ba2762}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Avi">
|
||||
<UniqueIdentifier>{8b0e23bf-1bd9-4cc1-8046-784fd01e8688}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Patches">
|
||||
<UniqueIdentifier>{6d519bc1-7c40-448a-95d2-9ad94cd20644}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Hashes">
|
||||
<UniqueIdentifier>{7b254092-7a93-4010-b203-ec6d48276d11}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Video">
|
||||
<UniqueIdentifier>{954e8e7b-1ee6-4ab4-a197-3154ce63061e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Video\xBRZ">
|
||||
<UniqueIdentifier>{34df7dd9-5f1b-4aec-9212-1b70f1fada59}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Video\Scale2x">
|
||||
<UniqueIdentifier>{87329bd1-28ac-4ced-a4c2-b51777018d16}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Video\KreedSaiEagle">
|
||||
<UniqueIdentifier>{8e159744-fb91-4e16-aa82-8d8703ba2762}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Video\HQX">
|
||||
<UniqueIdentifier>{c29925fd-7698-4db8-a328-73ef7f8993a9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Archives">
|
||||
<UniqueIdentifier>{99c6afb9-49a2-4609-b3cd-3d26eb16d8a5}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Audio">
|
||||
<UniqueIdentifier>{cde7b53f-be5e-4201-8194-0352d00216aa}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Misc">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FolderUtilities.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Socket.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SimpleLock.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UPnPPortMapper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CRC32.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="miniz.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UTF8Util.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PNGHelper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AutoResetEvent.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="md5.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZipWriter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZipReader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LowPassFilter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="blip_buf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="xBRZ\config.h">
|
||||
<Filter>xBRZ</Filter>
|
||||
<Filter>Video\xBRZ</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="xBRZ\xbrz.h">
|
||||
<Filter>xBRZ</Filter>
|
||||
<Filter>Video\xBRZ</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HQX\hqx.h">
|
||||
<Filter>HQX</Filter>
|
||||
<Filter>Video\HQX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HQX\common.h">
|
||||
<Filter>HQX</Filter>
|
||||
<Filter>Video\HQX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Scale2x\scale2x.h">
|
||||
<Filter>Scale2x</Filter>
|
||||
<Filter>Video\Scale2x</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Scale2x\scale3x.h">
|
||||
<Filter>Scale2x</Filter>
|
||||
<Filter>Video\Scale2x</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Scale2x\scalebit.h">
|
||||
<Filter>Scale2x</Filter>
|
||||
<Filter>Video\Scale2x</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KreedSaiEagle\SaiEagle.h">
|
||||
<Filter>KreedSaiEagle</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SZReader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Video\KreedSaiEagle</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PlatformUtilities.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HexUtilities.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZmbvCodec.h">
|
||||
<Filter>Avi</Filter>
|
||||
|
@ -129,7 +110,7 @@
|
|||
<Filter>Avi</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringUtilities.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IpsPatcher.h">
|
||||
<Filter>Patches</Filter>
|
||||
|
@ -140,130 +121,106 @@
|
|||
<ClInclude Include="BpsPatcher.h">
|
||||
<Filter>Patches</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="orfanidis_eq.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sha1.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ArchiveReader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stb_vorbis.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Base64.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VirtualFile.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FastString.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="snes_ntsc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<ClInclude Include="CRC32.h">
|
||||
<Filter>Hashes</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="snes_ntsc_config.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<ClInclude Include="sha1.h">
|
||||
<Filter>Hashes</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="md5.h">
|
||||
<Filter>Hashes</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="snes_ntsc_impl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="snes_ntsc.h">
|
||||
<Filter>Video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="snes_ntsc_config.h">
|
||||
<Filter>Video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PNGHelper.h">
|
||||
<Filter>Video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ArchiveReader.h">
|
||||
<Filter>Archives</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZipReader.h">
|
||||
<Filter>Archives</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZipWriter.h">
|
||||
<Filter>Archives</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SZReader.h">
|
||||
<Filter>Archives</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="miniz.h">
|
||||
<Filter>Archives</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stb_vorbis.h">
|
||||
<Filter>Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="orfanidis_eq.h">
|
||||
<Filter>Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LowPassFilter.h">
|
||||
<Filter>Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Equalizer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
<Filter>Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="blip_buf.h">
|
||||
<Filter>Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Serializer.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ISerializable.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FolderUtilities.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="miniz.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SimpleLock.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Socket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UPnPPortMapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UTF8Util.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CRC32.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PNGHelper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AutoResetEvent.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="md5.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZipWriter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZipReader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="blip_buf.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="xBRZ\xbrz.cpp">
|
||||
<Filter>xBRZ</Filter>
|
||||
<Filter>Video\xBRZ</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HQX\hq2x.cpp">
|
||||
<Filter>HQX</Filter>
|
||||
<Filter>Video\HQX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HQX\hq3x.cpp">
|
||||
<Filter>HQX</Filter>
|
||||
<Filter>Video\HQX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HQX\hq4x.cpp">
|
||||
<Filter>HQX</Filter>
|
||||
<Filter>Video\HQX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HQX\init.cpp">
|
||||
<Filter>HQX</Filter>
|
||||
<Filter>Video\HQX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Scale2x\scale2x.cpp">
|
||||
<Filter>Scale2x</Filter>
|
||||
<Filter>Video\Scale2x</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Scale2x\scale3x.cpp">
|
||||
<Filter>Scale2x</Filter>
|
||||
<Filter>Video\Scale2x</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Scale2x\scalebit.cpp">
|
||||
<Filter>Scale2x</Filter>
|
||||
<Filter>Video\Scale2x</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KreedSaiEagle\SuperEagle.cpp">
|
||||
<Filter>KreedSaiEagle</Filter>
|
||||
<Filter>Video\KreedSaiEagle</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KreedSaiEagle\Super2xSai.cpp">
|
||||
<Filter>KreedSaiEagle</Filter>
|
||||
<Filter>Video\KreedSaiEagle</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KreedSaiEagle\2xSai.cpp">
|
||||
<Filter>KreedSaiEagle</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SZReader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ArchiveReader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PlatformUtilities.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HexUtilities.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
<Filter>Video\KreedSaiEagle</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZmbvCodec.cpp">
|
||||
<Filter>Avi</Filter>
|
||||
|
@ -283,20 +240,80 @@
|
|||
<ClCompile Include="BpsPatcher.cpp">
|
||||
<Filter>Patches</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="md5.cpp">
|
||||
<Filter>Hashes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CRC32.cpp">
|
||||
<Filter>Hashes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sha1.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stb_vorbis.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VirtualFile.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
<Filter>Hashes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="snes_ntsc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
<Filter>Video</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PNGHelper.cpp">
|
||||
<Filter>Video</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ArchiveReader.cpp">
|
||||
<Filter>Archives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZipReader.cpp">
|
||||
<Filter>Archives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZipWriter.cpp">
|
||||
<Filter>Archives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SZReader.cpp">
|
||||
<Filter>Archives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="miniz.cpp">
|
||||
<Filter>Archives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="blip_buf.cpp">
|
||||
<Filter>Audio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Equalizer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
<Filter>Audio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stb_vorbis.cpp">
|
||||
<Filter>Audio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AutoResetEvent.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FolderUtilities.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HexUtilities.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PlatformUtilities.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SimpleLock.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Socket.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UPnPPortMapper.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UTF8Util.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VirtualFile.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Serializer.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -303,6 +303,16 @@ std::string SHA1::GetHash(vector<uint8_t> &data)
|
|||
return checksum.final();
|
||||
}
|
||||
|
||||
std::string SHA1::GetHash(uint8_t* data, size_t size)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.write((char*)data, size);
|
||||
|
||||
SHA1 checksum;
|
||||
checksum.update(ss);
|
||||
return checksum.final();
|
||||
}
|
||||
|
||||
std::string SHA1::GetHash(std::istream &stream)
|
||||
{
|
||||
SHA1 checksum;
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
static std::string GetHash(const std::string &filename);
|
||||
static std::string GetHash(std::istream &stream);
|
||||
static std::string GetHash(vector<uint8_t> &data);
|
||||
static std::string GetHash(uint8_t* data, size_t size);
|
||||
|
||||
private:
|
||||
uint32_t digest[5];
|
||||
|
|
|
@ -14,6 +14,8 @@ using std::shared_ptr;
|
|||
using std::unique_ptr;
|
||||
using utf8::ifstream;
|
||||
using utf8::ofstream;
|
||||
using std::ostream;
|
||||
using std::istream;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::atomic;
|
||||
|
|
Loading…
Reference in a new issue