Added movies recording/playback support
This commit is contained in:
parent
cae71b7907
commit
ed4a0e60e8
45 changed files with 1679 additions and 167 deletions
|
@ -8,6 +8,7 @@
|
|||
#include "MessageManager.h"
|
||||
#include "Console.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "BatteryManager.h"
|
||||
#include "NecDsp.h"
|
||||
#include "Sa1.h"
|
||||
#include "Gsu.h"
|
||||
|
@ -265,23 +266,19 @@ CartFlags::CartFlags BaseCartridge::GetCartFlags()
|
|||
|
||||
void BaseCartridge::LoadBattery()
|
||||
{
|
||||
string saveFilePath = FolderUtilities::CombinePath(FolderUtilities::GetSaveFolder(), FolderUtilities::GetFilename(((VirtualFile)_romPath).GetFileName(), false) + ".srm");
|
||||
if(_saveRamSize > 0) {
|
||||
VirtualFile saveFile(saveFilePath);
|
||||
saveFile.ReadFile(_saveRam, _saveRamSize);
|
||||
_console->GetBatteryManager()->LoadBattery(".srm", _saveRam, _saveRamSize);
|
||||
} else if(_coprocessor && _hasBattery) {
|
||||
_coprocessor->LoadBattery(saveFilePath);
|
||||
_coprocessor->LoadBattery();
|
||||
}
|
||||
}
|
||||
|
||||
void BaseCartridge::SaveBattery()
|
||||
{
|
||||
string saveFilePath = FolderUtilities::CombinePath(FolderUtilities::GetSaveFolder(), FolderUtilities::GetFilename(((VirtualFile)_romPath).GetFileName(), false) + ".srm");
|
||||
if(_saveRamSize > 0) {
|
||||
ofstream saveFile(saveFilePath, ios::binary);
|
||||
saveFile.write((char*)_saveRam, _saveRamSize);
|
||||
_console->GetBatteryManager()->SaveBattery(".srm", _saveRam, _saveRamSize);
|
||||
} else if(_coprocessor && _hasBattery) {
|
||||
_coprocessor->SaveBattery(saveFilePath);
|
||||
_coprocessor->SaveBattery();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,10 +103,13 @@ void BaseControlDevice::SetTextState(string textState)
|
|||
|
||||
int i = 0;
|
||||
for(char c : textState) {
|
||||
if(c != '.') {
|
||||
SetBit(i);
|
||||
if(c != ':') {
|
||||
//Ignore colons (used by multitap to separate inputs)
|
||||
if(c != '.') {
|
||||
SetBit(i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,8 +128,15 @@ string BaseControlDevice::GetTextState()
|
|||
output += std::to_string(pos.X) + " " + std::to_string(pos.Y) + " ";
|
||||
}
|
||||
|
||||
int keyNumber = 0;
|
||||
for(size_t i = 0; i < keyNames.size(); i++) {
|
||||
output += IsPressed((uint8_t)i) ? keyNames[i] : '.';
|
||||
if(keyNames[i] != ':') {
|
||||
//Ignore colons in string (used by multitap to split controllers)
|
||||
output += IsPressed((uint8_t)keyNumber) ? keyNames[i] : '.';
|
||||
keyNumber++;
|
||||
} else {
|
||||
output += ':';
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
|
|
|
@ -9,6 +9,6 @@ public:
|
|||
virtual void Reset() = 0;
|
||||
|
||||
virtual void ProcessEndOfFrame() { }
|
||||
virtual void LoadBattery(string filePath) { }
|
||||
virtual void SaveBattery(string filePath) { }
|
||||
virtual void LoadBattery() { }
|
||||
virtual void SaveBattery() { }
|
||||
};
|
65
Core/BatteryManager.cpp
Normal file
65
Core/BatteryManager.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include "stdafx.h"
|
||||
#include "BatteryManager.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
|
||||
void BatteryManager::Initialize(string romName)
|
||||
{
|
||||
_romName = romName;
|
||||
}
|
||||
|
||||
string BatteryManager::GetBasePath()
|
||||
{
|
||||
return FolderUtilities::CombinePath(FolderUtilities::GetSaveFolder(), _romName);
|
||||
}
|
||||
|
||||
void BatteryManager::SetBatteryProvider(shared_ptr<IBatteryProvider> provider)
|
||||
{
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
void BatteryManager::SetBatteryRecorder(shared_ptr<IBatteryRecorder> recorder)
|
||||
{
|
||||
_recorder = recorder;
|
||||
}
|
||||
|
||||
void BatteryManager::SaveBattery(string extension, uint8_t* data, uint32_t length)
|
||||
{
|
||||
ofstream out(GetBasePath() + extension, ios::binary);
|
||||
if(out) {
|
||||
out.write((char*)data, length);
|
||||
}
|
||||
}
|
||||
|
||||
vector<uint8_t> BatteryManager::LoadBattery(string extension)
|
||||
{
|
||||
shared_ptr<IBatteryProvider> provider = _provider.lock();
|
||||
|
||||
vector<uint8_t> batteryData;
|
||||
if(provider) {
|
||||
//Used by movie player to provider initial state of ram at startup
|
||||
batteryData = provider->LoadBattery(extension);
|
||||
} else {
|
||||
VirtualFile file = GetBasePath() + extension;
|
||||
if(file.IsValid()) {
|
||||
file.ReadFile(batteryData);
|
||||
}
|
||||
}
|
||||
|
||||
if(!batteryData.empty()) {
|
||||
shared_ptr<IBatteryRecorder> recorder = _recorder.lock();
|
||||
if(recorder) {
|
||||
//Used by movies to record initial state of battery-backed ram at power on
|
||||
recorder->OnLoadBattery(extension, batteryData);
|
||||
}
|
||||
}
|
||||
|
||||
return batteryData;
|
||||
}
|
||||
|
||||
void BatteryManager::LoadBattery(string extension, uint8_t* data, uint32_t length)
|
||||
{
|
||||
vector<uint8_t> batteryData = LoadBattery(extension);
|
||||
memset(data, 0, length);
|
||||
memcpy(data, batteryData.data(), std::min((uint32_t)batteryData.size(), length));
|
||||
}
|
35
Core/BatteryManager.h
Normal file
35
Core/BatteryManager.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
class IBatteryProvider
|
||||
{
|
||||
public:
|
||||
virtual vector<uint8_t> LoadBattery(string extension) = 0;
|
||||
};
|
||||
|
||||
class IBatteryRecorder
|
||||
{
|
||||
public:
|
||||
virtual void OnLoadBattery(string extension, vector<uint8_t> batteryData) = 0;
|
||||
};
|
||||
|
||||
class BatteryManager
|
||||
{
|
||||
private:
|
||||
string _romName;
|
||||
std::weak_ptr<IBatteryProvider> _provider;
|
||||
std::weak_ptr<IBatteryRecorder> _recorder;
|
||||
|
||||
string GetBasePath();
|
||||
|
||||
public:
|
||||
void Initialize(string romName);
|
||||
|
||||
void SetBatteryProvider(shared_ptr<IBatteryProvider> provider);
|
||||
void SetBatteryRecorder(shared_ptr<IBatteryRecorder> recorder);
|
||||
|
||||
void SaveBattery(string extension, uint8_t* data, uint32_t length);
|
||||
|
||||
vector<uint8_t> LoadBattery(string extension);
|
||||
void LoadBattery(string extension, uint8_t* data, uint32_t length);
|
||||
};
|
|
@ -27,6 +27,8 @@
|
|||
#include "CartTypes.h"
|
||||
#include "RewindManager.h"
|
||||
#include "ConsoleLock.h"
|
||||
#include "MovieManager.h"
|
||||
#include "BatteryManager.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
#include "../Utilities/Timer.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
|
@ -53,6 +55,7 @@ void Console::Initialize()
|
|||
_lockCounter = 0;
|
||||
|
||||
_notificationManager.reset(new NotificationManager());
|
||||
_batteryManager.reset(new BatteryManager());
|
||||
_videoDecoder.reset(new VideoDecoder(shared_from_this()));
|
||||
_videoRenderer.reset(new VideoRenderer(shared_from_this()));
|
||||
_saveStateManager.reset(new SaveStateManager(shared_from_this()));
|
||||
|
@ -153,6 +156,8 @@ void Console::Run()
|
|||
}
|
||||
}
|
||||
|
||||
MovieManager::Stop();
|
||||
|
||||
_emulationThreadId = thread::id();
|
||||
|
||||
PlatformUtilities::RestoreTimerResolution();
|
||||
|
@ -285,6 +290,8 @@ bool Console::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom)
|
|||
}
|
||||
|
||||
_cart = cart;
|
||||
_batteryManager->Initialize(FolderUtilities::GetFilename(romFile.GetFileName(), false));
|
||||
|
||||
UpdateRegion();
|
||||
|
||||
_internalRegisters.reset(new InternalRegisters());
|
||||
|
@ -550,6 +557,11 @@ shared_ptr<DebugHud> Console::GetDebugHud()
|
|||
return _debugHud;
|
||||
}
|
||||
|
||||
shared_ptr<BatteryManager> Console::GetBatteryManager()
|
||||
{
|
||||
return _batteryManager;
|
||||
}
|
||||
|
||||
shared_ptr<Cpu> Console::GetCpu()
|
||||
{
|
||||
return _cpu;
|
||||
|
|
|
@ -23,6 +23,7 @@ class NotificationManager;
|
|||
class EmuSettings;
|
||||
class SaveStateManager;
|
||||
class RewindManager;
|
||||
class BatteryManager;
|
||||
enum class MemoryOperationType;
|
||||
enum class SnesMemoryType;
|
||||
enum class EventType;
|
||||
|
@ -43,6 +44,7 @@ private:
|
|||
shared_ptr<Debugger> _debugger;
|
||||
|
||||
shared_ptr<NotificationManager> _notificationManager;
|
||||
shared_ptr<BatteryManager> _batteryManager;
|
||||
shared_ptr<SoundMixer> _soundMixer;
|
||||
shared_ptr<VideoRenderer> _videoRenderer;
|
||||
shared_ptr<VideoDecoder> _videoDecoder;
|
||||
|
@ -110,6 +112,7 @@ public:
|
|||
shared_ptr<SaveStateManager> GetSaveStateManager();
|
||||
shared_ptr<RewindManager> GetRewindManager();
|
||||
shared_ptr<DebugHud> GetDebugHud();
|
||||
shared_ptr<BatteryManager> GetBatteryManager();
|
||||
|
||||
shared_ptr<Cpu> GetCpu();
|
||||
shared_ptr<Ppu> GetPpu();
|
||||
|
|
|
@ -126,7 +126,7 @@ void ControlManager::UpdateControlDevices()
|
|||
auto lock = _deviceLock.AcquireSafe();
|
||||
_controlDevices.clear();
|
||||
RegisterControlDevice(_systemActionManager);
|
||||
for(int i = 0; i < 4; i++) {
|
||||
for(int i = 0; i < 2; i++) {
|
||||
shared_ptr<BaseControlDevice> device = CreateControllerDevice(GetControllerType(i), i, _console);
|
||||
if(device) {
|
||||
RegisterControlDevice(device);
|
||||
|
@ -207,7 +207,7 @@ void ControlManager::Write(uint16_t addr, uint8_t value)
|
|||
void ControlManager::Serialize(Serializer &s)
|
||||
{
|
||||
InputConfig cfg = _console->GetSettings()->GetInputConfig();
|
||||
s.Stream(cfg.Controllers[0].Type, cfg.Controllers[1].Type, cfg.Controllers[2].Type, cfg.Controllers[3].Type);
|
||||
s.Stream(cfg.Controllers[0].Type, cfg.Controllers[1].Type, cfg.Controllers[2].Type, cfg.Controllers[3].Type, cfg.Controllers[4].Type);
|
||||
if(!s.IsSaving()) {
|
||||
_console->GetSettings()->SetInputConfig(cfg);
|
||||
UpdateControlDevices();
|
||||
|
|
|
@ -20,7 +20,6 @@ private:
|
|||
vector<IInputRecorder*> _inputRecorders;
|
||||
vector<IInputProvider*> _inputProviders;
|
||||
|
||||
//TODO: Static so that power cycle does not reset its value
|
||||
uint32_t _pollCounter;
|
||||
uint32_t _inputConfigVersion;
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
<ClInclude Include="BaseCartridge.h" />
|
||||
<ClInclude Include="BaseControlDevice.h" />
|
||||
<ClInclude Include="BaseCoprocessor.h" />
|
||||
<ClInclude Include="BatteryManager.h" />
|
||||
<ClInclude Include="Cpu.Shared.h" />
|
||||
<ClInclude Include="CpuBwRamHandler.h" />
|
||||
<ClInclude Include="CpuDebugger.h" />
|
||||
|
@ -95,7 +96,11 @@
|
|||
<ClInclude Include="LuaCallHelper.h" />
|
||||
<ClInclude Include="LuaScriptingContext.h" />
|
||||
<ClInclude Include="MemoryAccessCounter.h" />
|
||||
<ClInclude Include="MovieTypes.h" />
|
||||
<ClInclude Include="Multitap.h" />
|
||||
<ClInclude Include="MesenMovie.h" />
|
||||
<ClInclude Include="MovieManager.h" />
|
||||
<ClInclude Include="MovieRecorder.h" />
|
||||
<ClInclude Include="NecDsp.h" />
|
||||
<ClInclude Include="NecDspDisUtils.h" />
|
||||
<ClInclude Include="NecDspTypes.h" />
|
||||
|
@ -180,6 +185,7 @@
|
|||
<ClCompile Include="BaseRenderer.cpp" />
|
||||
<ClCompile Include="BaseSoundManager.cpp" />
|
||||
<ClCompile Include="BaseVideoFilter.cpp" />
|
||||
<ClCompile Include="BatteryManager.cpp" />
|
||||
<ClCompile Include="Breakpoint.cpp" />
|
||||
<ClCompile Include="BreakpointManager.cpp" />
|
||||
<ClCompile Include="CallstackManager.cpp" />
|
||||
|
@ -217,7 +223,10 @@
|
|||
<ClCompile Include="MemoryDumper.cpp" />
|
||||
<ClCompile Include="MemoryManager.cpp" />
|
||||
<ClCompile Include="MemoryMappings.cpp" />
|
||||
<ClCompile Include="MesenMovie.cpp" />
|
||||
<ClCompile Include="MessageManager.cpp" />
|
||||
<ClCompile Include="MovieManager.cpp" />
|
||||
<ClCompile Include="MovieRecorder.cpp" />
|
||||
<ClCompile Include="NecDsp.cpp" />
|
||||
<ClCompile Include="NecDspDisUtils.cpp" />
|
||||
<ClCompile Include="NotificationManager.cpp" />
|
||||
|
|
|
@ -152,9 +152,6 @@
|
|||
<ClInclude Include="ControlManager.h">
|
||||
<Filter>SNES\Input</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FrameLimiter.h">
|
||||
<Filter>SNES</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CodeDataLogger.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
|
@ -383,6 +380,24 @@
|
|||
<ClInclude Include="Multitap.h">
|
||||
<Filter>SNES\Input</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MesenMovie.h">
|
||||
<Filter>Movies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MovieManager.h">
|
||||
<Filter>Movies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MovieRecorder.h">
|
||||
<Filter>Movies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MovieTypes.h">
|
||||
<Filter>Movies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BatteryManager.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FrameLimiter.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
|
@ -620,6 +635,18 @@
|
|||
<ClCompile Include="Obc1.cpp">
|
||||
<Filter>SNES\Coprocessors\OBC1</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MesenMovie.cpp">
|
||||
<Filter>Movies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MovieRecorder.cpp">
|
||||
<Filter>Movies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MovieManager.cpp">
|
||||
<Filter>Movies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BatteryManager.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="SNES">
|
||||
|
@ -679,5 +706,8 @@
|
|||
<Filter Include="SNES\Coprocessors\OBC1">
|
||||
<UniqueIdentifier>{244dec9a-54e9-478d-91a2-ab3ab5f6db1c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Movies">
|
||||
<UniqueIdentifier>{e6a0a09a-5e38-4a63-83bf-095f297b7633}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
11
Core/Gsu.cpp
11
Core/Gsu.cpp
|
@ -9,6 +9,7 @@
|
|||
#include "GsuRamHandler.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "MessageManager.h"
|
||||
#include "BatteryManager.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
|
||||
Gsu::Gsu(Console *console, uint32_t gsuRamSize)
|
||||
|
@ -616,16 +617,14 @@ void Gsu::Serialize(Serializer &s)
|
|||
s.StreamArray(_gsuRam, _gsuRamSize);
|
||||
}
|
||||
|
||||
void Gsu::LoadBattery(string filePath)
|
||||
void Gsu::LoadBattery()
|
||||
{
|
||||
VirtualFile saveFile(filePath);
|
||||
saveFile.ReadFile((uint8_t*)_gsuRam, _gsuRamSize);
|
||||
_console->GetBatteryManager()->LoadBattery(".srm", (uint8_t*)_gsuRam, _gsuRamSize);
|
||||
}
|
||||
|
||||
void Gsu::SaveBattery(string filePath)
|
||||
void Gsu::SaveBattery()
|
||||
{
|
||||
ofstream saveFile(filePath, ios::binary);
|
||||
saveFile.write((char*)_gsuRam, _gsuRamSize);
|
||||
_console->GetBatteryManager()->SaveBattery(".srm", (uint8_t*)_gsuRam, _gsuRamSize);
|
||||
}
|
||||
|
||||
GsuState Gsu::GetState()
|
||||
|
|
|
@ -151,8 +151,8 @@ public:
|
|||
uint8_t ReadGsu(uint32_t addr, MemoryOperationType opType);
|
||||
void WriteGsu(uint32_t addr, uint8_t value, MemoryOperationType opType);
|
||||
|
||||
void LoadBattery(string filePath) override;
|
||||
void SaveBattery(string filePath) override;
|
||||
void LoadBattery() override;
|
||||
void SaveBattery() override;
|
||||
|
||||
void Run();
|
||||
void Reset() override;
|
||||
|
|
285
Core/MesenMovie.cpp
Normal file
285
Core/MesenMovie.cpp
Normal file
|
@ -0,0 +1,285 @@
|
|||
#include "stdafx.h"
|
||||
#include "../Utilities/ZipReader.h"
|
||||
#include "../Utilities/StringUtilities.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "MesenMovie.h"
|
||||
#include "MessageManager.h"
|
||||
#include "ControlManager.h"
|
||||
#include "BaseControlDevice.h"
|
||||
#include "Console.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "SaveStateManager.h"
|
||||
#include "MovieTypes.h"
|
||||
#include "MovieManager.h"
|
||||
#include "NotificationManager.h"
|
||||
#include "BatteryManager.h"
|
||||
|
||||
MesenMovie::MesenMovie(shared_ptr<Console> console)
|
||||
{
|
||||
_console = console;
|
||||
}
|
||||
|
||||
MesenMovie::~MesenMovie()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
void MesenMovie::Stop()
|
||||
{
|
||||
if(_playing) {
|
||||
MessageManager::DisplayMessage("Movies", "MovieEnded");
|
||||
|
||||
if(_console->GetSettings()->GetPreferences().PauseOnMovieEnd) {
|
||||
_console->Pause();
|
||||
}
|
||||
|
||||
_playing = false;
|
||||
}
|
||||
_console->GetControlManager()->UnregisterInputProvider(this);
|
||||
}
|
||||
|
||||
bool MesenMovie::SetInput(BaseControlDevice *device)
|
||||
{
|
||||
uint32_t inputRowIndex = _console->GetControlManager()->GetPollCounter();
|
||||
_lastPollCounter = inputRowIndex;
|
||||
|
||||
if(_inputData.size() > inputRowIndex && _inputData[inputRowIndex].size() > _deviceIndex) {
|
||||
device->SetTextState(_inputData[inputRowIndex][_deviceIndex]);
|
||||
|
||||
_deviceIndex++;
|
||||
if(_deviceIndex >= _inputData[inputRowIndex].size()) {
|
||||
//Move to the next frame's data
|
||||
_deviceIndex = 0;
|
||||
}
|
||||
} else {
|
||||
MovieManager::Stop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MesenMovie::IsPlaying()
|
||||
{
|
||||
return _playing;
|
||||
}
|
||||
|
||||
vector<uint8_t> MesenMovie::LoadBattery(string extension)
|
||||
{
|
||||
vector<uint8_t> batteryData;
|
||||
_reader->ExtractFile("Battery" + extension, batteryData);
|
||||
return batteryData;
|
||||
}
|
||||
|
||||
void MesenMovie::ProcessNotification(ConsoleNotificationType type, void * parameter)
|
||||
{
|
||||
if(type == ConsoleNotificationType::GameLoaded) {
|
||||
_console->GetControlManager()->RegisterInputProvider(this);
|
||||
_console->GetControlManager()->SetPollCounter(_lastPollCounter + 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool MesenMovie::Play(VirtualFile &file)
|
||||
{
|
||||
_movieFile = file;
|
||||
|
||||
std::stringstream ss;
|
||||
file.ReadFile(ss);
|
||||
|
||||
_reader.reset(new ZipReader());
|
||||
_reader->LoadArchive(ss);
|
||||
|
||||
stringstream settingsData, inputData;
|
||||
if(!_reader->GetStream("GameSettings.txt", settingsData)) {
|
||||
MessageManager::Log("[Movie] File not found: GameSettings.txt");
|
||||
return false;
|
||||
}
|
||||
if(!_reader->GetStream("Input.txt", inputData)) {
|
||||
MessageManager::Log("[Movie] File not found: Input.txt");
|
||||
return false;
|
||||
}
|
||||
|
||||
while(inputData) {
|
||||
string line;
|
||||
std::getline(inputData, line);
|
||||
if(line.substr(0, 1) == "|") {
|
||||
_inputData.push_back(StringUtilities::Split(line.substr(1), '|'));
|
||||
}
|
||||
}
|
||||
|
||||
_deviceIndex = 0;
|
||||
|
||||
ParseSettings(settingsData);
|
||||
|
||||
_console->Lock();
|
||||
|
||||
_console->GetBatteryManager()->SetBatteryProvider(shared_from_this());
|
||||
_console->GetNotificationManager()->RegisterNotificationListener(shared_from_this());
|
||||
ApplySettings();
|
||||
|
||||
//TODO
|
||||
//Disable auto-configure input option (otherwise the movie file's input types are ignored)
|
||||
//bool autoConfigureInput = _console->GetSettings()->CheckFlag(EmulationFlags::AutoConfigureInput);
|
||||
//_console->GetSettings()->ClearFlags(EmulationFlags::AutoConfigureInput);
|
||||
|
||||
ControlManager *controlManager = _console->GetControlManager().get();
|
||||
if(controlManager) {
|
||||
//ControlManager can be empty if no game is loaded
|
||||
controlManager->SetPollCounter(0);
|
||||
}
|
||||
|
||||
//bool gameLoaded = LoadGame();
|
||||
//TODO
|
||||
//_console->GetSettings()->SetFlagState(EmulationFlags::AutoConfigureInput, autoConfigureInput);
|
||||
|
||||
/*if(!gameLoaded) {
|
||||
_console->Unlock();
|
||||
return false;
|
||||
}*/
|
||||
|
||||
_console->PowerCycle();
|
||||
|
||||
stringstream saveStateData;
|
||||
if(_reader->GetStream("SaveState.mss", saveStateData)) {
|
||||
if(!_console->GetSaveStateManager()->LoadState(saveStateData, true)) {
|
||||
_console->Resume();
|
||||
return false;
|
||||
} else {
|
||||
_console->GetControlManager()->SetPollCounter(0);
|
||||
}
|
||||
}
|
||||
|
||||
_playing = true;
|
||||
|
||||
_console->Unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T FromString(string name, const vector<string> &enumNames, T defaultValue)
|
||||
{
|
||||
for(size_t i = 0; i < enumNames.size(); i++) {
|
||||
if(name == enumNames[i]) {
|
||||
return (T)i;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
void MesenMovie::ParseSettings(stringstream &data)
|
||||
{
|
||||
while(!data.eof()) {
|
||||
string line;
|
||||
std::getline(data, line);
|
||||
|
||||
if(!line.empty()) {
|
||||
size_t index = line.find_first_of(' ');
|
||||
if(index != string::npos) {
|
||||
string name = line.substr(0, index);
|
||||
string value = line.substr(index + 1);
|
||||
|
||||
if(name == "Cheat") {
|
||||
_cheats.push_back(value);
|
||||
} else {
|
||||
_settings[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MesenMovie::LoadGame()
|
||||
{
|
||||
/*string mesenVersion = LoadString(_settings, MovieKeys::MesenVersion);
|
||||
string gameFile = LoadString(_settings, MovieKeys::GameFile);
|
||||
string sha1Hash = LoadString(_settings, MovieKeys::Sha1);
|
||||
//string patchFile = LoadString(_settings, MovieKeys::PatchFile);
|
||||
//string patchFileSha1 = LoadString(_settings, MovieKeys::PatchFileSha1);
|
||||
//string patchedRomSha1 = LoadString(_settings, MovieKeys::PatchedRomSha1);
|
||||
|
||||
if(_console->GetSettings()->CheckFlag(EmulationFlags::AllowMismatchingSaveState) && _console->GetRomInfo().RomName == gameFile) {
|
||||
//Loaded game has the right name, and we don't want to validate the hash values
|
||||
_console->PowerCycle();
|
||||
return true;
|
||||
}
|
||||
|
||||
HashInfo hashInfo;
|
||||
hashInfo.Sha1 = sha1Hash;
|
||||
|
||||
VirtualFile romFile = _console->FindMatchingRom(gameFile, hashInfo);
|
||||
bool gameLoaded = false;
|
||||
if(romFile.IsValid()) {
|
||||
VirtualFile patchFile(_movieFile.GetFilePath(), "PatchData.dat");
|
||||
if(patchFile.IsValid()) {
|
||||
gameLoaded = _console->Initialize(romFile, patchFile);
|
||||
} else {
|
||||
gameLoaded = _console->Initialize(romFile);
|
||||
}
|
||||
}
|
||||
|
||||
return gameLoaded;*/
|
||||
return true;
|
||||
}
|
||||
|
||||
void MesenMovie::ApplySettings()
|
||||
{
|
||||
EmuSettings* settings = _console->GetSettings().get();
|
||||
EmulationConfig emuConfig = settings->GetEmulationConfig();
|
||||
InputConfig inputConfig = settings->GetInputConfig();
|
||||
|
||||
inputConfig.Controllers[0].Type = FromString(LoadString(_settings, MovieKeys::Controller1), ControllerTypeNames, ControllerType::None);
|
||||
inputConfig.Controllers[1].Type = FromString(LoadString(_settings, MovieKeys::Controller2), ControllerTypeNames, ControllerType::None);
|
||||
inputConfig.Controllers[2].Type = FromString(LoadString(_settings, MovieKeys::Controller3), ControllerTypeNames, ControllerType::None);
|
||||
inputConfig.Controllers[3].Type = FromString(LoadString(_settings, MovieKeys::Controller4), ControllerTypeNames, ControllerType::None);
|
||||
inputConfig.Controllers[4].Type = FromString(LoadString(_settings, MovieKeys::Controller5), ControllerTypeNames, ControllerType::None);
|
||||
|
||||
emuConfig.Region = FromString(LoadString(_settings, MovieKeys::Region), ConsoleRegionNames, ConsoleRegion::Ntsc);
|
||||
emuConfig.RamPowerOnState = FromString(LoadString(_settings, MovieKeys::RamPowerOnState), RamStateNames, RamState::AllOnes);
|
||||
emuConfig.PpuExtraScanlinesAfterNmi = LoadInt(_settings, MovieKeys::ExtraScanlinesAfterNmi);
|
||||
emuConfig.PpuExtraScanlinesBeforeNmi = LoadInt(_settings, MovieKeys::ExtraScanlinesBeforeNmi);
|
||||
|
||||
settings->SetEmulationConfig(emuConfig);
|
||||
settings->SetInputConfig(inputConfig);
|
||||
}
|
||||
|
||||
uint32_t MesenMovie::LoadInt(std::unordered_map<string, string> &settings, string name, uint32_t defaultValue)
|
||||
{
|
||||
auto result = settings.find(name);
|
||||
if(result != settings.end()) {
|
||||
try {
|
||||
return (uint32_t)std::stoul(result->second);
|
||||
} catch(std::exception ex) {
|
||||
MessageManager::Log("[Movies] Invalid value for tag: " + name);
|
||||
return defaultValue;
|
||||
}
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
bool MesenMovie::LoadBool(std::unordered_map<string, string> &settings, string name)
|
||||
{
|
||||
auto result = settings.find(name);
|
||||
if(result != settings.end()) {
|
||||
if(result->second == "true") {
|
||||
return true;
|
||||
} else if(result->second == "false") {
|
||||
return false;
|
||||
} else {
|
||||
MessageManager::Log("[Movies] Invalid value for tag: " + name);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string MesenMovie::LoadString(std::unordered_map<string, string> &settings, string name)
|
||||
{
|
||||
auto result = settings.find(name);
|
||||
if(result != settings.end()) {
|
||||
return result->second;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
50
Core/MesenMovie.h
Normal file
50
Core/MesenMovie.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "MovieManager.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "BatteryManager.h"
|
||||
#include "INotificationListener.h"
|
||||
|
||||
class ZipReader;
|
||||
class Console;
|
||||
|
||||
class MesenMovie : public IMovie, public INotificationListener, public IBatteryProvider, public std::enable_shared_from_this<MesenMovie>
|
||||
{
|
||||
private:
|
||||
shared_ptr<Console> _console;
|
||||
|
||||
VirtualFile _movieFile;
|
||||
shared_ptr<ZipReader> _reader;
|
||||
bool _playing = false;
|
||||
size_t _deviceIndex = 0;
|
||||
uint32_t _lastPollCounter = 0;
|
||||
vector<vector<string>> _inputData;
|
||||
vector<string> _cheats;
|
||||
std::unordered_map<string, string> _settings;
|
||||
string _filename;
|
||||
|
||||
private:
|
||||
void ParseSettings(stringstream &data);
|
||||
void ApplySettings();
|
||||
bool LoadGame();
|
||||
void Stop();
|
||||
|
||||
uint32_t LoadInt(std::unordered_map<string, string> &settings, string name, uint32_t defaultValue = 0);
|
||||
bool LoadBool(std::unordered_map<string, string> &settings, string name);
|
||||
string LoadString(std::unordered_map<string, string> &settings, string name);
|
||||
|
||||
public:
|
||||
MesenMovie(shared_ptr<Console> console);
|
||||
virtual ~MesenMovie();
|
||||
|
||||
bool Play(VirtualFile &file) override;
|
||||
bool SetInput(BaseControlDevice* device) override;
|
||||
bool IsPlaying() override;
|
||||
|
||||
//Inherited via IBatteryProvider
|
||||
vector<uint8_t> LoadBattery(string extension) override;
|
||||
|
||||
//Inherited via INotificationListener
|
||||
void ProcessNotification(ConsoleNotificationType type, void * parameter) override;
|
||||
};
|
|
@ -33,6 +33,7 @@ std::unordered_map<string, string> MessageManager::_enResources = {
|
|||
{ "CouldNotConnect", u8"Could not connect to the server." },
|
||||
{ "CouldNotInitializeAudioSystem", u8"Could not initialize audio system" },
|
||||
{ "CouldNotFindRom", u8"Could not find matching game ROM." },
|
||||
{ "CouldNotWriteToFile", u8"Could not write to file: %1" },
|
||||
{ "CouldNotLoadFile", u8"Could not load file: %1" },
|
||||
{ "EmulationMaximumSpeed", u8"Maximum speed" },
|
||||
{ "EmulationSpeedPercent", u8"%1%" },
|
||||
|
|
62
Core/MovieManager.cpp
Normal file
62
Core/MovieManager.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "stdafx.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "../Utilities/ZipReader.h"
|
||||
#include "MovieManager.h"
|
||||
#include "MesenMovie.h"
|
||||
#include "MovieRecorder.h"
|
||||
|
||||
shared_ptr<IMovie> MovieManager::_player;
|
||||
shared_ptr<MovieRecorder> MovieManager::_recorder;
|
||||
|
||||
void MovieManager::Record(RecordMovieOptions options, shared_ptr<Console> console)
|
||||
{
|
||||
shared_ptr<MovieRecorder> recorder(new MovieRecorder(console));
|
||||
if(recorder->Record(options)) {
|
||||
_recorder = recorder;
|
||||
}
|
||||
}
|
||||
|
||||
void MovieManager::Play(VirtualFile file, shared_ptr<Console> console)
|
||||
{
|
||||
vector<uint8_t> fileData;
|
||||
if(file.IsValid() && file.ReadFile(fileData)) {
|
||||
shared_ptr<IMovie> player;
|
||||
if(memcmp(fileData.data(), "PK", 2) == 0) {
|
||||
//Mesen movie
|
||||
ZipReader reader;
|
||||
reader.LoadArchive(fileData);
|
||||
|
||||
vector<string> files = reader.GetFileList();
|
||||
if(std::find(files.begin(), files.end(), "GameSettings.txt") != files.end()) {
|
||||
player.reset(new MesenMovie(console));
|
||||
}
|
||||
}
|
||||
|
||||
if(player && player->Play(file)) {
|
||||
_player = player;
|
||||
MessageManager::DisplayMessage("Movies", "MoviePlaying", file.GetFileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovieManager::Stop()
|
||||
{
|
||||
_player.reset();
|
||||
|
||||
if(_recorder) {
|
||||
_recorder->Stop();
|
||||
_recorder.reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool MovieManager::Playing()
|
||||
{
|
||||
shared_ptr<IMovie> player = _player;
|
||||
return player && player->IsPlaying();
|
||||
}
|
||||
|
||||
bool MovieManager::Recording()
|
||||
{
|
||||
return _recorder != nullptr;
|
||||
}
|
30
Core/MovieManager.h
Normal file
30
Core/MovieManager.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "MessageManager.h"
|
||||
#include "IInputProvider.h"
|
||||
#include "MovieTypes.h"
|
||||
|
||||
class MovieRecorder;
|
||||
class VirtualFile;
|
||||
class Console;
|
||||
|
||||
class IMovie : public IInputProvider
|
||||
{
|
||||
public:
|
||||
virtual bool Play(VirtualFile &file) = 0;
|
||||
virtual bool IsPlaying() = 0;
|
||||
};
|
||||
|
||||
class MovieManager
|
||||
{
|
||||
private:
|
||||
static shared_ptr<IMovie> _player;
|
||||
static shared_ptr<MovieRecorder> _recorder;
|
||||
|
||||
public:
|
||||
static void Record(RecordMovieOptions options, shared_ptr<Console> console);
|
||||
static void Play(VirtualFile file, shared_ptr<Console> console);
|
||||
static void Stop();
|
||||
static bool Playing();
|
||||
static bool Recording();
|
||||
};
|
234
Core/MovieRecorder.cpp
Normal file
234
Core/MovieRecorder.cpp
Normal file
|
@ -0,0 +1,234 @@
|
|||
#include "stdafx.h"
|
||||
#include <deque>
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/ZipWriter.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "MovieRecorder.h"
|
||||
#include "MessageManager.h"
|
||||
#include "ControlManager.h"
|
||||
#include "BaseControlDevice.h"
|
||||
#include "Console.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "SaveStateManager.h"
|
||||
#include "NotificationManager.h"
|
||||
#include "RewindData.h"
|
||||
#include "MovieTypes.h"
|
||||
#include "BatteryManager.h"
|
||||
|
||||
MovieRecorder::MovieRecorder(shared_ptr<Console> console)
|
||||
{
|
||||
_console = console;
|
||||
}
|
||||
|
||||
MovieRecorder::~MovieRecorder()
|
||||
{
|
||||
}
|
||||
|
||||
bool MovieRecorder::Record(RecordMovieOptions options)
|
||||
{
|
||||
_filename = options.Filename;
|
||||
_author = options.Author;
|
||||
_description = options.Description;
|
||||
_writer.reset(new ZipWriter());
|
||||
_inputData = stringstream();
|
||||
_saveStateData = stringstream();
|
||||
_hasSaveState = false;
|
||||
|
||||
if(!_writer->Initialize(_filename)) {
|
||||
MessageManager::DisplayMessage("Movies", "CouldNotWriteToFile", FolderUtilities::GetFilename(_filename, true));
|
||||
_writer.reset();
|
||||
return false;
|
||||
} else {
|
||||
_console->Lock();
|
||||
_console->GetNotificationManager()->RegisterNotificationListener(shared_from_this());
|
||||
|
||||
if(options.RecordFrom == RecordMovieFrom::StartWithoutSaveData) {
|
||||
//Power cycle and ignore save data that exists on the disk
|
||||
_console->GetBatteryManager()->SetBatteryProvider(shared_from_this());
|
||||
_console->PowerCycle();
|
||||
} else if(options.RecordFrom == RecordMovieFrom::StartWithSaveData) {
|
||||
//Power cycle and save existing battery files into the movie file
|
||||
_console->GetBatteryManager()->SetBatteryRecorder(shared_from_this());
|
||||
_console->PowerCycle();
|
||||
} else if(options.RecordFrom == RecordMovieFrom::CurrentState) {
|
||||
//Record from current state, store a save state in the movie file
|
||||
_console->GetControlManager()->RegisterInputRecorder(this);
|
||||
_console->GetSaveStateManager()->SaveState(_saveStateData);
|
||||
_hasSaveState = true;
|
||||
}
|
||||
|
||||
_console->GetBatteryManager()->SetBatteryRecorder(nullptr);
|
||||
_console->Unlock();
|
||||
|
||||
MessageManager::DisplayMessage("Movies", "MovieRecordingTo", FolderUtilities::GetFilename(_filename, true));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void MovieRecorder::GetGameSettings(stringstream &out)
|
||||
{
|
||||
EmuSettings* settings = _console->GetSettings().get();
|
||||
EmulationConfig emuConfig = settings->GetEmulationConfig();
|
||||
InputConfig inputConfig = settings->GetInputConfig();
|
||||
|
||||
WriteString(out, MovieKeys::MesenVersion, settings->GetVersionString());
|
||||
WriteInt(out, MovieKeys::MovieFormatVersion, MovieRecorder::MovieFormatVersion);
|
||||
|
||||
VirtualFile romFile = _console->GetRomInfo().RomFile;
|
||||
WriteString(out, MovieKeys::GameFile, romFile.GetFileName());
|
||||
WriteString(out, MovieKeys::Sha1, romFile.GetSha1Hash());
|
||||
|
||||
VirtualFile patchFile = _console->GetRomInfo().PatchFile;
|
||||
if(patchFile.IsValid()) {
|
||||
WriteString(out, MovieKeys::PatchFile, patchFile.GetFileName());
|
||||
WriteString(out, MovieKeys::PatchFileSha1, patchFile.GetSha1Hash());
|
||||
|
||||
romFile.ApplyPatch(patchFile);
|
||||
WriteString(out, MovieKeys::PatchedRomSha1, romFile.GetSha1Hash());
|
||||
}
|
||||
|
||||
ConsoleRegion region = _console->GetRegion();
|
||||
switch(region) {
|
||||
case ConsoleRegion::Auto:
|
||||
case ConsoleRegion::Ntsc: WriteString(out, MovieKeys::Region, "NTSC"); break;
|
||||
|
||||
case ConsoleRegion::Pal: WriteString(out, MovieKeys::Region, "PAL"); break;
|
||||
}
|
||||
|
||||
WriteString(out, MovieKeys::Controller1, ControllerTypeNames[(int)inputConfig.Controllers[0].Type]);
|
||||
WriteString(out, MovieKeys::Controller2, ControllerTypeNames[(int)inputConfig.Controllers[1].Type]);
|
||||
WriteString(out, MovieKeys::Controller3, ControllerTypeNames[(int)inputConfig.Controllers[2].Type]);
|
||||
WriteString(out, MovieKeys::Controller4, ControllerTypeNames[(int)inputConfig.Controllers[3].Type]);
|
||||
WriteString(out, MovieKeys::Controller5, ControllerTypeNames[(int)inputConfig.Controllers[4].Type]);
|
||||
|
||||
WriteInt(out, MovieKeys::ExtraScanlinesBeforeNmi, emuConfig.PpuExtraScanlinesBeforeNmi);
|
||||
WriteInt(out, MovieKeys::ExtraScanlinesAfterNmi, emuConfig.PpuExtraScanlinesAfterNmi);
|
||||
|
||||
switch(emuConfig.RamPowerOnState) {
|
||||
case RamState::AllZeros: WriteString(out, MovieKeys::RamPowerOnState, "AllZeros"); break;
|
||||
case RamState::AllOnes: WriteString(out, MovieKeys::RamPowerOnState, "AllOnes"); break;
|
||||
case RamState::Random: WriteString(out, MovieKeys::RamPowerOnState, "AllOnes"); break; //TODO: Random memory isn't supported for movies yet
|
||||
}
|
||||
}
|
||||
|
||||
void MovieRecorder::WriteString(stringstream &out, string name, string value)
|
||||
{
|
||||
out << name << " " << value << "\n";
|
||||
}
|
||||
|
||||
void MovieRecorder::WriteInt(stringstream &out, string name, uint32_t value)
|
||||
{
|
||||
out << name << " " << std::to_string(value) << "\n";
|
||||
}
|
||||
|
||||
void MovieRecorder::WriteBool(stringstream &out, string name, bool enabled)
|
||||
{
|
||||
out << name << " " << (enabled ? "true" : "false") << "\n";
|
||||
}
|
||||
|
||||
bool MovieRecorder::Stop()
|
||||
{
|
||||
if(_writer) {
|
||||
_console->GetControlManager()->UnregisterInputRecorder(this);
|
||||
|
||||
_writer->AddFile(_inputData, "Input.txt");
|
||||
|
||||
stringstream out;
|
||||
GetGameSettings(out);
|
||||
_writer->AddFile(out, "GameSettings.txt");
|
||||
|
||||
if(!_author.empty() || !_description.empty()) {
|
||||
stringstream movieInfo;
|
||||
WriteString(movieInfo, "Author", _author);
|
||||
movieInfo << "Description\n" << _description;
|
||||
_writer->AddFile(movieInfo, "MovieInfo.txt");
|
||||
}
|
||||
|
||||
VirtualFile patchFile = _console->GetRomInfo().PatchFile;
|
||||
vector<uint8_t> patchData;
|
||||
if(patchFile.IsValid() && patchFile.ReadFile(patchData)) {
|
||||
_writer->AddFile(patchData, "PatchData.dat");
|
||||
}
|
||||
|
||||
if(_hasSaveState) {
|
||||
_writer->AddFile(_saveStateData, "SaveState.mss");
|
||||
}
|
||||
|
||||
for(auto kvp : _batteryData) {
|
||||
_writer->AddFile(kvp.second, "Battery" + kvp.first);
|
||||
}
|
||||
|
||||
bool result = _writer->Save();
|
||||
if(result) {
|
||||
MessageManager::DisplayMessage("Movies", "MovieSaved", FolderUtilities::GetFilename(_filename, true));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MovieRecorder::RecordInput(vector<shared_ptr<BaseControlDevice>> devices)
|
||||
{
|
||||
for(shared_ptr<BaseControlDevice> &device : devices) {
|
||||
_inputData << ("|" + device->GetTextState());
|
||||
}
|
||||
_inputData << "\n";
|
||||
}
|
||||
|
||||
void MovieRecorder::OnLoadBattery(string extension, vector<uint8_t> batteryData)
|
||||
{
|
||||
_batteryData[extension] = batteryData;
|
||||
}
|
||||
|
||||
vector<uint8_t> MovieRecorder::LoadBattery(string extension)
|
||||
{
|
||||
return vector<uint8_t>();
|
||||
}
|
||||
|
||||
void MovieRecorder::ProcessNotification(ConsoleNotificationType type, void *parameter)
|
||||
{
|
||||
if(type == ConsoleNotificationType::GameLoaded) {
|
||||
_console->GetControlManager()->RegisterInputRecorder(this);
|
||||
}
|
||||
}
|
||||
/*
|
||||
bool MovieRecorder::CreateMovie(string movieFile, std::deque<RewindData> &data, uint32_t startPosition, uint32_t endPosition)
|
||||
{
|
||||
_filename = movieFile;
|
||||
_writer.reset(new ZipWriter());
|
||||
if(startPosition < data.size() && endPosition <= data.size() && _writer->Initialize(_filename)) {
|
||||
vector<shared_ptr<BaseControlDevice>> devices = _console->GetControlManager()->GetControlDevices();
|
||||
|
||||
if(startPosition > 0 || _console->GetRomInfo().HasBattery || _console->GetSettings()->GetRamPowerOnState() == RamPowerOnState::Random) {
|
||||
//Create a movie from a savestate if we don't start from the beginning (or if the game has save ram, or if the power on ram state is random)
|
||||
_hasSaveState = true;
|
||||
_saveStateData = stringstream();
|
||||
_console->GetSaveStateManager()->GetSaveStateHeader(_saveStateData);
|
||||
data[startPosition].GetStateData(_saveStateData);
|
||||
}
|
||||
|
||||
_inputData = stringstream();
|
||||
|
||||
for(uint32_t i = startPosition; i < endPosition; i++) {
|
||||
RewindData rewindData = data[i];
|
||||
for(uint32_t i = 0; i < 30; i++) {
|
||||
for(shared_ptr<BaseControlDevice> &device : devices) {
|
||||
uint8_t port = device->GetPort();
|
||||
if(i < rewindData.InputLogs[port].size()) {
|
||||
device->SetRawState(rewindData.InputLogs[port][i]);
|
||||
_inputData << ("|" + device->GetTextState());
|
||||
}
|
||||
}
|
||||
_inputData << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
//Write the movie file
|
||||
return Stop();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
52
Core/MovieRecorder.h
Normal file
52
Core/MovieRecorder.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include <deque>
|
||||
#include <unordered_map>
|
||||
#include "IInputRecorder.h"
|
||||
#include "BatteryManager.h"
|
||||
#include "INotificationListener.h"
|
||||
#include "MovieTypes.h"
|
||||
|
||||
class ZipWriter;
|
||||
class Console;
|
||||
//class RewindData;
|
||||
//struct CodeInfo;
|
||||
|
||||
class MovieRecorder : public INotificationListener, public IInputRecorder, public IBatteryRecorder, public IBatteryProvider, public std::enable_shared_from_this<MovieRecorder>
|
||||
{
|
||||
private:
|
||||
static const uint32_t MovieFormatVersion = 1;
|
||||
|
||||
shared_ptr<Console> _console;
|
||||
string _filename;
|
||||
string _author;
|
||||
string _description;
|
||||
unique_ptr<ZipWriter> _writer;
|
||||
std::unordered_map<string, vector<uint8_t>> _batteryData;
|
||||
stringstream _inputData;
|
||||
bool _hasSaveState = false;
|
||||
stringstream _saveStateData;
|
||||
|
||||
void GetGameSettings(stringstream &out);
|
||||
//void WriteCheat(stringstream &out, CodeInfo &code);
|
||||
void WriteString(stringstream &out, string name, string value);
|
||||
void WriteInt(stringstream &out, string name, uint32_t value);
|
||||
void WriteBool(stringstream &out, string name, bool enabled);
|
||||
|
||||
public:
|
||||
MovieRecorder(shared_ptr<Console> console);
|
||||
virtual ~MovieRecorder();
|
||||
|
||||
bool Record(RecordMovieOptions options);
|
||||
bool Stop();
|
||||
|
||||
// Inherited via IInputRecorder
|
||||
void RecordInput(vector<shared_ptr<BaseControlDevice>> devices) override;
|
||||
|
||||
// Inherited via IBatteryRecorder
|
||||
void OnLoadBattery(string extension, vector<uint8_t> batteryData) override;
|
||||
vector<uint8_t> LoadBattery(string extension) override;
|
||||
|
||||
// Inherited via INotificationListener
|
||||
void ProcessNotification(ConsoleNotificationType type, void *parameter) override;
|
||||
};
|
60
Core/MovieTypes.h
Normal file
60
Core/MovieTypes.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
enum class RecordMovieFrom
|
||||
{
|
||||
StartWithoutSaveData = 0,
|
||||
StartWithSaveData,
|
||||
CurrentState
|
||||
};
|
||||
|
||||
struct RecordMovieOptions
|
||||
{
|
||||
char Filename[2000] = {};
|
||||
char Author[250] = {};
|
||||
char Description[10000] = {};
|
||||
|
||||
RecordMovieFrom RecordFrom = RecordMovieFrom::StartWithoutSaveData;
|
||||
};
|
||||
|
||||
const vector<string> ConsoleRegionNames = {
|
||||
"Auto",
|
||||
"NTSC",
|
||||
"PAL"
|
||||
};
|
||||
|
||||
const vector<string> ControllerTypeNames = {
|
||||
"None",
|
||||
"SnesController",
|
||||
"SnesMouse",
|
||||
"SuperScope",
|
||||
"Multitap"
|
||||
};
|
||||
|
||||
const vector<string> RamStateNames = {
|
||||
"AllZeros",
|
||||
"AllOnes",
|
||||
"Random"
|
||||
};
|
||||
|
||||
namespace MovieKeys
|
||||
{
|
||||
constexpr const char* MesenVersion = "MesenVersion";
|
||||
constexpr const char* MovieFormatVersion = "MovieFormatVersion";
|
||||
constexpr const char* GameFile = "GameFile";
|
||||
constexpr const char* Sha1 = "SHA1";
|
||||
constexpr const char* PatchFile = "PatchFile";
|
||||
constexpr const char* PatchFileSha1 = "PatchFileSHA1";
|
||||
constexpr const char* PatchedRomSha1 = "PatchedRomSHA1";
|
||||
constexpr const char* Region = "Region";
|
||||
constexpr const char* ConsoleType = "ConsoleType";
|
||||
constexpr const char* Controller1 = "Controller1";
|
||||
constexpr const char* Controller2 = "Controller2";
|
||||
constexpr const char* Controller3 = "Controller3";
|
||||
constexpr const char* Controller4 = "Controller4";
|
||||
constexpr const char* Controller5 = "Controller5";
|
||||
constexpr const char* ExtraScanlinesBeforeNmi = "ExtraScanlinesBeforeNmi";
|
||||
constexpr const char* ExtraScanlinesAfterNmi = "ExtraScanlinesAfterNmi";
|
||||
constexpr const char* RamPowerOnState = "RamPowerOnState";
|
||||
constexpr const char* InputPollScanline = "InputPollScanline";
|
||||
};
|
|
@ -17,8 +17,8 @@ private:
|
|||
protected:
|
||||
string GetKeyNames() override
|
||||
{
|
||||
//Repeat key names 4x to
|
||||
return string("ABXYLRSTUDLR") + "ABXYLRSTUDLR" + "ABXYLRSTUDLR" + "ABXYLRSTUDLR";
|
||||
//Repeat key names 4x, once for each controller
|
||||
return "ABXYLRSTUDLR:ABXYLRSTUDLR:ABXYLRSTUDLR:ABXYLRSTUDLR";
|
||||
}
|
||||
|
||||
void InternalSetStateFromInput() override
|
||||
|
@ -88,7 +88,8 @@ public:
|
|||
|
||||
uint8_t ReadRam(uint16_t addr) override
|
||||
{
|
||||
uint8_t portSelect = (_internalRegs->GetIoPortOutput() & 0x80) ? 0 : 2;
|
||||
uint8_t selectBit = 0x80 >> ((_port == 0) ? 1 : 0);
|
||||
uint8_t portSelect = (_internalRegs->GetIoPortOutput() & selectBit) ? 0 : 2;
|
||||
uint8_t output = 0;
|
||||
|
||||
if(IsCurrentPort(addr)) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "MessageManager.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "RamHandler.h"
|
||||
#include "BatteryManager.h"
|
||||
#include "FirmwareHelper.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
|
||||
|
@ -105,19 +106,17 @@ void NecDsp::Reset()
|
|||
_state = {};
|
||||
}
|
||||
|
||||
void NecDsp::LoadBattery(string filePath)
|
||||
void NecDsp::LoadBattery()
|
||||
{
|
||||
if(_type == CoprocessorType::ST010 || _type == CoprocessorType::ST011) {
|
||||
VirtualFile saveFile(filePath);
|
||||
saveFile.ReadFile((uint8_t*)_ram, _ramSize * sizeof(uint16_t));
|
||||
_console->GetBatteryManager()->LoadBattery(".srm", (uint8_t*)_ram, _ramSize * sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
|
||||
void NecDsp::SaveBattery(string filePath)
|
||||
void NecDsp::SaveBattery()
|
||||
{
|
||||
if(_type == CoprocessorType::ST010 || _type == CoprocessorType::ST011) {
|
||||
ofstream saveFile(filePath, ios::binary);
|
||||
saveFile.write((char*)_ram, _ramSize * sizeof(uint16_t));
|
||||
_console->GetBatteryManager()->SaveBattery(".srm", (uint8_t*)_ram, _ramSize * sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@ public:
|
|||
void Reset() override;
|
||||
void Run();
|
||||
|
||||
void LoadBattery(string filePath) override;
|
||||
void SaveBattery(string filePath) override;
|
||||
void LoadBattery() override;
|
||||
void SaveBattery() override;
|
||||
|
||||
uint8_t Read(uint32_t addr) override;
|
||||
void Write(uint32_t addr, uint8_t value) override;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "EmuSettings.h"
|
||||
#include "VideoDecoder.h"
|
||||
#include "BaseCartridge.h"
|
||||
#include "MovieManager.h"
|
||||
|
||||
SaveStateManager::SaveStateManager(shared_ptr<Console> console)
|
||||
{
|
||||
|
@ -148,7 +149,7 @@ bool SaveStateManager::LoadState(istream &stream, bool hashCheckRequired)
|
|||
|
||||
//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();
|
||||
MovieManager::Stop();
|
||||
|
||||
_console->Deserialize(stream, fileFormatVersion);
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ struct AudioConfig
|
|||
double Band20Gain = 0;
|
||||
};
|
||||
|
||||
//Update ControllerTypeNames when changing this
|
||||
enum class ControllerType
|
||||
{
|
||||
None = 0,
|
||||
|
@ -277,6 +278,7 @@ struct PreferencesConfig
|
|||
bool ShowDebugInfo = false;
|
||||
bool DisableOsd = false;
|
||||
bool AllowBackgroundInput = false;
|
||||
bool PauseOnMovieEnd = false;
|
||||
|
||||
uint32_t RewindBufferSize = 30;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "RewindManager.h"
|
||||
#include "NotificationManager.h"
|
||||
#include "SaveStateManager.h"
|
||||
#include "MovieManager.h"
|
||||
|
||||
ShortcutKeyHandler::ShortcutKeyHandler(shared_ptr<Console> console)
|
||||
{
|
||||
|
@ -102,8 +103,8 @@ void ShortcutKeyHandler::CheckMappedKeys()
|
|||
{
|
||||
shared_ptr<EmuSettings> settings = _console->GetSettings();
|
||||
bool isNetplayClient = false; //TODO GameClient::Connected();
|
||||
//bool isMovieActive = false; //TODO MovieManager::Playing() || MovieManager::Recording();
|
||||
bool isMovieRecording = false; //TODO MovieManager::Recording();
|
||||
//bool isMovieActive = MovieManager::Playing() || MovieManager::Recording();
|
||||
bool isMovieRecording = MovieManager::Recording();
|
||||
|
||||
//Let the UI handle these shortcuts
|
||||
for(uint64_t i = (uint64_t)EmulatorShortcut::TakeScreenshot; i < (uint64_t)EmulatorShortcut::ShortcutCount; i++) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "../Core/Console.h"
|
||||
#include "../Core/VideoRenderer.h"
|
||||
#include "../Core/SoundMixer.h"
|
||||
#include "../Core/MovieManager.h"
|
||||
|
||||
extern shared_ptr<Console> _console;
|
||||
enum class VideoCodec;
|
||||
|
@ -15,4 +16,14 @@ extern "C"
|
|||
DllExport void __stdcall WaveRecord(char* filename) { _console->GetSoundMixer()->StartRecording(filename); }
|
||||
DllExport void __stdcall WaveStop() { _console->GetSoundMixer()->StopRecording(); }
|
||||
DllExport bool __stdcall WaveIsRecording() { return _console->GetSoundMixer()->IsRecording(); }
|
||||
|
||||
DllExport void __stdcall MoviePlay(char* filename) { MovieManager::Play(string(filename), _console); }
|
||||
DllExport void __stdcall MovieStop() { MovieManager::Stop(); }
|
||||
DllExport bool __stdcall MoviePlaying() { return MovieManager::Playing(); }
|
||||
DllExport bool __stdcall MovieRecording() { return MovieManager::Recording(); }
|
||||
DllExport void __stdcall MovieRecord(RecordMovieOptions *options)
|
||||
{
|
||||
RecordMovieOptions opt = *options;
|
||||
MovieManager::Record(opt, _console);
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \
|
|||
$(CORE_DIR)/BaseRenderer.cpp \
|
||||
$(CORE_DIR)/BaseSoundManager.cpp \
|
||||
$(CORE_DIR)/BaseVideoFilter.cpp \
|
||||
$(CORE_DIR)/BatteryManager.cpp \
|
||||
$(CORE_DIR)/Breakpoint.cpp \
|
||||
$(CORE_DIR)/BreakpointManager.cpp \
|
||||
$(CORE_DIR)/CallstackManager.cpp \
|
||||
|
@ -61,7 +62,10 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \
|
|||
$(CORE_DIR)/MemoryDumper.cpp \
|
||||
$(CORE_DIR)/MemoryManager.cpp \
|
||||
$(CORE_DIR)/MemoryMappings.cpp \
|
||||
$(CORE_DIR)/MesenMovie.cpp \
|
||||
$(CORE_DIR)/MessageManager.cpp \
|
||||
$(CORE_DIR)/MovieManager.cpp \
|
||||
$(CORE_DIR)/MovieRecorder.cpp \
|
||||
$(CORE_DIR)/NecDsp.cpp \
|
||||
$(CORE_DIR)/NecDspDisUtils.cpp \
|
||||
$(CORE_DIR)/NotificationManager.cpp \
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Mesen.GUI.Config
|
|||
public DebugInfo Debug;
|
||||
public RecentItems RecentFiles;
|
||||
public AviRecordConfig AviRecord;
|
||||
public MovieRecordConfig MovieRecord;
|
||||
public Point WindowLocation;
|
||||
public Size WindowSize;
|
||||
public bool NeedInputReinit = true;
|
||||
|
@ -38,6 +39,7 @@ namespace Mesen.GUI.Config
|
|||
Emulation = new EmulationConfig();
|
||||
Preferences = new PreferencesConfig();
|
||||
AviRecord = new AviRecordConfig();
|
||||
MovieRecord = new MovieRecordConfig();
|
||||
}
|
||||
|
||||
~Configuration()
|
||||
|
|
|
@ -77,8 +77,8 @@ namespace Mesen.GUI.Config
|
|||
CreateMimeType("x-mesen-nes", "smc", "SNES Rom", mimeTypes, cfg.AssociateRomFiles);
|
||||
CreateMimeType("x-mesen-nes", "swc", "SNES Rom", mimeTypes, cfg.AssociateRomFiles);
|
||||
CreateMimeType("x-mesen-nes", "fig", "SNES Rom", mimeTypes, cfg.AssociateRomFiles);
|
||||
CreateMimeType("x-mesen-mst", "mst", "Mesen-S Save State", mimeTypes, cfg.AssociateMssFiles);
|
||||
CreateMimeType("x-mesen-mmo", "mmo", "Mesen-S Movie File", mimeTypes, cfg.AssociateMsmFiles);
|
||||
CreateMimeType("x-mesen-mss", "mss", "Mesen-S Save State", mimeTypes, cfg.AssociateMssFiles);
|
||||
CreateMimeType("x-mesen-msm", "msm", "Mesen-S Movie File", mimeTypes, cfg.AssociateMsmFiles);
|
||||
|
||||
//Icon used for shortcuts
|
||||
//TOOD
|
||||
|
|
15
UI/Config/MovieRecordConfig.cs
Normal file
15
UI/Config/MovieRecordConfig.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mesen.GUI.Config
|
||||
{
|
||||
public class MovieRecordConfig
|
||||
{
|
||||
public RecordMovieFrom RecordFrom;
|
||||
public string Author;
|
||||
public string Description;
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ namespace Mesen.GUI.Config
|
|||
public bool PauseWhenInMenusAndConfig = false;
|
||||
public bool PauseWhenInDebuggingTools = false;
|
||||
public bool AllowBackgroundInput = false;
|
||||
public bool PauseOnMovieEnd = true;
|
||||
|
||||
public bool AssociateRomFiles = false;
|
||||
public bool AssociateMsmFiles = false;
|
||||
|
@ -86,12 +87,6 @@ namespace Mesen.GUI.Config
|
|||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.ToggleFullscreen, new KeyCombination() { Key1 = InputApi.GetKeyCode("F11") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.TakeScreenshot, new KeyCombination() { Key1 = InputApi.GetKeyCode("F12") }));
|
||||
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.ToggleBgLayer0, new KeyCombination() { Key1 = InputApi.GetKeyCode("1") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.ToggleBgLayer1, new KeyCombination() { Key1 = InputApi.GetKeyCode("2") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.ToggleBgLayer2, new KeyCombination() { Key1 = InputApi.GetKeyCode("3") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.ToggleBgLayer3, new KeyCombination() { Key1 = InputApi.GetKeyCode("4") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.ToggleSprites, new KeyCombination() { Key1 = InputApi.GetKeyCode("5") }));
|
||||
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.Reset, new KeyCombination() { Key1 = InputApi.GetKeyCode("Ctrl"), Key2 = InputApi.GetKeyCode("R") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.PowerCycle, new KeyCombination() { Key1 = InputApi.GetKeyCode("Ctrl"), Key2 = InputApi.GetKeyCode("T") }));
|
||||
ShortcutKeys1.Add(new ShortcutKeyInfo(EmulatorShortcut.Pause, new KeyCombination() { Key1 = InputApi.GetKeyCode("Esc") }));
|
||||
|
@ -161,6 +156,7 @@ namespace Mesen.GUI.Config
|
|||
ShowDebugInfo = ShowDebugInfo,
|
||||
DisableOsd = DisableOsd,
|
||||
AllowBackgroundInput = AllowBackgroundInput,
|
||||
PauseOnMovieEnd = PauseOnMovieEnd,
|
||||
SaveFolderOverride = OverrideSaveDataFolder ? SaveDataFolder : "",
|
||||
SaveStateFolderOverride = OverrideSaveStateFolder ? SaveStateFolder : "",
|
||||
ScreenshotFolderOverride = OverrideScreenshotFolder ? ScreenshotFolder : "",
|
||||
|
@ -177,6 +173,7 @@ namespace Mesen.GUI.Config
|
|||
[MarshalAs(UnmanagedType.I1)] public bool ShowDebugInfo;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool DisableOsd;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool AllowBackgroundInput;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool PauseOnMovieEnd;
|
||||
|
||||
public UInt32 RewindBufferSize;
|
||||
|
||||
|
|
|
@ -672,7 +672,7 @@
|
|||
<Messages>
|
||||
<Message ID="FilterAll">All Files (*.*)|*.*</Message>
|
||||
<Message ID="FilterZipFiles">Zip files (*.zip)|*.zip</Message>
|
||||
<Message ID="FilterMovie">Movie files (*.mmo)|*.mmo|All Files (*.*)|*.*</Message>
|
||||
<Message ID="FilterMovie">Movie files (*.msm)|*.msm|All Files (*.*)|*.*</Message>
|
||||
<Message ID="FilterWave">Wave files (*.wav)|*.wav|All Files (*.*)|*.*</Message>
|
||||
<Message ID="FilterAvi">Avi files (*.avi)|*.avi|All Files (*.*)|*.*</Message>
|
||||
<Message ID="FilterPalette">Palette Files (*.pal)|*.pal|All Files (*.*)|*.*</Message>
|
||||
|
@ -704,7 +704,7 @@
|
|||
|
||||
<Message ID="HelpFullscreen">/fullscreen - Start Mesen-S in fullscreen mode</Message>
|
||||
<Message ID="HelpDoNotSaveSettings">/DoNotSaveSettings - Prevent settings from being saved to the disk (useful to prevent command line options from becoming the default settings)</Message>
|
||||
<Message ID="HelpRecordMovie">/RecordMovie="filename.mmo" - Start recording a movie after the specified game is loaded.</Message>
|
||||
<Message ID="HelpRecordMovie">/RecordMovie="filename.msm" - Start recording a movie after the specified game is loaded.</Message>
|
||||
<Message ID="HelpLoadLastSession">/LoadLastSession - Resumes the game in the state it was left in when it was last played.</Message>
|
||||
|
||||
<Message ID="Resume">Resume</Message>
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace Mesen.GUI.Emulation
|
|||
if(EmuRunner.IsRunning()) {
|
||||
using(SaveFileDialog sfd = new SaveFileDialog()) {
|
||||
sfd.InitialDirectory = ConfigManager.SaveStateFolder;
|
||||
sfd.FileName = EmuApi.GetRomInfo().GetRomName() + ".mst";
|
||||
sfd.FileName = EmuApi.GetRomInfo().GetRomName() + ".mss";
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterSavestate"));
|
||||
if(sfd.ShowDialog(Application.OpenForms[0]) == DialogResult.OK) {
|
||||
EmuApi.SaveStateFile(sfd.FileName);
|
||||
|
|
213
UI/Forms/Config/frmPreferences.Designer.cs
generated
213
UI/Forms/Config/frmPreferences.Designer.cs
generated
|
@ -30,6 +30,13 @@
|
|||
this.tabMain = new System.Windows.Forms.TabControl();
|
||||
this.tpgGeneral = new System.Windows.Forms.TabPage();
|
||||
this.tlpMain = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.chkAllowBackgroundInput = new System.Windows.Forms.CheckBox();
|
||||
this.flowLayoutPanel8 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.lblPauseIn = new System.Windows.Forms.Label();
|
||||
this.chkPauseWhenInBackground = new System.Windows.Forms.CheckBox();
|
||||
this.chkPauseInMenuAndConfig = new System.Windows.Forms.CheckBox();
|
||||
this.chkPauseInDebugger = new System.Windows.Forms.CheckBox();
|
||||
this.lblPauseBackgroundSettings = new System.Windows.Forms.Label();
|
||||
this.chkAutoHideMenu = new System.Windows.Forms.CheckBox();
|
||||
this.chkSingleInstance = new System.Windows.Forms.CheckBox();
|
||||
this.chkAutomaticallyCheckForUpdates = new System.Windows.Forms.CheckBox();
|
||||
|
@ -90,16 +97,11 @@
|
|||
this.chkAlwaysOnTop = new System.Windows.Forms.CheckBox();
|
||||
this.chkShowFps = new System.Windows.Forms.CheckBox();
|
||||
this.chkShowDebugInfo = new System.Windows.Forms.CheckBox();
|
||||
this.lblPauseBackgroundSettings = new System.Windows.Forms.Label();
|
||||
this.flowLayoutPanel8 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.lblPauseIn = new System.Windows.Forms.Label();
|
||||
this.chkPauseWhenInBackground = new System.Windows.Forms.CheckBox();
|
||||
this.chkPauseInMenuAndConfig = new System.Windows.Forms.CheckBox();
|
||||
this.chkPauseInDebugger = new System.Windows.Forms.CheckBox();
|
||||
this.chkAllowBackgroundInput = new System.Windows.Forms.CheckBox();
|
||||
this.chkPauseOnMovieEnd = new System.Windows.Forms.CheckBox();
|
||||
this.tabMain.SuspendLayout();
|
||||
this.tpgGeneral.SuspendLayout();
|
||||
this.tlpMain.SuspendLayout();
|
||||
this.flowLayoutPanel8.SuspendLayout();
|
||||
this.flowLayoutPanel2.SuspendLayout();
|
||||
this.tableLayoutPanel5.SuspendLayout();
|
||||
this.tpgShortcuts.SuspendLayout();
|
||||
|
@ -116,7 +118,6 @@
|
|||
this.tpgAdvanced.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.flowLayoutPanel6.SuspendLayout();
|
||||
this.flowLayoutPanel8.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// baseConfigPanel
|
||||
|
@ -153,26 +154,28 @@
|
|||
//
|
||||
this.tlpMain.ColumnCount = 1;
|
||||
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tlpMain.Controls.Add(this.chkPauseOnMovieEnd, 0, 6);
|
||||
this.tlpMain.Controls.Add(this.chkAllowBackgroundInput, 0, 5);
|
||||
this.tlpMain.Controls.Add(this.flowLayoutPanel8, 0, 4);
|
||||
this.tlpMain.Controls.Add(this.lblPauseBackgroundSettings, 0, 3);
|
||||
this.tlpMain.Controls.Add(this.chkAutoHideMenu, 0, 8);
|
||||
this.tlpMain.Controls.Add(this.chkAutoHideMenu, 0, 9);
|
||||
this.tlpMain.Controls.Add(this.chkSingleInstance, 0, 2);
|
||||
this.tlpMain.Controls.Add(this.chkAutomaticallyCheckForUpdates, 0, 1);
|
||||
this.tlpMain.Controls.Add(this.flowLayoutPanel2, 0, 0);
|
||||
this.tlpMain.Controls.Add(this.lblMiscSettings, 0, 6);
|
||||
this.tlpMain.Controls.Add(this.chkAutoLoadPatches, 0, 7);
|
||||
this.tlpMain.Controls.Add(this.tableLayoutPanel5, 0, 10);
|
||||
this.tlpMain.Controls.Add(this.lblMiscSettings, 0, 7);
|
||||
this.tlpMain.Controls.Add(this.chkAutoLoadPatches, 0, 8);
|
||||
this.tlpMain.Controls.Add(this.tableLayoutPanel5, 0, 11);
|
||||
this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tlpMain.Location = new System.Drawing.Point(3, 3);
|
||||
this.tlpMain.Name = "tlpMain";
|
||||
this.tlpMain.RowCount = 11;
|
||||
this.tlpMain.RowCount = 12;
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
|
@ -181,10 +184,87 @@
|
|||
this.tlpMain.Size = new System.Drawing.Size(534, 383);
|
||||
this.tlpMain.TabIndex = 1;
|
||||
//
|
||||
// chkAllowBackgroundInput
|
||||
//
|
||||
this.chkAllowBackgroundInput.AutoSize = true;
|
||||
this.chkAllowBackgroundInput.Location = new System.Drawing.Point(13, 120);
|
||||
this.chkAllowBackgroundInput.Margin = new System.Windows.Forms.Padding(13, 3, 3, 3);
|
||||
this.chkAllowBackgroundInput.Name = "chkAllowBackgroundInput";
|
||||
this.chkAllowBackgroundInput.Size = new System.Drawing.Size(177, 17);
|
||||
this.chkAllowBackgroundInput.TabIndex = 30;
|
||||
this.chkAllowBackgroundInput.Text = "Allow input when in background";
|
||||
this.chkAllowBackgroundInput.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// flowLayoutPanel8
|
||||
//
|
||||
this.flowLayoutPanel8.Controls.Add(this.lblPauseIn);
|
||||
this.flowLayoutPanel8.Controls.Add(this.chkPauseWhenInBackground);
|
||||
this.flowLayoutPanel8.Controls.Add(this.chkPauseInMenuAndConfig);
|
||||
this.flowLayoutPanel8.Controls.Add(this.chkPauseInDebugger);
|
||||
this.flowLayoutPanel8.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.flowLayoutPanel8.Location = new System.Drawing.Point(7, 95);
|
||||
this.flowLayoutPanel8.Margin = new System.Windows.Forms.Padding(7, 3, 0, 0);
|
||||
this.flowLayoutPanel8.Name = "flowLayoutPanel8";
|
||||
this.flowLayoutPanel8.Size = new System.Drawing.Size(527, 22);
|
||||
this.flowLayoutPanel8.TabIndex = 29;
|
||||
//
|
||||
// lblPauseIn
|
||||
//
|
||||
this.lblPauseIn.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblPauseIn.AutoSize = true;
|
||||
this.lblPauseIn.Location = new System.Drawing.Point(3, 4);
|
||||
this.lblPauseIn.Margin = new System.Windows.Forms.Padding(3, 0, 3, 1);
|
||||
this.lblPauseIn.Name = "lblPauseIn";
|
||||
this.lblPauseIn.Size = new System.Drawing.Size(80, 13);
|
||||
this.lblPauseIn.TabIndex = 0;
|
||||
this.lblPauseIn.Text = "Pause when in:";
|
||||
//
|
||||
// chkPauseWhenInBackground
|
||||
//
|
||||
this.chkPauseWhenInBackground.AutoSize = true;
|
||||
this.chkPauseWhenInBackground.Location = new System.Drawing.Point(89, 3);
|
||||
this.chkPauseWhenInBackground.Name = "chkPauseWhenInBackground";
|
||||
this.chkPauseWhenInBackground.Size = new System.Drawing.Size(84, 17);
|
||||
this.chkPauseWhenInBackground.TabIndex = 13;
|
||||
this.chkPauseWhenInBackground.Text = "Background";
|
||||
this.chkPauseWhenInBackground.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkPauseInMenuAndConfig
|
||||
//
|
||||
this.chkPauseInMenuAndConfig.AutoSize = true;
|
||||
this.chkPauseInMenuAndConfig.Location = new System.Drawing.Point(179, 3);
|
||||
this.chkPauseInMenuAndConfig.Name = "chkPauseInMenuAndConfig";
|
||||
this.chkPauseInMenuAndConfig.Size = new System.Drawing.Size(142, 17);
|
||||
this.chkPauseInMenuAndConfig.TabIndex = 16;
|
||||
this.chkPauseInMenuAndConfig.Text = "Menu and config dialogs";
|
||||
this.chkPauseInMenuAndConfig.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkPauseInDebugger
|
||||
//
|
||||
this.chkPauseInDebugger.AutoSize = true;
|
||||
this.chkPauseInDebugger.Location = new System.Drawing.Point(327, 3);
|
||||
this.chkPauseInDebugger.Name = "chkPauseInDebugger";
|
||||
this.chkPauseInDebugger.Size = new System.Drawing.Size(103, 17);
|
||||
this.chkPauseInDebugger.TabIndex = 18;
|
||||
this.chkPauseInDebugger.Text = "Debugging tools";
|
||||
this.chkPauseInDebugger.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lblPauseBackgroundSettings
|
||||
//
|
||||
this.lblPauseBackgroundSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.lblPauseBackgroundSettings.AutoSize = true;
|
||||
this.lblPauseBackgroundSettings.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.lblPauseBackgroundSettings.Location = new System.Drawing.Point(0, 79);
|
||||
this.lblPauseBackgroundSettings.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||
this.lblPauseBackgroundSettings.Name = "lblPauseBackgroundSettings";
|
||||
this.lblPauseBackgroundSettings.Size = new System.Drawing.Size(141, 13);
|
||||
this.lblPauseBackgroundSettings.TabIndex = 26;
|
||||
this.lblPauseBackgroundSettings.Text = "Pause/Background Settings";
|
||||
//
|
||||
// chkAutoHideMenu
|
||||
//
|
||||
this.chkAutoHideMenu.AutoSize = true;
|
||||
this.chkAutoHideMenu.Location = new System.Drawing.Point(13, 186);
|
||||
this.chkAutoHideMenu.Location = new System.Drawing.Point(13, 209);
|
||||
this.chkAutoHideMenu.Margin = new System.Windows.Forms.Padding(13, 3, 3, 3);
|
||||
this.chkAutoHideMenu.Name = "chkAutoHideMenu";
|
||||
this.chkAutoHideMenu.Size = new System.Drawing.Size(158, 17);
|
||||
|
@ -247,7 +327,7 @@
|
|||
this.lblMiscSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.lblMiscSettings.AutoSize = true;
|
||||
this.lblMiscSettings.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.lblMiscSettings.Location = new System.Drawing.Point(0, 147);
|
||||
this.lblMiscSettings.Location = new System.Drawing.Point(0, 170);
|
||||
this.lblMiscSettings.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||
this.lblMiscSettings.Name = "lblMiscSettings";
|
||||
this.lblMiscSettings.Size = new System.Drawing.Size(73, 13);
|
||||
|
@ -257,7 +337,7 @@
|
|||
// chkAutoLoadPatches
|
||||
//
|
||||
this.chkAutoLoadPatches.AutoSize = true;
|
||||
this.chkAutoLoadPatches.Location = new System.Drawing.Point(13, 163);
|
||||
this.chkAutoLoadPatches.Location = new System.Drawing.Point(13, 186);
|
||||
this.chkAutoLoadPatches.Margin = new System.Windows.Forms.Padding(13, 3, 3, 3);
|
||||
this.chkAutoLoadPatches.Name = "chkAutoLoadPatches";
|
||||
this.chkAutoLoadPatches.Size = new System.Drawing.Size(198, 17);
|
||||
|
@ -310,7 +390,7 @@
|
|||
this.tpgShortcuts.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpgShortcuts.Name = "tpgShortcuts";
|
||||
this.tpgShortcuts.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tpgShortcuts.Size = new System.Drawing.Size(540, 418);
|
||||
this.tpgShortcuts.Size = new System.Drawing.Size(540, 389);
|
||||
this.tpgShortcuts.TabIndex = 7;
|
||||
this.tpgShortcuts.Text = "Shortcut Keys";
|
||||
this.tpgShortcuts.UseVisualStyleBackColor = true;
|
||||
|
@ -320,7 +400,7 @@
|
|||
this.ctrlEmulatorShortcuts.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ctrlEmulatorShortcuts.Location = new System.Drawing.Point(3, 3);
|
||||
this.ctrlEmulatorShortcuts.Name = "ctrlEmulatorShortcuts";
|
||||
this.ctrlEmulatorShortcuts.Size = new System.Drawing.Size(534, 412);
|
||||
this.ctrlEmulatorShortcuts.Size = new System.Drawing.Size(534, 383);
|
||||
this.ctrlEmulatorShortcuts.TabIndex = 0;
|
||||
//
|
||||
// tpgFiles
|
||||
|
@ -329,7 +409,7 @@
|
|||
this.tpgFiles.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpgFiles.Name = "tpgFiles";
|
||||
this.tpgFiles.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tpgFiles.Size = new System.Drawing.Size(540, 418);
|
||||
this.tpgFiles.Size = new System.Drawing.Size(540, 389);
|
||||
this.tpgFiles.TabIndex = 2;
|
||||
this.tpgFiles.Text = "Folders/Files";
|
||||
this.tpgFiles.UseVisualStyleBackColor = true;
|
||||
|
@ -350,7 +430,7 @@
|
|||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel6.Size = new System.Drawing.Size(534, 412);
|
||||
this.tableLayoutPanel6.Size = new System.Drawing.Size(534, 383);
|
||||
this.tableLayoutPanel6.TabIndex = 13;
|
||||
//
|
||||
// grpPathOverrides
|
||||
|
@ -757,7 +837,7 @@
|
|||
this.tpgAdvanced.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpgAdvanced.Name = "tpgAdvanced";
|
||||
this.tpgAdvanced.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tpgAdvanced.Size = new System.Drawing.Size(540, 418);
|
||||
this.tpgAdvanced.Size = new System.Drawing.Size(540, 389);
|
||||
this.tpgAdvanced.TabIndex = 1;
|
||||
this.tpgAdvanced.Text = "Advanced";
|
||||
this.tpgAdvanced.UseVisualStyleBackColor = true;
|
||||
|
@ -793,7 +873,7 @@
|
|||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(534, 412);
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(534, 383);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// lblAdvancedMisc
|
||||
|
@ -973,82 +1053,16 @@
|
|||
this.chkShowDebugInfo.Text = "Show debug information";
|
||||
this.chkShowDebugInfo.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lblPauseBackgroundSettings
|
||||
// chkPauseOnMovieEnd
|
||||
//
|
||||
this.lblPauseBackgroundSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.lblPauseBackgroundSettings.AutoSize = true;
|
||||
this.lblPauseBackgroundSettings.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.lblPauseBackgroundSettings.Location = new System.Drawing.Point(0, 79);
|
||||
this.lblPauseBackgroundSettings.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||
this.lblPauseBackgroundSettings.Name = "lblPauseBackgroundSettings";
|
||||
this.lblPauseBackgroundSettings.Size = new System.Drawing.Size(141, 13);
|
||||
this.lblPauseBackgroundSettings.TabIndex = 26;
|
||||
this.lblPauseBackgroundSettings.Text = "Pause/Background Settings";
|
||||
//
|
||||
// flowLayoutPanel8
|
||||
//
|
||||
this.flowLayoutPanel8.Controls.Add(this.lblPauseIn);
|
||||
this.flowLayoutPanel8.Controls.Add(this.chkPauseWhenInBackground);
|
||||
this.flowLayoutPanel8.Controls.Add(this.chkPauseInMenuAndConfig);
|
||||
this.flowLayoutPanel8.Controls.Add(this.chkPauseInDebugger);
|
||||
this.flowLayoutPanel8.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.flowLayoutPanel8.Location = new System.Drawing.Point(7, 95);
|
||||
this.flowLayoutPanel8.Margin = new System.Windows.Forms.Padding(7, 3, 0, 0);
|
||||
this.flowLayoutPanel8.Name = "flowLayoutPanel8";
|
||||
this.flowLayoutPanel8.Size = new System.Drawing.Size(527, 22);
|
||||
this.flowLayoutPanel8.TabIndex = 29;
|
||||
//
|
||||
// lblPauseIn
|
||||
//
|
||||
this.lblPauseIn.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblPauseIn.AutoSize = true;
|
||||
this.lblPauseIn.Location = new System.Drawing.Point(3, 4);
|
||||
this.lblPauseIn.Margin = new System.Windows.Forms.Padding(3, 0, 3, 1);
|
||||
this.lblPauseIn.Name = "lblPauseIn";
|
||||
this.lblPauseIn.Size = new System.Drawing.Size(80, 13);
|
||||
this.lblPauseIn.TabIndex = 0;
|
||||
this.lblPauseIn.Text = "Pause when in:";
|
||||
//
|
||||
// chkPauseWhenInBackground
|
||||
//
|
||||
this.chkPauseWhenInBackground.AutoSize = true;
|
||||
this.chkPauseWhenInBackground.Location = new System.Drawing.Point(89, 3);
|
||||
this.chkPauseWhenInBackground.Name = "chkPauseWhenInBackground";
|
||||
this.chkPauseWhenInBackground.Size = new System.Drawing.Size(84, 17);
|
||||
this.chkPauseWhenInBackground.TabIndex = 13;
|
||||
this.chkPauseWhenInBackground.Text = "Background";
|
||||
this.chkPauseWhenInBackground.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkPauseInMenuAndConfig
|
||||
//
|
||||
this.chkPauseInMenuAndConfig.AutoSize = true;
|
||||
this.chkPauseInMenuAndConfig.Location = new System.Drawing.Point(179, 3);
|
||||
this.chkPauseInMenuAndConfig.Name = "chkPauseInMenuAndConfig";
|
||||
this.chkPauseInMenuAndConfig.Size = new System.Drawing.Size(142, 17);
|
||||
this.chkPauseInMenuAndConfig.TabIndex = 16;
|
||||
this.chkPauseInMenuAndConfig.Text = "Menu and config dialogs";
|
||||
this.chkPauseInMenuAndConfig.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkPauseInDebugger
|
||||
//
|
||||
this.chkPauseInDebugger.AutoSize = true;
|
||||
this.chkPauseInDebugger.Location = new System.Drawing.Point(327, 3);
|
||||
this.chkPauseInDebugger.Name = "chkPauseInDebugger";
|
||||
this.chkPauseInDebugger.Size = new System.Drawing.Size(103, 17);
|
||||
this.chkPauseInDebugger.TabIndex = 18;
|
||||
this.chkPauseInDebugger.Text = "Debugging tools";
|
||||
this.chkPauseInDebugger.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkAllowBackgroundInput
|
||||
//
|
||||
this.chkAllowBackgroundInput.AutoSize = true;
|
||||
this.chkAllowBackgroundInput.Location = new System.Drawing.Point(13, 120);
|
||||
this.chkAllowBackgroundInput.Margin = new System.Windows.Forms.Padding(13, 3, 3, 3);
|
||||
this.chkAllowBackgroundInput.Name = "chkAllowBackgroundInput";
|
||||
this.chkAllowBackgroundInput.Size = new System.Drawing.Size(177, 17);
|
||||
this.chkAllowBackgroundInput.TabIndex = 30;
|
||||
this.chkAllowBackgroundInput.Text = "Allow input when in background";
|
||||
this.chkAllowBackgroundInput.UseVisualStyleBackColor = true;
|
||||
this.chkPauseOnMovieEnd.AutoSize = true;
|
||||
this.chkPauseOnMovieEnd.Location = new System.Drawing.Point(13, 143);
|
||||
this.chkPauseOnMovieEnd.Margin = new System.Windows.Forms.Padding(13, 3, 3, 3);
|
||||
this.chkPauseOnMovieEnd.Name = "chkPauseOnMovieEnd";
|
||||
this.chkPauseOnMovieEnd.Size = new System.Drawing.Size(199, 17);
|
||||
this.chkPauseOnMovieEnd.TabIndex = 31;
|
||||
this.chkPauseOnMovieEnd.Text = "Pause when a movie finishes playing";
|
||||
this.chkPauseOnMovieEnd.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// frmPreferences
|
||||
//
|
||||
|
@ -1065,6 +1079,8 @@
|
|||
this.tpgGeneral.ResumeLayout(false);
|
||||
this.tlpMain.ResumeLayout(false);
|
||||
this.tlpMain.PerformLayout();
|
||||
this.flowLayoutPanel8.ResumeLayout(false);
|
||||
this.flowLayoutPanel8.PerformLayout();
|
||||
this.flowLayoutPanel2.ResumeLayout(false);
|
||||
this.flowLayoutPanel2.PerformLayout();
|
||||
this.tableLayoutPanel5.ResumeLayout(false);
|
||||
|
@ -1090,8 +1106,6 @@
|
|||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.flowLayoutPanel6.ResumeLayout(false);
|
||||
this.flowLayoutPanel6.PerformLayout();
|
||||
this.flowLayoutPanel8.ResumeLayout(false);
|
||||
this.flowLayoutPanel8.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
|
@ -1169,5 +1183,6 @@
|
|||
private System.Windows.Forms.CheckBox chkPauseInMenuAndConfig;
|
||||
private System.Windows.Forms.CheckBox chkPauseInDebugger;
|
||||
private System.Windows.Forms.Label lblPauseBackgroundSettings;
|
||||
private System.Windows.Forms.CheckBox chkPauseOnMovieEnd;
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ namespace Mesen.GUI.Forms.Config
|
|||
AddBinding(nameof(PreferencesConfig.PauseWhenInMenusAndConfig), chkPauseInMenuAndConfig);
|
||||
AddBinding(nameof(PreferencesConfig.PauseWhenInDebuggingTools), chkPauseInDebugger);
|
||||
AddBinding(nameof(PreferencesConfig.AllowBackgroundInput), chkAllowBackgroundInput);
|
||||
AddBinding(nameof(PreferencesConfig.PauseOnMovieEnd), chkPauseOnMovieEnd);
|
||||
|
||||
AddBinding(nameof(PreferencesConfig.AssociateRomFiles), chkRomFormat);
|
||||
AddBinding(nameof(PreferencesConfig.AssociateMsmFiles), chkMsmFormat);
|
||||
|
|
56
UI/Forms/Config/frmRecordMovie.cs
Normal file
56
UI/Forms/Config/frmRecordMovie.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Mesen.GUI.Config;
|
||||
|
||||
namespace Mesen.GUI.Forms
|
||||
{
|
||||
public partial class frmRecordMovie : BaseConfigForm
|
||||
{
|
||||
public frmRecordMovie()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Entity = ConfigManager.Config.MovieRecord;
|
||||
AddBinding(nameof(MovieRecordConfig.Author), txtAuthor);
|
||||
AddBinding(nameof(MovieRecordConfig.Description), txtDescription);
|
||||
AddBinding(nameof(MovieRecordConfig.RecordFrom), cboRecordFrom);
|
||||
}
|
||||
|
||||
protected override bool ValidateInput()
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(txtFilename.Text);
|
||||
}
|
||||
|
||||
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||
{
|
||||
base.OnFormClosed(e);
|
||||
if(this.DialogResult == DialogResult.OK) {
|
||||
RecordMovieOptions options = new RecordMovieOptions(
|
||||
this.txtFilename.Text,
|
||||
this.txtAuthor.Text,
|
||||
this.txtDescription.Text,
|
||||
this.cboRecordFrom.GetEnumValue<RecordMovieFrom>()
|
||||
);
|
||||
RecordApi.MovieRecord(ref options);
|
||||
}
|
||||
}
|
||||
|
||||
private void btnBrowse_Click(object sender, EventArgs e)
|
||||
{
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterMovie"));
|
||||
sfd.InitialDirectory = ConfigManager.MovieFolder;
|
||||
sfd.FileName = EmuApi.GetRomInfo().GetRomName() + ".msm";
|
||||
if(sfd.ShowDialog() == DialogResult.OK) {
|
||||
txtFilename.Text = sfd.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
219
UI/Forms/Config/frmRecordMovie.designer.cs
generated
Normal file
219
UI/Forms/Config/frmRecordMovie.designer.cs
generated
Normal file
|
@ -0,0 +1,219 @@
|
|||
namespace Mesen.GUI.Forms
|
||||
{
|
||||
partial class frmRecordMovie
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.lblSaveTo = new System.Windows.Forms.Label();
|
||||
this.txtFilename = new System.Windows.Forms.TextBox();
|
||||
this.btnBrowse = new System.Windows.Forms.Button();
|
||||
this.txtAuthor = new System.Windows.Forms.TextBox();
|
||||
this.lblRecordFrom = new System.Windows.Forms.Label();
|
||||
this.lblAuthor = new System.Windows.Forms.Label();
|
||||
this.lblDescription = new System.Windows.Forms.Label();
|
||||
this.cboRecordFrom = new System.Windows.Forms.ComboBox();
|
||||
this.txtDescription = new System.Windows.Forms.TextBox();
|
||||
this.lblMovieInformation = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// baseConfigPanel
|
||||
//
|
||||
this.baseConfigPanel.Location = new System.Drawing.Point(0, 202);
|
||||
this.baseConfigPanel.Size = new System.Drawing.Size(397, 29);
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 3;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.Controls.Add(this.lblSaveTo, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtFilename, 1, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.btnBrowse, 2, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtAuthor, 1, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.lblRecordFrom, 0, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.lblAuthor, 0, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.lblDescription, 0, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.cboRecordFrom, 1, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.txtDescription, 1, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.lblMovieInformation, 0, 2);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 6;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(397, 231);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// lblSaveTo
|
||||
//
|
||||
this.lblSaveTo.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblSaveTo.AutoSize = true;
|
||||
this.lblSaveTo.Location = new System.Drawing.Point(3, 8);
|
||||
this.lblSaveTo.Name = "lblSaveTo";
|
||||
this.lblSaveTo.Size = new System.Drawing.Size(47, 13);
|
||||
this.lblSaveTo.TabIndex = 0;
|
||||
this.lblSaveTo.Text = "Save to:";
|
||||
//
|
||||
// txtFilename
|
||||
//
|
||||
this.txtFilename.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.txtFilename.Location = new System.Drawing.Point(82, 3);
|
||||
this.txtFilename.MaxLength = 1999;
|
||||
this.txtFilename.Name = "txtFilename";
|
||||
this.txtFilename.ReadOnly = true;
|
||||
this.txtFilename.Size = new System.Drawing.Size(231, 20);
|
||||
this.txtFilename.TabIndex = 1;
|
||||
//
|
||||
// btnBrowse
|
||||
//
|
||||
this.btnBrowse.Location = new System.Drawing.Point(319, 3);
|
||||
this.btnBrowse.Name = "btnBrowse";
|
||||
this.btnBrowse.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnBrowse.TabIndex = 2;
|
||||
this.btnBrowse.Text = "Browse...";
|
||||
this.btnBrowse.UseVisualStyleBackColor = true;
|
||||
this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click);
|
||||
//
|
||||
// txtAuthor
|
||||
//
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.txtAuthor, 2);
|
||||
this.txtAuthor.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.txtAuthor.Location = new System.Drawing.Point(82, 84);
|
||||
this.txtAuthor.MaxLength = 249;
|
||||
this.txtAuthor.Name = "txtAuthor";
|
||||
this.txtAuthor.Size = new System.Drawing.Size(312, 20);
|
||||
this.txtAuthor.TabIndex = 12;
|
||||
//
|
||||
// lblRecordFrom
|
||||
//
|
||||
this.lblRecordFrom.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblRecordFrom.AutoSize = true;
|
||||
this.lblRecordFrom.Location = new System.Drawing.Point(3, 36);
|
||||
this.lblRecordFrom.Name = "lblRecordFrom";
|
||||
this.lblRecordFrom.Size = new System.Drawing.Size(68, 13);
|
||||
this.lblRecordFrom.TabIndex = 6;
|
||||
this.lblRecordFrom.Text = "Record from:";
|
||||
//
|
||||
// lblAuthor
|
||||
//
|
||||
this.lblAuthor.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblAuthor.AutoSize = true;
|
||||
this.lblAuthor.Location = new System.Drawing.Point(13, 87);
|
||||
this.lblAuthor.Margin = new System.Windows.Forms.Padding(13, 0, 3, 0);
|
||||
this.lblAuthor.Name = "lblAuthor";
|
||||
this.lblAuthor.Size = new System.Drawing.Size(41, 13);
|
||||
this.lblAuthor.TabIndex = 5;
|
||||
this.lblAuthor.Text = "Author:";
|
||||
//
|
||||
// lblDescription
|
||||
//
|
||||
this.lblDescription.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblDescription.AutoSize = true;
|
||||
this.lblDescription.Location = new System.Drawing.Point(13, 146);
|
||||
this.lblDescription.Margin = new System.Windows.Forms.Padding(13, 0, 3, 0);
|
||||
this.lblDescription.Name = "lblDescription";
|
||||
this.lblDescription.Size = new System.Drawing.Size(63, 13);
|
||||
this.lblDescription.TabIndex = 11;
|
||||
this.lblDescription.Text = "Description:";
|
||||
//
|
||||
// cboRecordFrom
|
||||
//
|
||||
this.cboRecordFrom.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.cboRecordFrom.FormattingEnabled = true;
|
||||
this.cboRecordFrom.Location = new System.Drawing.Point(82, 32);
|
||||
this.cboRecordFrom.Name = "cboRecordFrom";
|
||||
this.cboRecordFrom.Size = new System.Drawing.Size(231, 21);
|
||||
this.cboRecordFrom.TabIndex = 13;
|
||||
//
|
||||
// txtDescription
|
||||
//
|
||||
this.txtDescription.AcceptsReturn = true;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.txtDescription, 2);
|
||||
this.txtDescription.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.txtDescription.Location = new System.Drawing.Point(82, 110);
|
||||
this.txtDescription.MaxLength = 9999;
|
||||
this.txtDescription.Multiline = true;
|
||||
this.txtDescription.Name = "txtDescription";
|
||||
this.txtDescription.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txtDescription.Size = new System.Drawing.Size(312, 86);
|
||||
this.txtDescription.TabIndex = 10;
|
||||
//
|
||||
// lblMovieInformation
|
||||
//
|
||||
this.lblMovieInformation.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.lblMovieInformation.AutoSize = true;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.lblMovieInformation, 2);
|
||||
this.lblMovieInformation.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.lblMovieInformation.Location = new System.Drawing.Point(3, 65);
|
||||
this.lblMovieInformation.Name = "lblMovieInformation";
|
||||
this.lblMovieInformation.Padding = new System.Windows.Forms.Padding(0, 0, 0, 3);
|
||||
this.lblMovieInformation.Size = new System.Drawing.Size(139, 16);
|
||||
this.lblMovieInformation.TabIndex = 24;
|
||||
this.lblMovieInformation.Text = "Movie Information (Optional)";
|
||||
//
|
||||
// frmRecordMovie
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(397, 231);
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "frmRecordMovie";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Movie Recording Options";
|
||||
this.Controls.SetChildIndex(this.tableLayoutPanel1, 0);
|
||||
this.Controls.SetChildIndex(this.baseConfigPanel, 0);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Label lblSaveTo;
|
||||
private System.Windows.Forms.TextBox txtFilename;
|
||||
private System.Windows.Forms.Button btnBrowse;
|
||||
private System.Windows.Forms.Label lblAuthor;
|
||||
private System.Windows.Forms.Label lblRecordFrom;
|
||||
private System.Windows.Forms.TextBox txtDescription;
|
||||
private System.Windows.Forms.Label lblDescription;
|
||||
private System.Windows.Forms.TextBox txtAuthor;
|
||||
private System.Windows.Forms.ComboBox cboRecordFrom;
|
||||
private System.Windows.Forms.Label lblMovieInformation;
|
||||
}
|
||||
}
|
123
UI/Forms/Config/frmRecordMovie.resx
Normal file
123
UI/Forms/Config/frmRecordMovie.resx
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
52
UI/Forms/frmMain.Designer.cs
generated
52
UI/Forms/frmMain.Designer.cs
generated
|
@ -144,6 +144,11 @@
|
|||
this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.pnlRenderer = new System.Windows.Forms.Panel();
|
||||
this.ctrlRecentGames = new Mesen.GUI.Controls.ctrlRecentGames();
|
||||
this.mnuMovies = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuPlayMovie = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuRecordMovie = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuStopMovie = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem25 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuMain.SuspendLayout();
|
||||
this.pnlRenderer.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
|
@ -764,6 +769,8 @@
|
|||
// mnuTools
|
||||
//
|
||||
this.mnuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuMovies,
|
||||
this.toolStripMenuItem25,
|
||||
this.mnuSoundRecorder,
|
||||
this.mnuVideoRecorder,
|
||||
this.toolStripMenuItem11,
|
||||
|
@ -1039,6 +1046,46 @@
|
|||
this.ctrlRecentGames.TabIndex = 1;
|
||||
this.ctrlRecentGames.Visible = false;
|
||||
//
|
||||
// mnuMovies
|
||||
//
|
||||
this.mnuMovies.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuPlayMovie,
|
||||
this.mnuRecordMovie,
|
||||
this.mnuStopMovie});
|
||||
this.mnuMovies.Image = global::Mesen.GUI.Properties.Resources.Movie;
|
||||
this.mnuMovies.Name = "mnuMovies";
|
||||
this.mnuMovies.Size = new System.Drawing.Size(159, 22);
|
||||
this.mnuMovies.Text = "Movies";
|
||||
//
|
||||
// mnuPlayMovie
|
||||
//
|
||||
this.mnuPlayMovie.Image = global::Mesen.GUI.Properties.Resources.MediaPlay;
|
||||
this.mnuPlayMovie.Name = "mnuPlayMovie";
|
||||
this.mnuPlayMovie.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuPlayMovie.Text = "Play...";
|
||||
this.mnuPlayMovie.Click += new System.EventHandler(this.mnuPlayMovie_Click);
|
||||
//
|
||||
// mnuRecordMovie
|
||||
//
|
||||
this.mnuRecordMovie.Image = global::Mesen.GUI.Properties.Resources.Record;
|
||||
this.mnuRecordMovie.Name = "mnuRecordMovie";
|
||||
this.mnuRecordMovie.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRecordMovie.Text = "Record...";
|
||||
this.mnuRecordMovie.Click += new System.EventHandler(this.mnuRecordMovie_Click);
|
||||
//
|
||||
// mnuStopMovie
|
||||
//
|
||||
this.mnuStopMovie.Image = global::Mesen.GUI.Properties.Resources.MediaStop;
|
||||
this.mnuStopMovie.Name = "mnuStopMovie";
|
||||
this.mnuStopMovie.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuStopMovie.Text = "Stop";
|
||||
this.mnuStopMovie.Click += new System.EventHandler(this.mnuStopMovie_Click);
|
||||
//
|
||||
// toolStripMenuItem25
|
||||
//
|
||||
this.toolStripMenuItem25.Name = "toolStripMenuItem25";
|
||||
this.toolStripMenuItem25.Size = new System.Drawing.Size(156, 6);
|
||||
//
|
||||
// frmMain
|
||||
//
|
||||
this.AllowDrop = true;
|
||||
|
@ -1181,5 +1228,10 @@
|
|||
private System.Windows.Forms.ToolStripMenuItem mnuScriptWindow;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuSa1Debugger;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuGsuDebugger;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuMovies;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuPlayMovie;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuRecordMovie;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuStopMovie;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem25;
|
||||
}
|
||||
}
|
|
@ -517,6 +517,22 @@ namespace Mesen.GUI.Forms
|
|||
mnuRegionPal.Checked = ConfigManager.Config.Emulation.Region == ConsoleRegion.Pal;
|
||||
}
|
||||
|
||||
private void mnuTools_DropDownOpening(object sender, EventArgs e)
|
||||
{
|
||||
mnuMovies.Enabled = EmuRunner.IsRunning();
|
||||
mnuPlayMovie.Enabled = EmuRunner.IsRunning() && !RecordApi.MoviePlaying() && !RecordApi.MovieRecording();
|
||||
mnuRecordMovie.Enabled = EmuRunner.IsRunning() && !RecordApi.MoviePlaying() && !RecordApi.MovieRecording();
|
||||
mnuStopMovie.Enabled = EmuRunner.IsRunning() && (RecordApi.MoviePlaying() || RecordApi.MovieRecording());
|
||||
|
||||
mnuSoundRecorder.Enabled = EmuRunner.IsRunning();
|
||||
mnuWaveRecord.Enabled = EmuRunner.IsRunning() && !RecordApi.WaveIsRecording();
|
||||
mnuWaveStop.Enabled = EmuRunner.IsRunning() && RecordApi.WaveIsRecording();
|
||||
|
||||
mnuVideoRecorder.Enabled = EmuRunner.IsRunning();
|
||||
mnuAviRecord.Enabled = EmuRunner.IsRunning() && !RecordApi.AviIsRecording();
|
||||
mnuAviStop.Enabled = EmuRunner.IsRunning() && RecordApi.AviIsRecording();
|
||||
}
|
||||
|
||||
private void mnuAviRecord_Click(object sender, EventArgs e)
|
||||
{
|
||||
using(frmRecordAvi frm = new frmRecordAvi()) {
|
||||
|
@ -531,17 +547,6 @@ namespace Mesen.GUI.Forms
|
|||
RecordApi.AviStop();
|
||||
}
|
||||
|
||||
private void mnuTools_DropDownOpening(object sender, EventArgs e)
|
||||
{
|
||||
mnuSoundRecorder.Enabled = EmuRunner.IsRunning();
|
||||
mnuWaveRecord.Enabled = EmuRunner.IsRunning() && !RecordApi.WaveIsRecording();
|
||||
mnuWaveStop.Enabled = EmuRunner.IsRunning() && RecordApi.WaveIsRecording();
|
||||
|
||||
mnuVideoRecorder.Enabled = EmuRunner.IsRunning();
|
||||
mnuAviRecord.Enabled = EmuRunner.IsRunning() && !RecordApi.AviIsRecording();
|
||||
mnuAviStop.Enabled = EmuRunner.IsRunning() && RecordApi.AviIsRecording();
|
||||
}
|
||||
|
||||
private void mnuWaveRecord_Click(object sender, EventArgs e)
|
||||
{
|
||||
using(SaveFileDialog sfd = new SaveFileDialog()) {
|
||||
|
@ -559,6 +564,29 @@ namespace Mesen.GUI.Forms
|
|||
RecordApi.WaveStop();
|
||||
}
|
||||
|
||||
private void mnuPlayMovie_Click(object sender, EventArgs e)
|
||||
{
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterMovie"));
|
||||
ofd.InitialDirectory = ConfigManager.MovieFolder;
|
||||
if(ofd.ShowDialog(this) == DialogResult.OK) {
|
||||
RecordApi.MoviePlay(ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuStopMovie_Click(object sender, EventArgs e)
|
||||
{
|
||||
RecordApi.MovieStop();
|
||||
}
|
||||
|
||||
private void mnuRecordMovie_Click(object sender, EventArgs e)
|
||||
{
|
||||
using(frmRecordMovie frm = new frmRecordMovie()) {
|
||||
frm.ShowDialog(mnuMovies, this);
|
||||
}
|
||||
}
|
||||
|
||||
private void mnu_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
Interlocked.Increment(ref _inMenu);
|
||||
|
|
|
@ -20,10 +20,52 @@ namespace Mesen.GUI
|
|||
[DllImport(DllPath)] public static extern void WaveStop();
|
||||
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool WaveIsRecording();
|
||||
|
||||
/*[DllImport(DllPath)] public static extern void MoviePlay([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filename);
|
||||
[DllImport(DllPath)] public static extern void MoviePlay([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filename);
|
||||
[DllImport(DllPath)] public static extern void MovieRecord(ref RecordMovieOptions options);
|
||||
[DllImport(DllPath)] public static extern void MovieStop();
|
||||
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool MoviePlaying();
|
||||
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool MovieRecording();*/
|
||||
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool MovieRecording();
|
||||
}
|
||||
|
||||
public enum RecordMovieFrom
|
||||
{
|
||||
StartWithoutSaveData,
|
||||
StartWithSaveData,
|
||||
CurrentState
|
||||
}
|
||||
|
||||
public struct RecordMovieOptions
|
||||
{
|
||||
private const int AuthorMaxSize = 250;
|
||||
private const int DescriptionMaxSize = 10000;
|
||||
private const int FilenameMaxSize = 2000;
|
||||
|
||||
public RecordMovieOptions(string filename, string author, string description, RecordMovieFrom recordFrom)
|
||||
{
|
||||
Author = Encoding.UTF8.GetBytes(author);
|
||||
Array.Resize(ref Author, AuthorMaxSize);
|
||||
Author[AuthorMaxSize - 1] = 0;
|
||||
|
||||
Description = Encoding.UTF8.GetBytes(description.Replace("\r", ""));
|
||||
Array.Resize(ref Description, DescriptionMaxSize);
|
||||
Description[DescriptionMaxSize - 1] = 0;
|
||||
|
||||
Filename = Encoding.UTF8.GetBytes(filename);
|
||||
Array.Resize(ref Filename, FilenameMaxSize);
|
||||
Filename[FilenameMaxSize - 1] = 0;
|
||||
|
||||
RecordFrom = recordFrom;
|
||||
}
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = FilenameMaxSize)]
|
||||
public byte[] Filename;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = AuthorMaxSize)]
|
||||
public byte[] Author;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DescriptionMaxSize)]
|
||||
public byte[] Description;
|
||||
|
||||
public RecordMovieFrom RecordFrom;
|
||||
}
|
||||
}
|
||||
|
|
10
UI/UI.csproj
10
UI/UI.csproj
|
@ -217,6 +217,7 @@
|
|||
<Compile Include="Config\ConfigManager.cs" />
|
||||
<Compile Include="Config\InputConfig.cs" />
|
||||
<Compile Include="Config\FileAssociationHelper.cs" />
|
||||
<Compile Include="Config\MovieRecordConfig.cs" />
|
||||
<Compile Include="Config\PreferencesConfig.cs" />
|
||||
<Compile Include="Config\Shortcuts\EmulatorShortcut.cs" />
|
||||
<Compile Include="Config\Shortcuts\KeyCombination.cs" />
|
||||
|
@ -767,6 +768,12 @@
|
|||
<Compile Include="Forms\frmFullscreenRenderer.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\Config\frmRecordMovie.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\Config\frmRecordMovie.Designer.cs">
|
||||
<DependentUpon>frmRecordMovie.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Forms\Tools\frmLogWindow.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
@ -1048,6 +1055,9 @@
|
|||
<EmbeddedResource Include="Forms\frmConfigWizard.resx">
|
||||
<DependentUpon>frmConfigWizard.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\Config\frmRecordMovie.resx">
|
||||
<DependentUpon>frmRecordMovie.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\Tools\frmLogWindow.resx">
|
||||
<DependentUpon>frmLogWindow.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
|
|
@ -52,8 +52,8 @@ namespace Mesen.GUI.Utilities
|
|||
} else if(!Path.IsPathRooted(moviePath)) {
|
||||
moviePath = Path.Combine(Program.OriginalFolder, moviePath);
|
||||
}
|
||||
if(!moviePath.ToLower().EndsWith(".mmo")) {
|
||||
moviePath += ".mmo";
|
||||
if(!moviePath.ToLower().EndsWith(".msm")) {
|
||||
moviePath += ".msm";
|
||||
}
|
||||
_movieToRecord = moviePath;
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue