Rewrite the way full speed works.
This is more and more similar to AppleWin's logic. Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
parent
24971328ba
commit
0b3e57d934
9 changed files with 100 additions and 79 deletions
|
@ -27,7 +27,7 @@ namespace common2
|
|||
|
||||
uint64_t Speed::getCyclesTillNext(const size_t microseconds) const
|
||||
{
|
||||
if (myFixedSpeed)
|
||||
if (myFixedSpeed || g_bFullSpeed)
|
||||
{
|
||||
return getCyclesAtFixedSpeed(microseconds);
|
||||
}
|
||||
|
|
|
@ -133,12 +133,14 @@ namespace sa2
|
|||
{
|
||||
if (ImGui::Begin("Apple ]["))
|
||||
{
|
||||
UpdateTexture();
|
||||
ImGui::Image(myTexture, ImGui::GetContentRegionAvail(), uv0, uv1);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateTexture();
|
||||
const ImVec2 zero(0, menuBarHeight);
|
||||
// draw on the background
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
@ -159,7 +161,7 @@ namespace sa2
|
|||
y = GetRelativePosition(posY, height);
|
||||
}
|
||||
|
||||
void SDLImGuiFrame::RenderPresent()
|
||||
void SDLImGuiFrame::VideoPresentScreen()
|
||||
{
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame(myWindow.get());
|
||||
|
|
|
@ -19,9 +19,7 @@ namespace sa2
|
|||
|
||||
~SDLImGuiFrame() override;
|
||||
|
||||
void UpdateTexture() override;
|
||||
void RenderPresent() override;
|
||||
|
||||
void VideoPresentScreen() override;
|
||||
void ResetSpeed() override;
|
||||
|
||||
protected:
|
||||
|
@ -31,6 +29,7 @@ namespace sa2
|
|||
|
||||
private:
|
||||
|
||||
void UpdateTexture();
|
||||
void ClearBackground();
|
||||
void DrawAppleVideo();
|
||||
|
||||
|
|
|
@ -235,6 +235,12 @@ namespace sa2
|
|||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
ImGui::Checkbox("Full speed", &g_bFullSpeed);
|
||||
ImGui::PopItemFlag();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("Restart"))
|
||||
{
|
||||
frame->Restart();
|
||||
|
@ -1096,7 +1102,7 @@ namespace sa2
|
|||
if (ImGui::Button("Step"))
|
||||
{
|
||||
frame->ChangeMode(MODE_DEBUG);
|
||||
frame->Execute(0);
|
||||
frame->SingleStep();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
|
|
|
@ -56,17 +56,6 @@ namespace
|
|||
common2::Timer * timer;
|
||||
};
|
||||
|
||||
void setGLSwapInterval(const int interval)
|
||||
{
|
||||
const int current = SDL_GL_GetSwapInterval();
|
||||
// in QEMU with GL_RENDERER: llvmpipe (LLVM 12.0.0, 256 bits)
|
||||
// SDL_GL_SetSwapInterval() always fails
|
||||
if (interval != current && SDL_GL_SetSwapInterval(interval))
|
||||
{
|
||||
throw std::runtime_error(std::string("SDL_GL_SetSwapInterval: ") + SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void run_sdl(int argc, const char * argv [])
|
||||
|
@ -116,11 +105,10 @@ void run_sdl(int argc, const char * argv [])
|
|||
{
|
||||
// we need to switch off vsync, otherwise FPS is limited to 60
|
||||
// and it will take longer to run
|
||||
setGLSwapInterval(0);
|
||||
sa2::SDLFrame::setGLSwapInterval(0);
|
||||
|
||||
const auto redraw = [&frame]{
|
||||
frame->UpdateTexture();
|
||||
frame->RenderPresent();
|
||||
frame->VideoPresentScreen();
|
||||
};
|
||||
|
||||
const auto refresh = [redraw, &video]{
|
||||
|
@ -133,10 +121,7 @@ void run_sdl(int argc, const char * argv [])
|
|||
}
|
||||
else
|
||||
{
|
||||
setGLSwapInterval(options.glSwapInterval);
|
||||
|
||||
common2::Timer global;
|
||||
common2::Timer updateTextureTimer;
|
||||
common2::Timer refreshScreenTimer;
|
||||
common2::Timer cpuTimer;
|
||||
common2::Timer eventTimer;
|
||||
|
@ -164,14 +149,10 @@ void run_sdl(int argc, const char * argv [])
|
|||
frame->ExecuteOneFrame(oneFrame);
|
||||
cpuTimer.toc();
|
||||
|
||||
updateTextureTimer.tic();
|
||||
frame->UpdateTexture();
|
||||
updateTextureTimer.toc();
|
||||
|
||||
if (!options.headless)
|
||||
{
|
||||
refreshScreenTimer.tic();
|
||||
frame->RenderPresent();
|
||||
frame->VideoPresentScreen();
|
||||
refreshScreenTimer.toc();
|
||||
}
|
||||
frameTimer.toc();
|
||||
|
@ -182,7 +163,6 @@ void run_sdl(int argc, const char * argv [])
|
|||
std::cerr << "Global: " << global << std::endl;
|
||||
std::cerr << "Frame: " << frameTimer << std::endl;
|
||||
std::cerr << "Screen: " << refreshScreenTimer << std::endl;
|
||||
std::cerr << "Texture: " << updateTextureTimer << std::endl;
|
||||
std::cerr << "Events: " << eventTimer << std::endl;
|
||||
std::cerr << "CPU: " << cpuTimer << std::endl;
|
||||
|
||||
|
|
|
@ -49,13 +49,9 @@ namespace sa2
|
|||
myPitch = width * sizeof(bgra_t);
|
||||
}
|
||||
|
||||
void SDLRendererFrame::UpdateTexture()
|
||||
void SDLRendererFrame::VideoPresentScreen()
|
||||
{
|
||||
SDL_UpdateTexture(myTexture.get(), nullptr, myFramebuffer.data(), myPitch);
|
||||
}
|
||||
|
||||
void SDLRendererFrame::RenderPresent()
|
||||
{
|
||||
SDL_RenderCopyEx(myRenderer.get(), myTexture.get(), &myRect, nullptr, 0.0, nullptr, SDL_FLIP_VERTICAL);
|
||||
SDL_RenderPresent(myRenderer.get());
|
||||
}
|
||||
|
|
|
@ -15,8 +15,7 @@ namespace sa2
|
|||
public:
|
||||
SDLRendererFrame(const common2::EmulatorOptions & options);
|
||||
|
||||
void UpdateTexture() override;
|
||||
void RenderPresent() override;
|
||||
void VideoPresentScreen() override;
|
||||
|
||||
protected:
|
||||
void GetRelativeMousePosition(const SDL_MouseMotionEvent & motion, double & x, double & y) const override;
|
||||
|
|
|
@ -32,11 +32,6 @@
|
|||
namespace
|
||||
{
|
||||
|
||||
bool canDoFullSpeed()
|
||||
{
|
||||
return GetCardMgr().GetDisk2CardMgr().IsConditionForFullSpeed() && !Spkr_IsActive() && !MB_IsActive();
|
||||
}
|
||||
|
||||
void processAppleKey(const SDL_KeyboardEvent & key, const bool forceCapsLock)
|
||||
{
|
||||
// using keycode (or scan code) one takes a physical view of the keyboard
|
||||
|
@ -130,19 +125,33 @@ namespace sa2
|
|||
{
|
||||
|
||||
SDLFrame::SDLFrame(const common2::EmulatorOptions & options)
|
||||
: myForceCapsLock(true)
|
||||
: myTargetGLSwap(options.glSwapInterval)
|
||||
, myForceCapsLock(true)
|
||||
, myMultiplier(1)
|
||||
, myFullscreen(false)
|
||||
, myDragAndDropSlot(SLOT6)
|
||||
, myDragAndDropDrive(DRIVE_1)
|
||||
, myScrollLockFullSpeed(false)
|
||||
, mySpeed(options.fixedSpeed)
|
||||
{
|
||||
}
|
||||
|
||||
void SDLFrame::setGLSwapInterval(const int interval)
|
||||
{
|
||||
const int current = SDL_GL_GetSwapInterval();
|
||||
// in QEMU with GL_RENDERER: llvmpipe (LLVM 12.0.0, 256 bits)
|
||||
// SDL_GL_SetSwapInterval() always fails
|
||||
if (interval != current && SDL_GL_SetSwapInterval(interval))
|
||||
{
|
||||
throw std::runtime_error(std::string("SDL_GL_SetSwapInterval: ") + SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
void SDLFrame::Initialize()
|
||||
{
|
||||
CommonFrame::Initialize();
|
||||
mySpeed.reset();
|
||||
setGLSwapInterval(myTargetGLSwap);
|
||||
}
|
||||
|
||||
void SDLFrame::FrameRefreshStatus(int drawflags)
|
||||
|
@ -164,12 +173,6 @@ namespace sa2
|
|||
}
|
||||
}
|
||||
|
||||
void SDLFrame::VideoPresentScreen()
|
||||
{
|
||||
UpdateTexture();
|
||||
RenderPresent();
|
||||
}
|
||||
|
||||
const std::shared_ptr<SDL_Window> & SDLFrame::GetWindow() const
|
||||
{
|
||||
return myWindow;
|
||||
|
@ -497,6 +500,11 @@ namespace sa2
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SDLK_SCROLLLOCK:
|
||||
{
|
||||
myScrollLockFullSpeed = !myScrollLockFullSpeed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,44 +566,35 @@ namespace sa2
|
|||
const DWORD executedCycles = CpuExecute(thisCyclesToExecute, bVideoUpdate);
|
||||
totalCyclesExecuted += executedCycles;
|
||||
|
||||
g_dwCyclesThisFrame = (g_dwCyclesThisFrame + executedCycles) % dwClksPerFrame;
|
||||
GetCardMgr().GetDisk2CardMgr().UpdateDriveState(executedCycles);
|
||||
MB_PeriodicUpdate(executedCycles);
|
||||
SpkrUpdate(executedCycles);
|
||||
|
||||
g_dwCyclesThisFrame += executedCycles;
|
||||
if (g_dwCyclesThisFrame >= dwClksPerFrame)
|
||||
{
|
||||
g_dwCyclesThisFrame -= dwClksPerFrame;
|
||||
if (g_bFullSpeed)
|
||||
{
|
||||
NTSC_VideoClockResync(g_dwCyclesThisFrame);
|
||||
GetVideo().VideoRefreshBuffer(GetVideo().GetVideoMode(), true);
|
||||
}
|
||||
}
|
||||
} while (totalCyclesExecuted < cyclesToExecute);
|
||||
}
|
||||
|
||||
void SDLFrame::ExecuteInRunningMode(const size_t msNextFrame)
|
||||
{
|
||||
// 1 frame at normal speed
|
||||
const uint64_t cyclesToExecute = mySpeed.getCyclesTillNext(msNextFrame * 1000);
|
||||
SetFullSpeed(CanDoFullSpeed());
|
||||
const uint64_t cyclesToExecute = mySpeed.getCyclesTillNext(msNextFrame * 1000); // this checks g_bFullSpeed
|
||||
Execute(cyclesToExecute);
|
||||
|
||||
// up to 5x more as maximum speed
|
||||
const int maximumFrames = 5;
|
||||
|
||||
const uint64_t cyclesToExecutePerFrame = mySpeed.getCyclesAtFixedSpeed(msNextFrame * 1000);
|
||||
int count = maximumFrames;
|
||||
while ((g_bFullSpeed = (count && canDoFullSpeed())))
|
||||
{
|
||||
Execute(cyclesToExecutePerFrame);
|
||||
--count;
|
||||
}
|
||||
|
||||
if (count < maximumFrames)
|
||||
{
|
||||
// we have run something in full speed
|
||||
// Redraw and Reset
|
||||
VideoRedrawScreenDuringFullSpeed(g_dwCyclesThisFrame);
|
||||
ResetSpeed();
|
||||
}
|
||||
}
|
||||
|
||||
void SDLFrame::ExecuteInDebugMode(const size_t msNextFrame)
|
||||
{
|
||||
// In AppleWin this is called without a timer for just one iteration
|
||||
// because we run a "frame" at a time, we need a bit of ingenuity
|
||||
const uint64_t cyclesToExecute = mySpeed.getCyclesTillNext(msNextFrame * 1000);
|
||||
const uint64_t cyclesToExecute = mySpeed.getCyclesAtFixedSpeed(msNextFrame * 1000);
|
||||
const uint64_t target = g_nCumulativeCycles + cyclesToExecute;
|
||||
|
||||
while (g_nAppMode == MODE_STEPPING && g_nCumulativeCycles < target)
|
||||
|
@ -664,9 +663,44 @@ namespace sa2
|
|||
myDragAndDropDrive = drive;
|
||||
}
|
||||
|
||||
void SDLFrame::SetFullSpeed(const bool value)
|
||||
{
|
||||
if (g_bFullSpeed != value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
// entering full speed
|
||||
MB_Mute();
|
||||
setGLSwapInterval(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// leaving full speed
|
||||
MB_Unmute();
|
||||
setGLSwapInterval(myTargetGLSwap);
|
||||
mySpeed.reset();
|
||||
}
|
||||
g_bFullSpeed = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool SDLFrame::CanDoFullSpeed()
|
||||
{
|
||||
return myScrollLockFullSpeed ||
|
||||
(g_dwSpeed == SPEED_MAX) ||
|
||||
(GetCardMgr().GetDisk2CardMgr().IsConditionForFullSpeed() && !Spkr_IsActive() && !MB_IsActive()) ||
|
||||
IsDebugSteppingAtFullSpeed();
|
||||
}
|
||||
|
||||
void SDLFrame::SingleStep()
|
||||
{
|
||||
SetFullSpeed(CanDoFullSpeed());
|
||||
Execute(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SingleStep(bool /* bReinit */)
|
||||
{
|
||||
dynamic_cast<sa2::SDLFrame &>(GetFrame()).Execute(0);
|
||||
dynamic_cast<sa2::SDLFrame &>(GetFrame()).SingleStep();
|
||||
}
|
||||
|
|
|
@ -20,26 +20,24 @@ namespace sa2
|
|||
|
||||
void Initialize() override;
|
||||
|
||||
void VideoPresentScreen() override;
|
||||
void FrameRefreshStatus(int drawflags) override;
|
||||
int FrameMessageBox(LPCSTR lpText, LPCSTR lpCaption, UINT uType) override;
|
||||
void GetBitmap(LPCSTR lpBitmapName, LONG cb, LPVOID lpvBits) override;
|
||||
|
||||
void ProcessEvents(bool &quit);
|
||||
|
||||
void Execute(const DWORD uCycles);
|
||||
void ExecuteOneFrame(const size_t msNextFrame);
|
||||
void ChangeMode(const AppMode_e mode);
|
||||
void SingleStep();
|
||||
virtual void ResetSpeed();
|
||||
|
||||
virtual void UpdateTexture() = 0;
|
||||
virtual void RenderPresent() = 0;
|
||||
|
||||
const std::shared_ptr<SDL_Window> & GetWindow() const;
|
||||
|
||||
void getDragDropSlotAndDrive(size_t & slot, size_t & drive) const;
|
||||
void setDragDropSlotAndDrive(const size_t slot, const size_t drive);
|
||||
|
||||
static void setGLSwapInterval(const int interval);
|
||||
|
||||
protected:
|
||||
void SetApplicationIcon();
|
||||
|
||||
|
@ -55,11 +53,14 @@ namespace sa2
|
|||
|
||||
void ExecuteInRunningMode(const size_t msNextFrame);
|
||||
void ExecuteInDebugMode(const size_t msNextFrame);
|
||||
void Execute(const DWORD uCycles);
|
||||
|
||||
void SetFullSpeed(const bool value);
|
||||
bool CanDoFullSpeed();
|
||||
|
||||
static double GetRelativePosition(const int value, const int width);
|
||||
|
||||
std::shared_ptr<SDL_Window> myWindow;
|
||||
|
||||
int myTargetGLSwap;
|
||||
bool myForceCapsLock;
|
||||
int myMultiplier;
|
||||
bool myFullscreen;
|
||||
|
@ -67,7 +68,11 @@ namespace sa2
|
|||
size_t myDragAndDropSlot;
|
||||
size_t myDragAndDropDrive;
|
||||
|
||||
bool myScrollLockFullSpeed;
|
||||
|
||||
common2::Speed mySpeed;
|
||||
|
||||
std::shared_ptr<SDL_Window> myWindow;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue