Skip to content

Commit 50ac397

Browse files
committed
Add 8-bit video mode for SDL2 and use it in DOS
There are still some glitches in screen transitions but that's probably our fault. We can improve it later.
1 parent 469d57c commit 50ac397

File tree

7 files changed

+98
-35
lines changed

7 files changed

+98
-35
lines changed

3rdParty/SDL2/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ if(TARGET_PLATFORM STREQUAL "dos")
1919
set(DOS ON)
2020
FetchContent_Declare(SDL2
2121
# branch: dos-vbe-rebase
22-
URL https://github.com/diasurgical/SDL/archive/d9cf9066d9cb796b56d1d70c9c560c055a32149b.tar.gz
23-
URL_HASH MD5=9ad9ae69ee0266c895e79cf05a1e0e49
22+
URL https://github.com/diasurgical/SDL/archive/b55cac0c06aa191dcc7a3e63ae6fe6656593026e.tar.gz
23+
URL_HASH MD5=99eabd2fc675f5539e055b1d8fa519e4
2424
)
2525
else()
2626
FetchContent_Declare(SDL2

CMake/Definitions.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ foreach(
9393
REMAP_KEYBOARD_KEYS
9494
DEVILUTIONX_DEFAULT_RESAMPLER
9595
STREAM_ALL_AUDIO_MIN_FILE_SIZE
96-
DEVILUTIONX_DISPLAY_TEXTURE_FORMAT
96+
DEVILUTIONX_DISPLAY_PIXELFORMAT # SDL2-only
97+
DEVILUTIONX_DISPLAY_TEXTURE_FORMAT # SDL2-only
9798
DEVILUTIONX_SCREENSHOT_FORMAT
9899
DARWIN_MAJOR_VERSION
99100
DARWIN_MINOR_VERSION

CMake/platforms/dos.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ set(DEVILUTIONX_SYSTEM_SDL2 OFF)
1616
set(DEVILUTIONX_STATIC_SDL2 ON)
1717
set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF)
1818
set(DEVILUTIONX_SYSTEM_LIBPNG OFF)
19+
set(DEVILUTIONX_DISPLAY_PIXELFORMAT SDL_PIXELFORMAT_INDEX8)
1920

2021
set(DEVILUTIONX_PLATFORM_FILE_UTIL_LINK_LIBRARIES "")
2122

Source/engine/dx.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,12 @@ bool CanRenderDirectlyToOutputSurface()
6363
&& outputSurface->format->BitsPerPixel == 8);
6464
#endif
6565
#else // !USE_SDL1
66-
return false;
66+
if (renderer != nullptr) return false;
67+
SDL_Surface *outputSurface = GetOutputSurface();
68+
// Assumes double-buffering is available.
69+
return outputSurface->w == static_cast<int>(gnScreenWidth)
70+
&& outputSurface->h == static_cast<int>(gnScreenHeight)
71+
&& outputSurface->format->BitsPerPixel == 8;
6772
#endif
6873
}
6974

Source/storm/storm_svid.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,11 @@ void UpdatePalette()
180180
if (SDL_SetSurfacePalette(SVidSurface.get(), SVidPalette.get()) <= -1) {
181181
ErrSdl();
182182
}
183+
if (GetOutputSurface()->format->BitsPerPixel == 8) {
184+
if (SDL_SetSurfacePalette(GetOutputSurface(), SVidPalette.get()) <= -1) {
185+
ErrSdl();
186+
}
187+
}
183188
#endif
184189
}
185190

@@ -311,6 +316,15 @@ bool SVidPlayBegin(const char *filename, int flags)
311316
ErrSdl();
312317
}
313318
}
319+
#if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT) && DEVILUTIONX_DISPLAY_PIXELFORMAT == SDL_PIXELFORMAT_INDEX8
320+
else {
321+
const Size windowSize = { static_cast<int>(SVidWidth), static_cast<int>(SVidHeight) };
322+
SDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT);
323+
if (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) {
324+
ErrSdl();
325+
}
326+
}
327+
#endif
314328
#else
315329
TrySetVideoModeToSVidForSDL1();
316330
#endif
@@ -405,6 +419,15 @@ void SVidPlayEnd()
405419
ErrSdl();
406420
}
407421
}
422+
#if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT) && DEVILUTIONX_DISPLAY_PIXELFORMAT == SDL_PIXELFORMAT_INDEX8
423+
else {
424+
const Size windowSize = { static_cast<int>(gnScreenWidth), static_cast<int>(gnScreenHeight) };
425+
SDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT);
426+
if (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) {
427+
ErrSdl();
428+
}
429+
}
430+
#endif
408431
#else
409432
if (IsSVidVideoMode) {
410433
SetVideoModeToPrimary(IsFullScreen(), gnScreenWidth, gnScreenHeight);

Source/utils/display.cpp

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -107,37 +107,6 @@ void CalculatePreferredWindowSize(int &width, int &height)
107107
height = mode.h * width / mode.w;
108108
}
109109
}
110-
111-
SDL_DisplayMode GetNearestDisplayMode(Size preferredSize)
112-
{
113-
SDL_DisplayMode nearestDisplayMode;
114-
if (SDL_GetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0)
115-
ErrSdl();
116-
117-
const int displayIndex = SDL_GetWindowDisplayIndex(ghMainWnd);
118-
const int modeCount = SDL_GetNumDisplayModes(displayIndex);
119-
for (int modeIndex = 0; modeIndex < modeCount; modeIndex++) {
120-
SDL_DisplayMode displayMode;
121-
if (SDL_GetDisplayMode(displayIndex, modeIndex, &displayMode) != 0)
122-
continue;
123-
124-
const int diffHeight = std::abs(nearestDisplayMode.h - preferredSize.height) - std::abs(displayMode.h - preferredSize.height);
125-
const int diffWidth = std::abs(nearestDisplayMode.w - preferredSize.width) - std::abs(displayMode.w - preferredSize.width);
126-
if (diffHeight < 0)
127-
continue;
128-
if (diffHeight == 0 && diffWidth < 0)
129-
continue;
130-
nearestDisplayMode = displayMode;
131-
}
132-
133-
LogVerbose("Nearest display mode to {}x{} is {}x{} {}bpp {}Hz",
134-
preferredSize.width, preferredSize.height,
135-
nearestDisplayMode.w, nearestDisplayMode.h,
136-
SDL_BITSPERPIXEL(nearestDisplayMode.format),
137-
nearestDisplayMode.refresh_rate);
138-
139-
return nearestDisplayMode;
140-
}
141110
#endif
142111

