Core: Added runahead support (1 to 10 frames)
This commit is contained in:
parent
fd02e406b0
commit
c7675bcd49
24 changed files with 1143 additions and 964 deletions
267
Core/Console.cpp
267
Core/Console.cpp
|
@ -720,6 +720,17 @@ void Console::RunSlaveCpu()
|
|||
}
|
||||
}
|
||||
|
||||
void Console::RunFrame()
|
||||
{
|
||||
uint32_t frameCount = _ppu->GetFrameCount();
|
||||
while(_ppu->GetFrameCount() == frameCount) {
|
||||
_cpu->Exec();
|
||||
if(_slave) {
|
||||
RunSlaveCpu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Console::Run()
|
||||
{
|
||||
Timer clockTimer;
|
||||
|
@ -729,7 +740,6 @@ void Console::Run()
|
|||
double targetTime;
|
||||
double lastFrameMin = 9999;
|
||||
double lastFrameMax = 0;
|
||||
uint32_t lastFrameNumber = -1;
|
||||
double lastDelay = GetFrameDelay();
|
||||
|
||||
_runLock.Acquire();
|
||||
|
@ -753,131 +763,135 @@ void Console::Run()
|
|||
bool crashed = false;
|
||||
try {
|
||||
while(true) {
|
||||
_cpu->Exec();
|
||||
|
||||
if(_slave) {
|
||||
RunSlaveCpu();
|
||||
stringstream runAheadState;
|
||||
bool useRunAhead = _settings->GetRunAheadFrames() > 0 && !_debugger && !_rewindManager->IsRewinding();
|
||||
if(useRunAhead) {
|
||||
RunFrameWithRunAhead(runAheadState);
|
||||
} else {
|
||||
RunFrame();
|
||||
}
|
||||
|
||||
if(_ppu->GetFrameCount() != lastFrameNumber) {
|
||||
_soundMixer->ProcessEndOfFrame();
|
||||
if(_slave) {
|
||||
_slave->_soundMixer->ProcessEndOfFrame();
|
||||
}
|
||||
_soundMixer->ProcessEndOfFrame();
|
||||
if(_slave) {
|
||||
_slave->_soundMixer->ProcessEndOfFrame();
|
||||
}
|
||||
|
||||
if(_historyViewer) {
|
||||
_historyViewer->ProcessEndOfFrame();
|
||||
}
|
||||
_rewindManager->ProcessEndOfFrame();
|
||||
_settings->DisableOverclocking(_disableOcNextFrame || IsNsf());
|
||||
_disableOcNextFrame = false;
|
||||
if(_historyViewer) {
|
||||
_historyViewer->ProcessEndOfFrame();
|
||||
}
|
||||
_rewindManager->ProcessEndOfFrame();
|
||||
_settings->DisableOverclocking(_disableOcNextFrame || IsNsf());
|
||||
_disableOcNextFrame = false;
|
||||
|
||||
//Update model (ntsc/pal) and get delay for next frame
|
||||
UpdateNesModel(true);
|
||||
double delay = GetFrameDelay();
|
||||
//Update model (ntsc/pal) and get delay for next frame
|
||||
UpdateNesModel(true);
|
||||
double delay = GetFrameDelay();
|
||||
|
||||
if(_resetRunTimers || delay != lastDelay || (clockTimer.GetElapsedMS() - targetTime) > 300) {
|
||||
//Reset the timers, this can happen in 3 scenarios:
|
||||
//1) Target frame rate changed
|
||||
//2) The console was reset/power cycled or the emulation was paused (with or without the debugger)
|
||||
//3) As a satefy net, if we overshoot our target by over 300 milliseconds, the timer is reset, too.
|
||||
// This can happen when something slows the emulator down severely (or when breaking execution in VS when debugging Mesen itself, etc.)
|
||||
clockTimer.Reset();
|
||||
targetTime = 0;
|
||||
if(_resetRunTimers || delay != lastDelay || (clockTimer.GetElapsedMS() - targetTime) > 300) {
|
||||
//Reset the timers, this can happen in 3 scenarios:
|
||||
//1) Target frame rate changed
|
||||
//2) The console was reset/power cycled or the emulation was paused (with or without the debugger)
|
||||
//3) As a satefy net, if we overshoot our target by over 300 milliseconds, the timer is reset, too.
|
||||
// This can happen when something slows the emulator down severely (or when breaking execution in VS when debugging Mesen itself, etc.)
|
||||
clockTimer.Reset();
|
||||
targetTime = 0;
|
||||
|
||||
_resetRunTimers = false;
|
||||
lastDelay = delay;
|
||||
}
|
||||
_resetRunTimers = false;
|
||||
lastDelay = delay;
|
||||
}
|
||||
|
||||
targetTime += delay;
|
||||
targetTime += delay;
|
||||
|
||||
bool displayDebugInfo = _settings->CheckFlag(EmulationFlags::DisplayDebugInfo);
|
||||
if(displayDebugInfo) {
|
||||
double lastFrameTime = lastFrameTimer.GetElapsedMS();
|
||||
lastFrameTimer.Reset();
|
||||
frameDurations[frameDurationIndex] = lastFrameTime;
|
||||
frameDurationIndex = (frameDurationIndex + 1) % 60;
|
||||
bool displayDebugInfo = _settings->CheckFlag(EmulationFlags::DisplayDebugInfo);
|
||||
if(displayDebugInfo) {
|
||||
double lastFrameTime = lastFrameTimer.GetElapsedMS();
|
||||
lastFrameTimer.Reset();
|
||||
frameDurations[frameDurationIndex] = lastFrameTime;
|
||||
frameDurationIndex = (frameDurationIndex + 1) % 60;
|
||||
|
||||
DisplayDebugInformation(lastFrameTime, lastFrameMin, lastFrameMax, frameDurations);
|
||||
if(_slave) {
|
||||
_slave->DisplayDebugInformation(lastFrameTime, lastFrameMin, lastFrameMax, frameDurations);
|
||||
}
|
||||
DisplayDebugInformation(lastFrameTime, lastFrameMin, lastFrameMax, frameDurations);
|
||||
if(_slave) {
|
||||
_slave->DisplayDebugInformation(lastFrameTime, lastFrameMin, lastFrameMax, frameDurations);
|
||||
}
|
||||
}
|
||||
|
||||
//When sleeping for a long time (e.g <= 25% speed), sleep in small chunks and check to see if we need to stop sleeping between each sleep call
|
||||
while(targetTime - clockTimer.GetElapsedMS() > 50) {
|
||||
clockTimer.WaitUntil(clockTimer.GetElapsedMS() + 40);
|
||||
if(delay != GetFrameDelay() || _stop || _settings->NeedsPause() || _pauseCounter > 0) {
|
||||
targetTime = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Sleep until we're ready to start the next frame
|
||||
clockTimer.WaitUntil(targetTime);
|
||||
|
||||
if(_pauseCounter > 0) {
|
||||
//Need to temporarely pause the emu (to save/load a state, etc.)
|
||||
_runLock.Release();
|
||||
|
||||
//Spin wait until we are allowed to start again
|
||||
while(_pauseCounter > 0) { }
|
||||
|
||||
_runLock.Acquire();
|
||||
}
|
||||
|
||||
if(_pauseOnNextFrameRequested) {
|
||||
//Used by "Run Single Frame" option
|
||||
_settings->SetFlags(EmulationFlags::Paused);
|
||||
_pauseOnNextFrameRequested = false;
|
||||
}
|
||||
|
||||
bool pausedRequired = _settings->NeedsPause();
|
||||
if(pausedRequired && !_stop && !_settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) {
|
||||
_notificationManager->SendNotification(ConsoleNotificationType::GamePaused);
|
||||
|
||||
//Prevent audio from looping endlessly while game is paused
|
||||
_soundMixer->StopAudio();
|
||||
if(_slave) {
|
||||
_slave->_soundMixer->StopAudio();
|
||||
}
|
||||
|
||||
_runLock.Release();
|
||||
|
||||
PlatformUtilities::EnableScreensaver();
|
||||
PlatformUtilities::RestoreTimerResolution();
|
||||
while(pausedRequired && !_stop && !_settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) {
|
||||
//Sleep until emulation is resumed
|
||||
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(30));
|
||||
pausedRequired = _settings->NeedsPause();
|
||||
_paused = true;
|
||||
}
|
||||
_paused = false;
|
||||
|
||||
PlatformUtilities::DisableScreensaver();
|
||||
_runLock.Acquire();
|
||||
_notificationManager->SendNotification(ConsoleNotificationType::GameResumed);
|
||||
lastFrameTimer.Reset();
|
||||
|
||||
//Reset the timer to avoid speed up after a pause
|
||||
_resetRunTimers = true;
|
||||
}
|
||||
|
||||
if(_settings->CheckFlag(EmulationFlags::UseHighResolutionTimer)) {
|
||||
PlatformUtilities::EnableHighResolutionTimer();
|
||||
} else {
|
||||
PlatformUtilities::RestoreTimerResolution();
|
||||
}
|
||||
|
||||
_systemActionManager->ProcessSystemActions();
|
||||
|
||||
lastFrameNumber = _ppu->GetFrameCount();
|
||||
|
||||
if(_stop) {
|
||||
_stop = false;
|
||||
//When sleeping for a long time (e.g <= 25% speed), sleep in small chunks and check to see if we need to stop sleeping between each sleep call
|
||||
while(targetTime - clockTimer.GetElapsedMS() > 50) {
|
||||
clockTimer.WaitUntil(clockTimer.GetElapsedMS() + 40);
|
||||
if(delay != GetFrameDelay() || _stop || _settings->NeedsPause() || _pauseCounter > 0) {
|
||||
targetTime = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Sleep until we're ready to start the next frame
|
||||
clockTimer.WaitUntil(targetTime);
|
||||
|
||||
if(useRunAhead) {
|
||||
_settings->SetRunAheadFrameFlag(true);
|
||||
LoadState(runAheadState);
|
||||
_settings->SetRunAheadFrameFlag(false);
|
||||
}
|
||||
|
||||
if(_pauseCounter > 0) {
|
||||
//Need to temporarely pause the emu (to save/load a state, etc.)
|
||||
_runLock.Release();
|
||||
|
||||
//Spin wait until we are allowed to start again
|
||||
while(_pauseCounter > 0) { }
|
||||
|
||||
_runLock.Acquire();
|
||||
}
|
||||
|
||||
if(_pauseOnNextFrameRequested) {
|
||||
//Used by "Run Single Frame" option
|
||||
_settings->SetFlags(EmulationFlags::Paused);
|
||||
_pauseOnNextFrameRequested = false;
|
||||
}
|
||||
|
||||
bool pausedRequired = _settings->NeedsPause();
|
||||
if(pausedRequired && !_stop && !_settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) {
|
||||
_notificationManager->SendNotification(ConsoleNotificationType::GamePaused);
|
||||
|
||||
//Prevent audio from looping endlessly while game is paused
|
||||
_soundMixer->StopAudio();
|
||||
if(_slave) {
|
||||
_slave->_soundMixer->StopAudio();
|
||||
}
|
||||
|
||||
_runLock.Release();
|
||||
|
||||
PlatformUtilities::EnableScreensaver();
|
||||
PlatformUtilities::RestoreTimerResolution();
|
||||
while(pausedRequired && !_stop && !_settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) {
|
||||
//Sleep until emulation is resumed
|
||||
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(30));
|
||||
pausedRequired = _settings->NeedsPause();
|
||||
_paused = true;
|
||||
}
|
||||
_paused = false;
|
||||
|
||||
PlatformUtilities::DisableScreensaver();
|
||||
_runLock.Acquire();
|
||||
_notificationManager->SendNotification(ConsoleNotificationType::GameResumed);
|
||||
lastFrameTimer.Reset();
|
||||
|
||||
//Reset the timer to avoid speed up after a pause
|
||||
_resetRunTimers = true;
|
||||
}
|
||||
|
||||
if(_settings->CheckFlag(EmulationFlags::UseHighResolutionTimer)) {
|
||||
PlatformUtilities::EnableHighResolutionTimer();
|
||||
} else {
|
||||
PlatformUtilities::RestoreTimerResolution();
|
||||
}
|
||||
|
||||
_systemActionManager->ProcessSystemActions();
|
||||
|
||||
if(_stop) {
|
||||
_stop = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(const std::runtime_error &ex) {
|
||||
crashed = true;
|
||||
|
@ -926,6 +940,26 @@ void Console::Run()
|
|||
_notificationManager->SendNotification(ConsoleNotificationType::EmulationStopped);
|
||||
}
|
||||
|
||||
void Console::RunFrameWithRunAhead(std::stringstream& runAheadState)
|
||||
{
|
||||
uint32_t runAheadFrames = _settings->GetRunAheadFrames();
|
||||
_settings->SetRunAheadFrameFlag(true);
|
||||
//Run a single frame and save the state (no audio/video)
|
||||
RunFrame();
|
||||
SaveState(runAheadState);
|
||||
while(runAheadFrames > 1) {
|
||||
//Run extra frames if the requested run ahead frame count is higher than 1
|
||||
runAheadFrames--;
|
||||
RunFrame();
|
||||
}
|
||||
_apu->EndFrame();
|
||||
_settings->SetRunAheadFrameFlag(false);
|
||||
|
||||
//Run one frame normally (with audio/video output)
|
||||
RunFrame();
|
||||
_apu->EndFrame();
|
||||
}
|
||||
|
||||
void Console::ResetRunTimers()
|
||||
{
|
||||
_resetRunTimers = true;
|
||||
|
@ -1023,6 +1057,9 @@ double Console::GetFrameDelay()
|
|||
void Console::SaveState(ostream &saveStream)
|
||||
{
|
||||
if(_initialized) {
|
||||
//Send any unprocessed sound to the SoundMixer - needed for rewind
|
||||
_apu->EndFrame();
|
||||
|
||||
_cpu->SaveSnapshot(&saveStream);
|
||||
_ppu->SaveSnapshot(&saveStream);
|
||||
_memoryManager->SaveSnapshot(&saveStream);
|
||||
|
@ -1050,6 +1087,9 @@ void Console::LoadState(istream &loadStream)
|
|||
void Console::LoadState(istream &loadStream, uint32_t stateVersion)
|
||||
{
|
||||
if(_initialized) {
|
||||
//Send any unprocessed sound to the SoundMixer - needed for rewind
|
||||
_apu->EndFrame();
|
||||
|
||||
_cpu->LoadSnapshot(&loadStream, stateVersion);
|
||||
_ppu->LoadSnapshot(&loadStream, stateVersion);
|
||||
_memoryManager->LoadSnapshot(&loadStream, stateVersion);
|
||||
|
@ -1080,9 +1120,6 @@ void Console::LoadState(istream &loadStream, uint32_t stateVersion)
|
|||
|
||||
void Console::LoadState(uint8_t *buffer, uint32_t bufferSize)
|
||||
{
|
||||
//Send any unprocessed sound to the SoundMixer - needed for rewind
|
||||
_apu->EndFrame();
|
||||
|
||||
stringstream stream;
|
||||
stream.write((char*)buffer, bufferSize);
|
||||
stream.seekg(0, ios::beg);
|
||||
|
|
|
@ -100,6 +100,8 @@ private:
|
|||
bool _initialized = false;
|
||||
std::thread::id _emulationThreadId;
|
||||
|
||||
void RunFrameWithRunAhead(std::stringstream& runAheadState);
|
||||
|
||||
void LoadHdPack(VirtualFile &romFile, VirtualFile &patchFile);
|
||||
|
||||
void UpdateNesModel(bool sendNotification);
|
||||
|
@ -156,6 +158,7 @@ public:
|
|||
|
||||
void RunSingleFrame();
|
||||
void RunSlaveCpu();
|
||||
void RunFrame();
|
||||
bool UpdateHdPackMode();
|
||||
|
||||
shared_ptr<SystemActionManager> GetSystemActionManager();
|
||||
|
|
|
@ -293,8 +293,10 @@ void ControlManager::UpdateInputState()
|
|||
debugger->ProcessEvent(EventType::InputPolled);
|
||||
}
|
||||
|
||||
for(IInputRecorder* recorder : _inputRecorders) {
|
||||
recorder->RecordInput(_controlDevices);
|
||||
if(!_console->GetSettings()->IsRunAheadFrame()) {
|
||||
for(IInputRecorder* recorder : _inputRecorders) {
|
||||
recorder->RecordInput(_controlDevices);
|
||||
}
|
||||
}
|
||||
|
||||
//Used by VS System games
|
||||
|
|
|
@ -654,7 +654,10 @@ private:
|
|||
double _volumeReduction = 0.75;
|
||||
uint32_t _sampleRate = 48000;
|
||||
AudioFilterSettings _audioFilterSettings;
|
||||
|
||||
|
||||
uint32_t _runAheadFrames = 0;
|
||||
bool _isRunAheadFrame = false;
|
||||
|
||||
NesModel _model = NesModel::Auto;
|
||||
PpuModel _ppuModel = PpuModel::Ppu2C02;
|
||||
|
||||
|
@ -991,7 +994,27 @@ public:
|
|||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void SetRunAheadFrames(uint32_t frameCount)
|
||||
{
|
||||
_runAheadFrames = frameCount;
|
||||
}
|
||||
|
||||
uint32_t GetRunAheadFrames()
|
||||
{
|
||||
return _runAheadFrames;
|
||||
}
|
||||
|
||||
void SetRunAheadFrameFlag(bool disabled)
|
||||
{
|
||||
_isRunAheadFrame = disabled;
|
||||
}
|
||||
|
||||
bool IsRunAheadFrame()
|
||||
{
|
||||
return _isRunAheadFrame;
|
||||
}
|
||||
|
||||
//0: No limit, Number: % of default speed (50/60fps)
|
||||
void SetEmulationSpeed(uint32_t emulationSpeed, bool displaySpeed = false)
|
||||
{
|
||||
|
|
|
@ -48,6 +48,10 @@ void RewindManager::ClearBuffer()
|
|||
|
||||
void RewindManager::ProcessNotification(ConsoleNotificationType type, void * parameter)
|
||||
{
|
||||
if(_settings->IsRunAheadFrame()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == ConsoleNotificationType::PpuFrameDone) {
|
||||
_hasHistory = _history.size() >= 2;
|
||||
if(_settings->GetRewindBufferSize() > 0) {
|
||||
|
|
|
@ -164,7 +164,7 @@ void SoundMixer::PlayAudioBuffer(uint32_t time)
|
|||
_crossFeedFilter.ApplyFilter(_outputBuffer, sampleCount, filterSettings.CrossFadeRatio);
|
||||
}
|
||||
|
||||
if(rewindManager && rewindManager->SendAudio(_outputBuffer, (uint32_t)sampleCount, _sampleRate)) {
|
||||
if(!_settings->IsRunAheadFrame() && rewindManager && rewindManager->SendAudio(_outputBuffer, (uint32_t)sampleCount, _sampleRate)) {
|
||||
bool isRecording = _waveRecorder || _console->GetVideoRenderer()->IsRecording();
|
||||
if(isRecording) {
|
||||
shared_ptr<WaveRecorder> recorder = _waveRecorder;
|
||||
|
|
|
@ -41,11 +41,9 @@ public:
|
|||
{
|
||||
if(_needReset) {
|
||||
SetBit(SystemActionManager::Buttons::ResetButton);
|
||||
_needReset = false;
|
||||
}
|
||||
if(_needPowerCycle) {
|
||||
SetBit(SystemActionManager::Buttons::PowerButton);
|
||||
_needPowerCycle = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +70,7 @@ public:
|
|||
shared_ptr<Console> console = _console;
|
||||
if(console) {
|
||||
if(IsPressed(SystemActionManager::Buttons::ResetButton)) {
|
||||
_needReset = false;
|
||||
console->ResetComponents(true);
|
||||
console->GetControlManager()->UpdateInputState();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
VideoDecoder::VideoDecoder(shared_ptr<Console> console)
|
||||
{
|
||||
_console = console;
|
||||
_settings = _console->GetSettings();
|
||||
_frameChanged = false;
|
||||
_stopFlag = false;
|
||||
UpdateVideoFilter();
|
||||
|
@ -158,6 +159,10 @@ uint32_t VideoDecoder::GetFrameCount()
|
|||
|
||||
void VideoDecoder::UpdateFrameSync(void *ppuOutputBuffer, HdScreenInfo *hdScreenInfo)
|
||||
{
|
||||
if(_settings->IsRunAheadFrame()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_frameNumber = _console->GetFrameCount();
|
||||
_hdScreenInfo = hdScreenInfo;
|
||||
_ppuOutputBuffer = (uint16_t*)ppuOutputBuffer;
|
||||
|
@ -167,6 +172,10 @@ void VideoDecoder::UpdateFrameSync(void *ppuOutputBuffer, HdScreenInfo *hdScreen
|
|||
|
||||
void VideoDecoder::UpdateFrame(void *ppuOutputBuffer, HdScreenInfo *hdScreenInfo)
|
||||
{
|
||||
if(_settings->IsRunAheadFrame()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(_frameChanged) {
|
||||
//Last frame isn't done decoding yet - sometimes Signal() introduces a 25-30ms delay
|
||||
while(_frameChanged) {
|
||||
|
|
|
@ -27,7 +27,7 @@ class VideoDecoder
|
|||
{
|
||||
private:
|
||||
shared_ptr<Console> _console;
|
||||
|
||||
EmulationSettings* _settings;
|
||||
uint16_t *_ppuOutputBuffer = nullptr;
|
||||
HdScreenInfo *_hdScreenInfo = nullptr;
|
||||
bool _hdFilterEnabled = false;
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace Mesen.GUI.Config
|
|||
[MinMax(0, 5000)] public UInt32 EmulationSpeed = 100;
|
||||
[MinMax(0, 5000)] public UInt32 TurboSpeed = 300;
|
||||
[MinMax(0, 5000)] public UInt32 RewindSpeed = 100;
|
||||
[MinMax(0, 10)] public UInt32 RunAheadFrames = 0;
|
||||
|
||||
public EmulationInfo()
|
||||
{
|
||||
|
@ -49,6 +50,7 @@ namespace Mesen.GUI.Config
|
|||
|
||||
InteropEmu.SetEmulationSpeed(emulationInfo.EmulationSpeed);
|
||||
InteropEmu.SetTurboRewindSpeed(emulationInfo.TurboSpeed, emulationInfo.RewindSpeed);
|
||||
InteropEmu.SetRunAheadFrames(emulationInfo.RunAheadFrames);
|
||||
|
||||
InteropEmu.SetFlag(EmulationFlags.Mmc3IrqAltBehavior, emulationInfo.UseAlternativeMmc3Irq);
|
||||
InteropEmu.SetFlag(EmulationFlags.AllowInvalidInput, emulationInfo.AllowInvalidInput);
|
||||
|
|
|
@ -308,6 +308,8 @@
|
|||
<Control ID="lblEmulationSpeed">Velocitat d'emulació:</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = Velocitat màxima)</Control>
|
||||
<Control ID="lblRewindSpeed">Velocitat del rebobinat:</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">frames (reduces input lag, increases CPU usage)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">Avançat</Control>
|
||||
<Control ID="lblDeveloperSettings">Recommended settings for developers (homebrew / ROM hacking)</Control>
|
||||
|
|
|
@ -308,6 +308,8 @@
|
|||
<Control ID="lblTurboSpeed">Fast Forward Speed:</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = Maximum speed)</Control>
|
||||
<Control ID="lblRewindSpeed">Rewind Speed:</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">frames (reduces input lag, increases CPU usage)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">Advanced</Control>
|
||||
<Control ID="lblDeveloperSettings">Recommended settings for developers (homebrew / ROM hacking)</Control>
|
||||
|
|
|
@ -307,6 +307,8 @@
|
|||
<Control ID="lblEmulationSpeed">Velocidad de emulación:</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = Velocidad máxima)</Control>
|
||||
<Control ID="lblRewindSpeed">Velocidad de rebobinado:</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">frames (reduces input lag, increases CPU usage)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">Avanzado</Control>
|
||||
<Control ID="lblDeveloperSettings">Configuración recomendada para desarrolladores (homebrew / ROM hacking)</Control>
|
||||
|
|
|
@ -308,6 +308,8 @@
|
|||
<Control ID="lblTurboSpeed">Vitesse d'avance rapide :</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = Vitesse maximale)</Control>
|
||||
<Control ID="lblRewindSpeed">Vitesse du rembobinage :</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">images (réduit l'input lag, au coût de la performance)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">Avancé</Control>
|
||||
<Control ID="lblDeveloperSettings">Options recommandées pour les développeurs (homebrew / ROM hacking)</Control>
|
||||
|
|
|
@ -308,6 +308,8 @@
|
|||
<Control ID="lblTurboSpeed">Velocità avanti veloce:</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = Velocità massima)</Control>
|
||||
<Control ID="lblRewindSpeed">Velocità Riavvolgimento:</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">frames (reduces input lag, increases CPU usage)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">Avanzato</Control>
|
||||
<Control ID="lblDeveloperSettings">Opzioni raccomandate per sviluppatori (homebrew / ROM hacking)</Control>
|
||||
|
|
|
@ -307,6 +307,8 @@
|
|||
<Control ID="lblTurboSpeed">早送りの速度:</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = 最高速度)</Control>
|
||||
<Control ID="lblRewindSpeed">巻き戻しの速度:</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">フレーム (入力遅延低下)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">詳細設定</Control>
|
||||
<Control ID="lblDeveloperSettings">開発者向け設定 (自作ソフト / ROM hacking)</Control>
|
||||
|
|
|
@ -308,6 +308,8 @@
|
|||
<Control ID="lblTurboSpeed">Velocidade de avanço rápido:</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = Velocidade máxima)</Control>
|
||||
<Control ID="lblRewindSpeed">Velocidade de rebobinamento:</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">frames (reduces input lag, increases CPU usage)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">Avançado</Control>
|
||||
<Control ID="lblDeveloperSettings">Configurações recomendadas para programadores (homebrew / ROM hacking)</Control>
|
||||
|
|
|
@ -307,6 +307,8 @@
|
|||
<Control ID="lblTurboSpeed">Перемотка:</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = Максимальная скорость)</Control>
|
||||
<Control ID="lblRewindSpeed">Скорость перемотки:</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">frames (reduces input lag, increases CPU usage)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">Расширенные</Control>
|
||||
<Control ID="lblDeveloperSettings">Рекомендованные настройки для разработчиков (homebrew / ROM hacking)</Control>
|
||||
|
|
|
@ -307,6 +307,8 @@
|
|||
<Control ID="lblTurboSpeed">Перемотка:</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = Максимальна швидкiсть)</Control>
|
||||
<Control ID="lblRewindSpeed">Швидкість перемотування:</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">frames (reduces input lag, increases CPU usage)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">Розширені</Control>
|
||||
<Control ID="lblDeveloperSettings">Recommended settings for developers (homebrew / ROM hacking)</Control>
|
||||
|
|
|
@ -334,6 +334,8 @@
|
|||
<Control ID="lblTurboSpeed">快进速度:</Control>
|
||||
<Control ID="lblRewindSpeedHint">% (0 = 最快)</Control>
|
||||
<Control ID="lblRewindSpeed">快退速度:</Control>
|
||||
<Control ID="lblRunAhead">Run Ahead:</Control>
|
||||
<Control ID="lblRunAheadFrames">frames (reduces input lag, increases CPU usage)</Control>
|
||||
|
||||
<Control ID="tpgAdvanced">高级</Control>
|
||||
<Control ID="lblDeveloperSettings">开发者推荐设置 (自作/修改 ROM)</Control>
|
||||
|
|
1758
GUI.NET/Forms/Config/frmEmulationConfig.Designer.cs
generated
1758
GUI.NET/Forms/Config/frmEmulationConfig.Designer.cs
generated
File diff suppressed because it is too large
Load diff
|
@ -27,6 +27,7 @@ namespace Mesen.GUI.Forms.Config
|
|||
AddBinding("EmulationSpeed", nudEmulationSpeed);
|
||||
AddBinding("TurboSpeed", nudTurboSpeed);
|
||||
AddBinding("RewindSpeed", nudRewindSpeed);
|
||||
AddBinding("RunAheadFrames", nudRunAheadFrames);
|
||||
|
||||
AddBinding("UseAlternativeMmc3Irq", chkUseAlternativeMmc3Irq);
|
||||
AddBinding("AllowInvalidInput", chkAllowInvalidInput);
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace Mesen.GUI
|
|||
[DllImport(DLLPath)] public static extern void HistoryViewerRelease();
|
||||
[DllImport(DLLPath)] public static extern void HistoryViewerRun();
|
||||
[DllImport(DLLPath)] public static extern void HistoryViewerStop();
|
||||
|
||||
[DllImport(DLLPath)] public static extern UInt32 HistoryViewerGetHistoryLength();
|
||||
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool HistoryViewerSaveMovie([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string movieFile, UInt32 startPosition, UInt32 endPosition);
|
||||
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool HistoryViewerCreateSaveState([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string outfileFile, UInt32 position);
|
||||
|
@ -192,6 +193,7 @@ namespace Mesen.GUI
|
|||
[DllImport(DLLPath)] public static extern void SetSampleRate(UInt32 sampleRate);
|
||||
[DllImport(DLLPath)] public static extern void SetAudioLatency(UInt32 msLatency);
|
||||
[DllImport(DLLPath)] public static extern void SetAudioFilterSettings(AudioFilterSettings settings);
|
||||
[DllImport(DLLPath)] public static extern void SetRunAheadFrames(UInt32 frameCount);
|
||||
|
||||
[DllImport(DLLPath)] public static extern NesModel GetNesModel();
|
||||
[DllImport(DLLPath)] public static extern void SetNesModel(NesModel model);
|
||||
|
|
|
@ -627,6 +627,7 @@ namespace InteropEmu {
|
|||
DllExport void __stdcall SetSampleRate(uint32_t sampleRate) { _settings->SetSampleRate(sampleRate); }
|
||||
DllExport void __stdcall SetAudioLatency(uint32_t msLatency) { _settings->SetAudioLatency(msLatency); }
|
||||
DllExport void __stdcall SetAudioFilterSettings(AudioFilterSettings settings) { _settings->SetAudioFilterSettings(settings); }
|
||||
DllExport void __stdcall SetRunAheadFrames(uint32_t frameCount) { _settings->SetRunAheadFrames(frameCount); }
|
||||
|
||||
DllExport NesModel __stdcall GetNesModel() { return _console->GetModel(); }
|
||||
DllExport void __stdcall SetNesModel(uint32_t model) { _settings->SetNesModel((NesModel)model); }
|
||||
|
|
Loading…
Add table
Reference in a new issue