Skip to content

Commit

Permalink
Fixed SAP-R/LZSS XEX export not updating screen.
Browse files Browse the repository at this point in the history
- Added a new function to perform screen updates on demand, with a rudimentary frameskip argument being supported
- Also rate limited the screen updates during SAP-R dumps to never perform more often than necessary, boosting performance a lot more in the process
  • Loading branch information
VinsCool committed Mar 11, 2023
1 parent 70762d8 commit b45dac6
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 40 deletions.
32 changes: 32 additions & 0 deletions cpp_src/GuiHelpers.cpp
Expand Up @@ -13,6 +13,38 @@ void SetStatusBarText(const char* text)
sb.SetWindowText(text);
}

static int lastTick;

BOOL RefreshScreen(int frameskip)
{
// Bail out of this function if it couldn't be performed
if (!g_hwnd || !g_viewhwnd || g_closeApplication)
return 0;

// Frameskip of 1 or higher
if (frameskip > 0)
{
// Frame was already processed
if (lastTick == g_timerGlobalCount)
return 0;

// Skip frame with modulo
if ((g_timerGlobalCount % frameskip))
return 0;

// Remember the last time a frame was processed
lastTick = g_timerGlobalCount;
}

// Force a screen update if the condition is met for it
AfxGetApp()->GetMainWnd()->Invalidate();
SCREENUPDATE;
UpdateWindow(g_viewhwnd);

// Screen was refreshed
return 1;
}

int EditText(int vk, int shift, int control, char* txt, int& cur, int max)
{
//returns 1 if TAB or ENTER was pressed
Expand Down
2 changes: 2 additions & 0 deletions cpp_src/GuiHelpers.h
Expand Up @@ -10,6 +10,8 @@


extern void SetStatusBarText(const char* text);
extern BOOL RefreshScreen(int frameskip = 0);

extern int EditText(int vk, int shift, int control, char* txt, int& cur, int max);

extern BOOL IsHoveredXY(int x, int y, int xLength, int yLength);
Expand Down
46 changes: 12 additions & 34 deletions cpp_src/IO_Song_ExportSaprLzss.cpp
Expand Up @@ -728,7 +728,9 @@ bool CSong::ExportLZSS_XEX(std::ofstream& ou)
/// <returns></returns>
void CSong::DumpSongToPokeyBuffer(int playmode, int songline, int trackline)
{
Stop();
CString statusBarLog;

Stop(); // Make sure RMT is stopped
Atari_InitRMTRoutine(); // Reset the RMT routines
SetChannelOnOff(-1, 0); // Switch all channels off

Expand All @@ -741,12 +743,7 @@ void CSong::DumpSongToPokeyBuffer(int playmode, int songline, int trackline)
Play(playmode, m_followplay);

// Wait in a tight loop pumping messages until the playback stops
MSG msg;
CString statusBarLog;
CWnd* wnd = AfxGetApp()->GetMainWnd();

wnd->EnableWindow(FALSE);
wnd->BeginWaitCursor();
EnableWindow(g_hwnd, FALSE);

// The SAP-R dumper is running during that time...
while (m_play != MPLAY_STOP)
Expand All @@ -770,21 +767,12 @@ void CSong::DumpSongToPokeyBuffer(int playmode, int songline, int trackline)

// Update the screen only once every few frames
// Displaying everything in real time slows things down considerably!
if (g_timerGlobalCount % 8 != 0)
if (!RefreshScreen(1))
continue;

SCREENUPDATE;

// Display the number of frames dumped so far
statusBarLog.Format("Generating Pokey stream, playing song in quick mode... %i frames recorded", g_PokeyStream.GetCurrentFrame());
SetStatusBarText(statusBarLog);

// Send pending messages to update the screen
if (::PeekMessage(&msg, wnd->m_hWnd, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}

// End playback now, the SAP-R data should have been dumped successfully!
Expand All @@ -793,26 +781,21 @@ void CSong::DumpSongToPokeyBuffer(int playmode, int songline, int trackline)
statusBarLog.Format("Done... %i frames recorded in total, Loop point found at frame %i", g_PokeyStream.GetCurrentFrame(), g_PokeyStream.GetFirstCountPoint());
SetStatusBarText(statusBarLog);

wnd->EndWaitCursor();
wnd->EnableWindow(); // Turn on the window again
EnableWindow(g_hwnd, TRUE);
}

// A dumb SAP-R LZSS optimisations bruteforcer, returns the optimal value and buffer
int CSong::BruteforceOptimalLZSS(unsigned char* src, int srclen, unsigned char* dst)
{
MSG msg;
CString statusBarLog;
CWnd* wnd = AfxGetApp()->GetMainWnd();

wnd->EnableWindow(FALSE);
wnd->BeginWaitCursor();

CCompressLzss lzssData;

// Start from a high value to force the first pattern to be the best one
int bestScore = 0xFFFFFF;
int optimal = 0;

EnableWindow(g_hwnd, FALSE);

for (int i = 0; i < SAPR_OPTIMISATIONS_COUNT; i++)
{
int bruteforced = lzssData.LZSS_SAP(src, srclen, dst, i);
Expand All @@ -823,23 +806,18 @@ int CSong::BruteforceOptimalLZSS(unsigned char* src, int srclen, unsigned char*
optimal = i;
}

// Always refresh the screen after each iteration
RefreshScreen();

statusBarLog.Format("Compressing %i bytes, bruteforcing optimisation pattern %i... Current best: %i bytes with optimisation pattern %i", srclen, i, bestScore, optimal);
SetStatusBarText(statusBarLog);

// Send pending messages to update the screen
if (::PeekMessage(&msg, wnd->m_hWnd, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}

// Bruteforcing was completed, display some stats
statusBarLog.Format("Done... %i bytes were shrunk to %i bytes using the optimisation pattern %i", srclen, bestScore, optimal);
SetStatusBarText(statusBarLog);

wnd->EndWaitCursor();
wnd->EnableWindow(); // Turn on the window again
EnableWindow(g_hwnd, TRUE);

return lzssData.LZSS_SAP(src, srclen, dst, optimal);
}
7 changes: 1 addition & 6 deletions cpp_src/RmtView.cpp
Expand Up @@ -276,12 +276,7 @@ void CRmtView::OnTimer(UINT_PTR nIDEvent)
{
KillTimer(m_timerDisplay);
m_timerDisplay = SetTimer(1, m_timerDisplayTick[g_timerGlobalCount % 3], NULL);

if (g_hwnd && !g_closeApplication)
{
AfxGetApp()->GetMainWnd()->Invalidate();
SCREENUPDATE;
}
RefreshScreen();
}

CView::OnTimer(nIDEvent);
Expand Down

0 comments on commit b45dac6

Please sign in to comment.