ft2-clone

Fasttracker 2 clone
Log | Files | Refs | README | LICENSE

commit 17ac33dc875bb058794df9d3ca2b0274f3cd9e54
parent 04baa345fb4255ca4a177fd7c4c3bee24d59db46
Author: Olav Sørensen <olav.sorensen@live.no>
Date:   Mon, 11 Jul 2022 21:39:41 +0200

Some fullscreen fixes and more

Diffstat:
Msrc/ft2_config.c | 57++++++++++++++++++++++++++++++++++-----------------------
Msrc/ft2_events.c | 54+++++++++++++++---------------------------------------
Msrc/ft2_keyboard.c | 4++--
Msrc/ft2_textboxes.c | 2+-
Msrc/ft2_video.c | 90++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/ft2_video.h | 6+++---
6 files changed, 130 insertions(+), 83 deletions(-)

diff --git a/src/ft2_config.c b/src/ft2_config.c @@ -210,12 +210,40 @@ static void setDefaultConfigSettings(void) loadConfigFromBuffer(true); } +static void updateImageStretchAndPixelFilter(uint8_t oldWindowFlags, uint8_t oldSpecialFlags2) +{ + bool didFullscreenUpdate = false; + + // handle pixel filter change + if ((oldWindowFlags & PIXEL_FILTER) != (config.windowFlags & PIXEL_FILTER)) + { + recreateTexture(); + if (video.fullscreen) // force an update if in fullscreen mode + { + leaveFullscreen(); + enterFullscreen(); + didFullscreenUpdate = true; + } + } + + // handle image stretch change + if ((oldSpecialFlags2 & STRETCH_IMAGE) != (config.specialFlags2 & STRETCH_IMAGE)) + { + if (video.fullscreen && !didFullscreenUpdate) // force an update if in fullscreen mode + { + leaveFullscreen(); + enterFullscreen(); + } + } +} + void resetConfig(void) { if (okBox(2, "System request", "Are you sure you want to reset your FT2 configuration?") != 1) return; const uint8_t oldWindowFlags = config.windowFlags; + const uint8_t oldSpecialFlags2 = config.specialFlags2; setDefaultConfigSettings(); setToDefaultAudioOutputDevice(); @@ -228,17 +256,7 @@ void resetConfig(void) showBottomScreen(); setWindowSizeFromConfig(true); - - // handle pixel filter change - if ((oldWindowFlags & PIXEL_FILTER) != (config.windowFlags & PIXEL_FILTER)) - { - recreateTexture(); - if (video.fullscreen) - { - leaveFullScreen(); - enterFullscreen(); - } - } + updateImageStretchAndPixelFilter(oldWindowFlags, oldSpecialFlags2); if (config.specialFlags2 & HARDWARE_MOUSE) SDL_ShowCursor(SDL_TRUE); @@ -339,6 +357,7 @@ bool loadConfig(bool showErrorFlag) void loadConfig2(void) // called by "Load config" button { const uint8_t oldWindowFlags = config.windowFlags; + const uint8_t oldSpecialFlags2 = config.specialFlags2; loadConfig(CONFIG_SHOW_ERRORS); @@ -346,16 +365,8 @@ void loadConfig2(void) // called by "Load config" button showTopScreen(false); showBottomScreen(); - // handle pixel filter change - if ((oldWindowFlags & PIXEL_FILTER) != (config.windowFlags & PIXEL_FILTER)) - { - recreateTexture(); - if (video.fullscreen) - { - leaveFullScreen(); - enterFullscreen(); - } - } + setWindowSizeFromConfig(true); + updateImageStretchAndPixelFilter(oldWindowFlags, oldSpecialFlags2); if (config.specialFlags2 & HARDWARE_MOUSE) SDL_ShowCursor(SDL_TRUE); @@ -2110,7 +2121,7 @@ void cbPixelFilter(void) recreateTexture(); if (video.fullscreen) { - leaveFullScreen(); + leaveFullscreen(); enterFullscreen(); } } @@ -2121,7 +2132,7 @@ void cbStretchImage(void) if (video.fullscreen) { - leaveFullScreen(); + leaveFullscreen(); enterFullscreen(); } } diff --git a/src/ft2_events.c b/src/ft2_events.c @@ -38,7 +38,7 @@ "Try to mention what you did before the crash happened.\n" \ "My email can be found at the bottom of www.16-bits.org." -static bool backupMadeAfterCrash; +static bool backupMadeAfterCrash, didDropFile; #ifdef _WIN32 #define SYSMSG_FILE_ARG (WM_USER+1) @@ -50,49 +50,14 @@ static HANDLE oneInstHandle, hMapFile; static LPCTSTR sharedMemBuf; #endif -static void handleInput(void); - -#ifdef _WIN32 // Windows usleep() implementation - -static NTSTATUS (__stdcall *NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval); -static NTSTATUS (__stdcall *NtQueryTimerResolution)(PULONG MinimumResolution, PULONG MaximumResolution, PULONG ActualResolution); -static NTSTATUS (__stdcall *NtSetTimerResolution)(ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution); - -static void (*usleep)(int32_t usec); - -static void usleepGood(int32_t usec) -{ - LARGE_INTEGER delayInterval; - - // NtDelayExecution() delays in 100ns-units, and negative value = delay from current time - usec *= -10; - - delayInterval.HighPart = 0xFFFFFFFF; - delayInterval.LowPart = usec; - NtDelayExecution(false, &delayInterval); -} - -static void usleepWeak(int32_t usec) // fallback if no NtDelayExecution() -{ - Sleep((usec + 500) / 1000); -} - -void windowsSetupUsleep(void) -{ - NtDelayExecution = (NTSTATUS (__stdcall *)(BOOL, PLARGE_INTEGER))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtDelayExecution"); - NtQueryTimerResolution = (NTSTATUS (__stdcall *)(PULONG, PULONG, PULONG))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryTimerResolution"); - NtSetTimerResolution = (NTSTATUS (__stdcall *)(ULONG, BOOLEAN, PULONG))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtSetTimerResolution"); - - usleep = (NtDelayExecution != NULL) ? usleepGood : usleepWeak; -} -#endif +static void handleSDLEvents(void); void readInput(void) { readMouseXY(); readKeyModifiers(); setSyncedReplayerVars(); - handleInput(); + handleSDLEvents(); } void handleThreadEvents(void) @@ -407,7 +372,7 @@ void handleWaitVblQuirk(SDL_Event *event) } } -static void handleInput(void) +static void handleSDLEvents(void) { SDL_Event event; @@ -483,6 +448,10 @@ static void handleInput(void) editor.autoPlayOnDrop = false; loadDroppedFile(event.drop.file, true); SDL_free(event.drop.file); + + // kludge: allow focus-clickthrough after drag-n-drop + SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); + didDropFile = true; } else if (event.type == SDL_QUIT) { @@ -520,6 +489,13 @@ static void handleInput(void) else if (event.type == SDL_MOUSEBUTTONUP) { mouseButtonUpHandler(event.button.button); + + // kludge: we drag-n-dropped a file before this mouse click release, restore focus-clickthrough mode + if (didDropFile) + { + didDropFile = false; + SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "0"); + } } else if (event.type == SDL_MOUSEBUTTONDOWN) { diff --git a/src/ft2_keyboard.c b/src/ft2_keyboard.c @@ -703,7 +703,7 @@ static bool checkModifiedKeys(SDL_Keycode keycode) { if (keyb.leftAltPressed) { - toggleFullScreen(); + toggleFullscreen(); // prevent fullscreen toggle from firing twice on certain SDL2 Linux ports #ifdef __unix__ @@ -896,7 +896,7 @@ static bool checkModifiedKeys(SDL_Keycode keycode) #ifdef __APPLE__ if (keyb.leftCommandPressed && keyb.leftCtrlPressed) { - toggleFullScreen(); + toggleFullscreen(); return true; } else diff --git a/src/ft2_textboxes.c b/src/ft2_textboxes.c @@ -896,7 +896,7 @@ void handleTextEditControl(SDL_Keycode keycode) { // ALT+ENTER = toggle fullscreen, even while text editing if (keyb.leftAltPressed) - toggleFullScreen(); + toggleFullscreen(); else exitTextEditing(); } diff --git a/src/ft2_video.c b/src/ft2_video.c @@ -51,9 +51,10 @@ static char wndTitle[256]; static sprite_t sprites[SPRITE_NUM]; // for FPS counter +#define FPS_LINES 15 #define FPS_SCAN_FRAMES 60 #define FPS_RENDER_W 285 -#define FPS_RENDER_H (((FONT1_CHAR_H + 1) * 8) + 1) +#define FPS_RENDER_H (((FONT1_CHAR_H + 1) * FPS_LINES) + 1) #define FPS_RENDER_X 2 #define FPS_RENDER_Y 2 @@ -79,6 +80,10 @@ void beginFPSCounter(void) static void drawFPSCounter(void) { + SDL_version SDLVer; + + SDL_GetVersion(&SDLVer); + if (editor.framesPassed >= FPS_SCAN_FRAMES && (editor.framesPassed % FPS_SCAN_FRAMES) == 0) { dAvgFPS = 1000.0 / (dRunningFrameDuration / FPS_SCAN_FRAMES); @@ -94,10 +99,12 @@ static void drawFPSCounter(void) hLineDouble(FPS_RENDER_X+1, FPS_RENDER_Y, FPS_RENDER_W, PAL_FORGRND); hLineDouble(FPS_RENDER_X+1, FPS_RENDER_Y+FPS_RENDER_H+2, FPS_RENDER_W, PAL_FORGRND); - // test if enough data is collected yet + // if enough frame data isn't collected yet, show a message if (editor.framesPassed < FPS_SCAN_FRAMES) { - textOut(FPS_RENDER_X+53, FPS_RENDER_Y+39, PAL_FORGRND, "Gathering frame information..."); + const char *text = "Gathering frame information..."; + const uint16_t textW = textWidth(text); + textOut(FPS_RENDER_X+((FPS_RENDER_W/2)-(textW/2)), FPS_RENDER_Y+((FPS_RENDER_H/2)-(FONT1_CHAR_H/2)), PAL_FORGRND, text); return; } @@ -109,20 +116,36 @@ static void drawFPSCounter(void) if (dAudLatency < 0.0 || dAudLatency > 999999999.9999) dAudLatency = 999999999.9999; // prevent number from overflowing text box - sprintf(fpsTextBuf, "Frames per second: %.4f\n" \ + sprintf(fpsTextBuf, + "SDL version: %u.%u.%u\n" \ + "Frames per second: %.3f\n" \ "Monitor refresh rate: %.1fHz (+/-)\n" \ "59..61Hz GPU VSync used: %s\n" \ "Audio frequency: %.1fkHz (expected %.1fkHz)\n" \ "Audio buffer samples: %d (expected %d)\n" \ "Audio channels: %d (expected %d)\n" \ "Audio latency: %.1fms (expected %.1fms)\n" \ + "Render size: %dx%d (offset %d,%d)\n" \ + "Disp. size: %dx%d (window: %dx%d)\n" \ + "Render scaling: x=%.2f, y=%.2f\n" \ + "Mouse to render space muls: x=%.2f, y=%.2f\n" \ + "Relative mouse coords: %d,%d\n" \ + "Absolute mouse coords: %d,%d\n" \ "Press CTRL+SHIFT+F to close this box.\n", - dAvgFPS, dRefreshRate, + SDLVer.major, SDLVer.minor, SDLVer.patch, + dAvgFPS, + dRefreshRate, video.vsync60HzPresent ? "yes" : "no", audio.haveFreq * (1.0 / 1000.0), audio.wantFreq * (1.0 / 1000.0), audio.haveSamples, audio.wantSamples, audio.haveChannels, audio.wantChannels, - dAudLatency, ((audio.wantSamples * 1000.0) / audio.wantFreq)); + dAudLatency, ((audio.wantSamples * 1000.0) / audio.wantFreq), + video.renderW, video.renderH, video.renderX, video.renderY, + video.displayW, video.displayH, video.windowW, video.windowH, + video.renderW / (float)SCREEN_W, video.renderH / (float)SCREEN_H, + video.fMouseXMul, video.fMouseYMul, + mouse.x, mouse.y, + mouse.absX, mouse.absY); // draw text @@ -136,13 +159,24 @@ static void drawFPSCounter(void) if (ch == '\n') { yPos += FONT1_CHAR_H+1; - xPos = FPS_RENDER_X + 3; + xPos = FPS_RENDER_X+3; continue; } charOut(xPos, yPos, PAL_FORGRND, ch); xPos += charWidth(ch); } + + // draw framerate tester symbol + + const uint16_t symbolEnd = 115; + + // ping-pong movement + uint16_t x = editor.framesPassed % (symbolEnd * 2); + if (x >= symbolEnd) + x = (symbolEnd * 2) - x; + + charOut(164 + x, 16, PAL_FORGRND, '*'); } void endFPSCounter(void) @@ -239,6 +273,8 @@ static void updateRenderSizeVars(void) SDL_GetWindowSize(video.window, &video.displayW, &video.displayH); } + SDL_GetWindowSize(video.window, &video.windowW, &video.windowH); + if (video.fullscreen) { if (config.specialFlags2 & STRETCH_IMAGE) @@ -293,11 +329,18 @@ static void updateRenderSizeVars(void) void enterFullscreen(void) { - SDL_DisplayMode dm; + SDL_SetWindowFullscreen(video.window, SDL_WINDOW_FULLSCREEN_DESKTOP); if (config.specialFlags2 & STRETCH_IMAGE) { - SDL_GetDesktopDisplayMode(0, &dm); + SDL_DisplayMode dm; + + int32_t di = SDL_GetWindowDisplayIndex(video.window); + if (di < 0) + di = 0; // return display index 0 (default) on error + + SDL_GetDesktopDisplayMode(di, &dm); + SDL_RenderSetLogicalSize(video.renderer, dm.w, dm.h); } else @@ -306,15 +349,17 @@ void enterFullscreen(void) } SDL_SetWindowSize(video.window, SCREEN_W, SCREEN_H); - SDL_SetWindowFullscreen(video.window, SDL_WINDOW_FULLSCREEN_DESKTOP); + +#ifndef __unix__ // can be severely buggy on Linux... (at least when used like this) SDL_SetWindowGrab(video.window, SDL_TRUE); +#endif updateRenderSizeVars(); updateMouseScaling(); setMousePosToCenter(); } -void leaveFullScreen(void) +void leaveFullscreen(void) { SDL_SetWindowFullscreen(video.window, 0); SDL_RenderSetLogicalSize(video.renderer, SCREEN_W, SCREEN_H); @@ -322,21 +367,28 @@ void leaveFullScreen(void) setWindowSizeFromConfig(false); SDL_SetWindowSize(video.window, SCREEN_W * video.upscaleFactor, SCREEN_H * video.upscaleFactor); + +#ifndef __unix__ SDL_SetWindowGrab(video.window, SDL_FALSE); +#endif updateRenderSizeVars(); updateMouseScaling(); setMousePosToCenter(); + +#ifdef __unix__ // can be required on Linux... (or else the window keeps moving down every time you leave fullscreen) + SDL_SetWindowPosition(video.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); +#endif } -void toggleFullScreen(void) +void toggleFullscreen(void) { video.fullscreen ^= 1; if (video.fullscreen) enterFullscreen(); else - leaveFullScreen(); + leaveFullscreen(); } bool setupSprites(void) @@ -774,8 +826,12 @@ void setWindowSizeFromConfig(bool updateRenderer) uint8_t oldUpscaleFactor = video.upscaleFactor; if (config.windowFlags & WINSIZE_AUTO) { + int32_t di = SDL_GetWindowDisplayIndex(video.window); + if (di < 0) + di = 0; // return display index 0 (default) on error + // find out which upscaling factor is the biggest to fit on screen - if (SDL_GetDesktopDisplayMode(0, &dm) == 0) + if (SDL_GetDesktopDisplayMode(di, &dm) == 0) { for (i = MAX_UPSCALE_FACTOR; i >= 1; i--) { @@ -886,7 +942,11 @@ bool setupWindow(void) setWindowSizeFromConfig(false); - SDL_GetDesktopDisplayMode(0, &dm); + int32_t di = SDL_GetWindowDisplayIndex(video.window); + if (di < 0) + di = 0; // return display index 0 (default) on error + + SDL_GetDesktopDisplayMode(di, &dm); video.dMonitorRefreshRate = (double)dm.refresh_rate; if (dm.refresh_rate >= 59 && dm.refresh_rate <= 61) diff --git a/src/ft2_video.h b/src/ft2_video.h @@ -31,7 +31,7 @@ typedef struct video_t float fMouseXMul, fMouseYMul; uint8_t upscaleFactor; bool vsync60HzPresent, windowHidden; - int32_t renderX, renderY, renderW, renderH, displayW, displayH; + int32_t renderX, renderY, renderW, renderH, displayW, displayH, windowW, windowH; uint32_t *frameBufferUnaligned; SDL_Renderer *renderer; SDL_Texture *texture; @@ -72,7 +72,7 @@ void changeSpriteData(int32_t sprite, const uint8_t *data); void hideSprite(int32_t sprite); void handleRedrawing(void); void enterFullscreen(void); -void leaveFullScreen(void); +void leaveFullscreen(void); void setWindowSizeFromConfig(bool updateRenderer); bool recreateTexture(void); -void toggleFullScreen(void); +void toggleFullscreen(void);