143112
void CalculateUIRectangle()
@@ -299,6 +268,59 @@ const auto OptionChangeHandlerVSync = (GetOptions().Graphics.frameRateControl.Se
299268

300269
} // namespace
301270

271+
#if SDL_VERSION_ATLEAST(2, 0, 0)
272+
SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, SDL_PixelFormatEnum preferredPixelFormat)
273+
{
274+
SDL_DisplayMode nearestDisplayMode;
275+
if (SDL_GetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0)
276+
ErrSdl();
277+
278+
const int displayIndex = SDL_GetWindowDisplayIndex(ghMainWnd);
279+
const int modeCount = SDL_GetNumDisplayModes(displayIndex);
280+
281+
// First, find the best mode among the modes with the requested pixel format.
282+
SDL_PixelFormatEnum bestPixelFormat = SDL_PIXELFORMAT_UNKNOWN;
283+
for (int modeIndex = 0; modeIndex < modeCount; modeIndex++) {
284+
SDL_DisplayMode displayMode;
285+
if (SDL_GetDisplayMode(displayIndex, modeIndex, &displayMode) != 0)
286+
continue;
287+
const int diffHeight = std::abs(nearestDisplayMode.h - preferredSize.height) - std::abs(displayMode.h - preferredSize.height);
288+
const int diffWidth = std::abs(nearestDisplayMode.w - preferredSize.width) - std::abs(displayMode.w - preferredSize.width);
289+
if (diffHeight < 0)
290+
continue;
291+
if (diffHeight == 0 && diffWidth < 0)
292+
continue;
293+
if (preferredPixelFormat == SDL_PIXELFORMAT_UNKNOWN
294+
|| displayMode.format == preferredPixelFormat) {
295+
nearestDisplayMode = displayMode;
296+
}
297+
}
298+
if (preferredPixelFormat != SDL_PIXELFORMAT_UNKNOWN && bestPixelFormat == SDL_PIXELFORMAT_UNKNOWN) {
299+
// If no mode with the preferred pixel format was found, allow any pixel format:
300+
for (int modeIndex = 0; modeIndex < modeCount; modeIndex++) {
301+
SDL_DisplayMode displayMode;
302+
if (SDL_GetDisplayMode(displayIndex, modeIndex, &displayMode) != 0)
303+
continue;
304+
const int diffHeight = std::abs(nearestDisplayMode.h - preferredSize.height) - std::abs(displayMode.h - preferredSize.height);
305+
const int diffWidth = std::abs(nearestDisplayMode.w - preferredSize.width) - std::abs(displayMode.w - preferredSize.width);
306+
if (diffHeight < 0)
307+
continue;
308+
if (diffHeight == 0 && diffWidth < 0)
309+
continue;
310+
nearestDisplayMode = displayMode;
311+
}
312+
}
313+
314+
LogVerbose("Nearest display mode to {}x{} is {}x{} {}bpp {}Hz",
315+
preferredSize.width, preferredSize.height,
316+
nearestDisplayMode.w, nearestDisplayMode.h,
317+
SDL_BITSPERPIXEL(nearestDisplayMode.format),
318+
nearestDisplayMode.refresh_rate);
319+
320+
return nearestDisplayMode;
321+
}
322+
#endif
323+
302324
void AdjustToScreenGeometry(Size windowSize)
303325
{
304326
gnScreenWidth = windowSize.width;
@@ -455,6 +477,13 @@ bool SpawnWindow(const char *lpWindowName)
455477

456478
ghMainWnd = SDL_CreateWindow(lpWindowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowSize.width, windowSize.height, flags);
457479

480+
#if defined(DEVILUTIONX_DISPLAY_PIXELFORMAT)
481+
SDL_DisplayMode nearestDisplayMode = GetNearestDisplayMode(windowSize, DEVILUTIONX_DISPLAY_PIXELFORMAT);
482+
if (SDL_SetWindowDisplayMode(ghMainWnd, &nearestDisplayMode) != 0) {
483+
ErrSdl();
484+
}
485+
#endif
486+
458487
// Note: https://github.com/libsdl-org/SDL/issues/962
459488
// This is a solution to a problem related to SDL mouse grab.
460489
// See https://github.com/diasurgical/devilutionX/issues/4251

Source/utils/display.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,8 @@ void LogicalToOutput(T *x, T *y)
109109
#endif
110110
}
111111

112+
#if SDL_VERSION_ATLEAST(2, 0, 0)
113+
SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, SDL_PixelFormatEnum preferredPixelFormat = SDL_PIXELFORMAT_UNKNOWN);
114+
#endif
115+
112116
} // namespace devilution

0 commit comments

Comments
 (0)